.md

sl.streams

Every Stacks event in order, as a loop you checkpoint or a page you read. The same data the Streams API serves over HTTP.

@secondlayer/sdk@15.5.014 methodsfrom source with openpkgStreams guideStreams API
consume(params)AsyncIterableIterator<StreamsBatch<…Read Streams page by page as an async iterator.
events.list(params)StreamsEventsEnvelope<VmStreamsEven…Read one page of chain events and the next cursor.
events.byTxId(txId)StreamsEventsListEnvelope<StreamsEv…Read every event a transaction emitted.
events.consume(params)StreamsEventsConsumeResultRun a checkpointed indexer that rewinds on reorgs.
events.replay(params)StreamsEventsConsumeResultBackfill from bulk dumps, then continue live in one call.
events.stream(params)AsyncIterable<StreamsEventOfTypes<T…Read events one at a time as an async iterator.
events.subscribe(params)StreamsSubscriptionGet each new event pushed to onEvent as it lands.
blocks.events(heightOrHash)StreamsEventsListEnvelope<StreamsEv…Read every event in one block, by height or hash.
reorgs.list(params)StreamsReorgsListEnvelopeList chain reorgs since a cursor.
dumps.list()StreamsDumpsManifestFetch and parse the latest dumps manifest.
dumps.fileUrl(file)stringAbsolute URL for a manifest file.
dumps.download(file)Uint8ArrayDownload a parquet file and verify its sha256 against the manifest.
canonical(height)StreamsCanonicalBlockGet the canonical block at a height.
tip()StreamsTipGet the current chain tip.

Read Streams page by page as an async iterator.

Yields one StreamsBatch per events page, so each yield is exactly one API call. Empty pages are skipped; at the tip the iterator polls again every intervalMs (default 2000) until signal aborts.

Reorgs appear on batch.reorgs, but the cursor is not rewound for you. Use events.consume with onReorg when you need rollback.

A literal types array narrows every batch's event union to those types. chain: "bitcoin" batches carry Runes rows only, on the bitcoin tip shape.

sl.streams.consume<const T extends readonly StreamsEventType[]>(
params: StreamsConsumeCommon
& {
chain?: "stacks";
types?: readonly ("stx_transfer" | "stx_mint" | "stx_burn" | "stx_lock" | "ft_transfer" | "ft_mint" | "ft_burn" | "nft_transfer" | "nft_mint" | "nft_burn" | "print")[];
notTypes?: readonly ("stx_transfer" | "stx_mint" | "stx_burn" | "stx_lock" | "ft_transfer" | "ft_mint" | "ft_burn" | "nft_transfer" | "nft_mint" | "nft_burn" | "print")[];
contractId?: StreamsFilterValue;
sender?: StreamsFilterValue;
recipient?: StreamsFilterValue;
assetIdentifier?: string;
filters?: StreamsFilterMap;
}
& { types: T },
): AsyncIterableIterator<StreamsBatch<StreamsEventOfTypes<T>, StreamsTip>, any, any>

Parameters

hover a row to find it in the code

Required

typesrequiredTStacks · Bitcoin only

Options

cursorstring | nullStacks · Bitcoin onlyResume strictly after this cursor; omit to start from the oldest seekable page.
batchSizenumberStacks · Bitcoin onlyEvents per page (the limit query param). Default 100.
intervalMsnumberStacks · Bitcoin onlyPoll interval while caught up at the tip, in ms. Default 2000.
signalAbortSignalStacks · Bitcoin only
chain"stacks"Stacks · Bitcoin only
notTypesreadonly ("stx_transfer" | "stx_mint" | "stx_burn" | "s…Stacks · Bitcoin only
contractIdStreamsFilterValueStacks only
senderStreamsFilterValueStacks only
6 more options
recipientStreamsFilterValueStacks only
assetIdentifierstringStacks only
filtersStreamsFilterMapStacks only
paramsStreamsConsumeBitcoinParams | StreamsConsumeStacksParamsAny chain only
runestringBitcoin onlyA RuneRef: an id (840000:3) or a name (DOG•GO•TO•THE•MOON).
addressstringBitcoin onlyA mainnet address.

Read one page of chain events and the next cursor.

Narrow with types, notTypes, contractId, sender, recipient, assetIdentifier, fromHeight/toHeight, or labelled filters. Filters match exactly, and an event type without a given field never matches it. Pass next_cursor back as cursor to continue. The envelope also carries the tip and any reorgs. To write the events somewhere with a checkpoint, use events.consume instead.

A literal types array narrows every row to those event types. clock: "vm" pages carry vm rows only (a parallel vocabulary, event_index = ordinal), never StreamsEvent; it is Stacks only. chain: "bitcoin" pages carry Runes rows only, on the bitcoin tip shape, and filter by rune or address.

sl.streams.events.list(
params: StreamsEventsListParamsCommon
& {
chain?: "stacks";
clock?: "classic" | "vm";
types?: readonly ("stx_transfer" | "stx_mint" | "stx_burn" | "stx_lock" | "ft_transfer" | "ft_mint" | "ft_burn" | "nft_transfer" | "nft_mint" | "nft_burn" | "print" | "nested_contract_call" | "var_set" | "map_set" | "map_insert" | "map_delete")[];
notTypes?: readonly ("stx_transfer" | "stx_mint" | "stx_burn" | "stx_lock" | "ft_transfer" | "ft_mint" | "ft_burn" | "nft_transfer" | "nft_mint" | "nft_burn" | "print" | "nested_contract_call" | "var_set" | "map_set" | "map_insert" | "map_delete")[];
contractId?: StreamsFilterValue;
sender?: StreamsFilterValue;
recipient?: StreamsFilterValue;
assetIdentifier?: string;
filters?: StreamsFilterMap;
}
& { clock: "vm" },
): Promise<StreamsEventsEnvelope<VmStreamsEvent, StreamsTip>>

Parameters

hover a row to find it in the code

Required

clockrequired"vm"Stacks only
paramsrequiredStreamsEventsListParamsAny chain only

Options

cursorstring | nullStacks · Bitcoin only
fromHeightnumberStacks · Bitcoin only
toHeightnumberStacks · Bitcoin only
limitnumberStacks · Bitcoin only
chain"stacks"Stacks · Bitcoin only
typesreadonly ("stx_transfer" | "stx_mint" | "stx_burn" | "s…Stacks · Bitcoin only
notTypesreadonly ("stx_transfer" | "stx_mint" | "stx_burn" | "s…Stacks · Bitcoin only
contractIdStreamsFilterValueStacks only
6 more options
senderStreamsFilterValueStacks only
recipientStreamsFilterValueStacks only
assetIdentifierstringStacks only
filtersStreamsFilterMapStacks only
runestringBitcoin onlyA RuneRef: an id (840000:3) or a name (DOG•GO•TO•THE•MOON).
addressstringBitcoin onlyA mainnet address.
Returns Promise<StreamsEventsEnvelope<VmStreamsEvent, StreamsTi…
events
TEvent[]
next_cursor
string | null
tip
TTip
reorgs
StreamsReorg[]

Read every event a transaction emitted.

Returns the events and the tip, with no next_cursor: one transaction is one response.

chain: "bitcoin" returns the Runes events for one Bitcoin transaction.

sl.streams.events.byTxId(
txId: string,
): Promise<StreamsEventsListEnvelope<StreamsEvent, StreamsTip>>

Parameters

hover a row to find it in the code

Required

txIdrequiredstring
opts.chainrequired"bitcoin"Bitcoin only
Returns Promise<StreamsEventsListEnvelope<StreamsEvent, Streams…
events
TEvent[]
tip
TTip
reorgs
StreamsReorg[]

Run a checkpointed indexer that rewinds on reorgs.

Write your rows in onBatch and commit ctx.cursor in the same transaction; resume with fromCursor. Reorgs at or below your checkpoint call onReorg, then the loop re-reads from the fork point. Delivery is at-least-once, so keep writes idempotent. With a sink, the checkpoint and rollback are handled for you. mode: "tail" (default) keeps polling at the tip; mode: "bounded" returns on the first empty page. It also stops on maxPages, maxEmptyPolls, or signal. Pass finalizedOnly to skip reorg handling entirely.

chain: "bitcoin" sweeps Runes events; see StreamsEventsConsumeBitcoinParams.

sl.streams.events.consume(
params: StreamsEventsConsumeParams<TTx, D, F> & { sink?: ConsumerSink<TTx> },
): Promise<StreamsEventsConsumeResult>
events.consume.tsts
import { Database } from "bun:sqlite";
import { SecondLayer } from "@secondlayer/sdk";
const db = new Database("transfers.sqlite");
db.run(`create table if not exists transfers (
cursor text primary key,
block_height integer not null,
sender text not null,
recipient text not null,
amount text not null
)`);
db.run(
"create table if not exists checkpoint (id integer primary key check (id = 1), cursor text)",
);
const sl = new SecondLayer({
apiKey: process.env.SECONDLAYER_API_KEY,
});
const saved = db
.query<{ cursor: string | null }, []>("select cursor from checkpoint")
.get();
await sl.streams.events.consume({
types: ["ft_transfer"],
fromCursor: saved?.cursor ?? null,
^Null on the first run, so the sweep starts at the beginning.
onBatch: (events, _envelope, ctx) => {
db.transaction(() => {
for (const event of events) {
if (event.event_type !== "ft_transfer") continue;
db.query("insert or replace into transfers values (?, ?, ?, ?, ?)").run(

Parameters

hover a row to find it in the code

Options

chain"stacks"chain: "stacks" (default, omit chain entirely) — the bitcoin branch is StreamsEventsConsumeBitcoinParams, a separate overload with no filters/on/decoded (Stacks-only concepts).
fromCursorstring | null
decodedDStacks onlyDeliver events pre-decoded as the flat, event_type-discriminated rows Index serves (IndexEvent), so Streams consumption reads identically to Index consumption — no guard+decode pairs in your handler.
sinkConsumerSink<TTx>
onProgress(ctx: ConsumerBatchContext<unknown, unknown>) => voidFires once per page, before onBatch and before any early return.
mode"tail" | "bounded"
finalizedOnlybooleanEmit only finalized (immutable) events and never surface reorgs. The SDK checkpoints at the last finalized event and re-reads the unfinalized tail until it settles. Trades finality lag for zero reorg handling; onReorg is ignored.
typesreadonly ("stx_transfer" | "stx_mint" | "stx_burn" | "s…
21 more options
notTypesreadonly ("stx_transfer" | "stx_mint" | "stx_burn" | "s…
contractIdStreamsFilterValueStacks only
senderStreamsFilterValueStacks only
recipientStreamsFilterValueStacks only
assetIdentifierstringStacks only
filtersFStacks onlyLabelled filter groups. The groups OR together in ONE server-side scan, so two unrelated concerns share one page, one cursor, and one checkpoint instead of two consume loops. Pair with on to handle each label.
on{ [K in keyof F]: ( events: StreamsEventForFilter<F[K],…Stacks onlyOne handler per label in filters. Every label must be handled, so adding a label is a compile error until its handler exists. A label's declared types narrows its handler's events, so payload is typed without an event_type guard. Labels are dispatched in declaration order: a label's own events stay in cursor order, but events of different labels do not interleave within a page — add onBatch when you need strict global order across labels.
batchSizenumber
onBatch(events: D extends true ? IndexEvent[] : StreamsEvent[]…Apply a page of canonical events. Persist ctx.cursor in the same transaction as your writes. Returning a cursor overrides ctx.cursor as the resume point (advanced manual control); returning nothing uses it. Optional only when on handles the page instead; a consume call with neither throws.
onReorg(reorg: StreamsReorg, ctx: StreamsReorgContext) => Prom…Roll your projection back to reorg.fork_point_height, persisting ctx.cursor in the same transaction. Called once per *new* reorg at or below the checkpoint (deduped in-memory, fork-ascending) before the SDK rewinds and re-reads the now-canonical events. A reorg whose fork sits above the checkpoint is not a rollback (nothing past it was written) and is skipped. Omit it to ignore reorgs (events stay canonical, but stale rows from an orphaned fork are left in place). With onReorg or a sink attached, every empty page also polls reorgs.list (one extra request per idle poll) so a fork that lands while the consumer idles at the tip is rolled back too.
maxRollbackDepthnumberDeepest rewind one reorg may make below the checkpoint before the loop refuses with ValidationError. Default 1000 blocks. The fork point is server supplied and drives a delete on every declared table, so raise this only for a source you trust.
retryCountnumberPage-fetch retries after the first failure (429/5xx/network only — 4xx and handler throws always propagate). Default 3; 0 disables.
retryDelaynumberBase retry delay in ms; the n-th retry waits retryDelay * n. A server Retry-After overrides it. Default 1000.
onError(err: unknown, ctx: { attempt: number; retriesLeft: num…Void observer, called before each retry sleep (metrics/logging).
emptyBackoffMsnumber
maxPagesnumber
maxEmptyPollsnumber
signalAbortSignal
wake() => Promise<void>Cuts the empty-poll backoff short: on an empty page, the loop races emptyBackoffMs against this promise instead of sleeping the full amount. Pass a function that resolves once when new data MIGHT be available (e.g. a Postgres NOTIFY listener) — it is called fresh on every empty page, never awaited more than once concurrently per page. The backoff timer still runs underneath, so a wake source that never resolves (or a wake this call omits) degrades to the same polling behavior as before.
runestringBitcoin onlyA RuneRef: an id (840000:3) or a name (DOG•GO•TO•THE•MOON).
addressstringBitcoin onlyA mainnet address.
Callback context ctx: ConsumerBatchContext<unknown, unknown>
cursor
Checkpoint to commit alongside your rows.
height
Highest canonical block a row was DELIVERED from. null before the first row of a fresh consume. With a sparse filter this parks at the last matching event — it measures event recency, not progress.
scannedHeight
Highest canonical block the sweep has VERIFIED through: an empty page is the server confirming nothing matches between the cursor and the tip, so a caught-up tail scans to the tip even when height is far below it. Rolls back with reorg rewinds.
tipHeight
Chain tip as of this page's read.
blocksBehind
tipHeight - scannedHeight, floored at 0 — the consumer's actual backlog. null until a position is known. A caught-up consumer on a quiet contract reads ~0 here while tipHeight - height grows — that difference is event age, not lag.
tip
The full tip for this page — StreamsTip or IndexTip depending on the surface. Exposed here so a handler never needs the envelope parameter, which is the only way to reach it today and is also how the worst finalizedOnly mistake becomes reachable (return envelope.next_cursor jumps the cursor past events that were filtered out and never delivered).
reorgs
Reorgs reported alongside this page; empty when none. Rollback still belongs in onReorg — this is for observability inside a batch.
Callback context ctx: StreamsReorgContext
cursor
string | null
Returns Promise<StreamsEventsConsumeResult>
cursor
string | null
pages
number
emptyPolls
number

Backfill from bulk dumps, then continue live in one call.

Hands each finalized dump file to onDumpFile in block order, then tails live from the manifest's latest_finalized_cursor, with no gap or duplicate at the seam. A file that straddles from is delivered whole, so skip the rows at or below it. Requires dumpsBaseUrl.

sl.streams.events.replay(
params: StreamsEventsReplayParams,
): Promise<StreamsEventsConsumeResult>
events.replay.tsts
import { SecondLayer } from "@secondlayer/sdk";
const sl = new SecondLayer({
apiKey: process.env.SECONDLAYER_API_KEY,
dumpsBaseUrl: process.env.STREAMS_DUMPS_BASE_URL,
});
const result = await sl.streams.events.replay({
from: "genesis",
mode: "bounded",
^Return at the first empty page instead of tailing forever.
onDumpFile: async (file, { from }) => {
const bytes = await sl.streams.dumps.download(file);
^Checks the file's sha256 against the signed manifest.
await Bun.write(`dumps/${file.from_block}-${file.to_block}.parquet`, bytes);
console.log(`dump ${file.path}, resume after ${from ?? "genesis"}`);
^Set on a resume. A file that straddles it arrives whole, so skip rows at or below it.
},
onBatch: (events, envelope) => {
console.log(`live page: ${events.length} events`);
return envelope.next_cursor;
},
});
console.log(`caught up at ${result.cursor} after ${result.pages} live pages`);

Parameters

hover a row to find it in the code

Required

onDumpFilerequired(file: StreamsDumpFile, ctx: { from: string | null }) =…Called once per finalized dump file, in block order, before live tailing. Process the parquet with your own tooling (e.g. DuckDB) — the SDK does not decode parquet. Use client.dumps.download(file) to fetch + verify bytes. Delivery is file-granular and at-least-once: a file whose range straddles from is handed over whole. ctx.from is that cursor (null from genesis); skip rows at or below it, or key rows by cursor so a re-run is an idempotent no-op. Files ending at or below from are not handed over at all.
onBatchrequired(events: StreamsEvent[], envelope: StreamsEventsEnvelop…Called per live page after the dump phase, like consume.

Options

fromstringStart point: "genesis" (default) or a <block>:<index> cursor.
onReorg(reorg: StreamsReorg, ctx: StreamsReorgContext) => Prom…Called when the live-tail phase (after the dump backfill) crosses a reorg, before the cursor rewinds and re-reads the now-canonical events — same contract as consume. The dump-backfill phase is finalized and never reorgs; omit this to leave stale rows from an orphaned fork in place.
mode"tail" | "bounded"
batchSizenumber
emptyBackoffMsnumber
maxPagesnumber
maxEmptyPollsnumber
signalAbortSignal
3 more options
typesreadonly ("stx_transfer" | "stx_mint" | "stx_burn" | "s…Narrow the LIVE TAIL after the dump phase. The dump files themselves are always all-type (block-partitioned parquet) — filter those in your own tooling while processing each file.
notTypesreadonly ("stx_transfer" | "stx_mint" | "stx_burn" | "s…
filtersStreamsFilterMapLabelled OR-groups for the live tail, like consume.
Callback context ctx: StreamsReorgContext
cursor
string | null
Returns Promise<StreamsEventsConsumeResult>
cursor
string | null
pages
number
emptyPolls
number

Read events one at a time as an async iterator.

For live processors and watch-style apps that keep their own state. It tails indefinitely and stops when signal, maxPages, or maxEmptyPolls ends it. There is no checkpoint or reorg handling; use events.consume for that.

A literal types array narrows every event to those types. chain: "bitcoin" yields Runes events only.

sl.streams.events.stream(
params: StreamsEventsStreamCommon
& {
chain?: "stacks";
types?: readonly ("stx_transfer" | "stx_mint" | "stx_burn" | "stx_lock" | "ft_transfer" | "ft_mint" | "ft_burn" | "nft_transfer" | "nft_mint" | "nft_burn" | "print")[];
notTypes?: readonly ("stx_transfer" | "stx_mint" | "stx_burn" | "stx_lock" | "ft_transfer" | "ft_mint" | "ft_burn" | "nft_transfer" | "nft_mint" | "nft_burn" | "print")[];
contractId?: StreamsFilterValue;
sender?: StreamsFilterValue;
recipient?: StreamsFilterValue;
assetIdentifier?: string;
filters?: StreamsFilterMap;
}
& { types: T },
): AsyncIterable<StreamsEventOfTypes<T>, any, any>

Parameters

hover a row to find it in the code

Required

typesrequiredTStacks · Bitcoin only

Options

fromCursorstring | nullStacks · Bitcoin only
batchSizenumberStacks · Bitcoin only
emptyBackoffMsnumberStacks · Bitcoin only
maxPagesnumberStacks · Bitcoin only
maxEmptyPollsnumberStacks · Bitcoin only
signalAbortSignalStacks · Bitcoin only
chain"stacks"Stacks · Bitcoin only
notTypesreadonly ("stx_transfer" | "stx_mint" | "stx_burn" | "s…Stacks · Bitcoin only
8 more options
contractIdStreamsFilterValueStacks only
senderStreamsFilterValueStacks only
recipientStreamsFilterValueStacks only
assetIdentifierstringStacks only
filtersStreamsFilterMapStacks only
paramsStreamsEventsStreamBitcoinParams | StreamsEventsStreamS…Any chain only
runestringBitcoin onlyA RuneRef: an id (840000:3) or a name (DOG•GO•TO•THE•MOON).
addressstringBitcoin onlyA mainnet address.

Get each new event pushed to onEvent as it lands.

Reconnects from the last handled cursor after a transport error, and verifies each frame's ed25519 signature when the client has verify on. Returns an unsubscribe function whose done promise settles when the loop ends. Not reorg-aware: an event delivered and then orphaned is never retracted. Durable writers use events.consume.

chain: "bitcoin" delivers Runes rows to onEvent.

sl.streams.events.subscribe(
params: StreamsEventsSubscribeStacksParams,
): StreamsSubscription
events.subscribe.tsts
import { SecondLayer } from "@secondlayer/sdk";
const sl = new SecondLayer({
apiKey: process.env.SECONDLAYER_API_KEY,
});
const subscription = sl.streams.events.subscribe({
types: ["print"],
contractId: "SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-registry",
onEvent: (event) => {
if (event.event_type !== "print") return;
^Each event is a union until you check its type.
console.log(event.cursor, event.payload.topic);
},
onError: (err) => console.error("subscription error", err),
^Transport errors reconnect from the last handled cursor; this just observes them.
});
// Calling the subscription unsubscribes.
process.on("SIGTERM", () => subscription());
await subscription.done;
^Settles when the loop ends, and rejects on an error a retry cannot fix.

Parameters

hover a row to find it in the code

Required

onEventrequired(event: StreamsEvent) => Promise<void> | voidCalled for each pushed event, in order. The resume cursor advances only after this resolves, so a handler that throws sees the same event again on reconnect (at-least-once). Key durable writes by cursor.

Options

fromCursorstring | nullResume strictly after this cursor; omit to live-tail from the tip.
signalAbortSignal
onError(err: unknown) => voidCalled on every failure. Transport errors (dropped socket, 5xx, 429, a stale connection, a throwing handler) reconnect from the last handled cursor with exponential backoff. Errors that a retry cannot fix (401, 4xx, a bad signature) end the subscription and reject its done.
reconnectDelayMsnumberFirst reconnect pause in ms (default 1000). Doubles per consecutive failure up to 30 s with jitter, resets once a frame arrives, and never undercuts a Retry-After.
staleAfterMsnumberReconnect when no frame (pings included) arrives for this long (default 60000, three server heartbeats). Catches a half-open socket that never errors; set it above your instance's heartbeat interval.
chain"stacks"
typesreadonly ("stx_transfer" | "stx_mint" | "stx_burn" | "s…
notTypesreadonly ("stx_transfer" | "stx_mint" | "stx_burn" | "s…
7 more options
contractIdStreamsFilterValueStacks only
senderStreamsFilterValueStacks only
recipientStreamsFilterValueStacks only
assetIdentifierstringStacks only
filtersStreamsFilterMapStacks onlyLabelled filter groups; see StreamsEventsListParams.filters.
runestringBitcoin onlyA RuneRef: an id (840000:3) or a name (DOG•GO•TO•THE•MOON).
addressstringBitcoin onlyA mainnet address.
Returns StreamsSubscription
done
Promise<void>

Read every event in one block, by height or hash.

Returns the events and the tip, with no next_cursor.

chain: "bitcoin" returns the Runes events in one Bitcoin block.

sl.streams.blocks.events(
heightOrHash: string | number,
): Promise<StreamsEventsListEnvelope<StreamsEvent, StreamsTip>>

Parameters

hover a row to find it in the code

Required

heightOrHashrequiredstring | number
opts.chainrequired"bitcoin"Bitcoin only
Returns Promise<StreamsEventsListEnvelope<StreamsEvent, Streams…
events
TEvent[]
tip
TTip
reorgs
StreamsReorg[]

List chain reorgs since a cursor.

since is required. Each reorg gives its fork_point_height and the orphaned range. Page with next_since.

chain: "bitcoin" lists Bitcoin reorgs, on their own cursor space.

sl.streams.reorgs.list(
params: StreamsReorgsListParams,
): Promise<StreamsReorgsListEnvelope>

Parameters

hover a row to find it in the code

Required

sincerequiredstring
chainrequired"bitcoin"Bitcoin only

Options

limitnumber
Returns Promise<StreamsReorgsListEnvelope>
reorgs
StreamsReorg[]
next_since
string | null

Fetch and parse the latest dumps manifest.

sl.streams.dumps.list(): Promise<StreamsDumpsManifest>
Returns Promise<StreamsDumpsManifest>
dataset
string
network
string
version
string
schema_version
number
generated_at
string
producer_version
string
finality_lag_blocks
number
latest_finalized_cursor
Cursor at the end of the finalized bulk coverage — hand to live tailing.
coverage
{ from_block: number; to_block: number }
files
StreamsDumpFile[]
signature
ed25519 signature over the manifest's canonical bytes. Absent on legacy unsigned manifests. Verified by list() when verifyDumpsManifest is on.
key_id
Short id of the signing public key.

Absolute URL for a manifest file.

sl.streams.dumps.fileUrl(file: StreamsDumpFile): string

Parameters

hover a row to find it in the code

Required

pathrequiredstring
from_blockrequirednumber
to_blockrequirednumber
min_cursorrequiredstring | null
max_cursorrequiredstring | null
row_countrequirednumber
byte_sizerequirednumber
sha256requiredstring
schema_versionrequirednumber
created_atrequiredstring

Download a parquet file and verify its sha256 against the manifest.

sl.streams.dumps.download(file: StreamsDumpFile): Promise<Uint8Array>

Parameters

hover a row to find it in the code

Required

pathrequiredstring
from_blockrequirednumber
to_blockrequirednumber
min_cursorrequiredstring | null
max_cursorrequiredstring | null
row_countrequirednumber
byte_sizerequirednumber
sha256requiredstring
schema_versionrequirednumber
created_atrequiredstring

Get the canonical block at a height.

Returns the block hash and, on Stacks, the burn block it anchors to.

chain: "bitcoin" returns the Bitcoin block, without burn-chain fields.

sl.streams.canonical(height: number): Promise<StreamsCanonicalBlock>

Parameters

hover a row to find it in the code

Required

heightrequirednumber
opts.chainrequired"bitcoin"Bitcoin only
Returns Promise<StreamsCanonicalBlock>
block_height
number
block_hash
string
burn_block_height
number
burn_block_hash
string | null
is_canonical
true

Get the current chain tip.

Returns the tip height and hash, finalized_height, and lag_seconds. On Stacks it also reports the oldest height your tier can seek; older reads come from the bulk dumps.

chain: "bitcoin" returns the Bitcoin tip, without burn-chain or retention fields.

sl.streams.tip(): Promise<StreamsTip>

Parameters

hover a row to find it in the code

Required

chainrequired"bitcoin"Bitcoin only
Returns Promise<StreamsTip>
block_height
number
block_hash
string
burn_block_height
number
finalized_height
Highest Stacks block past the burn-confirmation finality boundary. Optional for back-compat; the API always sets it.
lag_seconds
number
oldest_seekable_height
Oldest height still seekable on the live API for the caller's tier (tip - retention). null = unlimited retention. Older reads must use the cold dumps lane. Optional for back-compat.
oldest_cursor
Oldest seekable cursor (<oldest_seekable_height>:0); null = unlimited.
ConsumerBatchContext
What the loop knows at the end of a page, handed to onBatch.
ConsumerSink
A consumer sink: the destination adapter a consume loop writes through.
FtBurnPayload
asset_identifier, sender, amount
FtMintPayload
asset_identifier, recipient, amount
FtTransferPayload
asset_identifier, sender, recipient, amount
MapDeletePayload
contract_identifier, map_name, raw_key
MapWritePayload
contract_identifier, map_name, raw_key, raw_value
NestedContractCallPayload
contract_identifier, sender, caller, function_name, function_args, raw_result
NftBurnPayload
asset_identifier, sender, value, raw_value
NftMintPayload
asset_identifier, recipient, value, raw_value
NftTransferPayload
asset_identifier, sender, recipient, value, raw_value
PrintPayload
contract_id, topic, value, raw_value
RuneEtchEntry
The etch a rune_etch event created — everything a consumer needs to render a fresh rune without a second lookup, minus what the envelope already carries (rune_id).
RuneEventPayload
amount, vout, address, entry
RuneEventType
"rune_etch" | "rune_mint" | "rune_transfer" | "rune_burn"
RuneStreamsEvent
A Bitcoin rune event as Streams serves it.
StreamsBatch
One page yielded by consume, with cursor to persist and resume.
StreamsBatchContext
cursor, height, scannedHeight, tipHeight, blocksBehind, tip, … Deprecated. Use ConsumerBatchContext.
StreamsBitcoinCanonicalBlock
A Bitcoin canonical block, without burn-chain fields.
StreamsBitcoinTip
The Bitcoin tip, without burn-chain or retention fields.
StreamsCanonicalBlock
A canonical Stacks block with its Bitcoin anchor.
StreamsClarityValue
A Clarity value as Streams serves it: the canonical hex string, a typed object carrying that hex ({ hex }), or a decoded Clarity-JSON object.
StreamsConsumeBitcoinParams
Consume options for Runes batches, with their own cursor space.
StreamsConsumeCommon
Cursor, batch size, and polling options shared by every consume loop.
StreamsConsumeStacksParams
chain: "stacks" (default, omit chain entirely).
StreamsDumpFile
One bulk parquet file in the dumps manifest.
StreamsDumpsManifest
The index of finalized Parquet dump files for one dataset.
StreamsEvent
A raw Streams event.
StreamsEventOf
cursor, block_height, block_hash, burn_block_height, tx_id, tx_index, …
StreamsEventOfTypes
The event union narrowed to a types selection.
StreamsEventsBitcoinListParams
List options for Runes events, with their own cursor space.
StreamsEventsConsumeBitcoinParams
Options for the checkpointed sweep over Runes events.
StreamsEventsConsumeParams
Options for consuming Streams events: cursor, batching, filters, handler.
StreamsEventsConsumeResult
Where a consume loop stopped: cursor, pages read, empty polls.
StreamsEventsEnvelope
One page of events with the next cursor, tip, and reorgs.
StreamsEventsListEnvelope
One page of events with the tip and reorgs, no cursor.
StreamsEventsListParams
Chain, cursor, height range, and filters for listing Streams events.
StreamsEventsListParamsCommon
Cursor, height range, and limit shared by every list call.
StreamsEventsReplayParams
Options for replaying history from dump files, then tailing live.
StreamsEventsStacksListParams
chain: "stacks" (default, omit chain entirely) — unchanged since before Runes events were added.
StreamsEventsStreamBitcoinParams
Stream options for Runes events, tailed like the Stacks default.
StreamsEventsStreamCommon
Cursor, batching, and stop options shared by every event stream.
StreamsEventsStreamStacksParams
Stream options for Stacks events, the default chain.
StreamsEventsSubscribeBitcoinParams
Options for pushing Runes events live, on their own cursor space.
StreamsEventsSubscribeStacksParams
chain: "stacks" (default, omit chain entirely).
StreamsFilterMap
A map of label → filter group.
StreamsFilterValue
A single value or a list of values to match.
StreamsLabelledFilter
One labelled filter group.
StreamsReorg
detected_at, fork_point_height, orphaned_range, new_canonical_tip
StreamsReorgContext
cursor is the rewind position the loop resumes from after onReorg: the foot of the fork point, or null for a fork at genesis.
StreamsReorgsListEnvelope
A list of reorgs and the cursor to resume from.
StreamsReorgsListParams
A starting point and limit for listing reorgs.
StreamsSubscription
Handle for a live subscription: call it to unsubscribe.
StreamsTip
The chain tip: latest block, Bitcoin anchor, and finality boundary.
StreamsWireEvent
Any row GET /v1/streams/events can return.
StxBurnPayload
sender, amount
StxLockPayload
locked_address, locked_amount, unlock_height
StxMintPayload
recipient, amount
StxTransferPayload
sender, recipient, amount, memo
VarSetPayload
contract_identifier, var_name, raw_value
VmStreamsEvent
A Streams clock=vm row.
VmStreamsEventOf
cursor, block_height, block_hash, burn_block_height, tx_id, tx_index, …
Edit on GitHub