@secondlayer/subgraphs 4.4.1 → 5.0.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.
Files changed (65) hide show
  1. package/README.md +13 -21
  2. package/dist/{src/index.d.ts → index.d.ts} +59 -189
  3. package/dist/index.js +2151 -0
  4. package/dist/index.js.map +24 -0
  5. package/dist/{src/runtime → runtime}/emitter.d.ts +17 -11
  6. package/dist/{src/runtime → runtime}/emitter.js +58 -18
  7. package/dist/runtime/emitter.js.map +19 -0
  8. package/dist/{src/runtime → runtime}/replay.d.ts +15 -1
  9. package/dist/{src/runtime → runtime}/replay.js +418 -723
  10. package/dist/{src/runtime → runtime}/replay.js.map +6 -6
  11. package/dist/{src/schema → schema}/index.d.ts +10 -69
  12. package/dist/{src/schema → schema}/index.js +188 -281
  13. package/dist/schema/index.js.map +13 -0
  14. package/dist/{src/testing → testing}/index.d.ts +65 -115
  15. package/dist/{src/testing → testing}/index.js +554 -968
  16. package/dist/testing/index.js.map +21 -0
  17. package/dist/{src/types.d.ts → types.d.ts} +10 -66
  18. package/dist/{src/validate.d.ts → validate.d.ts} +11 -69
  19. package/dist/{src/validate.js → validate.js} +18 -98
  20. package/dist/validate.js.map +10 -0
  21. package/package.json +18 -26
  22. package/dist/src/index.js +0 -6081
  23. package/dist/src/index.js.map +0 -44
  24. package/dist/src/runtime/block-processor.d.ts +0 -559
  25. package/dist/src/runtime/block-processor.js +0 -3810
  26. package/dist/src/runtime/block-processor.js.map +0 -31
  27. package/dist/src/runtime/catchup.d.ts +0 -473
  28. package/dist/src/runtime/catchup.js +0 -4228
  29. package/dist/src/runtime/catchup.js.map +0 -35
  30. package/dist/src/runtime/clarity.d.ts +0 -15
  31. package/dist/src/runtime/clarity.js +0 -41
  32. package/dist/src/runtime/clarity.js.map +0 -10
  33. package/dist/src/runtime/context.d.ts +0 -325
  34. package/dist/src/runtime/context.js +0 -936
  35. package/dist/src/runtime/context.js.map +0 -13
  36. package/dist/src/runtime/emitter.js.map +0 -19
  37. package/dist/src/runtime/processor.d.ts +0 -11
  38. package/dist/src/runtime/processor.js +0 -5372
  39. package/dist/src/runtime/processor.js.map +0 -40
  40. package/dist/src/runtime/reindex.d.ts +0 -539
  41. package/dist/src/runtime/reindex.js +0 -4802
  42. package/dist/src/runtime/reindex.js.map +0 -37
  43. package/dist/src/runtime/reorg.d.ts +0 -432
  44. package/dist/src/runtime/reorg.js +0 -4355
  45. package/dist/src/runtime/reorg.js.map +0 -36
  46. package/dist/src/runtime/runner.d.ts +0 -719
  47. package/dist/src/runtime/runner.js +0 -1332
  48. package/dist/src/runtime/runner.js.map +0 -16
  49. package/dist/src/runtime/source-matcher.d.ts +0 -304
  50. package/dist/src/runtime/source-matcher.js +0 -335
  51. package/dist/src/runtime/source-matcher.js.map +0 -10
  52. package/dist/src/runtime/stats.d.ts +0 -23
  53. package/dist/src/runtime/stats.js +0 -71
  54. package/dist/src/runtime/stats.js.map +0 -10
  55. package/dist/src/schema/index.js.map +0 -13
  56. package/dist/src/service.d.ts +0 -0
  57. package/dist/src/service.js +0 -5398
  58. package/dist/src/service.js.map +0 -41
  59. package/dist/src/testing/index.js.map +0 -22
  60. package/dist/src/triggers/index.d.ts +0 -381
  61. package/dist/src/triggers/index.js +0 -31
  62. package/dist/src/triggers/index.js.map +0 -10
  63. package/dist/src/validate.js.map +0 -10
  64. /package/dist/{src/types.js → types.js} +0 -0
  65. /package/dist/{src/types.js.map → types.js.map} +0 -0
@@ -1,539 +0,0 @@
1
- import { AbiContract as AbiContract2 } from "@secondlayer/stacks/clarity";
2
- import { AssetIdentifier } from "@secondlayer/stacks/filters";
3
- /**
4
- * How long a read stays valid.
5
- *
6
- * - `per-block` (default): pinned to the block being processed, cached under
7
- * its `index_block_hash`. Sound for any read-only function — reindexing the
8
- * same block always returns the same value, and a reorg-replaced block has a
9
- * different id so it can't inherit the orphaned answer.
10
- * - `contract-constant`: the caller asserts the value cannot change for this
11
- * contract and these args (SIP-010 `get-decimals`/`get-symbol`), so it is
12
- * resolved ONCE instead of once per block. This is the mode that makes a
13
- * backfill affordable — under `per-block` every block is a distinct key and
14
- * therefore a distinct RPC. Declaring it on a value that does change pins the
15
- * first answer forever, so it is opt-in and never inferred.
16
- */
17
- type ChainReadCacheMode = "per-block" | "contract-constant";
18
- type ChainReadOptions = {
19
- cache?: ChainReadCacheMode
20
- };
21
- /**
22
- * `ChainReadClient` with the ABI generic erased. Structurally cheap, so the
23
- * base `SubgraphContext` can carry it; `TypedSubgraphContext` uses the real
24
- * one and handlers get full inference.
25
- */
26
- interface ErasedChainReadClient {
27
- contract(contractId: string, abi: unknown, options?: ChainReadOptions): {
28
- read: Record<string, (args?: Record<string, unknown>) => Promise<unknown>>
29
- };
30
- }
31
- /** Supported column types for subgraph schemas */
32
- type ColumnType = "text" | "uint" | "int" | "principal" | "boolean" | "timestamp" | "jsonb";
33
- /** Column definition in a subgraph table */
34
- interface SubgraphColumn {
35
- type: ColumnType;
36
- nullable?: boolean;
37
- indexed?: boolean;
38
- search?: boolean;
39
- default?: string | number | boolean;
40
- }
41
- /**
42
- * A foreign-key relation to another table in the same subgraph. Drives DDL FK
43
- * constraints and ORM codegen (`@relation` in Prisma, `relations()` in Drizzle)
44
- * so generated clients get typed joins. The referenced columns must form a
45
- * `uniqueKeys` entry on the target table.
46
- */
47
- interface SubgraphRelation {
48
- /** Relation field name on this table's generated model (e.g. "pool"). */
49
- name: string;
50
- /** Target table name in this subgraph. */
51
- references: string;
52
- /** Local column(s) holding the foreign key. */
53
- fields: string[];
54
- /** Target column(s) the fields point at (a uniqueKeys entry on the target). */
55
- referencedColumns: string[];
56
- }
57
- /**
58
- * Table definition within a subgraph schema.
59
- *
60
- * The array fields are `readonly` so a schema literal can be hoisted out of
61
- * the `defineSubgraph()` call with `as const` (or {@link defineSchema}) and
62
- * still typecheck — `as const` produces `readonly [readonly ["holder"]]`,
63
- * which a mutable `string[][]` rejects. Without that, extracting a helper
64
- * that takes `ctx` meant losing the entire typed surface, which is why the
65
- * shipped starter reached for `ctx: any`.
66
- */
67
- interface SubgraphTable {
68
- columns: Record<string, SubgraphColumn>;
69
- /** Composite indexes (each entry is an array of column names) */
70
- indexes?: readonly (readonly string[])[];
71
- /** Unique key constraints (each entry is an array of column names). Required for upsert. */
72
- uniqueKeys?: readonly (readonly string[])[];
73
- /** Foreign-key relations to other tables (for typed ORM joins). */
74
- relations?: readonly SubgraphRelation[];
75
- }
76
- /** Subgraph schema — maps table names to table definitions */
77
- type SubgraphSchema = Record<string, SubgraphTable>;
78
- /** STX event filters */
79
- interface StxTransferFilter {
80
- type: "stx_transfer";
81
- sender?: string;
82
- recipient?: string;
83
- minAmount?: bigint;
84
- maxAmount?: bigint;
85
- }
86
- interface StxMintFilter {
87
- type: "stx_mint";
88
- recipient?: string;
89
- minAmount?: bigint;
90
- }
91
- interface StxBurnFilter {
92
- type: "stx_burn";
93
- sender?: string;
94
- minAmount?: bigint;
95
- }
96
- interface StxLockFilter {
97
- type: "stx_lock";
98
- lockedAddress?: string;
99
- minAmount?: bigint;
100
- }
101
- /**
102
- * Restrict a source to contracts conforming to a trait/standard (e.g. "sip-010")
103
- * instead of a fixed contract — resolved from the contract registry at match time,
104
- * as-of each processed block. Lets a source index "all SIP-010 tokens" etc.
105
- */
106
- type TraitScope = {
107
- trait?: string
108
- };
109
- /**
110
- * Scope a source to a DYNAMIC address set discovered from another source's
111
- * events, instead of a fixed contract list.
112
- *
113
- * The standard shape it unlocks: a router plus pools created after you
114
- * deploy. `contractId` arrays cover a set you know at authoring time; a
115
- * factory covers the set that grows. It is deliberately NOT tied to contract
116
- * deployment — the address can come from any field of any event, so it also
117
- * covers launchpad-minted tokens, DAO extension allowlists, and registry
118
- * entries.
119
- *
120
- * ```ts
121
- * sources: {
122
- * registry: {
123
- * type: "print_event",
124
- * contractId: REGISTRY,
125
- * topic: "pool-created",
126
- * prints: { "pool-created": { pool: "principal" } },
127
- * },
128
- * swaps: {
129
- * type: "print_event",
130
- * topic: "swap",
131
- * // every pool the registry has ever announced, including new ones
132
- * factory: { from: "registry", field: "data.pool" },
133
- * },
134
- * }
135
- * ```
136
- *
137
- * Two guarantees the runtime provides:
138
- * - **Same-block ordering** — a contract discovered in block N receives its
139
- * own block-N events. Discovery runs before matching, within the block.
140
- * - **Reorg-scoped** — the discovered set is stamped with the block that
141
- * revealed it and rolled back with everything else on a fork, so an address
142
- * announced on an orphaned chain does not linger forever.
143
- */
144
- interface FactoryScope {
145
- factory?: {
146
- /** Source name whose events reveal the addresses. */
147
- from: string
148
- /** Dotted path to the address on that source's payload
149
- * (e.g. `"data.pool"`, `"contractId"`, `"data.token.id"`). */
150
- field: string
151
- };
152
- }
153
- /** FT event filters */
154
- interface FtTransferFilter extends TraitScope {
155
- type: "ft_transfer";
156
- assetIdentifier?: AssetIdentifier;
157
- sender?: string;
158
- recipient?: string;
159
- minAmount?: bigint;
160
- }
161
- interface FtMintFilter extends TraitScope {
162
- type: "ft_mint";
163
- assetIdentifier?: AssetIdentifier;
164
- recipient?: string;
165
- minAmount?: bigint;
166
- }
167
- interface FtBurnFilter extends TraitScope {
168
- type: "ft_burn";
169
- assetIdentifier?: AssetIdentifier;
170
- sender?: string;
171
- minAmount?: bigint;
172
- }
173
- /** NFT event filters */
174
- interface NftTransferFilter extends TraitScope {
175
- type: "nft_transfer";
176
- assetIdentifier?: AssetIdentifier;
177
- sender?: string;
178
- recipient?: string;
179
- }
180
- interface NftMintFilter extends TraitScope {
181
- type: "nft_mint";
182
- assetIdentifier?: AssetIdentifier;
183
- recipient?: string;
184
- }
185
- interface NftBurnFilter extends TraitScope {
186
- type: "nft_burn";
187
- assetIdentifier?: AssetIdentifier;
188
- sender?: string;
189
- }
190
- /** Contract event filters */
191
- interface ContractCallFilter extends TraitScope, FactoryScope {
192
- type: "contract_call";
193
- /**
194
- * One contract id, or a SET of them (max 20) — the standard DeFi shape is
195
- * a router plus N pools, which used to cost N near-identical sources and
196
- * handlers, or the `"*"` catch-all that erases per-source typing. Payload
197
- * types are identical per `type`, so one handler serves the set and
198
- * `event.contractId` disambiguates.
199
- *
200
- * Supports `*` wildcards (e.g. `"SP1ABC….pool-*"`). Mutually exclusive
201
- * with `trait`, which resolves its own set per block.
202
- */
203
- contractId?: string | readonly string[];
204
- functionName?: string;
205
- caller?: string;
206
- /**
207
- * Contract ABI (pass it `as const`) used to type `event.input` — the named,
208
- * decoded function arguments. Dev-provided; serialized into the deployed
209
- * definition and used at runtime to decode args by name. Omit to keep
210
- * `event.args` as a positional `unknown[]`.
211
- *
212
- * Deploy validation requires `abi` whenever `functionName` is set
213
- * (`normalizeAbi()` from `@secondlayer/stacks/clarity`).
214
- */
215
- abi?: AbiContract2;
216
- }
217
- interface ContractDeployFilter {
218
- type: "contract_deploy";
219
- deployer?: string;
220
- contractName?: string;
221
- }
222
- interface NestedContractCallFilter extends TraitScope, FactoryScope {
223
- type: "nested_contract_call";
224
- contractId?: string | readonly string[];
225
- functionName?: string;
226
- caller?: string;
227
- sender?: string;
228
- }
229
- interface VarSetFilter extends TraitScope, FactoryScope {
230
- type: "var_set";
231
- contractId?: string | readonly string[];
232
- varName?: string;
233
- }
234
- interface MapWriteFilter extends TraitScope, FactoryScope {
235
- type: "map_set" | "map_insert" | "map_delete";
236
- contractId?: string | readonly string[];
237
- map?: string;
238
- }
239
- /**
240
- * One declared field of a print payload.
241
- *
242
- * A bare {@link ColumnType} is a required scalar (`amount: "uint"`). The
243
- * composite forms exist because real print payloads are not flat: BNS-V2
244
- * emits `name` as a NESTED tuple, and a `prints` vocabulary that could only
245
- * say `"jsonb"` is why a handler reading flat `data.name` type-checked,
246
- * deployed, and then decoded to null on every event.
247
- *
248
- * - `{ type: F, optional: true }` — the KEY becomes optional on `event.data`
249
- * (mirrors `always_present: false` in the inferred schema).
250
- * - `{ tuple: { … } }` — a nested tuple, typed all the way down.
251
- * - `{ list: F }` — a list of `F`.
252
- */
253
- type PrintField = ColumnType | {
254
- type: PrintField
255
- optional: true
256
- } | {
257
- tuple: Record<string, PrintField>
258
- } | {
259
- list: PrintField
260
- };
261
- /**
262
- * Per-topic field schema for a print_event source. When declared, the handler's
263
- * `event` is a discriminated union keyed by `topic` and `event.data` is typed
264
- * per topic. Nested tuples, lists, and optional fields — see {@link PrintField}.
265
- *
266
- * Also opts the source into RUNTIME validation: a payload that does not match
267
- * is skipped and logged rather than written as nulls.
268
- */
269
- type PrintEventPrints = Record<string, Record<string, PrintField>>;
270
- /**
271
- * One column in a static identity map. Literals only — the bundler never
272
- * executes user code, so `{ from: "tokenX" }` is valid and `from("tokenX")`
273
- * is not.
274
- */
275
- type MaterializeColumn = {
276
- from: string
277
- } | {
278
- fromTx: "sender" | "txId"
279
- } | {
280
- fromBlock: "height" | "hash" | "timestamp"
281
- };
282
- /** Static insert from a source event — replaces a 1:1 handler. */
283
- interface MaterializeSpec {
284
- table: string;
285
- /** Keys = schema column names (snake). */
286
- columns: Record<string, MaterializeColumn>;
287
- }
288
- type PrintEventFields = FactoryScope & {
289
- type: "print_event"
290
- topic?: string
291
- /** Identity map: insert without a handler function. XOR with handlers[name]. */
292
- materialize?: MaterializeSpec
293
- };
294
- /**
295
- * Pinned to one or more contract ids with no trait — `prints` is required so
296
- * `event.data` is typed and empty-table handlers cannot typecheck.
297
- */
298
- type PinnedPrintEventFilter = PrintEventFields & {
299
- contractId: string | readonly string[]
300
- trait?: undefined
301
- prints: PrintEventPrints
302
- };
303
- /**
304
- * Trait-scoped print source (optionally narrowed by contractId). No single
305
- * schema — `prints` stays optional.
306
- */
307
- type TraitPrintEventFilter = PrintEventFields & {
308
- contractId?: string | readonly string[]
309
- trait: string
310
- prints?: PrintEventPrints
311
- };
312
- /**
313
- * Unpinned / factory-only print source (no contractId). `prints` optional.
314
- */
315
- type UnpinnedPrintEventFilter = PrintEventFields & {
316
- contractId?: undefined
317
- trait?: string
318
- prints?: PrintEventPrints
319
- };
320
- /**
321
- * Print-event filter. Pinned sources (contractId set, no trait) require
322
- * `prints`; trait and unpinned sources may omit it.
323
- */
324
- type PrintEventFilter = PinnedPrintEventFilter | TraitPrintEventFilter | UnpinnedPrintEventFilter;
325
- /** All subgraph filter types — discriminated on `type` */
326
- type SubgraphFilter = StxTransferFilter | StxMintFilter | StxBurnFilter | StxLockFilter | FtTransferFilter | FtMintFilter | FtBurnFilter | NftTransferFilter | NftMintFilter | NftBurnFilter | ContractCallFilter | ContractDeployFilter | PrintEventFilter | NestedContractCallFilter | VarSetFilter | MapWriteFilter;
327
- /** Transaction metadata available in handlers */
328
- interface TxMeta {
329
- txId: string;
330
- sender: string;
331
- type: string;
332
- status: string;
333
- contractId?: string | null;
334
- functionName?: string | null;
335
- }
336
- /** Scalar types that can appear as row values */
337
- type RowValue = string | number | bigint | boolean | null | undefined | Record<string, unknown> | unknown[];
338
- /** Value or computed function that receives existing row */
339
- type ComputedValue = RowValue | ((existing: Record<string, unknown> | null) => unknown);
340
- /** Context passed to subgraph handlers during event processing */
341
- interface SubgraphContext {
342
- block: {
343
- height: number
344
- hash: string
345
- timestamp: number
346
- burnBlockHeight: number
347
- /** Nakamoto StacksBlockId, when the block row carries one. */
348
- indexBlockHash?: string | null
349
- };
350
- tx: TxMeta;
351
- /**
352
- * Read-only contract calls pinned to this block. Cached, so the same
353
- * (contract, function, args) is fetched once per block rather than once
354
- * per event.
355
- *
356
- * Erased here on purpose: this interface is compared structurally wherever
357
- * a subgraph definition is passed around, and carrying an ABI-generic
358
- * method pushes those comparisons past TS's instantiation depth. Handlers
359
- * receive `TypedSubgraphContext`, which exposes the fully typed version.
360
- */
361
- client: ErasedChainReadClient;
362
- insert(table: string, row: Record<string, unknown>): void;
363
- update(table: string, where: Record<string, unknown>, set: Record<string, unknown>): void;
364
- upsert(table: string, key: Record<string, unknown>, row: Record<string, unknown>): void;
365
- delete(table: string, where: Record<string, unknown>): void;
366
- /**
367
- * Atomic counter update — the blessed accumulator primitive. Applies
368
- * `col = COALESCE(col, 0) + delta` per column (insert-or-add); deltas may
369
- * be negative. Requires a uniqueKeys constraint matching `key`. Prefer
370
- * this over patchOrInsert with functional updaters for running totals.
371
- */
372
- increment(table: string, key: Record<string, unknown>, deltas: Record<string, bigint | number>): void;
373
- /** Partial update — sets only specified fields, preserves others */
374
- patch(table: string, where: Record<string, unknown>, set: Record<string, unknown>): void;
375
- /** Find-then-merge-or-insert. Values can be functions: (existing) => newValue */
376
- patchOrInsert(table: string, key: Record<string, unknown>, row: Record<string, ComputedValue>): Promise<void>;
377
- findOne(table: string, where: Record<string, unknown>): Promise<Record<string, unknown> | null>;
378
- findMany(table: string, where: Record<string, unknown>): Promise<Record<string, unknown>[]>;
379
- /** Format a bigint amount with decimal places */
380
- formatUnits(value: bigint, decimals: number): string;
381
- /** Count rows matching filter */
382
- count(table: string, where?: Record<string, unknown>): Promise<number>;
383
- /** Sum a numeric column */
384
- sum(table: string, column: string, where?: Record<string, unknown>): Promise<bigint>;
385
- /** Min of a numeric column */
386
- min(table: string, column: string, where?: Record<string, unknown>): Promise<bigint | null>;
387
- /** Max of a numeric column */
388
- max(table: string, column: string, where?: Record<string, unknown>): Promise<bigint | null>;
389
- /** Count distinct values in a column */
390
- countDistinct(table: string, column: string, where?: Record<string, unknown>): Promise<number>;
391
- }
392
- /** Handler function that processes events and writes to the subgraph */
393
- type SubgraphHandler = (event: Record<string, unknown>, ctx: SubgraphContext) => Promise<void> | void;
394
- /** Complete subgraph definition */
395
- interface SubgraphDefinition {
396
- /** Unique subgraph name (lowercase, alphanumeric + hyphens) */
397
- name: string;
398
- /** Semantic version */
399
- version?: string;
400
- /** Human description */
401
- description?: string;
402
- /** Block height to start indexing from (default: 1) */
403
- startBlock?: number;
404
- /** 'concurrent' = tip-first: live at tip now, history backfills behind.
405
- * Requires order-tolerant handlers. Default 'blocking'. */
406
- backfillMode?: "blocking" | "concurrent";
407
- /** Named source filters — keys become handler keys */
408
- sources: Record<string, SubgraphFilter>;
409
- /** Tables in this subgraph */
410
- schema: SubgraphSchema;
411
- /** Handler functions — keys must match source names (or "*" for catch-all) */
412
- handlers: Record<string, SubgraphHandler>;
413
- }
414
- import { Block, Event, Transaction } from "@secondlayer/shared/db";
415
- /** A runtime event row. `clock: "vm"` marks an opt-in `vm_events` row whose
416
- * `event_index` is `ordinal` — a second ordinal that never sorts or
417
- * dedupes against classic `events.event_index`. */
418
- type RuntimeEvent = Event & {
419
- clock?: "vm"
420
- };
421
- interface BlockData {
422
- block: Block;
423
- txs: Transaction[];
424
- /** Classic `events` rows (Streams 1.0 clock). */
425
- events: Event[];
426
- /** Opt-in `vm_events` rows on their own clock. Absent/empty on `"*"`
427
- * nodes and on archives collected without `storage`/`contract_calls`. */
428
- vmEvents?: RuntimeEvent[];
429
- }
430
- /**
431
- * Where the subgraph runtime reads canonical chain data. Today it taps the
432
- * indexer Postgres directly (`PostgresBlockSource`); the re-point adds a
433
- * `PublicApiBlockSource` that consumes the Streams clock + Index data over
434
- * HTTP. `matchSources` / handlers / flush / outbox are unchanged — only the
435
- * loader + tip swap behind this seam.
436
- */
437
- interface BlockSource {
438
- /** Highest canonical block height available to process. */
439
- getTip(): Promise<number>;
440
- /** Canonical block data for [fromHeight, toHeight], keyed by height. */
441
- loadBlockRange(fromHeight: number, toHeight: number): Promise<Map<number, BlockData>>;
442
- /** Sparse-scan probe: lowest height in (afterHeight, untilHeight] holding
443
- * an event this source's subgraph could match, or null when the rest of
444
- * the range is empty. Optional — only event-scoped sources support it. */
445
- nextDataHeight?(afterHeight: number, untilHeight: number): Promise<number | null>;
446
- }
447
- type ReindexBatchConfig = {
448
- defaultBatchSize: number
449
- minBatchSize: number
450
- maxBatchSize: number
451
- };
452
- type ReindexBatchEnv = {
453
- SUBGRAPH_REINDEX_BATCH_SIZE?: string
454
- SUBGRAPH_REINDEX_MIN_BATCH_SIZE?: string
455
- SUBGRAPH_REINDEX_MAX_BATCH_SIZE?: string
456
- };
457
- type ReindexResumeRow = {
458
- last_processed_block: number | string
459
- reindex_from_block: number | string | null
460
- reindex_to_block: number | string | null
461
- };
462
- declare function initialReindexProgressBlock(fromBlock: number): number;
463
- declare function resolveReindexResumeBlock(row: ReindexResumeRow): number | null;
464
- declare function resolveReindexBatchConfig(env?: ReindexBatchEnv): ReindexBatchConfig;
465
- interface ReindexOptions {
466
- /**
467
- * Floor on the walk's first block — NOT a caller-supplied range. When set
468
- * (e.g. an op row carrying a `from_block`), it raises the walk start and
469
- * can never lower it. There is deliberately no `toBlock` counterpart:
470
- * a reindex always runs to chain tip. See {@link resolveBlockRange}.
471
- */
472
- startBlockFloor?: number;
473
- schemaName?: string;
474
- /** Op row to receive processed_events on each progress flush. */
475
- operationId?: string;
476
- signal?: AbortSignal;
477
- }
478
- /**
479
- * Resolve the reindex walk range. Always the whole subgraph:
480
- * `[def.startBlock, chain tip]`. Chain tip reads from `index_progress` —
481
- * lives in the source DB.
482
- *
483
- * Reindex drops the schema unconditionally, so the walk range is also the
484
- * ONLY data that survives. A narrower walk therefore does not "reindex a
485
- * range" — it silently destroys every row outside it while leaving the
486
- * subgraph reporting `active` at chain tip (f079: a single-block
487
- * `--from-block N --to-block N` emptied sbtc-flows, and the first recovery
488
- * attempt rebuilt only 21% of its history). Ranged, additive work is
489
- * `backfillSubgraph`'s job.
490
- *
491
- * `startBlockFloor` is a plan-policy floor, not a range: it can only raise
492
- * the start block, never lower it, and never bounds the end.
493
- */
494
- declare function resolveBlockRange(source: BlockSource, def: SubgraphDefinition, opts?: ReindexOptions): Promise<{
495
- fromBlock: number
496
- toBlock: number
497
- }>;
498
- /**
499
- * Reindex a subgraph by dropping its tables, recreating them, and reprocessing
500
- * all historical blocks through the handler pipeline.
501
- *
502
- * Always whole-subgraph: `[start_block, chain tip]`. There is no ranged
503
- * reindex — the drop cannot be scoped to a range without re-running delta
504
- * handlers (`ctx.increment` / `ctx.update` / `ctx.patchOrInsert`) over rows
505
- * that were never removed, which is the exact double-count hazard `backfill`
506
- * already refuses. Use `backfillSubgraph` for ranged, additive work.
507
- *
508
- * Supports cancellation via AbortSignal — on shutdown abort, status stays
509
- * "reindexing" for auto-resume; on user cancel, status resets to "active".
510
- */
511
- declare function reindexSubgraph(def: SubgraphDefinition, opts?: ReindexOptions): Promise<{
512
- processed: number
513
- }>;
514
- /**
515
- * Resume a previously interrupted reindex. Skips schema drop (already done)
516
- * and continues from last_processed_block + 1.
517
- */
518
- declare function resumeReindex(def: SubgraphDefinition, opts: {
519
- schemaName: string
520
- operationId?: string
521
- signal?: AbortSignal
522
- }): Promise<{
523
- processed: number
524
- }>;
525
- /**
526
- * Backfill a subgraph by re-processing a block range WITHOUT dropping the schema.
527
- * Uses upserts so existing data is updated, not duplicated. Safe to run while
528
- * the subgraph is actively syncing.
529
- */
530
- declare function backfillSubgraph(def: SubgraphDefinition, opts: {
531
- fromBlock: number
532
- toBlock: number
533
- schemaName?: string
534
- operationId?: string
535
- signal?: AbortSignal
536
- }): Promise<{
537
- processed: number
538
- }>;
539
- export { resumeReindex, resolveReindexResumeBlock, resolveReindexBatchConfig, resolveBlockRange, reindexSubgraph, initialReindexProgressBlock, backfillSubgraph, ReindexOptions };