@secondlayer/sdk 6.47.0 → 6.48.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,12 +14,83 @@ import { STREAMS_EVENT_TYPES, StreamsEventType } from "@secondlayer/shared";
14
14
  * The interface is dependency-free on purpose: implementations with real
15
15
  * database drivers live behind subpath exports (`@secondlayer/sdk/sinks/*`)
16
16
  * so the root entry ships no DB dependency.
17
+ *
18
+ * ## The contract
19
+ *
20
+ * Binding on every implementation; the conformance kit
21
+ * (`@secondlayer/sdk/sinks/testing`) probes each one. Violations are SILENT
22
+ * in production — they surface as gaps or duplicates weeks later, never as
23
+ * errors at the violation site — which is why they are spelled out here and
24
+ * mechanically tested.
25
+ *
26
+ * What the loop guarantees the sink:
27
+ *
28
+ * 1. **Init-before-first-page.** `loadCursor` is called exactly once, before
29
+ * the first fetch — even when the caller passed an explicit `fromCursor`.
30
+ * It is the sink's init hook: create checkpoint storage, validate
31
+ * rollback preconditions.
32
+ * 2. **Deterministic replay.** Re-reading from the same cursor yields the
33
+ * same rows in the same order. `cursor` is therefore a valid idempotency
34
+ * key: an append-only sink can dedup on it with no contract change.
35
+ * 3. **At-least-once delivery.** A batch whose commit outcome was lost (crash
36
+ * after commit, before the loop observed it) is re-committed on restart
37
+ * with the SAME cursor and the same rows.
38
+ *
39
+ * What the sink must guarantee — `commitBatch`:
40
+ *
41
+ * 4. **Rows+cursor atomicity.** The handler's writes and `cursor` commit in
42
+ * ONE transaction. Committing them separately is the classic torn-batch
43
+ * bug: a crash between the two either re-delivers (duplicates) or skips
44
+ * (gap) depending on the order.
45
+ * 5. **Abort on throw.** A throw from `write` aborts the WHOLE transaction —
46
+ * neither rows nor cursor land — so a crashed batch is simply re-read.
47
+ * 6. **The lent transaction is the real one.** `write(tx)` receives the same
48
+ * live transaction the cursor commits in; every handler write must go
49
+ * through it. Writes outside `tx` escape atomicity AND rollback.
50
+ * 7. **Replay safety.** Committing the same cursor twice must not corrupt
51
+ * state (per #3 the rows are identical; upsert/dedup make it exact).
52
+ *
53
+ * What the sink must guarantee — `rollback`:
54
+ *
55
+ * 8. **Delete+rewind atomicity.** Undoing rows at/above the fork and
56
+ * committing `rewindCursor` happen in ONE transaction. A crash between
57
+ * them resumes above the fork and the deleted range is never re-read —
58
+ * the silent-gap bug.
59
+ * 9. **Inclusive fork point.** Undo AT OR ABOVE `forkPointHeight` (`>=`) —
60
+ * the new canonical chain re-supplies the fork block itself.
61
+ * 10. **Idempotent.** The loop may re-apply the same rollback after a crash
62
+ * (reorgs are deduped in memory only); a second application must be a
63
+ * harmless no-op.
64
+ * 11. **Scope by height, not cursor.** On a page reporting several forks the
65
+ * loop calls `rollback` once per fork: each call carries its own
66
+ * `forkPointHeight` but ALL carry the same `rewindCursor` (the lowest
67
+ * fork point). Derive the undo range from `forkPointHeight` only; a
68
+ * sink that derives it from `rewindCursor` under-deletes silently.
69
+ *
70
+ * Error semantics and concurrency:
71
+ *
72
+ * 12. **Throw, don't swallow; no internal retry.** The loop owns retry
73
+ * policy. A swallowed commit error advances the loop past unwritten
74
+ * data; an internal retry can double-apply around a partial failure.
75
+ * 13. **Single writer per checkpoint id.** The loop assumes one live
76
+ * consumer per checkpoint identity. A sink that can detect a second
77
+ * writer (e.g. a lock) must fail loudly — never block or interleave.
17
78
  */
18
79
  interface ConsumerSink<Tx = unknown> {
19
80
  /** Phantom marker carrying `Tx` in a directly-inferable position, so the
20
81
  * consume loops' `TTx` type parameter resolves from the `sink` option
21
82
  * (never set at runtime). */
22
83
  readonly _tx?: Tx;
84
+ /** Static capabilities, read by the loop before the first fetch to fail
85
+ * fast on impossible pairings. */
86
+ readonly capabilities?: {
87
+ /** This sink cannot undo committed rows (append-only store, ClickHouse,
88
+ * parquet, …), so `rollback` is unimplementable and following the
89
+ * unfinalized tip would corrupt it on the first fork. The loop throws
90
+ * loudly unless consuming with `finalizedOnly: true` — in that mode
91
+ * reorgs never reach the sink and `rollback` may simply throw. */
92
+ finalizedOnly?: boolean;
93
+ };
23
94
  /** The committed checkpoint, or `null` on first run. Called once, before
24
95
  * the first page. Implementations may create their checkpoint storage
25
96
  * here and SHOULD validate their rollback preconditions (e.g. that every
@@ -39,6 +110,11 @@ interface ConsumerSink<Tx = unknown> {
39
110
  * without the rewound cursor is the classic silent-gap bug: a crash
40
111
  * between the two writes resumes above the fork and the deleted range is
41
112
  * never re-read.
113
+ *
114
+ * On a multi-fork page this is called once PER fork, every call with the
115
+ * same `rewindCursor` (the lowest fork point) but its own
116
+ * `forkPointHeight` — scope the undo by `forkPointHeight` only (contract
117
+ * invariant #11), and expect re-application after a crash (#10).
42
118
  */
43
119
  rollback(forkPointHeight: number, rewindCursor: string): Promise<void>;
44
120
  }
@@ -46,97 +122,97 @@ interface ConsumerSink<Tx = unknown> {
46
122
  * is unchanged (an intersection with `unknown` is an identity, so
47
123
  * contextual typing of `onBatch` callbacks never degrades to a union). */
48
124
  type WithSinkTx<TTx> = [TTx] extends [never] ? unknown : {
49
- tx: TTx
125
+ tx: TTx;
50
126
  };
51
127
  type IndexEventBase = {
52
- cursor: string
53
- block_height: number
54
- block_time?: string | null
55
- tx_id: string
56
- tx_index: number
57
- event_index: number
58
- contract_id: string | null
128
+ cursor: string;
129
+ block_height: number;
130
+ block_time?: string | null;
131
+ tx_id: string;
132
+ tx_index: number;
133
+ event_index: number;
134
+ contract_id: string | null;
59
135
  /** Submitting-transaction context, present only when `txContext: true` was
60
136
  * requested. `tx_sender` is the real tx sender — distinct from a transfer's
61
137
  * asset `sender`, and the only place a `print` event's sender is available.
62
138
  * Lets a consumer build per-event tx context without a `/v1/index/transactions`
63
139
  * call per event. */
64
- tx_sender?: string | null
65
- tx_type?: string | null
66
- tx_status?: string | null
67
- tx_contract_id?: string | null
68
- tx_function_name?: string | null
140
+ tx_sender?: string | null;
141
+ tx_type?: string | null;
142
+ tx_status?: string | null;
143
+ tx_contract_id?: string | null;
144
+ tx_function_name?: string | null;
69
145
  };
70
146
  type IndexFtTransfer = IndexEventBase & {
71
- event_type: "ft_transfer"
72
- asset_identifier: string
73
- sender: string
74
- recipient: string
75
- amount: string
147
+ event_type: "ft_transfer";
148
+ asset_identifier: string;
149
+ sender: string;
150
+ recipient: string;
151
+ amount: string;
76
152
  };
77
153
  type IndexNftTransfer = IndexEventBase & {
78
- event_type: "nft_transfer"
79
- asset_identifier: string
80
- sender: string
81
- recipient: string
82
- value: string
154
+ event_type: "nft_transfer";
155
+ asset_identifier: string;
156
+ sender: string;
157
+ recipient: string;
158
+ value: string;
83
159
  };
84
160
  type IndexStxTransfer = IndexEventBase & {
85
- event_type: "stx_transfer"
86
- sender: string
87
- recipient: string
88
- amount: string
89
- memo: string | null
161
+ event_type: "stx_transfer";
162
+ sender: string;
163
+ recipient: string;
164
+ amount: string;
165
+ memo: string | null;
90
166
  };
91
167
  type IndexStxMint = IndexEventBase & {
92
- event_type: "stx_mint"
93
- recipient: string
94
- amount: string
168
+ event_type: "stx_mint";
169
+ recipient: string;
170
+ amount: string;
95
171
  };
96
172
  type IndexStxBurn = IndexEventBase & {
97
- event_type: "stx_burn"
98
- sender: string
99
- amount: string
173
+ event_type: "stx_burn";
174
+ sender: string;
175
+ amount: string;
100
176
  };
101
177
  type IndexStxLock = IndexEventBase & {
102
- event_type: "stx_lock"
103
- sender: string
104
- amount: string
178
+ event_type: "stx_lock";
179
+ sender: string;
180
+ amount: string;
105
181
  payload: {
106
- unlock_height: string | null
107
- }
182
+ unlock_height: string | null;
183
+ };
108
184
  };
109
185
  type IndexFtMint = IndexEventBase & {
110
- event_type: "ft_mint"
111
- asset_identifier: string
112
- recipient: string
113
- amount: string
186
+ event_type: "ft_mint";
187
+ asset_identifier: string;
188
+ recipient: string;
189
+ amount: string;
114
190
  };
115
191
  type IndexFtBurn = IndexEventBase & {
116
- event_type: "ft_burn"
117
- asset_identifier: string
118
- sender: string
119
- amount: string
192
+ event_type: "ft_burn";
193
+ asset_identifier: string;
194
+ sender: string;
195
+ amount: string;
120
196
  };
121
197
  type IndexNftMint = IndexEventBase & {
122
- event_type: "nft_mint"
123
- asset_identifier: string
124
- recipient: string
125
- value: string
198
+ event_type: "nft_mint";
199
+ asset_identifier: string;
200
+ recipient: string;
201
+ value: string;
126
202
  };
127
203
  type IndexNftBurn = IndexEventBase & {
128
- event_type: "nft_burn"
129
- asset_identifier: string
130
- sender: string
131
- value: string
204
+ event_type: "nft_burn";
205
+ asset_identifier: string;
206
+ sender: string;
207
+ value: string;
132
208
  };
133
209
  type IndexPrint = IndexEventBase & {
134
- event_type: "print"
210
+ event_type: "print";
135
211
  payload: {
136
- topic: string | null
137
- value: unknown
138
- raw_value: string | null
139
- }
212
+ topic: string | null;
213
+ value: unknown;
214
+ raw_value: string | null;
215
+ };
140
216
  };
141
217
  /** Decoded chain event, discriminated by `event_type`. */
142
218
  type IndexEvent = IndexFtTransfer | IndexNftTransfer | IndexStxTransfer | IndexStxMint | IndexStxBurn | IndexStxLock | IndexFtMint | IndexFtBurn | IndexNftMint | IndexNftBurn | IndexPrint;
@@ -144,68 +220,68 @@ type IndexEvent = IndexFtTransfer | IndexNftTransfer | IndexStxTransfer | IndexS
144
220
  * object carrying that hex (`{ hex }`), or a decoded Clarity-JSON object.
145
221
  * Decode helpers (`decodeNftTransfer`, etc.) resolve it to a concrete value. */
146
222
  type StreamsClarityValue = string | {
147
- hex: string
223
+ hex: string;
148
224
  } | Record<string, unknown>;
149
225
  type StxTransferPayload = {
150
- sender: string
151
- recipient: string
152
- amount: string
153
- memo?: string
226
+ sender: string;
227
+ recipient: string;
228
+ amount: string;
229
+ memo?: string;
154
230
  };
155
231
  type StxMintPayload = {
156
- recipient: string
157
- amount: string
232
+ recipient: string;
233
+ amount: string;
158
234
  };
159
235
  type StxBurnPayload = {
160
- sender: string
161
- amount: string
236
+ sender: string;
237
+ amount: string;
162
238
  };
163
239
  type StxLockPayload = {
164
- locked_address: string
165
- locked_amount: string
166
- unlock_height: string
240
+ locked_address: string;
241
+ locked_amount: string;
242
+ unlock_height: string;
167
243
  };
168
244
  type FtTransferPayload = {
169
- asset_identifier: string
170
- sender: string
171
- recipient: string
172
- amount: string
245
+ asset_identifier: string;
246
+ sender: string;
247
+ recipient: string;
248
+ amount: string;
173
249
  };
174
250
  type FtMintPayload = {
175
- asset_identifier: string
176
- recipient: string
177
- amount: string
251
+ asset_identifier: string;
252
+ recipient: string;
253
+ amount: string;
178
254
  };
179
255
  type FtBurnPayload = {
180
- asset_identifier: string
181
- sender: string
182
- amount: string
256
+ asset_identifier: string;
257
+ sender: string;
258
+ amount: string;
183
259
  };
184
260
  type NftTransferPayload = {
185
- asset_identifier: string
186
- sender: string
187
- recipient: string
188
- value: StreamsClarityValue
261
+ asset_identifier: string;
262
+ sender: string;
263
+ recipient: string;
264
+ value: StreamsClarityValue;
189
265
  /** Canonical serialized hex of `value`, when the stream carries it. */
190
- raw_value?: string
266
+ raw_value?: string;
191
267
  };
192
268
  type NftMintPayload = {
193
- asset_identifier: string
194
- recipient: string
195
- value: StreamsClarityValue
196
- raw_value?: string
269
+ asset_identifier: string;
270
+ recipient: string;
271
+ value: StreamsClarityValue;
272
+ raw_value?: string;
197
273
  };
198
274
  type NftBurnPayload = {
199
- asset_identifier: string
200
- sender: string
201
- value: StreamsClarityValue
202
- raw_value?: string
275
+ asset_identifier: string;
276
+ sender: string;
277
+ value: StreamsClarityValue;
278
+ raw_value?: string;
203
279
  };
204
280
  type PrintPayload = {
205
- contract_id?: string | null
206
- topic?: string
207
- value?: unknown
208
- raw_value?: string
281
+ contract_id?: string | null;
282
+ topic?: string;
283
+ value?: unknown;
284
+ raw_value?: string;
209
285
  };
210
286
  /** Union of every Streams payload shape, discriminated by `event_type` on the
211
287
  * parent `StreamsEvent`. */
@@ -216,97 +292,97 @@ type StreamsEventBase = {
216
292
  * it as the primary key of your projection rows — replaying a batch then
217
293
  * upserts cleanly. Don't synthesize your own id from `tx_id`/`event_index`.
218
294
  */
219
- cursor: string
220
- block_height: number
221
- block_hash: string
222
- burn_block_height: number
223
- tx_id: string
224
- tx_index: number
225
- event_index: number
226
- contract_id: string | null
227
- ts: string
295
+ cursor: string;
296
+ block_height: number;
297
+ block_hash: string;
298
+ burn_block_height: number;
299
+ tx_id: string;
300
+ tx_index: number;
301
+ event_index: number;
302
+ contract_id: string | null;
303
+ ts: string;
228
304
  /**
229
305
  * True when this event's block is past the finality boundary (immutable).
230
306
  * Optional for back-compat; the API always sets it on Streams responses.
231
307
  */
232
- finalized?: boolean
308
+ finalized?: boolean;
233
309
  /**
234
310
  * Labels whose filter group this event satisfied, present only when the
235
311
  * request used a labelled `filters` map. The SDK dispatches on it for you
236
312
  * (`on.<label>`), so handlers rarely read it directly.
237
313
  */
238
- matched?: string[]
314
+ matched?: string[];
239
315
  };
240
316
  type StreamsEventOf<
241
317
  T extends StreamsEventType,
242
318
  P
243
319
  > = StreamsEventBase & {
244
- event_type: T
245
- payload: P
320
+ event_type: T;
321
+ payload: P;
246
322
  };
247
323
  /** A raw Streams event. Discriminated on `event_type`, so `event.payload`
248
324
  * narrows to the matching payload shape once the type is checked. */
249
325
  type StreamsEvent = StreamsEventOf<"stx_transfer", StxTransferPayload> | StreamsEventOf<"stx_mint", StxMintPayload> | StreamsEventOf<"stx_burn", StxBurnPayload> | StreamsEventOf<"stx_lock", StxLockPayload> | StreamsEventOf<"ft_transfer", FtTransferPayload> | StreamsEventOf<"ft_mint", FtMintPayload> | StreamsEventOf<"ft_burn", FtBurnPayload> | StreamsEventOf<"nft_transfer", NftTransferPayload> | StreamsEventOf<"nft_mint", NftMintPayload> | StreamsEventOf<"nft_burn", NftBurnPayload> | StreamsEventOf<"print", PrintPayload>;
250
326
  type StreamsTip = {
251
- block_height: number
252
- block_hash: string
253
- burn_block_height: number
327
+ block_height: number;
328
+ block_hash: string;
329
+ burn_block_height: number;
254
330
  /**
255
331
  * Highest Stacks block past the burn-confirmation finality boundary.
256
332
  * Optional for back-compat; the API always sets it.
257
333
  */
258
- finalized_height?: number
259
- lag_seconds: number
334
+ finalized_height?: number;
335
+ lag_seconds: number;
260
336
  /**
261
337
  * Oldest height still seekable on the live API for the caller's tier
262
338
  * (`tip - retention`). `null` = unlimited retention. Older reads must use the
263
339
  * cold dumps lane. Optional for back-compat.
264
340
  */
265
- oldest_seekable_height?: number | null
341
+ oldest_seekable_height?: number | null;
266
342
  /** Oldest seekable cursor (`<oldest_seekable_height>:0`); `null` = unlimited. */
267
- oldest_cursor?: string | null
343
+ oldest_cursor?: string | null;
268
344
  };
269
345
  type StreamsCanonicalBlock = {
270
- block_height: number
271
- block_hash: string
272
- burn_block_height: number
273
- burn_block_hash: string | null
274
- is_canonical: true
346
+ block_height: number;
347
+ block_hash: string;
348
+ burn_block_height: number;
349
+ burn_block_hash: string | null;
350
+ is_canonical: true;
275
351
  };
276
352
  type StreamsReorg = {
277
- detected_at: string
278
- fork_point_height: number
353
+ detected_at: string;
354
+ fork_point_height: number;
279
355
  orphaned_range: {
280
- from: string
281
- to: string
282
- }
356
+ from: string;
357
+ to: string;
358
+ };
283
359
  /**
284
360
  * First position of the new canonical chain at the fork, `fork:0`
285
361
  * (INCLUSIVE). Not an exclusive resume token — resuming directly from it
286
362
  * skips `fork:0`. The consumer rewinds to the foot of `fork_point_height`
287
363
  * (`Cursor.atHeight`) to re-read the new run from `fork:0` inclusive.
288
364
  */
289
- new_canonical_tip: string
365
+ new_canonical_tip: string;
290
366
  };
291
367
  type StreamsEventsEnvelope<TEvent = StreamsEvent> = {
292
- events: TEvent[]
293
- next_cursor: string | null
294
- tip: StreamsTip
295
- reorgs: StreamsReorg[]
368
+ events: TEvent[];
369
+ next_cursor: string | null;
370
+ tip: StreamsTip;
371
+ reorgs: StreamsReorg[];
296
372
  };
297
373
  type StreamsEventsListEnvelope = Omit<StreamsEventsEnvelope, "next_cursor">;
298
374
  /** The StreamsEvent union narrowed to a `types` selection — what a
299
375
  * const-generic `types: ["ft_transfer"]` buys at the type level. */
300
376
  type StreamsEventOfTypes<T extends readonly StreamsEventType[]> = Extract<StreamsEvent, {
301
- event_type: T[number]
377
+ event_type: T[number];
302
378
  }>;
303
379
  type StreamsReorgsListParams = {
304
- since: string
305
- limit?: number
380
+ since: string;
381
+ limit?: number;
306
382
  };
307
383
  type StreamsReorgsListEnvelope = {
308
- reorgs: StreamsReorg[]
309
- next_since: string | null
384
+ reorgs: StreamsReorg[];
385
+ next_since: string | null;
310
386
  };
311
387
  /** A filter that matches a single value or any value in a list. */
312
388
  type StreamsFilterValue = string | readonly string[];
@@ -315,11 +391,11 @@ type StreamsFilterValue = string | readonly string[];
315
391
  * map OR together server-side.
316
392
  */
317
393
  type StreamsLabelledFilter = {
318
- types?: readonly StreamsEventType[]
319
- contractId?: StreamsFilterValue
320
- sender?: StreamsFilterValue
321
- recipient?: StreamsFilterValue
322
- assetIdentifier?: string
394
+ types?: readonly StreamsEventType[];
395
+ contractId?: StreamsFilterValue;
396
+ sender?: StreamsFilterValue;
397
+ recipient?: StreamsFilterValue;
398
+ assetIdentifier?: string;
323
399
  };
324
400
  /** A map of label → filter group. Labels are yours; the server echoes them. */
325
401
  type StreamsFilterMap = Record<string, StreamsLabelledFilter>;
@@ -332,65 +408,65 @@ type StreamsEventForFilter<
332
408
  F,
333
409
  D extends boolean = false
334
410
  > = F extends {
335
- types: readonly (infer T extends StreamsEventType)[]
411
+ types: readonly (infer T extends StreamsEventType)[];
336
412
  } ? D extends true ? Extract<IndexEvent, {
337
- event_type: T
413
+ event_type: T;
338
414
  }> : Extract<StreamsEvent, {
339
- event_type: T
415
+ event_type: T;
340
416
  }> : D extends true ? IndexEvent : StreamsEvent;
341
417
  type StreamsEventsListParams = {
342
- cursor?: string | null
343
- fromHeight?: number
344
- toHeight?: number
345
- types?: readonly StreamsEventType[]
418
+ cursor?: string | null;
419
+ fromHeight?: number;
420
+ toHeight?: number;
421
+ types?: readonly StreamsEventType[];
346
422
  /** Event types to exclude (applied after `types`). */
347
- notTypes?: readonly StreamsEventType[]
348
- contractId?: StreamsFilterValue
349
- sender?: StreamsFilterValue
350
- recipient?: StreamsFilterValue
351
- assetIdentifier?: string
423
+ notTypes?: readonly StreamsEventType[];
424
+ contractId?: StreamsFilterValue;
425
+ sender?: StreamsFilterValue;
426
+ recipient?: StreamsFilterValue;
427
+ assetIdentifier?: string;
352
428
  /**
353
429
  * Labelled filter groups. The groups OR together in one scan and each
354
430
  * returned event carries the labels it matched (`event.matched`) — two
355
431
  * unrelated concerns share one page, one cursor, one checkpoint.
356
432
  */
357
- filters?: StreamsFilterMap
358
- limit?: number
433
+ filters?: StreamsFilterMap;
434
+ limit?: number;
359
435
  };
360
436
  type StreamsEventsStreamParams = {
361
- fromCursor?: string | null
362
- types?: readonly StreamsEventType[]
363
- notTypes?: readonly StreamsEventType[]
364
- contractId?: StreamsFilterValue
365
- sender?: StreamsFilterValue
366
- recipient?: StreamsFilterValue
367
- assetIdentifier?: string
437
+ fromCursor?: string | null;
438
+ types?: readonly StreamsEventType[];
439
+ notTypes?: readonly StreamsEventType[];
440
+ contractId?: StreamsFilterValue;
441
+ sender?: StreamsFilterValue;
442
+ recipient?: StreamsFilterValue;
443
+ assetIdentifier?: string;
368
444
  /** Labelled filter groups; see {@link StreamsEventsListParams.filters}. */
369
- filters?: StreamsFilterMap
370
- batchSize?: number
371
- emptyBackoffMs?: number
372
- maxPages?: number
373
- maxEmptyPolls?: number
374
- signal?: AbortSignal
445
+ filters?: StreamsFilterMap;
446
+ batchSize?: number;
447
+ emptyBackoffMs?: number;
448
+ maxPages?: number;
449
+ maxEmptyPolls?: number;
450
+ signal?: AbortSignal;
375
451
  };
376
452
  type StreamsEventsSubscribeParams = {
377
453
  /** Resume strictly after this cursor; omit to live-tail from the tip. */
378
- fromCursor?: string | null
379
- types?: readonly StreamsEventType[]
380
- notTypes?: readonly StreamsEventType[]
381
- contractId?: StreamsFilterValue
382
- sender?: StreamsFilterValue
383
- recipient?: StreamsFilterValue
384
- assetIdentifier?: string
454
+ fromCursor?: string | null;
455
+ types?: readonly StreamsEventType[];
456
+ notTypes?: readonly StreamsEventType[];
457
+ contractId?: StreamsFilterValue;
458
+ sender?: StreamsFilterValue;
459
+ recipient?: StreamsFilterValue;
460
+ assetIdentifier?: string;
385
461
  /** Labelled filter groups; see {@link StreamsEventsListParams.filters}. */
386
- filters?: StreamsFilterMap
462
+ filters?: StreamsFilterMap;
387
463
  /** Abort to unsubscribe (the returned function does the same). */
388
- signal?: AbortSignal
464
+ signal?: AbortSignal;
389
465
  /** Called for each pushed event, in order. */
390
- onEvent: (event: StreamsEvent) => void | Promise<void>
466
+ onEvent: (event: StreamsEvent) => void | Promise<void>;
391
467
  /** Called on a connection error; the subscription auto-reconnects from the
392
468
  * last delivered cursor unless the signal has aborted. */
393
- onError?: (err: unknown) => void
469
+ onError?: (err: unknown) => void;
394
470
  };
395
471
  /**
396
472
  * The checkpoint the SDK computes for a batch. Persist `cursor` inside the same
@@ -417,14 +493,14 @@ type ConsumerBatchContext<
417
493
  TReorg = unknown
418
494
  > = {
419
495
  /** Checkpoint to commit alongside your rows. */
420
- cursor: string | null
496
+ cursor: string | null;
421
497
  /** Highest canonical block the sweep has reached. `null` before the first
422
498
  * row of a fresh consume. */
423
- height: number | null
499
+ height: number | null;
424
500
  /** Chain tip as of this page's read. */
425
- tipHeight: number
501
+ tipHeight: number;
426
502
  /** `tipHeight - height`, floored at 0. `null` until `height` is known. */
427
- blocksBehind: number | null
503
+ blocksBehind: number | null;
428
504
  /**
429
505
  * The full tip for this page — `StreamsTip` or `IndexTip` depending on the
430
506
  * surface. Exposed here so a handler never needs the `envelope` parameter,
@@ -432,12 +508,12 @@ type ConsumerBatchContext<
432
508
  * `finalizedOnly` mistake becomes reachable (`return envelope.next_cursor`
433
509
  * jumps the cursor past events that were filtered out and never delivered).
434
510
  */
435
- tip: TTip
511
+ tip: TTip;
436
512
  /**
437
513
  * Reorgs reported alongside this page; empty when none. Rollback still
438
514
  * belongs in `onReorg` — this is for observability inside a batch.
439
515
  */
440
- reorgs: readonly TReorg[]
516
+ reorgs: readonly TReorg[];
441
517
  };
442
518
  /** @deprecated Use {@link ConsumerBatchContext} — the Index and Streams loops
443
519
  * share one shape now. Kept as an alias so existing annotations compile. */
@@ -447,20 +523,20 @@ type StreamsBatchContext = ConsumerBatchContext;
447
523
  * inside the same transaction as your rollback so the two commit atomically.
448
524
  */
449
525
  type StreamsReorgContext = {
450
- cursor: string
526
+ cursor: string;
451
527
  };
452
528
  type StreamsEventsConsumeParams<
453
529
  TTx = never,
454
530
  D extends boolean = false,
455
531
  F extends StreamsFilterMap = Record<never, never>
456
532
  > = {
457
- fromCursor?: string | null
533
+ fromCursor?: string | null;
458
534
  /**
459
535
  * Deliver events pre-decoded as the flat, `event_type`-discriminated rows
460
536
  * Index serves (`IndexEvent`), so Streams consumption reads identically
461
537
  * to Index consumption — no guard+decode pairs in your handler.
462
538
  */
463
- decoded?: D
539
+ decoded?: D;
464
540
  /**
465
541
  * Destination adapter that owns the checkpoint + rollback transaction
466
542
  * (e.g. `kyselySink` from `@secondlayer/sdk/sinks/kysely`). With a sink:
@@ -469,29 +545,29 @@ type StreamsEventsConsumeParams<
469
545
  * transaction), reorg rollback is automatic, and `onBatch`'s return value
470
546
  * is ignored.
471
547
  */
472
- sink?: ConsumerSink<TTx>
548
+ sink?: ConsumerSink<TTx>;
473
549
  /** Fires once per page, before `onBatch` and before any early return. */
474
- onProgress?: (ctx: ConsumerBatchContext) => void
475
- mode?: "tail" | "bounded"
550
+ onProgress?: (ctx: ConsumerBatchContext) => void;
551
+ mode?: "tail" | "bounded";
476
552
  /**
477
553
  * Emit only finalized (immutable) events and never surface reorgs. The SDK
478
554
  * checkpoints at the last finalized event and re-reads the unfinalized tail
479
555
  * until it settles. Trades finality lag for zero reorg handling; `onReorg` is
480
556
  * ignored.
481
557
  */
482
- finalizedOnly?: boolean
483
- types?: readonly StreamsEventType[]
484
- notTypes?: readonly StreamsEventType[]
485
- contractId?: StreamsFilterValue
486
- sender?: StreamsFilterValue
487
- recipient?: StreamsFilterValue
488
- assetIdentifier?: string
558
+ finalizedOnly?: boolean;
559
+ types?: readonly StreamsEventType[];
560
+ notTypes?: readonly StreamsEventType[];
561
+ contractId?: StreamsFilterValue;
562
+ sender?: StreamsFilterValue;
563
+ recipient?: StreamsFilterValue;
564
+ assetIdentifier?: string;
489
565
  /**
490
566
  * Labelled filter groups. The groups OR together in ONE server-side scan,
491
567
  * so two unrelated concerns share one page, one cursor, and one checkpoint
492
568
  * instead of two consume loops. Pair with `on` to handle each label.
493
569
  */
494
- filters?: F
570
+ filters?: F;
495
571
  /**
496
572
  * One handler per label in `filters`. Every label must be handled, so
497
573
  * adding a label is a compile error until its handler exists.
@@ -502,8 +578,8 @@ type StreamsEventsConsumeParams<
502
578
  * labels do not interleave within a page — add `onBatch` when you need
503
579
  * strict global order across labels.
504
580
  */
505
- on?: { [K in keyof F] : (events: StreamsEventForFilter<F[K], D>[], ctx: StreamsBatchContext & WithSinkTx<TTx>) => void | Promise<void> }
506
- batchSize?: number
581
+ on?: { [K in keyof F] : (events: StreamsEventForFilter<F[K], D>[], ctx: StreamsBatchContext & WithSinkTx<TTx>) => void | Promise<void> };
582
+ batchSize?: number;
507
583
  /**
508
584
  * Apply a page of canonical events. Persist `ctx.cursor` in the same
509
585
  * transaction as your writes. Returning a cursor overrides `ctx.cursor` as
@@ -512,7 +588,7 @@ type StreamsEventsConsumeParams<
512
588
  * Optional only when `on` handles the page instead; a consume call with
513
589
  * neither throws.
514
590
  */
515
- onBatch?: (events: D extends true ? IndexEvent[] : StreamsEvent[], envelope: StreamsEventsEnvelope, ctx: StreamsBatchContext & WithSinkTx<TTx>) => void | string | null | undefined | Promise<void> | Promise<string | null | undefined>
591
+ onBatch?: (events: D extends true ? IndexEvent[] : StreamsEvent[], envelope: StreamsEventsEnvelope, ctx: StreamsBatchContext & WithSinkTx<TTx>) => void | string | null | undefined | Promise<void> | Promise<string | null | undefined>;
516
592
  /**
517
593
  * Roll your projection back to `reorg.fork_point_height`, persisting
518
594
  * `ctx.cursor` in the same transaction. Called once per *new* reorg
@@ -520,23 +596,23 @@ type StreamsEventsConsumeParams<
520
596
  * now-canonical events. Omit it to ignore reorgs (events stay canonical, but
521
597
  * stale rows from an orphaned fork are left in place).
522
598
  */
523
- onReorg?: (reorg: StreamsReorg, ctx: StreamsReorgContext) => Promise<void> | void
599
+ onReorg?: (reorg: StreamsReorg, ctx: StreamsReorgContext) => Promise<void> | void;
524
600
  /** Page-fetch retries after the first failure (429/5xx/network only —
525
601
  * 4xx and handler throws always propagate). Default 3; `0` disables. */
526
- retryCount?: number
602
+ retryCount?: number;
527
603
  /** Base retry delay in ms; the n-th retry waits `retryDelay * n`. A server
528
604
  * `Retry-After` overrides it. Default 1000. */
529
- retryDelay?: number
605
+ retryDelay?: number;
530
606
  /** Void observer, called before each retry sleep (metrics/logging). */
531
607
  onError?: (err: unknown, ctx: {
532
- attempt: number
533
- retriesLeft: number
534
- delayMs: number
535
- }) => void
536
- emptyBackoffMs?: number
537
- maxPages?: number
538
- maxEmptyPolls?: number
539
- signal?: AbortSignal
608
+ attempt: number;
609
+ retriesLeft: number;
610
+ delayMs: number;
611
+ }) => void;
612
+ emptyBackoffMs?: number;
613
+ maxPages?: number;
614
+ maxEmptyPolls?: number;
615
+ signal?: AbortSignal;
540
616
  };
541
617
  /**
542
618
  * One yielded page from {@link StreamsClient.consume} — the
@@ -545,112 +621,112 @@ type StreamsEventsConsumeParams<
545
621
  */
546
622
  type StreamsBatch<TEvent = StreamsEvent> = {
547
623
  /** Canonical events of this page, in cursor order. */
548
- events: TEvent[]
624
+ events: TEvent[];
549
625
  /** Checkpoint after this page — pass back as `consume({ cursor })` to resume. */
550
- cursor: string | null
551
- tip: StreamsTip
626
+ cursor: string | null;
627
+ tip: StreamsTip;
552
628
  /** Chain reorgs reported alongside this page; empty when none. */
553
- reorgs: StreamsReorg[]
629
+ reorgs: StreamsReorg[];
554
630
  };
555
631
  type StreamsConsumeParams = {
556
632
  /** Resume strictly after this cursor; omit to start from the oldest seekable page. */
557
- cursor?: string | null
558
- types?: readonly StreamsEventType[]
559
- notTypes?: readonly StreamsEventType[]
560
- contractId?: StreamsFilterValue
561
- sender?: StreamsFilterValue
562
- recipient?: StreamsFilterValue
563
- assetIdentifier?: string
633
+ cursor?: string | null;
634
+ types?: readonly StreamsEventType[];
635
+ notTypes?: readonly StreamsEventType[];
636
+ contractId?: StreamsFilterValue;
637
+ sender?: StreamsFilterValue;
638
+ recipient?: StreamsFilterValue;
639
+ assetIdentifier?: string;
564
640
  /** Labelled OR-groups — same semantics as `events.consume`; each returned
565
641
  * event echoes the labels it matched. */
566
- filters?: StreamsFilterMap
642
+ filters?: StreamsFilterMap;
567
643
  /** Events per page (the `limit` query param). Default 100. */
568
- batchSize?: number
644
+ batchSize?: number;
569
645
  /** Poll interval while caught up at the tip, in ms. Default 2000. */
570
- intervalMs?: number
646
+ intervalMs?: number;
571
647
  /** Abort to end the iteration. */
572
- signal?: AbortSignal
648
+ signal?: AbortSignal;
573
649
  };
574
650
  type StreamsEventsConsumeResult = {
575
- cursor: string | null
576
- pages: number
577
- emptyPolls: number
651
+ cursor: string | null;
652
+ pages: number;
653
+ emptyPolls: number;
578
654
  };
579
655
  type StreamsEventsReplayParams = {
580
656
  /** Start point: `"genesis"` (default) or a `<block>:<index>` cursor. */
581
- from?: "genesis" | string
657
+ from?: "genesis" | string;
582
658
  /**
583
659
  * Called once per finalized dump file, in block order, before live tailing.
584
660
  * Process the parquet with your own tooling (e.g. DuckDB) — the SDK does not
585
661
  * decode parquet. Use `client.dumps.download(file)` to fetch + verify bytes.
586
662
  */
587
- onDumpFile: (file: StreamsDumpFile) => Promise<void> | void
663
+ onDumpFile: (file: StreamsDumpFile) => Promise<void> | void;
588
664
  /** Called per live page after the dump phase, like `consume`. */
589
- onBatch: (events: StreamsEvent[], envelope: StreamsEventsEnvelope) => Promise<string | null | undefined> | string | null | undefined
665
+ onBatch: (events: StreamsEvent[], envelope: StreamsEventsEnvelope) => Promise<string | null | undefined> | string | null | undefined;
590
666
  /**
591
667
  * Called when the live-tail phase (after the dump backfill) crosses a reorg,
592
668
  * before the cursor rewinds and re-reads the now-canonical events — same
593
669
  * contract as `consume`. The dump-backfill phase is finalized and never
594
670
  * reorgs; omit this to leave stale rows from an orphaned fork in place.
595
671
  */
596
- onReorg?: (reorg: StreamsReorg, ctx: StreamsReorgContext) => Promise<void> | void
597
- mode?: "tail" | "bounded"
598
- batchSize?: number
599
- emptyBackoffMs?: number
600
- maxPages?: number
601
- maxEmptyPolls?: number
602
- signal?: AbortSignal
672
+ onReorg?: (reorg: StreamsReorg, ctx: StreamsReorgContext) => Promise<void> | void;
673
+ mode?: "tail" | "bounded";
674
+ batchSize?: number;
675
+ emptyBackoffMs?: number;
676
+ maxPages?: number;
677
+ maxEmptyPolls?: number;
678
+ signal?: AbortSignal;
603
679
  /** Narrow the LIVE TAIL after the dump phase. The dump files themselves are
604
680
  * always all-type (block-partitioned parquet) — filter those in your own
605
681
  * tooling while processing each file. */
606
- types?: readonly StreamsEventType[]
607
- notTypes?: readonly StreamsEventType[]
682
+ types?: readonly StreamsEventType[];
683
+ notTypes?: readonly StreamsEventType[];
608
684
  /** Labelled OR-groups for the live tail, like `consume`. */
609
- filters?: StreamsFilterMap
685
+ filters?: StreamsFilterMap;
610
686
  };
611
687
  type FetchLike2 = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
612
688
  /** One bulk parquet file in the dumps manifest. `path` is the object key under
613
689
  * the dumps base URL. */
614
690
  type StreamsDumpFile = {
615
- path: string
616
- from_block: number
617
- to_block: number
618
- min_cursor: string | null
619
- max_cursor: string | null
620
- row_count: number
621
- byte_size: number
622
- sha256: string
623
- schema_version: number
624
- created_at: string
691
+ path: string;
692
+ from_block: number;
693
+ to_block: number;
694
+ min_cursor: string | null;
695
+ max_cursor: string | null;
696
+ row_count: number;
697
+ byte_size: number;
698
+ sha256: string;
699
+ schema_version: number;
700
+ created_at: string;
625
701
  };
626
702
  type StreamsDumpsManifest = {
627
- dataset: string
628
- network: string
629
- version: string
630
- schema_version: number
631
- generated_at: string
632
- producer_version: string
633
- finality_lag_blocks: number
703
+ dataset: string;
704
+ network: string;
705
+ version: string;
706
+ schema_version: number;
707
+ generated_at: string;
708
+ producer_version: string;
709
+ finality_lag_blocks: number;
634
710
  /** Cursor at the end of the finalized bulk coverage — hand to live tailing. */
635
- latest_finalized_cursor: string | null
711
+ latest_finalized_cursor: string | null;
636
712
  coverage: {
637
- from_block: number
638
- to_block: number
639
- }
640
- files: StreamsDumpFile[]
713
+ from_block: number;
714
+ to_block: number;
715
+ };
716
+ files: StreamsDumpFile[];
641
717
  /** ed25519 signature over the manifest's canonical bytes. Absent on legacy
642
718
  * unsigned manifests. Verified by `list()` when `verifyDumpsManifest` is on. */
643
- signature?: string
719
+ signature?: string;
644
720
  /** Short id of the signing public key. */
645
- key_id?: string
721
+ key_id?: string;
646
722
  };
647
723
  type StreamsDumps = {
648
724
  /** Fetch and parse the latest dumps manifest. */
649
- list(): Promise<StreamsDumpsManifest>
725
+ list(): Promise<StreamsDumpsManifest>;
650
726
  /** Absolute URL for a manifest file. */
651
- fileUrl(file: StreamsDumpFile): string
727
+ fileUrl(file: StreamsDumpFile): string;
652
728
  /** Download a parquet file and verify its sha256 against the manifest. */
653
- download(file: StreamsDumpFile): Promise<Uint8Array>
729
+ download(file: StreamsDumpFile): Promise<Uint8Array>;
654
730
  };
655
731
  type StreamsClient = {
656
732
  /**
@@ -670,16 +746,16 @@ type StreamsClient = {
670
746
  /** Narrowing overload: a literal `types` array narrows every batch's
671
747
  * event union to exactly those members. */
672
748
  consume<const T extends readonly StreamsEventType[]>(params: StreamsConsumeParams & {
673
- types: T
674
- }): AsyncIterableIterator<StreamsBatch<StreamsEventOfTypes<T>>>
675
- consume(params?: StreamsConsumeParams): AsyncIterableIterator<StreamsBatch>
749
+ types: T;
750
+ }): AsyncIterableIterator<StreamsBatch<StreamsEventOfTypes<T>>>;
751
+ consume(params?: StreamsConsumeParams): AsyncIterableIterator<StreamsBatch>;
676
752
  events: {
677
753
  /** Narrowing overload, matching `consume`. */
678
754
  list<const T extends readonly StreamsEventType[]>(params: StreamsEventsListParams & {
679
- types: T
680
- }): Promise<StreamsEventsEnvelope<StreamsEventOfTypes<T>>>
681
- list(params?: StreamsEventsListParams): Promise<StreamsEventsEnvelope>
682
- byTxId(txId: string): Promise<StreamsEventsListEnvelope>
755
+ types: T;
756
+ }): Promise<StreamsEventsEnvelope<StreamsEventOfTypes<T>>>;
757
+ list(params?: StreamsEventsListParams): Promise<StreamsEventsEnvelope>;
758
+ byTxId(txId: string): Promise<StreamsEventsListEnvelope>;
683
759
  /**
684
760
  * Pull pages from Streams and call `onBatch` after each page.
685
761
  *
@@ -694,8 +770,8 @@ type StreamsClient = {
694
770
  TTx = never,
695
771
  D extends boolean = false
696
772
  >(params: StreamsEventsConsumeParams<TTx, D, F> & {
697
- sink?: ConsumerSink<TTx>
698
- }): Promise<StreamsEventsConsumeResult>
773
+ sink?: ConsumerSink<TTx>;
774
+ }): Promise<StreamsEventsConsumeResult>;
699
775
  /**
700
776
  * Backfill from bulk dumps, then continue live from the dump→live seam in
701
777
  * one call. Iterates finalized dump files (via `onDumpFile`) in block
@@ -703,7 +779,7 @@ type StreamsClient = {
703
779
  * (exclusive input → no gap or duplicate at the seam). Requires
704
780
  * `dumpsBaseUrl`.
705
781
  */
706
- replay(params: StreamsEventsReplayParams): Promise<StreamsEventsConsumeResult>
782
+ replay(params: StreamsEventsReplayParams): Promise<StreamsEventsConsumeResult>;
707
783
  /**
708
784
  * Follow Streams as an async iterator.
709
785
  *
@@ -713,51 +789,51 @@ type StreamsClient = {
713
789
  */
714
790
  /** Narrowing overload, matching `consume`. */
715
791
  stream<const T extends readonly StreamsEventType[]>(params: StreamsEventsStreamParams & {
716
- types: T
717
- }): AsyncIterable<StreamsEventOfTypes<T>>
718
- stream(params?: StreamsEventsStreamParams): AsyncIterable<StreamsEvent>
792
+ types: T;
793
+ }): AsyncIterable<StreamsEventOfTypes<T>>;
794
+ stream(params?: StreamsEventsStreamParams): AsyncIterable<StreamsEvent>;
719
795
  /**
720
796
  * Subscribe to the real-time SSE push surface. Calls `onEvent` for each new
721
797
  * canonical event as the server pushes it (chain cadence, not poll-bounded),
722
798
  * and verifies each frame's inline ed25519 signature when the client was
723
799
  * created with `verify`. Returns an unsubscribe function.
724
800
  */
725
- subscribe(params: StreamsEventsSubscribeParams): () => void
726
- }
801
+ subscribe(params: StreamsEventsSubscribeParams): () => void;
802
+ };
727
803
  blocks: {
728
- events(heightOrHash: number | string): Promise<StreamsEventsListEnvelope>
729
- }
804
+ events(heightOrHash: number | string): Promise<StreamsEventsListEnvelope>;
805
+ };
730
806
  reorgs: {
731
- list(params: StreamsReorgsListParams): Promise<StreamsReorgsListEnvelope>
732
- }
807
+ list(params: StreamsReorgsListParams): Promise<StreamsReorgsListEnvelope>;
808
+ };
733
809
  /** Bulk parquet dumps. Requires `dumpsBaseUrl` on the client. */
734
- dumps: StreamsDumps
735
- canonical(height: number): Promise<StreamsCanonicalBlock>
736
- tip(): Promise<StreamsTip>
810
+ dumps: StreamsDumps;
811
+ canonical(height: number): Promise<StreamsCanonicalBlock>;
812
+ tip(): Promise<StreamsTip>;
737
813
  /** Your own Streams consumption (events today + this month) and tier limits. */
738
- usage(): Promise<StreamsUsage>
814
+ usage(): Promise<StreamsUsage>;
739
815
  };
740
816
  type StreamsUsage = {
741
- product: "streams"
742
- tier: string
817
+ product: "streams";
818
+ tier: string;
743
819
  limits: {
744
- rate_limit_per_second: number | null
745
- retention_days: number | null
746
- }
820
+ rate_limit_per_second: number | null;
821
+ retention_days: number | null;
822
+ };
747
823
  usage: {
748
- events_today: number
749
- events_this_month: number
750
- }
824
+ events_today: number;
825
+ events_this_month: number;
826
+ };
751
827
  };
752
828
  type CreateStreamsClientOptions = {
753
- apiKey: string
754
- baseUrl?: string
755
- fetchImpl?: FetchLike2
829
+ apiKey: string;
830
+ baseUrl?: string;
831
+ fetchImpl?: FetchLike2;
756
832
  /**
757
833
  * Public base URL for bulk parquet dumps (the R2/CDN bucket root). Required
758
834
  * to use `client.dumps`. See `GET /public/streams/dumps/manifest`.
759
835
  */
760
- dumpsBaseUrl?: string
836
+ dumpsBaseUrl?: string;
761
837
  /**
762
838
  * Verify the ed25519 `X-Signature` on every REST response and per-frame SSE
763
839
  * signature. Three states:
@@ -776,8 +852,8 @@ type CreateStreamsClientOptions = {
776
852
  * rotated `X-Signature-KeyId` triggers one refresh) unless a PEM is pinned.
777
853
  */
778
854
  verify?: boolean | {
779
- publicKey: string
780
- }
855
+ publicKey: string;
856
+ };
781
857
  /**
782
858
  * Verify the bulk dumps manifest's ed25519 signature in `client.dumps.list()`
783
859
  * before trusting any file sha256 (default ON). Uses the same key source as
@@ -785,7 +861,7 @@ type CreateStreamsClientOptions = {
785
861
  * `false` to opt out. A missing or invalid signature throws
786
862
  * `StreamsSignatureError`.
787
863
  */
788
- verifyDumpsManifest?: boolean
864
+ verifyDumpsManifest?: boolean;
789
865
  };
790
866
  declare function createStreamsClient(options: CreateStreamsClientOptions): StreamsClient;
791
867
  /**
@@ -848,14 +924,14 @@ declare class SecondLayerError extends Error {
848
924
  */
849
925
  walk(fn?: (err: unknown) => boolean): unknown;
850
926
  toJSON(): {
851
- name: string
852
- message: string
853
- shortMessage: string
854
- cause: string | undefined
855
- code: string | undefined
856
- docsUrl: string | undefined
857
- retryable: boolean
858
- retryAfterSeconds: number | undefined
927
+ name: string;
928
+ message: string;
929
+ shortMessage: string;
930
+ cause: string | undefined;
931
+ code: string | undefined;
932
+ docsUrl: string | undefined;
933
+ retryable: boolean;
934
+ retryAfterSeconds: number | undefined;
859
935
  };
860
936
  }
861
937
  /**
@@ -889,9 +965,9 @@ declare class AuthError extends ApiError {
889
965
  * with `retryAfterSeconds` parsed from the `Retry-After` header when sent. */
890
966
  declare class RateLimitError extends ApiError {
891
967
  /** Raw `Retry-After` header value (seconds or HTTP-date). */
892
- readonly retryAfter?: string;
968
+ readonly retryAfter?: string | undefined;
893
969
  readonly status: 429;
894
- constructor(message?: string, retryAfter?: string);
970
+ constructor(message?: string, retryAfter?: string | undefined);
895
971
  }
896
972
  /** Thrown on a 4xx the caller can fix (bad cursor, bad params). Never retried. */
897
973
  declare class ValidationError extends ApiError {
@@ -906,210 +982,210 @@ declare class StreamsSignatureError extends SecondLayerError {
906
982
  constructor(message?: string);
907
983
  }
908
984
  type FtTransferEvent = Extract<StreamsEvent, {
909
- event_type: "ft_transfer"
985
+ event_type: "ft_transfer";
910
986
  }>;
911
987
  type DecodedFtTransferPayload = {
912
- asset_identifier: string
913
- contract_id: string
914
- token_name: string | null
915
- sender: string
916
- recipient: string
917
- amount: string
988
+ asset_identifier: string;
989
+ contract_id: string;
990
+ token_name: string | null;
991
+ sender: string;
992
+ recipient: string;
993
+ amount: string;
918
994
  };
919
995
  type DecodedFtTransfer = {
920
- cursor: string
921
- block_height: number
922
- tx_id: string
923
- tx_index: number
924
- event_index: number
925
- event_type: "ft_transfer"
926
- decoded_payload: DecodedFtTransferPayload
927
- source_cursor: string
996
+ cursor: string;
997
+ block_height: number;
998
+ tx_id: string;
999
+ tx_index: number;
1000
+ event_index: number;
1001
+ event_type: "ft_transfer";
1002
+ decoded_payload: DecodedFtTransferPayload;
1003
+ source_cursor: string;
928
1004
  };
929
1005
  declare function isFtTransfer(event: StreamsEvent): event is FtTransferEvent;
930
1006
  declare function decodeFtTransfer(event: StreamsEvent): DecodedFtTransfer;
931
1007
  type NftTransferEvent = Extract<StreamsEvent, {
932
- event_type: "nft_transfer"
1008
+ event_type: "nft_transfer";
933
1009
  }>;
934
1010
  type DecodedNftTransferPayload = {
935
- asset_identifier: string
936
- contract_id: string
937
- token_name: string | null
938
- sender: string
939
- recipient: string
940
- value: string
1011
+ asset_identifier: string;
1012
+ contract_id: string;
1013
+ token_name: string | null;
1014
+ sender: string;
1015
+ recipient: string;
1016
+ value: string;
941
1017
  };
942
1018
  type DecodedNftTransfer = {
943
- cursor: string
944
- block_height: number
945
- tx_id: string
946
- tx_index: number
947
- event_index: number
948
- event_type: "nft_transfer"
949
- decoded_payload: DecodedNftTransferPayload
950
- source_cursor: string
1019
+ cursor: string;
1020
+ block_height: number;
1021
+ tx_id: string;
1022
+ tx_index: number;
1023
+ event_index: number;
1024
+ event_type: "nft_transfer";
1025
+ decoded_payload: DecodedNftTransferPayload;
1026
+ source_cursor: string;
951
1027
  };
952
1028
  declare function isNftTransfer(event: StreamsEvent): event is NftTransferEvent;
953
1029
  declare function decodeNftTransfer(event: StreamsEvent): DecodedNftTransfer;
954
1030
  type DecodedStxTransferPayload = {
955
- sender: string
956
- recipient: string
957
- amount: string
958
- memo: string | null
1031
+ sender: string;
1032
+ recipient: string;
1033
+ amount: string;
1034
+ memo: string | null;
959
1035
  };
960
1036
  type DecodedStxTransfer = {
961
- cursor: string
962
- block_height: number
963
- tx_id: string
964
- tx_index: number
965
- event_index: number
966
- event_type: "stx_transfer"
967
- decoded_payload: DecodedStxTransferPayload
968
- source_cursor: string
1037
+ cursor: string;
1038
+ block_height: number;
1039
+ tx_id: string;
1040
+ tx_index: number;
1041
+ event_index: number;
1042
+ event_type: "stx_transfer";
1043
+ decoded_payload: DecodedStxTransferPayload;
1044
+ source_cursor: string;
969
1045
  };
970
1046
  type DecodedStxMintPayload = {
971
- recipient: string
972
- amount: string
1047
+ recipient: string;
1048
+ amount: string;
973
1049
  };
974
1050
  type DecodedStxMint = {
975
- cursor: string
976
- block_height: number
977
- tx_id: string
978
- tx_index: number
979
- event_index: number
980
- event_type: "stx_mint"
981
- decoded_payload: DecodedStxMintPayload
982
- source_cursor: string
1051
+ cursor: string;
1052
+ block_height: number;
1053
+ tx_id: string;
1054
+ tx_index: number;
1055
+ event_index: number;
1056
+ event_type: "stx_mint";
1057
+ decoded_payload: DecodedStxMintPayload;
1058
+ source_cursor: string;
983
1059
  };
984
1060
  type DecodedStxBurnPayload = {
985
- sender: string
986
- amount: string
1061
+ sender: string;
1062
+ amount: string;
987
1063
  };
988
1064
  type DecodedStxBurn = {
989
- cursor: string
990
- block_height: number
991
- tx_id: string
992
- tx_index: number
993
- event_index: number
994
- event_type: "stx_burn"
995
- decoded_payload: DecodedStxBurnPayload
996
- source_cursor: string
1065
+ cursor: string;
1066
+ block_height: number;
1067
+ tx_id: string;
1068
+ tx_index: number;
1069
+ event_index: number;
1070
+ event_type: "stx_burn";
1071
+ decoded_payload: DecodedStxBurnPayload;
1072
+ source_cursor: string;
997
1073
  };
998
1074
  declare function isStxTransfer(event: StreamsEvent): event is StreamsEvent & {
999
- event_type: "stx_transfer"
1075
+ event_type: "stx_transfer";
1000
1076
  };
1001
1077
  declare function decodeStxTransfer(event: StreamsEvent): DecodedStxTransfer;
1002
1078
  declare function isStxMint(event: StreamsEvent): event is StreamsEvent & {
1003
- event_type: "stx_mint"
1079
+ event_type: "stx_mint";
1004
1080
  };
1005
1081
  declare function decodeStxMint(event: StreamsEvent): DecodedStxMint;
1006
1082
  declare function isStxBurn(event: StreamsEvent): event is StreamsEvent & {
1007
- event_type: "stx_burn"
1083
+ event_type: "stx_burn";
1008
1084
  };
1009
1085
  declare function decodeStxBurn(event: StreamsEvent): DecodedStxBurn;
1010
1086
  type DecodedStxLockPayload = {
1011
- sender: string
1012
- amount: string
1087
+ sender: string;
1088
+ amount: string;
1013
1089
  payload: {
1014
- unlock_height: string | null
1015
- }
1090
+ unlock_height: string | null;
1091
+ };
1016
1092
  };
1017
1093
  type DecodedStxLock = {
1018
- cursor: string
1019
- block_height: number
1020
- tx_id: string
1021
- tx_index: number
1022
- event_index: number
1023
- event_type: "stx_lock"
1024
- decoded_payload: DecodedStxLockPayload
1025
- source_cursor: string
1094
+ cursor: string;
1095
+ block_height: number;
1096
+ tx_id: string;
1097
+ tx_index: number;
1098
+ event_index: number;
1099
+ event_type: "stx_lock";
1100
+ decoded_payload: DecodedStxLockPayload;
1101
+ source_cursor: string;
1026
1102
  };
1027
1103
  declare function isStxLock(event: StreamsEvent): event is StreamsEvent & {
1028
- event_type: "stx_lock"
1104
+ event_type: "stx_lock";
1029
1105
  };
1030
1106
  declare function decodeStxLock(event: StreamsEvent): DecodedStxLock;
1031
1107
  type DecodedFtMintPayload = {
1032
- asset_identifier: string
1033
- contract_id: string
1034
- token_name: string | null
1035
- recipient: string
1036
- amount: string
1108
+ asset_identifier: string;
1109
+ contract_id: string;
1110
+ token_name: string | null;
1111
+ recipient: string;
1112
+ amount: string;
1037
1113
  };
1038
1114
  type DecodedFtMint = {
1039
- cursor: string
1040
- block_height: number
1041
- tx_id: string
1042
- tx_index: number
1043
- event_index: number
1044
- event_type: "ft_mint"
1045
- decoded_payload: DecodedFtMintPayload
1046
- source_cursor: string
1115
+ cursor: string;
1116
+ block_height: number;
1117
+ tx_id: string;
1118
+ tx_index: number;
1119
+ event_index: number;
1120
+ event_type: "ft_mint";
1121
+ decoded_payload: DecodedFtMintPayload;
1122
+ source_cursor: string;
1047
1123
  };
1048
1124
  type DecodedFtBurnPayload = {
1049
- asset_identifier: string
1050
- contract_id: string
1051
- token_name: string | null
1052
- sender: string
1053
- amount: string
1125
+ asset_identifier: string;
1126
+ contract_id: string;
1127
+ token_name: string | null;
1128
+ sender: string;
1129
+ amount: string;
1054
1130
  };
1055
1131
  type DecodedFtBurn = {
1056
- cursor: string
1057
- block_height: number
1058
- tx_id: string
1059
- tx_index: number
1060
- event_index: number
1061
- event_type: "ft_burn"
1062
- decoded_payload: DecodedFtBurnPayload
1063
- source_cursor: string
1132
+ cursor: string;
1133
+ block_height: number;
1134
+ tx_id: string;
1135
+ tx_index: number;
1136
+ event_index: number;
1137
+ event_type: "ft_burn";
1138
+ decoded_payload: DecodedFtBurnPayload;
1139
+ source_cursor: string;
1064
1140
  };
1065
1141
  type DecodedNftMintPayload = {
1066
- asset_identifier: string
1067
- contract_id: string
1068
- token_name: string | null
1069
- recipient: string
1070
- value: string
1142
+ asset_identifier: string;
1143
+ contract_id: string;
1144
+ token_name: string | null;
1145
+ recipient: string;
1146
+ value: string;
1071
1147
  };
1072
1148
  type DecodedNftMint = {
1073
- cursor: string
1074
- block_height: number
1075
- tx_id: string
1076
- tx_index: number
1077
- event_index: number
1078
- event_type: "nft_mint"
1079
- decoded_payload: DecodedNftMintPayload
1080
- source_cursor: string
1149
+ cursor: string;
1150
+ block_height: number;
1151
+ tx_id: string;
1152
+ tx_index: number;
1153
+ event_index: number;
1154
+ event_type: "nft_mint";
1155
+ decoded_payload: DecodedNftMintPayload;
1156
+ source_cursor: string;
1081
1157
  };
1082
1158
  type DecodedNftBurnPayload = {
1083
- asset_identifier: string
1084
- contract_id: string
1085
- token_name: string | null
1086
- sender: string
1087
- value: string
1159
+ asset_identifier: string;
1160
+ contract_id: string;
1161
+ token_name: string | null;
1162
+ sender: string;
1163
+ value: string;
1088
1164
  };
1089
1165
  type DecodedNftBurn = {
1090
- cursor: string
1091
- block_height: number
1092
- tx_id: string
1093
- tx_index: number
1094
- event_index: number
1095
- event_type: "nft_burn"
1096
- decoded_payload: DecodedNftBurnPayload
1097
- source_cursor: string
1166
+ cursor: string;
1167
+ block_height: number;
1168
+ tx_id: string;
1169
+ tx_index: number;
1170
+ event_index: number;
1171
+ event_type: "nft_burn";
1172
+ decoded_payload: DecodedNftBurnPayload;
1173
+ source_cursor: string;
1098
1174
  };
1099
1175
  declare function isFtMint(event: StreamsEvent): event is StreamsEvent & {
1100
- event_type: "ft_mint"
1176
+ event_type: "ft_mint";
1101
1177
  };
1102
1178
  declare function decodeFtMint(event: StreamsEvent): DecodedFtMint;
1103
1179
  declare function isFtBurn(event: StreamsEvent): event is StreamsEvent & {
1104
- event_type: "ft_burn"
1180
+ event_type: "ft_burn";
1105
1181
  };
1106
1182
  declare function decodeFtBurn(event: StreamsEvent): DecodedFtBurn;
1107
1183
  declare function isNftMint(event: StreamsEvent): event is StreamsEvent & {
1108
- event_type: "nft_mint"
1184
+ event_type: "nft_mint";
1109
1185
  };
1110
1186
  declare function decodeNftMint(event: StreamsEvent): DecodedNftMint;
1111
1187
  declare function isNftBurn(event: StreamsEvent): event is StreamsEvent & {
1112
- event_type: "nft_burn"
1188
+ event_type: "nft_burn";
1113
1189
  };
1114
1190
  declare function decodeNftBurn(event: StreamsEvent): DecodedNftBurn;
1115
1191
  /** Decoded form of a Clarity `print` event:
@@ -1118,41 +1194,41 @@ declare function decodeNftBurn(event: StreamsEvent): DecodedNftBurn;
1118
1194
  * `0x…` hex, tuples as objects)
1119
1195
  * - `raw_value`: the canonical serialized hex, for byte-exact consumers */
1120
1196
  type DecodedPrintValue = {
1121
- topic: string | null
1122
- value: unknown
1123
- raw_value: string | null
1197
+ topic: string | null;
1198
+ value: unknown;
1199
+ raw_value: string | null;
1124
1200
  };
1125
1201
  type DecodedPrintPayload = {
1126
- contract_id: string | null
1127
- payload: DecodedPrintValue
1202
+ contract_id: string | null;
1203
+ payload: DecodedPrintValue;
1128
1204
  };
1129
1205
  type DecodedPrint = {
1130
- cursor: string
1131
- block_height: number
1132
- tx_id: string
1133
- tx_index: number
1134
- event_index: number
1135
- event_type: "print"
1136
- decoded_payload: DecodedPrintPayload
1137
- source_cursor: string
1206
+ cursor: string;
1207
+ block_height: number;
1208
+ tx_id: string;
1209
+ tx_index: number;
1210
+ event_index: number;
1211
+ event_type: "print";
1212
+ decoded_payload: DecodedPrintPayload;
1213
+ source_cursor: string;
1138
1214
  };
1139
1215
  declare function isPrint(event: StreamsEvent): event is StreamsEvent & {
1140
- event_type: "print"
1216
+ event_type: "print";
1141
1217
  };
1142
1218
  declare function decodePrint(event: StreamsEvent): DecodedPrint;
1143
1219
  /** Superset of the columns the decoded_events table holds. Every decoded
1144
1220
  * event's `decoded_payload` is assignable to this, so the indexer's writer
1145
1221
  * can map columns generically instead of per-event-type. */
1146
1222
  type DecodedEventColumns = {
1147
- contract_id?: string | null
1148
- asset_identifier?: string | null
1149
- sender?: string | null
1150
- recipient?: string | null
1151
- amount?: string | null
1152
- value?: string | null
1153
- memo?: string | null
1223
+ contract_id?: string | null;
1224
+ asset_identifier?: string | null;
1225
+ sender?: string | null;
1226
+ recipient?: string | null;
1227
+ amount?: string | null;
1228
+ value?: string | null;
1229
+ memo?: string | null;
1154
1230
  /** JSONB overflow for non-flat types (e.g. print's decoded value). */
1155
- payload?: unknown
1231
+ payload?: unknown;
1156
1232
  };
1157
1233
  /**
1158
1234
  * Helpers for Streams cursors. A cursor is the opaque `<block>:<index>` string
@@ -1177,12 +1253,12 @@ declare const Cursor: {
1177
1253
  * type), larger than any real index, so nothing at `height - 1` survives the
1178
1254
  * keyset and the next returned row is exactly `(height, 0)`.
1179
1255
  */
1180
- atHeight(height: number): string
1256
+ atHeight(height: number): string;
1181
1257
  /** Parse a `<block>:<index>` cursor. Throws `ValidationError` if malformed. */
1182
1258
  parse(cursor: string): {
1183
- blockHeight: number
1184
- eventIndex: number
1185
- }
1259
+ blockHeight: number;
1260
+ eventIndex: number;
1261
+ };
1186
1262
  };
1187
1263
  type DecodedEventRow = DecodedFtTransfer | DecodedNftTransfer | DecodedStxTransfer | DecodedStxMint | DecodedStxBurn | DecodedStxLock | DecodedFtMint | DecodedFtBurn | DecodedNftMint | DecodedNftBurn | DecodedPrint;
1188
1264
  export { isStxTransfer, isStxMint, isStxLock, isStxBurn, isPrint, isNftTransfer, isNftMint, isNftBurn, isFtTransfer, isFtMint, isFtBurn, decodeStxTransfer, decodeStxMint, decodeStxLock, decodeStxBurn, decodePrint, decodeNftTransfer, decodeNftMint, decodeNftBurn, decodeFtTransfer, decodeFtMint, decodeFtBurn, decode, createStreamsClient, ValidationError, StreamsUsage, StreamsTip, StreamsSignatureError, StreamsServerError, StreamsReorgsListParams, StreamsReorgsListEnvelope, StreamsReorgContext, StreamsReorg, StreamsEventsSubscribeParams, StreamsEventsStreamParams, StreamsEventsListParams, StreamsEventsListEnvelope, StreamsEventsEnvelope, StreamsEventsConsumeResult, StreamsEventsConsumeParams, StreamsEventType, StreamsEventPayload, StreamsEvent, StreamsDumpsManifest, StreamsDumps, StreamsDumpFile, StreamsConsumeParams, StreamsClient, StreamsCanonicalBlock, StreamsBatchContext, StreamsBatch, STREAMS_EVENT_TYPES, RateLimitError, NftTransferPayload, NftTransferEvent, FtTransferPayload, FtTransferEvent, FetchLike2 as FetchLike, DecodedStxTransferPayload, DecodedStxTransfer, DecodedStxMintPayload, DecodedStxMint, DecodedStxLockPayload, DecodedStxLock, DecodedStxBurnPayload, DecodedStxBurn, DecodedPrintValue, DecodedPrintPayload, DecodedPrint, DecodedNftTransferPayload, DecodedNftTransfer, DecodedNftMintPayload, DecodedNftMint, DecodedNftBurnPayload, DecodedNftBurn, DecodedFtTransferPayload, DecodedFtTransfer, DecodedFtMintPayload, DecodedFtMint, DecodedFtBurnPayload, DecodedFtBurn, DecodedEventRow, DecodedEventColumns, Cursor, ConsumerBatchContext, AuthError };