@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
@@ -272,6 +272,23 @@ interface ContractDeployFilter {
272
272
  deployer?: string;
273
273
  contractName?: string;
274
274
  }
275
+ interface NestedContractCallFilter extends TraitScope, FactoryScope {
276
+ type: "nested_contract_call";
277
+ contractId?: string | readonly string[];
278
+ functionName?: string;
279
+ caller?: string;
280
+ sender?: string;
281
+ }
282
+ interface VarSetFilter extends TraitScope, FactoryScope {
283
+ type: "var_set";
284
+ contractId?: string | readonly string[];
285
+ varName?: string;
286
+ }
287
+ interface MapWriteFilter extends TraitScope, FactoryScope {
288
+ type: "map_set" | "map_insert" | "map_delete";
289
+ contractId?: string | readonly string[];
290
+ map?: string;
291
+ }
275
292
  /**
276
293
  * One declared field of a print payload.
277
294
  *
@@ -359,7 +376,7 @@ type UnpinnedPrintEventFilter = PrintEventFields & {
359
376
  */
360
377
  type PrintEventFilter = PinnedPrintEventFilter | TraitPrintEventFilter | UnpinnedPrintEventFilter;
361
378
  /** All subgraph filter types — discriminated on `type` */
362
- type SubgraphFilter = StxTransferFilter | StxMintFilter | StxBurnFilter | StxLockFilter | FtTransferFilter | FtMintFilter | FtBurnFilter | NftTransferFilter | NftMintFilter | NftBurnFilter | ContractCallFilter | ContractDeployFilter | PrintEventFilter;
379
+ type SubgraphFilter = StxTransferFilter | StxMintFilter | StxBurnFilter | StxLockFilter | FtTransferFilter | FtMintFilter | FtBurnFilter | NftTransferFilter | NftMintFilter | NftBurnFilter | ContractCallFilter | ContractDeployFilter | PrintEventFilter | NestedContractCallFilter | VarSetFilter | MapWriteFilter;
363
380
  /** Transaction metadata available in handlers */
364
381
  interface TxMeta {
365
382
  txId: string;
@@ -469,8 +486,11 @@ type EventRecord = {
469
486
  id: string
470
487
  tx_id: string
471
488
  type: string
489
+ /** Classic `event_index`, or `ordinal` when `clock === "vm"`. */
472
490
  event_index: number
473
491
  data: unknown
492
+ /** Set on opt-in `vm_events` rows. Two clocks never sort or dedupe together. */
493
+ clock?: "vm"
474
494
  };
475
495
  import { Database as Database2 } from "@secondlayer/shared/db";
476
496
  import { Kysely as Kysely2, Transaction } from "kysely";
@@ -82,7 +82,7 @@ function printContractId(data) {
82
82
  const id = (typeof data.contract_identifier === "string" ? data.contract_identifier : undefined) ?? (typeof data.contract_id === "string" ? data.contract_id : undefined);
83
83
  return id || undefined;
84
84
  }
85
- function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts = new Map) {
85
+ function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts = new Map, vmEventsByTx = new Map) {
86
86
  const results = [];
87
87
  switch (filter.type) {
88
88
  case "stx_transfer":
@@ -247,6 +247,57 @@ function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryCo
247
247
  }
248
248
  break;
249
249
  }
250
+ case "nested_contract_call":
251
+ case "var_set":
252
+ case "map_set":
253
+ case "map_insert":
254
+ case "map_delete": {
255
+ for (const tx of transactions) {
256
+ const txEvents = vmEventsByTx.get(tx.tx_id) ?? [];
257
+ const matched = txEvents.filter((e) => {
258
+ if (e.type !== filter.type)
259
+ return false;
260
+ const data = e.data;
261
+ if (!data)
262
+ return false;
263
+ const contractId = printContractId(data);
264
+ if ("contractId" in filter && filter.contractId) {
265
+ if (!contractId || !matchAny(contractId, filter.contractId))
266
+ return false;
267
+ }
268
+ if (!traitAllows(filter, contractId, traitContracts))
269
+ return false;
270
+ if (!factoryAllows(filter, contractId, factoryContracts))
271
+ return false;
272
+ if (filter.type === "nested_contract_call") {
273
+ if (filter.functionName) {
274
+ if (typeof data.function_name !== "string" || !matchPattern(data.function_name, filter.functionName))
275
+ return false;
276
+ }
277
+ if (filter.caller) {
278
+ if (typeof data.caller !== "string" || !matchPattern(data.caller, filter.caller))
279
+ return false;
280
+ }
281
+ if (filter.sender) {
282
+ if (typeof data.sender !== "string" || !matchPattern(data.sender, filter.sender))
283
+ return false;
284
+ }
285
+ }
286
+ if (filter.type === "var_set" && filter.varName) {
287
+ if (typeof data.var_name !== "string" || !matchPattern(data.var_name, filter.varName))
288
+ return false;
289
+ }
290
+ if ((filter.type === "map_set" || filter.type === "map_insert" || filter.type === "map_delete") && filter.map) {
291
+ if (typeof data.map_name !== "string" || !matchPattern(data.map_name, filter.map))
292
+ return false;
293
+ }
294
+ return true;
295
+ });
296
+ if (matched.length > 0)
297
+ results.push({ tx, events: matched });
298
+ }
299
+ break;
300
+ }
250
301
  case "print_event": {
251
302
  for (const tx of transactions) {
252
303
  const txEvents = eventsByTx.get(tx.tx_id) ?? [];
@@ -278,17 +329,23 @@ function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryCo
278
329
  }
279
330
  return results;
280
331
  }
281
- function matchSources(sources, transactions, events, traitContracts = new Map, factoryContracts = new Map) {
332
+ function matchSources(sources, transactions, events, traitContracts = new Map, factoryContracts = new Map, vmEvents = []) {
282
333
  const eventsByTx = new Map;
283
334
  for (const event of events) {
284
335
  const list = eventsByTx.get(event.tx_id) ?? [];
285
336
  list.push(event);
286
337
  eventsByTx.set(event.tx_id, list);
287
338
  }
339
+ const vmEventsByTx = new Map;
340
+ for (const event of vmEvents) {
341
+ const list = vmEventsByTx.get(event.tx_id) ?? [];
342
+ list.push(event);
343
+ vmEventsByTx.set(event.tx_id, list);
344
+ }
288
345
  const seen = new Set;
289
346
  const results = [];
290
347
  for (const [sourceName, filter] of Object.entries(sources)) {
291
- const matches = matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts);
348
+ const matches = matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts, vmEventsByTx);
292
349
  for (const match of matches) {
293
350
  const dedupeKey = `${match.tx.tx_id}:${sourceName}`;
294
351
  if (!seen.has(dedupeKey)) {
@@ -863,6 +920,12 @@ function decodeRawResult(raw) {
863
920
  }
864
921
  return null;
865
922
  }
923
+ function decodeRawHex(hex) {
924
+ if (hex.startsWith("0x") && hex.length > 2) {
925
+ return decodeClarityValue(hex);
926
+ }
927
+ return hex;
928
+ }
866
929
  function safeBigInt(val) {
867
930
  if (typeof val === "bigint")
868
931
  return val;
@@ -1056,6 +1119,58 @@ function buildEventPayload(filter, tx, event) {
1056
1119
  deployer: tx.sender,
1057
1120
  tx: txMeta
1058
1121
  };
1122
+ case "nested_contract_call": {
1123
+ const data = event.data ?? {};
1124
+ const argsHex = Array.isArray(data.function_args) ? data.function_args.filter((a) => typeof a === "string") : [];
1125
+ return {
1126
+ contractId: printContractId(data) ?? "",
1127
+ sender: typeof data.sender === "string" ? data.sender : null,
1128
+ caller: typeof data.caller === "string" ? data.caller : "",
1129
+ functionName: typeof data.function_name === "string" ? data.function_name : "",
1130
+ args: decodeFunctionArgs2(argsHex),
1131
+ arguments: argsHex,
1132
+ rawResult: typeof data.raw_result === "string" ? data.raw_result : "",
1133
+ result: decodeRawResult(data.raw_result),
1134
+ tx: txMeta
1135
+ };
1136
+ }
1137
+ case "var_set": {
1138
+ const data = event.data ?? {};
1139
+ const rawValue = typeof data.raw_value === "string" ? data.raw_value : "";
1140
+ return {
1141
+ contractId: printContractId(data) ?? "",
1142
+ varName: typeof data.var_name === "string" ? data.var_name : "",
1143
+ rawValue,
1144
+ value: decodeRawHex(rawValue),
1145
+ tx: txMeta
1146
+ };
1147
+ }
1148
+ case "map_set":
1149
+ case "map_insert": {
1150
+ const data = event.data ?? {};
1151
+ const rawKey = typeof data.raw_key === "string" ? data.raw_key : "";
1152
+ const rawValue = typeof data.raw_value === "string" ? data.raw_value : "";
1153
+ return {
1154
+ contractId: printContractId(data) ?? "",
1155
+ map: typeof data.map_name === "string" ? data.map_name : "",
1156
+ rawKey,
1157
+ key: decodeRawHex(rawKey),
1158
+ rawValue,
1159
+ value: decodeRawHex(rawValue),
1160
+ tx: txMeta
1161
+ };
1162
+ }
1163
+ case "map_delete": {
1164
+ const data = event.data ?? {};
1165
+ const rawKey = typeof data.raw_key === "string" ? data.raw_key : "";
1166
+ return {
1167
+ contractId: printContractId(data) ?? "",
1168
+ map: typeof data.map_name === "string" ? data.map_name : "",
1169
+ rawKey,
1170
+ key: decodeRawHex(rawKey),
1171
+ tx: txMeta
1172
+ };
1173
+ }
1059
1174
  default:
1060
1175
  return {
1061
1176
  ...decoded,
@@ -1084,7 +1199,8 @@ async function runHandlers(subgraph, matched, ctx, opts) {
1084
1199
  units.push({ tx, sourceName, event });
1085
1200
  }
1086
1201
  }
1087
- units.sort((a, b) => (a.tx.tx_index ?? 0) - (b.tx.tx_index ?? 0) || (a.event?.event_index ?? -1) - (b.event?.event_index ?? -1));
1202
+ const clockRank = (e) => e?.clock === "vm" ? 1 : 0;
1203
+ 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));
1088
1204
  for (const { tx, event, sourceName } of units) {
1089
1205
  if (errors >= threshold) {
1090
1206
  logger2.error("Subgraph error threshold reached, skipping remaining events", {
@@ -1212,5 +1328,5 @@ export {
1212
1328
  buildContractCallInput
1213
1329
  };
1214
1330
 
1215
- //# debugId=B6BA5F58B8903CEC64756E2164756E21
1331
+ //# debugId=90E8BB694CDBE41B64756E2164756E21
1216
1332
  //# sourceMappingURL=runner.js.map