@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
@@ -331,6 +331,23 @@ interface ContractDeployFilter {
331
331
  deployer?: string;
332
332
  contractName?: string;
333
333
  }
334
+ interface NestedContractCallFilter extends TraitScope, FactoryScope {
335
+ type: "nested_contract_call";
336
+ contractId?: string | readonly string[];
337
+ functionName?: string;
338
+ caller?: string;
339
+ sender?: string;
340
+ }
341
+ interface VarSetFilter extends TraitScope, FactoryScope {
342
+ type: "var_set";
343
+ contractId?: string | readonly string[];
344
+ varName?: string;
345
+ }
346
+ interface MapWriteFilter extends TraitScope, FactoryScope {
347
+ type: "map_set" | "map_insert" | "map_delete";
348
+ contractId?: string | readonly string[];
349
+ map?: string;
350
+ }
334
351
  /**
335
352
  * One declared field of a print payload.
336
353
  *
@@ -418,7 +435,7 @@ type UnpinnedPrintEventFilter = PrintEventFields & {
418
435
  */
419
436
  type PrintEventFilter = PinnedPrintEventFilter | TraitPrintEventFilter | UnpinnedPrintEventFilter;
420
437
  /** All subgraph filter types — discriminated on `type` */
421
- type SubgraphFilter = StxTransferFilter | StxMintFilter | StxBurnFilter | StxLockFilter | FtTransferFilter | FtMintFilter | FtBurnFilter | NftTransferFilter | NftMintFilter | NftBurnFilter | ContractCallFilter | ContractDeployFilter | PrintEventFilter;
438
+ type SubgraphFilter = StxTransferFilter | StxMintFilter | StxBurnFilter | StxLockFilter | FtTransferFilter | FtMintFilter | FtBurnFilter | NftTransferFilter | NftMintFilter | NftBurnFilter | ContractCallFilter | ContractDeployFilter | PrintEventFilter | NestedContractCallFilter | VarSetFilter | MapWriteFilter;
422
439
  /** Transaction metadata available in handlers */
423
440
  interface TxMeta {
424
441
  txId: string;
@@ -894,6 +911,42 @@ type ContractCallPayload<F> = F extends {
894
911
  } ? N extends ExtractFunctionNames<A> ? ContractCallEvent & {
895
912
  input: ExtractFunctionArgs2<A, N>
896
913
  } : ContractCallEvent : ContractCallEvent;
914
+ interface NestedContractCallPayload {
915
+ contractId: string;
916
+ sender: string | null;
917
+ caller: string;
918
+ functionName: string;
919
+ /** Decoded `function_args`. */
920
+ args: unknown[];
921
+ /** Original hex `function_args`, preserved. */
922
+ arguments: string[];
923
+ rawResult: string;
924
+ result: unknown;
925
+ tx: TxMeta;
926
+ }
927
+ interface VarSetPayload {
928
+ contractId: string;
929
+ varName: string;
930
+ rawValue: string;
931
+ value: unknown;
932
+ tx: TxMeta;
933
+ }
934
+ interface MapWritePayload {
935
+ contractId: string;
936
+ map: string;
937
+ rawKey: string;
938
+ key: unknown;
939
+ rawValue: string;
940
+ value: unknown;
941
+ tx: TxMeta;
942
+ }
943
+ interface MapDeletePayload {
944
+ contractId: string;
945
+ map: string;
946
+ rawKey: string;
947
+ key: unknown;
948
+ tx: TxMeta;
949
+ }
897
950
  /**
898
951
  * Print event typed per topic. When a `print_event` source declares a `prints`
899
952
  * map, the payload is a discriminated union keyed by `topic` with `data` typed
@@ -955,9 +1008,15 @@ type EventForFilter<F extends SubgraphFilter> = F extends {
955
1008
  type: "contract_call"
956
1009
  } ? ContractCallPayload<F> : F extends {
957
1010
  type: "contract_deploy"
958
- } ? ContractDeployPayload : never;
1011
+ } ? ContractDeployPayload : F extends {
1012
+ type: "nested_contract_call"
1013
+ } ? NestedContractCallPayload : F extends {
1014
+ type: "var_set"
1015
+ } ? VarSetPayload : F extends {
1016
+ type: infer T extends "map_set" | "map_insert" | "map_delete"
1017
+ } ? T extends "map_delete" ? MapDeletePayload : MapWritePayload : never;
959
1018
  /** Union of every event payload — the `"*"` catch-all handler receives this. */
960
- type AnyEvent = FtTransferPayload | FtMintPayload | FtBurnPayload | NftTransferPayload | NftMintPayload | NftBurnPayload | StxTransferPayload | StxMintPayload | StxBurnPayload | StxLockPayload | PrintEventPayload | ContractCallEvent | ContractDeployPayload;
1019
+ type AnyEvent = FtTransferPayload | FtMintPayload | FtBurnPayload | NftTransferPayload | NftMintPayload | NftBurnPayload | StxTransferPayload | StxMintPayload | StxBurnPayload | StxLockPayload | PrintEventPayload | ContractCallEvent | ContractDeployPayload | NestedContractCallPayload | VarSetPayload | MapWritePayload | MapDeletePayload;
961
1020
  type HandlerFn<
962
1021
  F extends SubgraphFilter,
963
1022
  S extends SubgraphSchema
@@ -1268,4 +1327,4 @@ declare function deploySchema(db: AnyDb, def: SubgraphDefinition, handlerPath: s
1268
1327
  /** Non-fatal caveats the caller should surface (e.g. handler grafts at tip). */
1269
1328
  warnings?: string[]
1270
1329
  }>;
1271
- export { validateSubgraphDefinition, validatePrintPayload, sparseProbeTargets, resumeReindex, renderDeployPlan, reindexSubgraph, readContractAt, pgSchemaName, inferPrintTopics, hasBreakingChanges, generateSubgraphSQL, generatePrismaSchema, generateKyselySchema, generateIndexSchema, generateDrizzleSchema, filterFieldsByType, diffSchema, deploySchema, defineSubgraph, defineSchema, canSparseScan, camelizeKeys, camelizeDataKey, backfillSubgraph, WriteRow, WhereInput, UnpinnedPrintEventFilter, TypedSubgraphDefinition, TypedSubgraphContext, TypedHandlers, TxMeta, TraitPrintEventFilter, TableDiff, SystemRow, SubscribeOptions, SubgraphTableClient, SubgraphTable, SubgraphSchema, SubgraphHandler, SubgraphFilter, SubgraphDefinition, SubgraphContext, SubgraphColumn, StxTransferPayload, StxTransferFilter, StxMintPayload, StxMintFilter, StxLockPayload, StxLockFilter, StxBurnPayload, StxBurnFilter, SparseProbeTarget, RowValue, ReindexOptions, PrismaGenOptions, PrintValidationResult, PrintSample, PrintFieldToTS, PrintField, PrintEventPrints, PrintEventPayload, PrintEventFor, PrintEventFilter, PrintDataOf, PinnedPrintEventFilter, NftTransferPayload, NftTransferFilter, NftMintPayload, NftMintFilter, NftBurnPayload, NftBurnFilter, MaterializeSpec, MaterializeColumn, KyselyGenOptions, InferredTopicSchema, InferredPrintField, InferTableRow, InferSubgraphClient, InferContext, InferColumnType, IndexCodegenTarget, IndexCodegenOptions, INDEX_CODEGEN_TABLES, GeneratedSQL, FtTransferPayload, FtTransferFilter, FtMintPayload, FtMintFilter, FtBurnPayload, FtBurnFilter, FindManyOptions, FactoryScope, EventForFilter, ErasedChainReadClient, DrizzleGenOptions, DeployPlan, DeployDiff, ContractDeployPayload, ContractDeployFilter, ContractCallPayload, ContractCallFilter, ContractCallEvent, ComputedValue, ComparisonFilter, ColumnType, ColumnToTS, ColumnDiff, ChainReadOptions, ChainReadMethods, ChainReadError, ChainReadClient, ChainReadCacheMode, AnyEvent, AggregateSpec, AggregateResult };
1330
+ export { validateSubgraphDefinition, validatePrintPayload, sparseProbeTargets, resumeReindex, renderDeployPlan, reindexSubgraph, readContractAt, pgSchemaName, inferPrintTopics, hasBreakingChanges, generateSubgraphSQL, generatePrismaSchema, generateKyselySchema, generateIndexSchema, generateDrizzleSchema, filterFieldsByType, diffSchema, deploySchema, defineSubgraph, defineSchema, canSparseScan, camelizeKeys, camelizeDataKey, backfillSubgraph, WriteRow, WhereInput, VarSetPayload, UnpinnedPrintEventFilter, TypedSubgraphDefinition, TypedSubgraphContext, TypedHandlers, TxMeta, TraitPrintEventFilter, TableDiff, SystemRow, SubscribeOptions, SubgraphTableClient, SubgraphTable, SubgraphSchema, SubgraphHandler, SubgraphFilter, SubgraphDefinition, SubgraphContext, SubgraphColumn, StxTransferPayload, StxTransferFilter, StxMintPayload, StxMintFilter, StxLockPayload, StxLockFilter, StxBurnPayload, StxBurnFilter, SparseProbeTarget, RowValue, ReindexOptions, PrismaGenOptions, PrintValidationResult, PrintSample, PrintFieldToTS, PrintField, PrintEventPrints, PrintEventPayload, PrintEventFor, PrintEventFilter, PrintDataOf, PinnedPrintEventFilter, NftTransferPayload, NftTransferFilter, NftMintPayload, NftMintFilter, NftBurnPayload, NftBurnFilter, NestedContractCallPayload, MaterializeSpec, MaterializeColumn, MapWritePayload, MapDeletePayload, KyselyGenOptions, InferredTopicSchema, InferredPrintField, InferTableRow, InferSubgraphClient, InferContext, InferColumnType, IndexCodegenTarget, IndexCodegenOptions, INDEX_CODEGEN_TABLES, GeneratedSQL, FtTransferPayload, FtTransferFilter, FtMintPayload, FtMintFilter, FtBurnPayload, FtBurnFilter, FindManyOptions, FactoryScope, EventForFilter, ErasedChainReadClient, DrizzleGenOptions, DeployPlan, DeployDiff, ContractDeployPayload, ContractDeployFilter, ContractCallPayload, ContractCallFilter, ContractCallEvent, ComputedValue, ComparisonFilter, ColumnType, ColumnToTS, ColumnDiff, ChainReadOptions, ChainReadMethods, ChainReadError, ChainReadClient, ChainReadCacheMode, AnyEvent, AggregateSpec, AggregateResult };
package/dist/src/index.js CHANGED
@@ -84,7 +84,12 @@ var VALID_FILTER_TYPES = [
84
84
  "nft_burn",
85
85
  "contract_call",
86
86
  "contract_deploy",
87
- "print_event"
87
+ "print_event",
88
+ "nested_contract_call",
89
+ "var_set",
90
+ "map_set",
91
+ "map_insert",
92
+ "map_delete"
88
93
  ];
89
94
  var contractIdField = z.union([
90
95
  z.string(),
@@ -192,6 +197,43 @@ var SubgraphFilterUnion = z.discriminatedUnion("type", [
192
197
  materialize: MaterializeSpecSchema.optional(),
193
198
  ...traitScope,
194
199
  ...factoryScope
200
+ }).strict(),
201
+ z.object({
202
+ type: z.literal("nested_contract_call"),
203
+ contractId: contractIdField.optional(),
204
+ functionName: z.string().optional(),
205
+ caller: z.string().optional(),
206
+ sender: z.string().optional(),
207
+ ...traitScope,
208
+ ...factoryScope
209
+ }).strict(),
210
+ z.object({
211
+ type: z.literal("var_set"),
212
+ contractId: contractIdField.optional(),
213
+ varName: z.string().optional(),
214
+ ...traitScope,
215
+ ...factoryScope
216
+ }).strict(),
217
+ z.object({
218
+ type: z.literal("map_set"),
219
+ contractId: contractIdField.optional(),
220
+ map: z.string().optional(),
221
+ ...traitScope,
222
+ ...factoryScope
223
+ }).strict(),
224
+ z.object({
225
+ type: z.literal("map_insert"),
226
+ contractId: contractIdField.optional(),
227
+ map: z.string().optional(),
228
+ ...traitScope,
229
+ ...factoryScope
230
+ }).strict(),
231
+ z.object({
232
+ type: z.literal("map_delete"),
233
+ contractId: contractIdField.optional(),
234
+ map: z.string().optional(),
235
+ ...traitScope,
236
+ ...factoryScope
195
237
  }).strict()
196
238
  ]);
197
239
  var SubgraphFilterSchema = SubgraphFilterUnion;
@@ -1338,7 +1380,7 @@ function printContractId(data) {
1338
1380
  const id = (typeof data.contract_identifier === "string" ? data.contract_identifier : undefined) ?? (typeof data.contract_id === "string" ? data.contract_id : undefined);
1339
1381
  return id || undefined;
1340
1382
  }
1341
- function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts = new Map) {
1383
+ function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts = new Map, vmEventsByTx = new Map) {
1342
1384
  const results = [];
1343
1385
  switch (filter.type) {
1344
1386
  case "stx_transfer":
@@ -1503,6 +1545,57 @@ function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryCo
1503
1545
  }
1504
1546
  break;
1505
1547
  }
1548
+ case "nested_contract_call":
1549
+ case "var_set":
1550
+ case "map_set":
1551
+ case "map_insert":
1552
+ case "map_delete": {
1553
+ for (const tx of transactions) {
1554
+ const txEvents = vmEventsByTx.get(tx.tx_id) ?? [];
1555
+ const matched = txEvents.filter((e) => {
1556
+ if (e.type !== filter.type)
1557
+ return false;
1558
+ const data = e.data;
1559
+ if (!data)
1560
+ return false;
1561
+ const contractId = printContractId(data);
1562
+ if ("contractId" in filter && filter.contractId) {
1563
+ if (!contractId || !matchAny(contractId, filter.contractId))
1564
+ return false;
1565
+ }
1566
+ if (!traitAllows(filter, contractId, traitContracts))
1567
+ return false;
1568
+ if (!factoryAllows(filter, contractId, factoryContracts))
1569
+ return false;
1570
+ if (filter.type === "nested_contract_call") {
1571
+ if (filter.functionName) {
1572
+ if (typeof data.function_name !== "string" || !matchPattern(data.function_name, filter.functionName))
1573
+ return false;
1574
+ }
1575
+ if (filter.caller) {
1576
+ if (typeof data.caller !== "string" || !matchPattern(data.caller, filter.caller))
1577
+ return false;
1578
+ }
1579
+ if (filter.sender) {
1580
+ if (typeof data.sender !== "string" || !matchPattern(data.sender, filter.sender))
1581
+ return false;
1582
+ }
1583
+ }
1584
+ if (filter.type === "var_set" && filter.varName) {
1585
+ if (typeof data.var_name !== "string" || !matchPattern(data.var_name, filter.varName))
1586
+ return false;
1587
+ }
1588
+ if ((filter.type === "map_set" || filter.type === "map_insert" || filter.type === "map_delete") && filter.map) {
1589
+ if (typeof data.map_name !== "string" || !matchPattern(data.map_name, filter.map))
1590
+ return false;
1591
+ }
1592
+ return true;
1593
+ });
1594
+ if (matched.length > 0)
1595
+ results.push({ tx, events: matched });
1596
+ }
1597
+ break;
1598
+ }
1506
1599
  case "print_event": {
1507
1600
  for (const tx of transactions) {
1508
1601
  const txEvents = eventsByTx.get(tx.tx_id) ?? [];
@@ -1534,17 +1627,23 @@ function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryCo
1534
1627
  }
1535
1628
  return results;
1536
1629
  }
1537
- function matchSources(sources, transactions, events, traitContracts = new Map, factoryContracts = new Map) {
1630
+ function matchSources(sources, transactions, events, traitContracts = new Map, factoryContracts = new Map, vmEvents = []) {
1538
1631
  const eventsByTx = new Map;
1539
1632
  for (const event of events) {
1540
1633
  const list = eventsByTx.get(event.tx_id) ?? [];
1541
1634
  list.push(event);
1542
1635
  eventsByTx.set(event.tx_id, list);
1543
1636
  }
1637
+ const vmEventsByTx = new Map;
1638
+ for (const event of vmEvents) {
1639
+ const list = vmEventsByTx.get(event.tx_id) ?? [];
1640
+ list.push(event);
1641
+ vmEventsByTx.set(event.tx_id, list);
1642
+ }
1544
1643
  const seen = new Set;
1545
1644
  const results = [];
1546
1645
  for (const [sourceName, filter] of Object.entries(sources)) {
1547
- const matches = matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts);
1646
+ const matches = matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts, vmEventsByTx);
1548
1647
  for (const match of matches) {
1549
1648
  const dedupeKey = `${match.tx.tx_id}:${sourceName}`;
1550
1649
  if (!seen.has(dedupeKey)) {
@@ -2119,6 +2218,12 @@ function decodeRawResult(raw) {
2119
2218
  }
2120
2219
  return null;
2121
2220
  }
2221
+ function decodeRawHex(hex) {
2222
+ if (hex.startsWith("0x") && hex.length > 2) {
2223
+ return decodeClarityValue(hex);
2224
+ }
2225
+ return hex;
2226
+ }
2122
2227
  function safeBigInt(val) {
2123
2228
  if (typeof val === "bigint")
2124
2229
  return val;
@@ -2312,6 +2417,58 @@ function buildEventPayload(filter, tx, event) {
2312
2417
  deployer: tx.sender,
2313
2418
  tx: txMeta
2314
2419
  };
2420
+ case "nested_contract_call": {
2421
+ const data = event.data ?? {};
2422
+ const argsHex = Array.isArray(data.function_args) ? data.function_args.filter((a) => typeof a === "string") : [];
2423
+ return {
2424
+ contractId: printContractId(data) ?? "",
2425
+ sender: typeof data.sender === "string" ? data.sender : null,
2426
+ caller: typeof data.caller === "string" ? data.caller : "",
2427
+ functionName: typeof data.function_name === "string" ? data.function_name : "",
2428
+ args: decodeFunctionArgs2(argsHex),
2429
+ arguments: argsHex,
2430
+ rawResult: typeof data.raw_result === "string" ? data.raw_result : "",
2431
+ result: decodeRawResult(data.raw_result),
2432
+ tx: txMeta
2433
+ };
2434
+ }
2435
+ case "var_set": {
2436
+ const data = event.data ?? {};
2437
+ const rawValue = typeof data.raw_value === "string" ? data.raw_value : "";
2438
+ return {
2439
+ contractId: printContractId(data) ?? "",
2440
+ varName: typeof data.var_name === "string" ? data.var_name : "",
2441
+ rawValue,
2442
+ value: decodeRawHex(rawValue),
2443
+ tx: txMeta
2444
+ };
2445
+ }
2446
+ case "map_set":
2447
+ case "map_insert": {
2448
+ const data = event.data ?? {};
2449
+ const rawKey = typeof data.raw_key === "string" ? data.raw_key : "";
2450
+ const rawValue = typeof data.raw_value === "string" ? data.raw_value : "";
2451
+ return {
2452
+ contractId: printContractId(data) ?? "",
2453
+ map: typeof data.map_name === "string" ? data.map_name : "",
2454
+ rawKey,
2455
+ key: decodeRawHex(rawKey),
2456
+ rawValue,
2457
+ value: decodeRawHex(rawValue),
2458
+ tx: txMeta
2459
+ };
2460
+ }
2461
+ case "map_delete": {
2462
+ const data = event.data ?? {};
2463
+ const rawKey = typeof data.raw_key === "string" ? data.raw_key : "";
2464
+ return {
2465
+ contractId: printContractId(data) ?? "",
2466
+ map: typeof data.map_name === "string" ? data.map_name : "",
2467
+ rawKey,
2468
+ key: decodeRawHex(rawKey),
2469
+ tx: txMeta
2470
+ };
2471
+ }
2315
2472
  default:
2316
2473
  return {
2317
2474
  ...decoded,
@@ -2340,7 +2497,8 @@ async function runHandlers(subgraph, matched, ctx, opts) {
2340
2497
  units.push({ tx, sourceName, event });
2341
2498
  }
2342
2499
  }
2343
- units.sort((a, b) => (a.tx.tx_index ?? 0) - (b.tx.tx_index ?? 0) || (a.event?.event_index ?? -1) - (b.event?.event_index ?? -1));
2500
+ const clockRank = (e) => e?.clock === "vm" ? 1 : 0;
2501
+ 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));
2344
2502
  for (const { tx, event, sourceName } of units) {
2345
2503
  if (errors >= threshold) {
2346
2504
  logger4.error("Subgraph error threshold reached, skipping remaining events", {
@@ -2486,11 +2644,15 @@ import {
2486
2644
  import { logger as logger5 } from "@secondlayer/shared/logger";
2487
2645
 
2488
2646
  // src/runtime/batch-loader.ts
2647
+ function vmEventId(txId, vmEventIndex) {
2648
+ return `${txId}#vm:${vmEventIndex}`;
2649
+ }
2489
2650
  async function loadBlockRange(db, fromHeight, toHeight) {
2490
- const [blocks, txs, events] = await Promise.all([
2651
+ const [blocks, txs, events, vmRows] = await Promise.all([
2491
2652
  db.selectFrom("blocks").selectAll().where("height", ">=", fromHeight).where("height", "<=", toHeight).where("canonical", "=", true).execute(),
2492
2653
  db.selectFrom("transactions").selectAll().where("block_height", ">=", fromHeight).where("block_height", "<=", toHeight).execute(),
2493
- db.selectFrom("events").selectAll().where("block_height", ">=", fromHeight).where("block_height", "<=", toHeight).execute()
2654
+ db.selectFrom("events").selectAll().where("block_height", ">=", fromHeight).where("block_height", "<=", toHeight).execute(),
2655
+ db.selectFrom("vm_events").selectAll().where("block_height", ">=", fromHeight).where("block_height", "<=", toHeight).orderBy("ordinal", "asc").execute()
2494
2656
  ]);
2495
2657
  const txsByHeight = new Map;
2496
2658
  for (const tx of txs) {
@@ -2506,13 +2668,30 @@ async function loadBlockRange(db, fromHeight, toHeight) {
2506
2668
  list.push(evt);
2507
2669
  eventsByHeight.set(h, list);
2508
2670
  }
2671
+ const vmByHeight = new Map;
2672
+ for (const row of vmRows) {
2673
+ const h = Number(row.block_height);
2674
+ const list = vmByHeight.get(h) ?? [];
2675
+ list.push({
2676
+ id: vmEventId(row.tx_id, Number(row.ordinal)),
2677
+ tx_id: row.tx_id,
2678
+ block_height: h,
2679
+ event_index: Number(row.ordinal),
2680
+ type: row.type,
2681
+ data: row.data,
2682
+ created_at: row.created_at,
2683
+ clock: "vm"
2684
+ });
2685
+ vmByHeight.set(h, list);
2686
+ }
2509
2687
  const result = new Map;
2510
2688
  for (const block of blocks) {
2511
2689
  const h = Number(block.height);
2512
2690
  result.set(h, {
2513
2691
  block,
2514
2692
  txs: txsByHeight.get(h) ?? [],
2515
- events: eventsByHeight.get(h) ?? []
2693
+ events: eventsByHeight.get(h) ?? [],
2694
+ vmEvents: vmByHeight.get(h) ?? []
2516
2695
  });
2517
2696
  }
2518
2697
  return result;
@@ -2528,6 +2707,9 @@ function avgEventsPerBlock(batch) {
2528
2707
  }
2529
2708
 
2530
2709
  // src/runtime/observer-http-source.ts
2710
+ import {
2711
+ VM_NODE_TO_STORED_TYPE
2712
+ } from "@secondlayer/shared";
2531
2713
  var OBSERVER_HTTP_EXPORT_PATH = "/internal/observer-events";
2532
2714
  function stripTrailingSlash(url) {
2533
2715
  return url.replace(/\/+$/, "");
@@ -2605,7 +2787,29 @@ function mapNewBlockPayloadToBlockData(payload) {
2605
2787
  created_at: new Date(0)
2606
2788
  };
2607
2789
  });
2608
- return { block, txs, events };
2790
+ const vmEvents = [];
2791
+ for (const [i, trace] of (p.vm_events ?? []).entries()) {
2792
+ const nodeType = trace.type;
2793
+ if (typeof nodeType !== "string" || !(nodeType in VM_NODE_TO_STORED_TYPE))
2794
+ continue;
2795
+ const stored = VM_NODE_TO_STORED_TYPE[nodeType];
2796
+ const body = trace[nodeType];
2797
+ if (!body || typeof body !== "object")
2798
+ continue;
2799
+ const txId = trace.txid ?? "";
2800
+ const vmIndex = i;
2801
+ vmEvents.push({
2802
+ id: vmEventId(txId, vmIndex),
2803
+ tx_id: txId,
2804
+ block_height: height,
2805
+ event_index: vmIndex,
2806
+ type: stored,
2807
+ data: body,
2808
+ created_at: new Date(0),
2809
+ clock: "vm"
2810
+ });
2811
+ }
2812
+ return { block, txs, events, vmEvents };
2609
2813
  }
2610
2814
 
2611
2815
  class ObserverHttpBlockSource {
@@ -2808,6 +3012,30 @@ function reconstructEvent(e) {
2808
3012
  raw_value: e.payload.raw_value
2809
3013
  }
2810
3014
  };
3015
+ case "nested_contract_call":
3016
+ case "var_set":
3017
+ case "map_set":
3018
+ case "map_insert":
3019
+ case "map_delete":
3020
+ return {
3021
+ ...base,
3022
+ id: vmEventId(e.tx_id, e.event_index),
3023
+ clock: "vm",
3024
+ type: e.event_type,
3025
+ data: {
3026
+ contract_identifier: e.contract_id,
3027
+ ..."payload" in e && e.payload && typeof e.payload === "object" ? e.payload : {},
3028
+ sender: "sender" in e ? e.sender : undefined,
3029
+ caller: "caller" in e ? e.caller : undefined,
3030
+ function_name: "function_name" in e ? e.function_name : undefined,
3031
+ function_args: "function_args" in e ? e.function_args : undefined,
3032
+ raw_result: "raw_result" in e ? e.raw_result : undefined,
3033
+ map_name: "map" in e ? e.map : undefined,
3034
+ var_name: "var_name" in e ? e.var_name : undefined,
3035
+ raw_key: "raw_key" in e ? e.raw_key : undefined,
3036
+ raw_value: "raw_value" in e ? e.raw_value : undefined
3037
+ }
3038
+ };
2811
3039
  }
2812
3040
  }
2813
3041
 
@@ -2854,12 +3082,24 @@ var EVENT_FILTER_TO_INDEX_TYPE = {
2854
3082
  nft_transfer: "nft_transfer",
2855
3083
  nft_mint: "nft_mint",
2856
3084
  nft_burn: "nft_burn",
2857
- print_event: "print"
3085
+ print_event: "print",
3086
+ nested_contract_call: "nested_contract_call",
3087
+ var_set: "var_set",
3088
+ map_set: "map_set",
3089
+ map_insert: "map_insert",
3090
+ map_delete: "map_delete"
2858
3091
  };
2859
3092
  var TX_SOURCE_TYPES = new Set(["contract_call", "contract_deploy"]);
2860
- var ALL_INDEX_EVENT_TYPES = [
3093
+ var VM_INDEX_EVENT_TYPES = new Set([
3094
+ "nested_contract_call",
3095
+ "var_set",
3096
+ "map_set",
3097
+ "map_insert",
3098
+ "map_delete"
3099
+ ]);
3100
+ var CLASSIC_INDEX_EVENT_TYPES = [
2861
3101
  ...new Set(Object.values(EVENT_FILTER_TO_INDEX_TYPE))
2862
- ];
3102
+ ].filter((t) => !VM_INDEX_EVENT_TYPES.has(t));
2863
3103
  function sourceFilters(subgraph) {
2864
3104
  const sources = subgraph.sources;
2865
3105
  return Array.isArray(sources) ? sources : Object.values(sources);
@@ -2876,10 +3116,11 @@ function synthesizeTxsFromEvents(events) {
2876
3116
  return [...byId.values()];
2877
3117
  }
2878
3118
  function indexEventTypesForFilterTypes(filterTypes) {
3119
+ const types = new Set;
2879
3120
  if (filterTypes.some((t) => TX_SOURCE_TYPES.has(t))) {
2880
- return ALL_INDEX_EVENT_TYPES;
3121
+ for (const t of CLASSIC_INDEX_EVENT_TYPES)
3122
+ types.add(t);
2881
3123
  }
2882
- const types = new Set;
2883
3124
  for (const t of filterTypes) {
2884
3125
  const indexType = EVENT_FILTER_TO_INDEX_TYPE[t];
2885
3126
  if (indexType)
@@ -2925,6 +3166,9 @@ class PublicApiBlockSource {
2925
3166
  return found.length ? Math.min(...found) : null;
2926
3167
  }
2927
3168
  getTip() {
3169
+ if (this.eventTypes.some((t) => VM_INDEX_EVENT_TYPES.has(t))) {
3170
+ return this.http.getIndexSourceTip();
3171
+ }
2928
3172
  return this.http.getIndexTip();
2929
3173
  }
2930
3174
  async loadBlockRange(fromHeight, toHeight) {
@@ -2948,12 +3192,21 @@ class PublicApiBlockSource {
2948
3192
  }
2949
3193
  for (const list of eventLists) {
2950
3194
  for (const e of list) {
2951
- map.get(e.block_height)?.events.push(reconstructEvent(e));
3195
+ const bd = map.get(e.block_height);
3196
+ if (!bd)
3197
+ continue;
3198
+ if (VM_INDEX_EVENT_TYPES.has(e.event_type)) {
3199
+ bd.vmEvents ??= [];
3200
+ bd.vmEvents.push(reconstructEvent(e));
3201
+ } else {
3202
+ bd.events.push(reconstructEvent(e));
3203
+ }
2952
3204
  }
2953
3205
  }
2954
3206
  for (const bd of map.values()) {
2955
3207
  bd.txs.sort((a, b) => a.tx_index - b.tx_index);
2956
3208
  bd.events.sort((a, b) => a.event_index - b.event_index);
3209
+ bd.vmEvents?.sort((a, b) => a.event_index - b.event_index);
2957
3210
  }
2958
3211
  return map;
2959
3212
  }
@@ -3591,7 +3844,7 @@ function invalidateSubgraphRoute(subgraphName) {
3591
3844
  routeCache.delete(subgraphName);
3592
3845
  evictSandboxWorker(subgraphName);
3593
3846
  }
3594
- async function resolveFactoryContracts(subgraph, blockHeight, schemaName, db, txs, evts) {
3847
+ async function resolveFactoryContracts(subgraph, blockHeight, schemaName, db, txs, evts, vmEvts = []) {
3595
3848
  const factories = new Map;
3596
3849
  for (const source of Object.values(subgraph.sources)) {
3597
3850
  const factory = source.factory;
@@ -3614,7 +3867,7 @@ async function resolveFactoryContracts(subgraph, blockHeight, schemaName, db, tx
3614
3867
  } catch {}
3615
3868
  const discovering = subgraph.sources[factory.from];
3616
3869
  if (discovering) {
3617
- const matches = matchSources({ [factory.from]: discovering }, txs, evts, new Map, new Map);
3870
+ const matches = matchSources({ [factory.from]: discovering }, txs, evts, new Map, new Map, vmEvts);
3618
3871
  for (const match of matches) {
3619
3872
  for (const event of match.events ?? []) {
3620
3873
  const payload = buildEventPayload(discovering, match.tx, event);
@@ -3720,10 +3973,12 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
3720
3973
  let block;
3721
3974
  let txs;
3722
3975
  let evts;
3976
+ let vmEvts;
3723
3977
  if (opts?.preloaded) {
3724
3978
  block = opts.preloaded.block;
3725
3979
  txs = opts.preloaded.txs;
3726
3980
  evts = opts.preloaded.events;
3981
+ vmEvts = opts.preloaded.vmEvents ?? [];
3727
3982
  } else {
3728
3983
  const data = (await resolveBlockSource(subgraph).loadBlockRange(blockHeight, blockHeight)).get(blockHeight);
3729
3984
  if (!data) {
@@ -3737,12 +3992,13 @@ async function processBlock(subgraph, subgraphName, blockHeight, opts) {
3737
3992
  block = data.block;
3738
3993
  txs = data.txs;
3739
3994
  evts = data.events;
3995
+ vmEvts = data.vmEvents ?? [];
3740
3996
  }
3741
3997
  const route = await resolveRoute(subgraphName, targetDb);
3742
3998
  const schemaName = route.schemaName;
3743
3999
  const traitContracts = await resolveTraitContracts(subgraph, blockHeight, targetDb);
3744
- const { resolved: factoryContracts, discovered } = await resolveFactoryContracts(subgraph, blockHeight, schemaName, targetDb, txs, evts);
3745
- const matched = matchSources(subgraph.sources, txs, evts, traitContracts, factoryContracts);
4000
+ const { resolved: factoryContracts, discovered } = await resolveFactoryContracts(subgraph, blockHeight, schemaName, targetDb, txs, evts, vmEvts);
4001
+ const matched = matchSources(subgraph.sources, txs, evts, traitContracts, factoryContracts, vmEvts);
3746
4002
  result.matched = matched.length;
3747
4003
  if (matched.length === 0) {
3748
4004
  if (!opts?.skipProgressUpdate) {
@@ -4014,7 +4270,7 @@ function decoderNameForEventType(indexEventType) {
4014
4270
  return `decode.${indexEventType}.v1`;
4015
4271
  }
4016
4272
  function decoderNamesForIndexEventTypes(eventTypes) {
4017
- return eventTypes.map(decoderNameForEventType);
4273
+ return eventTypes.filter((t) => !VM_INDEX_EVENT_TYPES.has(t)).map(decoderNameForEventType);
4018
4274
  }
4019
4275
  function decoderNamesForSubgraph(subgraph) {
4020
4276
  return decoderNamesForIndexEventTypes(referencedIndexEventTypes(subgraph));
@@ -4544,7 +4800,7 @@ async function processBlockRange(def, opts) {
4544
4800
  }
4545
4801
  let result;
4546
4802
  try {
4547
- const mayWrite = blockData.txs.length > 0 || blockData.events.length > 0;
4803
+ const mayWrite = blockData.txs.length > 0 || blockData.events.length > 0 || (blockData.vmEvents?.length ?? 0) > 0;
4548
4804
  const runBlock = () => processBlockWithRetry(def, subgraphName, height, {
4549
4805
  skipProgressUpdate: true,
4550
4806
  atomicProgress,
@@ -5821,5 +6077,5 @@ export {
5821
6077
  ChainReadError
5822
6078
  };
5823
6079
 
5824
- //# debugId=DBCE838E06681C8A64756E2164756E21
6080
+ //# debugId=60A8B6033C8DF75764756E2164756E21
5825
6081
  //# sourceMappingURL=index.js.map