@secondlayer/subgraphs 4.1.5 → 4.2.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 (39) hide show
  1. package/dist/src/index.d.ts +87 -29
  2. package/dist/src/index.js +376 -128
  3. package/dist/src/index.js.map +9 -7
  4. package/dist/src/runtime/block-processor.d.ts +72 -23
  5. package/dist/src/runtime/block-processor.js +186 -53
  6. package/dist/src/runtime/block-processor.js.map +7 -5
  7. package/dist/src/runtime/catchup.d.ts +72 -23
  8. package/dist/src/runtime/catchup.js +201 -68
  9. package/dist/src/runtime/catchup.js.map +7 -5
  10. package/dist/src/runtime/emitter.js +24 -1
  11. package/dist/src/runtime/emitter.js.map +5 -4
  12. package/dist/src/runtime/processor.js +328 -166
  13. package/dist/src/runtime/processor.js.map +10 -7
  14. package/dist/src/runtime/reindex.d.ts +72 -23
  15. package/dist/src/runtime/reindex.js +238 -105
  16. package/dist/src/runtime/reindex.js.map +7 -5
  17. package/dist/src/runtime/reorg.d.ts +72 -23
  18. package/dist/src/runtime/reorg.js +215 -81
  19. package/dist/src/runtime/reorg.js.map +8 -6
  20. package/dist/src/runtime/runner.d.ts +72 -23
  21. package/dist/src/runtime/runner.js +156 -23
  22. package/dist/src/runtime/runner.js.map +8 -6
  23. package/dist/src/runtime/source-matcher.d.ts +72 -23
  24. package/dist/src/schema/index.d.ts +72 -23
  25. package/dist/src/schema/index.js +115 -1
  26. package/dist/src/schema/index.js.map +3 -3
  27. package/dist/src/service.js +348 -171
  28. package/dist/src/service.js.map +11 -8
  29. package/dist/src/testing/index.d.ts +195 -24
  30. package/dist/src/testing/index.js +448 -25
  31. package/dist/src/testing/index.js.map +9 -6
  32. package/dist/src/triggers/index.d.ts +83 -24
  33. package/dist/src/triggers/index.js +5 -2
  34. package/dist/src/triggers/index.js.map +3 -3
  35. package/dist/src/types.d.ts +73 -24
  36. package/dist/src/validate.d.ts +72 -23
  37. package/dist/src/validate.js +115 -1
  38. package/dist/src/validate.js.map +3 -3
  39. package/package.json +2 -2
@@ -119,7 +119,12 @@ type TraitScope = {
119
119
  *
120
120
  * ```ts
121
121
  * sources: {
122
- * registry: { type: "print_event", contractId: REGISTRY, topic: "pool-created" },
122
+ * registry: {
123
+ * type: "print_event",
124
+ * contractId: REGISTRY,
125
+ * topic: "pool-created",
126
+ * prints: { "pool-created": { pool: "principal" } },
127
+ * },
123
128
  * swaps: {
124
129
  * type: "print_event",
125
130
  * topic: "swap",
@@ -244,6 +249,9 @@ interface ContractCallFilter extends TraitScope, FactoryScope {
244
249
  * decoded function arguments. Dev-provided; serialized into the deployed
245
250
  * definition and used at runtime to decode args by name. Omit to keep
246
251
  * `event.args` as a positional `unknown[]`.
252
+ *
253
+ * Deploy validation requires `abi` whenever `functionName` is set
254
+ * (`normalizeAbi()` from `@secondlayer/stacks/clarity`).
247
255
  */
248
256
  abi?: AbiContract2;
249
257
  }
@@ -274,29 +282,70 @@ type PrintField = ColumnType | {
274
282
  } | {
275
283
  list: PrintField
276
284
  };
277
- interface PrintEventFilter extends TraitScope, FactoryScope {
278
- type: "print_event";
279
- /** One contract id, or a set of them (max 20). Supports `*` wildcards.
280
- * COMPOSES with `trait` — the matcher ANDs them, so the pair means
281
- * "contracts conforming to this trait, narrowed to these ids". (The Index
282
- * read API refuses the combination, but that is its query planner's
283
- * constraint, not a semantic one.) */
284
- contractId?: string | readonly string[];
285
- topic?: string;
286
- /**
287
- * Per-topic field schema. When declared, the handler's `event` is a
288
- * discriminated union keyed by `topic` and `event.data` is typed per topic
289
- * (e.g. `{ "completed-deposit": { amount: "uint", sender: "principal" } }`).
290
- * Nested tuples, lists, and optional fields are expressible — see
291
- * {@link PrintField}.
292
- *
293
- * Declaring `prints` also opts the source into RUNTIME validation: an
294
- * event whose decoded payload does not match is skipped and logged rather
295
- * than written as nulls (and the deploy-time field lint is promoted from
296
- * a warning to an error).
297
- */
298
- prints?: Record<string, Record<string, PrintField>>;
285
+ /**
286
+ * Per-topic field schema for a print_event source. When declared, the handler's
287
+ * `event` is a discriminated union keyed by `topic` and `event.data` is typed
288
+ * per topic. Nested tuples, lists, and optional fields — see {@link PrintField}.
289
+ *
290
+ * Also opts the source into RUNTIME validation: a payload that does not match
291
+ * is skipped and logged rather than written as nulls.
292
+ */
293
+ type PrintEventPrints = Record<string, Record<string, PrintField>>;
294
+ /**
295
+ * One column in a static identity map. Literals only — the bundler never
296
+ * executes user code, so `{ from: "tokenX" }` is valid and `from("tokenX")`
297
+ * is not.
298
+ */
299
+ type MaterializeColumn = {
300
+ from: string
301
+ } | {
302
+ fromTx: "sender" | "txId"
303
+ } | {
304
+ fromBlock: "height" | "hash" | "timestamp"
305
+ };
306
+ /** Static insert from a source event — replaces a 1:1 handler. */
307
+ interface MaterializeSpec {
308
+ table: string;
309
+ /** Keys = schema column names (snake). */
310
+ columns: Record<string, MaterializeColumn>;
299
311
  }
312
+ type PrintEventFields = FactoryScope & {
313
+ type: "print_event"
314
+ topic?: string
315
+ /** Identity map: insert without a handler function. XOR with handlers[name]. */
316
+ materialize?: MaterializeSpec
317
+ };
318
+ /**
319
+ * Pinned to one or more contract ids with no trait — `prints` is required so
320
+ * `event.data` is typed and empty-table handlers cannot typecheck.
321
+ */
322
+ type PinnedPrintEventFilter = PrintEventFields & {
323
+ contractId: string | readonly string[]
324
+ trait?: undefined
325
+ prints: PrintEventPrints
326
+ };
327
+ /**
328
+ * Trait-scoped print source (optionally narrowed by contractId). No single
329
+ * schema — `prints` stays optional.
330
+ */
331
+ type TraitPrintEventFilter = PrintEventFields & {
332
+ contractId?: string | readonly string[]
333
+ trait: string
334
+ prints?: PrintEventPrints
335
+ };
336
+ /**
337
+ * Unpinned / factory-only print source (no contractId). `prints` optional.
338
+ */
339
+ type UnpinnedPrintEventFilter = PrintEventFields & {
340
+ contractId?: undefined
341
+ trait?: string
342
+ prints?: PrintEventPrints
343
+ };
344
+ /**
345
+ * Print-event filter. Pinned sources (contractId set, no trait) require
346
+ * `prints`; trait and unpinned sources may omit it.
347
+ */
348
+ type PrintEventFilter = PinnedPrintEventFilter | TraitPrintEventFilter | UnpinnedPrintEventFilter;
300
349
  /** All subgraph filter types — discriminated on `type` */
301
350
  type SubgraphFilter = StxTransferFilter | StxMintFilter | StxBurnFilter | StxLockFilter | FtTransferFilter | FtMintFilter | FtBurnFilter | NftTransferFilter | NftMintFilter | NftBurnFilter | ContractCallFilter | ContractDeployFilter | PrintEventFilter;
302
351
  /** Transaction metadata available in handlers */
@@ -636,6 +685,14 @@ interface TestSubgraphContext<S extends SubgraphSchema> extends Omit<TypedSubgra
636
685
  commit(): Promise<void>;
637
686
  /** Swap the transaction metadata handlers see (`ctx.tx`). */
638
687
  setTx(tx: Partial<TxMeta2>): void;
688
+ /** Insert ops queued since `opsCheckpoint()`, for preview IN/OUT traces. */
689
+ pendingInsertsSince(checkpoint: number): Array<{
690
+ table: string
691
+ keys: string[]
692
+ row: Record<string, unknown>
693
+ }>;
694
+ /** Length of the pending-ops queue (same as runtime `opsCheckpoint`). */
695
+ opsCheckpoint(): number;
639
696
  }
640
697
  /**
641
698
  * Build an in-memory context for a subgraph's schema.
@@ -668,4 +725,118 @@ declare function createTestContext<const S extends SubgraphSchema>(schema: S, op
668
725
  declare function buildEvent<const F extends SubgraphFilter>(source: F, payload: Record<string, unknown>, options?: {
669
726
  tx?: Partial<TxMeta2>
670
727
  }): EventForFilter<F>;
671
- export { createTestContext, buildEventPayload, buildEvent, TxMeta2 as TxMeta, TestSubgraphContext, BlockMeta };
728
+ /**
729
+ * Shared subgraph test run — payload map + in-memory handlers + fail-closed
730
+ * EMPTY_MAPPING. CLI and MCP both call this; cassette/fetch/print stay in the
731
+ * CLI, Index fetch stays in each caller.
732
+ */
733
+ /** Structural Index event row (avoids an SDK dep on this package). */
734
+ interface IndexEventRow {
735
+ event_type: string;
736
+ contract_id?: string | null;
737
+ /** Print events carry `{ topic, value }`; other types vary. */
738
+ payload?: unknown;
739
+ sender?: unknown;
740
+ recipient?: unknown;
741
+ amount?: unknown;
742
+ asset_identifier?: unknown;
743
+ value?: unknown;
744
+ cursor?: string;
745
+ [key: string]: unknown;
746
+ }
747
+ /** Structural Index contract-call row. */
748
+ interface IndexContractCallRow {
749
+ sender: string;
750
+ contract_id?: string | null;
751
+ function_name?: string | null;
752
+ args?: unknown;
753
+ result?: unknown;
754
+ result_hex?: unknown;
755
+ tx_id: string;
756
+ status: string;
757
+ cursor?: string;
758
+ [key: string]: unknown;
759
+ }
760
+ type IndexTestRow = IndexEventRow | IndexContractCallRow;
761
+ interface SubgraphTestSource {
762
+ type: string;
763
+ contractId?: string | string[];
764
+ topic?: string;
765
+ functionName?: string;
766
+ }
767
+ /** Per-event IN/OUT trace for `subgraphs preview`. */
768
+ interface EventTrace {
769
+ source: string;
770
+ blockHeight?: number;
771
+ txId?: string;
772
+ /** Camelized event.data keys (or contract-call field names). */
773
+ inKeys: string[];
774
+ /** Tables written by this event; empty when the mapping wrote nothing. */
775
+ outs: Array<{
776
+ table: string
777
+ keys: string[]
778
+ }>;
779
+ }
780
+ interface SubgraphTestResult {
781
+ ok: boolean;
782
+ code?: "EMPTY_MAPPING" | "NO_EVENTS" | "NO_SOURCES";
783
+ matched: number;
784
+ written: number;
785
+ tables: Array<{
786
+ name: string
787
+ rows: number
788
+ sampleRow?: Record<string, unknown>
789
+ }>;
790
+ firstEvent?: {
791
+ source: string
792
+ data?: unknown
793
+ };
794
+ hint?: string;
795
+ /** Present when `trace: true`. */
796
+ traces?: EventTrace[];
797
+ /** Keys present on every matched IN and never written to any OUT column. */
798
+ unusedInKeys?: string[];
799
+ }
800
+ interface RunSubgraphTestInput {
801
+ schema: SubgraphSchema;
802
+ handlers: Record<string, unknown>;
803
+ sources: Record<string, SubgraphTestSource>;
804
+ events: Record<string, IndexTestRow[]>;
805
+ /** Collect per-event IN/OUT traces (preview). */
806
+ trace?: boolean;
807
+ }
808
+ /** Map an Index event row onto the payload shape a handler expects. */
809
+ declare function toHandlerPayload(_filter: {
810
+ type: string
811
+ } | undefined, row: IndexEventRow): Record<string, unknown>;
812
+ /** Map an Index contract-call row onto the ContractCallEvent handler shape. */
813
+ declare function toContractCallPayload(row: IndexContractCallRow): Record<string, unknown>;
814
+ /**
815
+ * Apply local handlers to Index rows in memory. Fail-closed: matched events
816
+ * with zero written rows is EMPTY_MAPPING (the bns-names field-mapping shape).
817
+ */
818
+ declare function runSubgraphTest(input: RunSubgraphTestInput): Promise<SubgraphTestResult>;
819
+ interface ProbeHandlersDef {
820
+ schema: SubgraphSchema;
821
+ sources: Record<string, {
822
+ type: string
823
+ [key: string]: unknown
824
+ }>;
825
+ handlers: Record<string, unknown>;
826
+ }
827
+ interface ProbeHandlersResult {
828
+ matched: number;
829
+ written: number;
830
+ tables: string[];
831
+ firstEventKeys?: string[];
832
+ }
833
+ /**
834
+ * Run handlers against pre-built sample payloads in memory (no Index, no
835
+ * Postgres). Deploy uses this with print-schema dummy events to refuse
836
+ * EMPTY_MAPPING before DDL apply.
837
+ */
838
+ declare function probeHandlers(def: ProbeHandlersDef, samples: Array<{
839
+ source: string
840
+ event: Record<string, unknown>
841
+ }>): Promise<ProbeHandlersResult>;
842
+ export { toHandlerPayload, toContractCallPayload, runSubgraphTest, probeHandlers, createTestContext, buildEventPayload, buildEvent, TxMeta2 as TxMeta, TestSubgraphContext, SubgraphTestSource, SubgraphTestResult, RunSubgraphTestInput, ProbeHandlersResult, ProbeHandlersDef, IndexTestRow, IndexEventRow, IndexContractCallRow, EventTrace, BlockMeta };