@secondlayer/subgraphs 4.3.5 → 4.4.0

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 (40) hide show
  1. package/dist/src/index.d.ts +63 -4
  2. package/dist/src/index.js +278 -22
  3. package/dist/src/index.js.map +12 -12
  4. package/dist/src/runtime/block-processor.d.ts +24 -2
  5. package/dist/src/runtime/block-processor.js +233 -19
  6. package/dist/src/runtime/block-processor.js.map +9 -9
  7. package/dist/src/runtime/catchup.d.ts +18 -1
  8. package/dist/src/runtime/catchup.js +234 -20
  9. package/dist/src/runtime/catchup.js.map +10 -10
  10. package/dist/src/runtime/processor.js +235 -21
  11. package/dist/src/runtime/processor.js.map +11 -11
  12. package/dist/src/runtime/reindex.d.ts +28 -1
  13. package/dist/src/runtime/reindex.js +235 -21
  14. package/dist/src/runtime/reindex.js.map +11 -11
  15. package/dist/src/runtime/reorg.d.ts +18 -1
  16. package/dist/src/runtime/reorg.js +234 -20
  17. package/dist/src/runtime/reorg.js.map +10 -10
  18. package/dist/src/runtime/replay.d.ts +10 -0
  19. package/dist/src/runtime/replay.js +184 -20
  20. package/dist/src/runtime/replay.js.map +9 -9
  21. package/dist/src/runtime/runner.d.ts +21 -1
  22. package/dist/src/runtime/runner.js +121 -5
  23. package/dist/src/runtime/runner.js.map +4 -4
  24. package/dist/src/runtime/source-matcher.d.ts +22 -2
  25. package/dist/src/runtime/source-matcher.js +61 -4
  26. package/dist/src/runtime/source-matcher.js.map +3 -3
  27. package/dist/src/schema/index.d.ts +18 -1
  28. package/dist/src/schema/index.js +44 -2
  29. package/dist/src/schema/index.js.map +3 -3
  30. package/dist/src/service.js +235 -21
  31. package/dist/src/service.js.map +11 -11
  32. package/dist/src/testing/index.d.ts +64 -2
  33. package/dist/src/testing/index.js +157 -5
  34. package/dist/src/testing/index.js.map +5 -5
  35. package/dist/src/triggers/index.d.ts +18 -1
  36. package/dist/src/types.d.ts +19 -2
  37. package/dist/src/validate.d.ts +19 -2
  38. package/dist/src/validate.js +44 -2
  39. package/dist/src/validate.js.map +3 -3
  40. package/package.json +3 -3
@@ -260,6 +260,23 @@ interface ContractDeployFilter {
260
260
  deployer?: string;
261
261
  contractName?: string;
262
262
  }
263
+ interface NestedContractCallFilter extends TraitScope, FactoryScope {
264
+ type: "nested_contract_call";
265
+ contractId?: string | readonly string[];
266
+ functionName?: string;
267
+ caller?: string;
268
+ sender?: string;
269
+ }
270
+ interface VarSetFilter extends TraitScope, FactoryScope {
271
+ type: "var_set";
272
+ contractId?: string | readonly string[];
273
+ varName?: string;
274
+ }
275
+ interface MapWriteFilter extends TraitScope, FactoryScope {
276
+ type: "map_set" | "map_insert" | "map_delete";
277
+ contractId?: string | readonly string[];
278
+ map?: string;
279
+ }
263
280
  /**
264
281
  * One declared field of a print payload.
265
282
  *
@@ -347,7 +364,7 @@ type UnpinnedPrintEventFilter = PrintEventFields & {
347
364
  */
348
365
  type PrintEventFilter = PinnedPrintEventFilter | TraitPrintEventFilter | UnpinnedPrintEventFilter;
349
366
  /** All subgraph filter types — discriminated on `type` */
350
- type SubgraphFilter = StxTransferFilter | StxMintFilter | StxBurnFilter | StxLockFilter | FtTransferFilter | FtMintFilter | FtBurnFilter | NftTransferFilter | NftMintFilter | NftBurnFilter | ContractCallFilter | ContractDeployFilter | PrintEventFilter;
367
+ type SubgraphFilter = StxTransferFilter | StxMintFilter | StxBurnFilter | StxLockFilter | FtTransferFilter | FtMintFilter | FtBurnFilter | NftTransferFilter | NftMintFilter | NftBurnFilter | ContractCallFilter | ContractDeployFilter | PrintEventFilter | NestedContractCallFilter | VarSetFilter | MapWriteFilter;
351
368
  /** Transaction metadata available in handlers */
352
369
  interface TxMeta {
353
370
  txId: string;
@@ -383,8 +400,11 @@ type EventRecord = {
383
400
  id: string
384
401
  tx_id: string
385
402
  type: string
403
+ /** Classic `event_index`, or `ordinal` when `clock === "vm"`. */
386
404
  event_index: number
387
405
  data: unknown
406
+ /** Set on opt-in `vm_events` rows. Two clocks never sort or dedupe together. */
407
+ clock?: "vm"
388
408
  };
389
409
  interface BlockMeta {
390
410
  height: number;
@@ -610,6 +630,42 @@ type ContractCallPayload<F> = F extends {
610
630
  } ? N extends ExtractFunctionNames<A> ? ContractCallEvent & {
611
631
  input: ExtractFunctionArgs2<A, N>
612
632
  } : ContractCallEvent : ContractCallEvent;
633
+ interface NestedContractCallPayload {
634
+ contractId: string;
635
+ sender: string | null;
636
+ caller: string;
637
+ functionName: string;
638
+ /** Decoded `function_args`. */
639
+ args: unknown[];
640
+ /** Original hex `function_args`, preserved. */
641
+ arguments: string[];
642
+ rawResult: string;
643
+ result: unknown;
644
+ tx: TxMeta;
645
+ }
646
+ interface VarSetPayload {
647
+ contractId: string;
648
+ varName: string;
649
+ rawValue: string;
650
+ value: unknown;
651
+ tx: TxMeta;
652
+ }
653
+ interface MapWritePayload {
654
+ contractId: string;
655
+ map: string;
656
+ rawKey: string;
657
+ key: unknown;
658
+ rawValue: string;
659
+ value: unknown;
660
+ tx: TxMeta;
661
+ }
662
+ interface MapDeletePayload {
663
+ contractId: string;
664
+ map: string;
665
+ rawKey: string;
666
+ key: unknown;
667
+ tx: TxMeta;
668
+ }
613
669
  /**
614
670
  * Print event typed per topic. When a `print_event` source declares a `prints`
615
671
  * map, the payload is a discriminated union keyed by `topic` with `data` typed
@@ -671,7 +727,13 @@ type EventForFilter<F extends SubgraphFilter> = F extends {
671
727
  type: "contract_call"
672
728
  } ? ContractCallPayload<F> : F extends {
673
729
  type: "contract_deploy"
674
- } ? ContractDeployPayload : never;
730
+ } ? ContractDeployPayload : F extends {
731
+ type: "nested_contract_call"
732
+ } ? NestedContractCallPayload : F extends {
733
+ type: "var_set"
734
+ } ? VarSetPayload : F extends {
735
+ type: infer T extends "map_set" | "map_insert" | "map_delete"
736
+ } ? T extends "map_delete" ? MapDeletePayload : MapWritePayload : never;
675
737
  /** An in-memory subgraph context for tests. */
676
738
  interface TestSubgraphContext<S extends SubgraphSchema> extends Omit<TypedSubgraphContext<S>, never> {
677
739
  /**
@@ -1009,7 +1009,7 @@ function printContractId(data) {
1009
1009
  const id = (typeof data.contract_identifier === "string" ? data.contract_identifier : undefined) ?? (typeof data.contract_id === "string" ? data.contract_id : undefined);
1010
1010
  return id || undefined;
1011
1011
  }
1012
- function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts = new Map) {
1012
+ function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts = new Map, vmEventsByTx = new Map) {
1013
1013
  const results = [];
1014
1014
  switch (filter.type) {
1015
1015
  case "stx_transfer":
@@ -1174,6 +1174,57 @@ function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryCo
1174
1174
  }
1175
1175
  break;
1176
1176
  }
1177
+ case "nested_contract_call":
1178
+ case "var_set":
1179
+ case "map_set":
1180
+ case "map_insert":
1181
+ case "map_delete": {
1182
+ for (const tx of transactions) {
1183
+ const txEvents = vmEventsByTx.get(tx.tx_id) ?? [];
1184
+ const matched = txEvents.filter((e) => {
1185
+ if (e.type !== filter.type)
1186
+ return false;
1187
+ const data = e.data;
1188
+ if (!data)
1189
+ return false;
1190
+ const contractId = printContractId(data);
1191
+ if ("contractId" in filter && filter.contractId) {
1192
+ if (!contractId || !matchAny(contractId, filter.contractId))
1193
+ return false;
1194
+ }
1195
+ if (!traitAllows(filter, contractId, traitContracts))
1196
+ return false;
1197
+ if (!factoryAllows(filter, contractId, factoryContracts))
1198
+ return false;
1199
+ if (filter.type === "nested_contract_call") {
1200
+ if (filter.functionName) {
1201
+ if (typeof data.function_name !== "string" || !matchPattern(data.function_name, filter.functionName))
1202
+ return false;
1203
+ }
1204
+ if (filter.caller) {
1205
+ if (typeof data.caller !== "string" || !matchPattern(data.caller, filter.caller))
1206
+ return false;
1207
+ }
1208
+ if (filter.sender) {
1209
+ if (typeof data.sender !== "string" || !matchPattern(data.sender, filter.sender))
1210
+ return false;
1211
+ }
1212
+ }
1213
+ if (filter.type === "var_set" && filter.varName) {
1214
+ if (typeof data.var_name !== "string" || !matchPattern(data.var_name, filter.varName))
1215
+ return false;
1216
+ }
1217
+ if ((filter.type === "map_set" || filter.type === "map_insert" || filter.type === "map_delete") && filter.map) {
1218
+ if (typeof data.map_name !== "string" || !matchPattern(data.map_name, filter.map))
1219
+ return false;
1220
+ }
1221
+ return true;
1222
+ });
1223
+ if (matched.length > 0)
1224
+ results.push({ tx, events: matched });
1225
+ }
1226
+ break;
1227
+ }
1177
1228
  case "print_event": {
1178
1229
  for (const tx of transactions) {
1179
1230
  const txEvents = eventsByTx.get(tx.tx_id) ?? [];
@@ -1205,17 +1256,23 @@ function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryCo
1205
1256
  }
1206
1257
  return results;
1207
1258
  }
1208
- function matchSources(sources, transactions, events, traitContracts = new Map, factoryContracts = new Map) {
1259
+ function matchSources(sources, transactions, events, traitContracts = new Map, factoryContracts = new Map, vmEvents = []) {
1209
1260
  const eventsByTx = new Map;
1210
1261
  for (const event of events) {
1211
1262
  const list = eventsByTx.get(event.tx_id) ?? [];
1212
1263
  list.push(event);
1213
1264
  eventsByTx.set(event.tx_id, list);
1214
1265
  }
1266
+ const vmEventsByTx = new Map;
1267
+ for (const event of vmEvents) {
1268
+ const list = vmEventsByTx.get(event.tx_id) ?? [];
1269
+ list.push(event);
1270
+ vmEventsByTx.set(event.tx_id, list);
1271
+ }
1215
1272
  const seen = new Set;
1216
1273
  const results = [];
1217
1274
  for (const [sourceName, filter] of Object.entries(sources)) {
1218
- const matches = matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts);
1275
+ const matches = matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts, vmEventsByTx);
1219
1276
  for (const match of matches) {
1220
1277
  const dedupeKey = `${match.tx.tx_id}:${sourceName}`;
1221
1278
  if (!seen.has(dedupeKey)) {
@@ -1790,6 +1847,12 @@ function decodeRawResult(raw) {
1790
1847
  }
1791
1848
  return null;
1792
1849
  }
1850
+ function decodeRawHex(hex) {
1851
+ if (hex.startsWith("0x") && hex.length > 2) {
1852
+ return decodeClarityValue(hex);
1853
+ }
1854
+ return hex;
1855
+ }
1793
1856
  function safeBigInt(val) {
1794
1857
  if (typeof val === "bigint")
1795
1858
  return val;
@@ -1983,6 +2046,58 @@ function buildEventPayload(filter, tx, event) {
1983
2046
  deployer: tx.sender,
1984
2047
  tx: txMeta
1985
2048
  };
2049
+ case "nested_contract_call": {
2050
+ const data = event.data ?? {};
2051
+ const argsHex = Array.isArray(data.function_args) ? data.function_args.filter((a) => typeof a === "string") : [];
2052
+ return {
2053
+ contractId: printContractId(data) ?? "",
2054
+ sender: typeof data.sender === "string" ? data.sender : null,
2055
+ caller: typeof data.caller === "string" ? data.caller : "",
2056
+ functionName: typeof data.function_name === "string" ? data.function_name : "",
2057
+ args: decodeFunctionArgs2(argsHex),
2058
+ arguments: argsHex,
2059
+ rawResult: typeof data.raw_result === "string" ? data.raw_result : "",
2060
+ result: decodeRawResult(data.raw_result),
2061
+ tx: txMeta
2062
+ };
2063
+ }
2064
+ case "var_set": {
2065
+ const data = event.data ?? {};
2066
+ const rawValue = typeof data.raw_value === "string" ? data.raw_value : "";
2067
+ return {
2068
+ contractId: printContractId(data) ?? "",
2069
+ varName: typeof data.var_name === "string" ? data.var_name : "",
2070
+ rawValue,
2071
+ value: decodeRawHex(rawValue),
2072
+ tx: txMeta
2073
+ };
2074
+ }
2075
+ case "map_set":
2076
+ case "map_insert": {
2077
+ const data = event.data ?? {};
2078
+ const rawKey = typeof data.raw_key === "string" ? data.raw_key : "";
2079
+ const rawValue = typeof data.raw_value === "string" ? data.raw_value : "";
2080
+ return {
2081
+ contractId: printContractId(data) ?? "",
2082
+ map: typeof data.map_name === "string" ? data.map_name : "",
2083
+ rawKey,
2084
+ key: decodeRawHex(rawKey),
2085
+ rawValue,
2086
+ value: decodeRawHex(rawValue),
2087
+ tx: txMeta
2088
+ };
2089
+ }
2090
+ case "map_delete": {
2091
+ const data = event.data ?? {};
2092
+ const rawKey = typeof data.raw_key === "string" ? data.raw_key : "";
2093
+ return {
2094
+ contractId: printContractId(data) ?? "",
2095
+ map: typeof data.map_name === "string" ? data.map_name : "",
2096
+ rawKey,
2097
+ key: decodeRawHex(rawKey),
2098
+ tx: txMeta
2099
+ };
2100
+ }
1986
2101
  default:
1987
2102
  return {
1988
2103
  ...decoded,
@@ -2011,7 +2126,8 @@ async function runHandlers(subgraph, matched, ctx, opts) {
2011
2126
  units.push({ tx, sourceName, event });
2012
2127
  }
2013
2128
  }
2014
- units.sort((a, b) => (a.tx.tx_index ?? 0) - (b.tx.tx_index ?? 0) || (a.event?.event_index ?? -1) - (b.event?.event_index ?? -1));
2129
+ const clockRank = (e) => e?.clock === "vm" ? 1 : 0;
2130
+ units.sort((a, b) => (a.tx.tx_index ?? 0) - (b.tx.tx_index ?? 0) || clockRank(a.event) - clockRank(b.event) || (a.event?.event_index ?? -1) - (b.event?.event_index ?? -1));
2015
2131
  for (const { tx, event, sourceName } of units) {
2016
2132
  if (errors >= threshold) {
2017
2133
  logger4.error("Subgraph error threshold reached, skipping remaining events", {
@@ -2277,6 +2393,42 @@ function toHandlerPayload(_filter, row) {
2277
2393
  };
2278
2394
  }
2279
2395
  const r = row;
2396
+ if (row.event_type === "var_set") {
2397
+ const rawValue = typeof r.raw_value === "string" ? r.raw_value : "";
2398
+ return {
2399
+ contractId: row.contract_id ?? "",
2400
+ varName: typeof r.var_name === "string" ? r.var_name : "",
2401
+ rawValue,
2402
+ value: rawValue,
2403
+ tx
2404
+ };
2405
+ }
2406
+ if (row.event_type === "nested_contract_call") {
2407
+ const argsHex = Array.isArray(r.function_args) ? r.function_args.filter((a) => typeof a === "string") : [];
2408
+ return {
2409
+ contractId: row.contract_id ?? "",
2410
+ sender: typeof r.sender === "string" ? r.sender : null,
2411
+ caller: typeof r.caller === "string" ? r.caller : "",
2412
+ functionName: typeof r.function_name === "string" ? r.function_name : "",
2413
+ args: argsHex,
2414
+ arguments: argsHex,
2415
+ rawResult: typeof r.raw_result === "string" ? r.raw_result : "",
2416
+ result: null,
2417
+ tx
2418
+ };
2419
+ }
2420
+ if (row.event_type === "map_set" || row.event_type === "map_insert" || row.event_type === "map_delete") {
2421
+ const rawKey = typeof r.raw_key === "string" ? r.raw_key : "";
2422
+ const rawValue = typeof r.raw_value === "string" ? r.raw_value : "";
2423
+ return {
2424
+ contractId: row.contract_id ?? "",
2425
+ map: typeof r.map === "string" ? r.map : "",
2426
+ rawKey,
2427
+ key: rawKey,
2428
+ ...row.event_type === "map_delete" ? {} : { rawValue, value: rawValue },
2429
+ tx
2430
+ };
2431
+ }
2280
2432
  return {
2281
2433
  ...r.sender !== undefined ? { sender: r.sender } : {},
2282
2434
  ...r.recipient !== undefined ? { recipient: r.recipient } : {},
@@ -2547,5 +2699,5 @@ export {
2547
2699
  buildEvent
2548
2700
  };
2549
2701
 
2550
- //# debugId=FD3EB07B0C64AE9F64756E2164756E21
2702
+ //# debugId=BBBAFF796E747D6364756E2164756E21
2551
2703
  //# sourceMappingURL=index.js.map