@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,9 +1,8 @@
1
- import { createRequire } from "node:module";
2
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
1
+ // src/testing/harness.ts
2
+ import { normalizeAbi as normalizeAbi2, toCamelCase as toCamelCase3 } from "@secondlayer/stacks/clarity";
3
3
 
4
4
  // src/runtime/context.ts
5
5
  import { logger as logger2 } from "@secondlayer/shared/logger";
6
- import { formatUnits } from "@secondlayer/stacks/utils";
7
6
  import { sql } from "kysely";
8
7
 
9
8
  // src/schema/generator.ts
@@ -149,12 +148,6 @@ function emitFactoryDDL(schemaName) {
149
148
  `CREATE INDEX IF NOT EXISTS idx_${schemaName}_factory_height ON ${schemaName}._factory_addresses (block_height)`
150
149
  ];
151
150
  }
152
- function emitForeignKeyDDL(schemaName, tableName, tableDef) {
153
- return (tableDef.relations ?? []).map((rel) => {
154
- const constraintName = quotePgIdent(`fk_${schemaName}_${tableName}_${rel.name}`);
155
- return `ALTER TABLE ${quotePgIdent(schemaName)}.${quotePgIdent(tableName)} ADD CONSTRAINT ${constraintName} ` + `FOREIGN KEY (${rel.fields.map(quotePgIdent).join(", ")}) ` + `REFERENCES ${quotePgIdent(schemaName)}.${quotePgIdent(rel.references)} (${rel.referencedColumns.map(quotePgIdent).join(", ")})`;
156
- });
157
- }
158
151
  function generateSubgraphSQL(def, schemaNameOverride) {
159
152
  const schemaName = schemaNameOverride ?? pgSchemaName(def.name);
160
153
  const statements = [];
@@ -170,9 +163,6 @@ function generateSubgraphSQL(def, schemaNameOverride) {
170
163
  if (Object.values(def.sources ?? {}).some((src) => src.factory !== undefined)) {
171
164
  statements.push(...emitFactoryDDL(schemaName));
172
165
  }
173
- for (const [tableName, tableDef] of Object.entries(def.schema)) {
174
- statements.push(...emitForeignKeyDDL(schemaName, tableName, tableDef));
175
- }
176
166
  const hashInput = JSON.stringify({
177
167
  name: def.name,
178
168
  schema: def.schema,
@@ -278,13 +268,13 @@ function createChainReadClient(ctx) {
278
268
  note: 'cache: "contract-constant" asserts this value cannot change; the node answered at its own tip'
279
269
  });
280
270
  }
281
- const value2 = await readContract(nodeClient(rpcUrl), {
271
+ const value = await readContract(nodeClient(rpcUrl), {
282
272
  contract: contractId,
283
273
  functionName: fn.name,
284
274
  args: clarityArgs,
285
275
  tip: ctx.indexBlockHash ?? undefined
286
276
  });
287
- return serializeCV(value2);
277
+ return serializeCV(value);
288
278
  });
289
279
  if (!cached) {
290
280
  await db.insertInto("chain_read_cache").values({
@@ -325,7 +315,6 @@ function createChainReadClient(ctx) {
325
315
  }
326
316
 
327
317
  // src/runtime/context.ts
328
- var JOURNAL_RETENTION_BLOCKS = 300;
329
318
  var journalEnsured = new Set;
330
319
  function validateColumnName(name) {
331
320
  if (!/^[a-z_][a-z0-9_]*$/i.test(name)) {
@@ -342,9 +331,9 @@ class SubgraphContext {
342
331
  ops = [];
343
332
  journal;
344
333
  _client;
345
- constructor(db, pgSchemaName2, subgraphSchema, block, tx, journal = false) {
334
+ constructor(db, pgSchemaName, subgraphSchema, block, tx, journal = false) {
346
335
  this.db = db;
347
- this.pgSchemaName = pgSchemaName2;
336
+ this.pgSchemaName = pgSchemaName;
348
337
  this.subgraphSchema = subgraphSchema;
349
338
  this.block = block;
350
339
  this._tx = tx;
@@ -448,20 +437,6 @@ class SubgraphContext {
448
437
  return;
449
438
  this.ops.length = checkpoint;
450
439
  }
451
- patch(table, where, set) {
452
- this.update(table, where, set);
453
- }
454
- async patchOrInsert(table, key, row) {
455
- const existing = await this.findOne(table, key);
456
- const resolved = {};
457
- for (const [k, v] of Object.entries(row)) {
458
- resolved[k] = typeof v === "function" ? v(existing) : v;
459
- }
460
- this.upsert(table, key, resolved);
461
- }
462
- formatUnits(value, decimals) {
463
- return formatUnits(value, decimals);
464
- }
465
440
  async readRows(table, where, limit) {
466
441
  const qualifiedTable = `"${this.pgSchemaName}"."${table}"`;
467
442
  const { clause } = buildWhereClause(where);
@@ -563,47 +538,6 @@ class SubgraphContext {
563
538
  return row && rowMatches(row, op.data) ? null : row;
564
539
  }
565
540
  }
566
- async count(table, where) {
567
- this.validateTable(table);
568
- const qualifiedTable = `"${this.pgSchemaName}"."${table}"`;
569
- const whereClause = where ? `WHERE ${buildWhereClause(where).clause}` : "";
570
- const { rows } = await sql.raw(`SELECT COUNT(*)::int AS count FROM ${qualifiedTable} ${whereClause}`).execute(this.db);
571
- return Number(rows[0]?.count ?? 0);
572
- }
573
- async sum(table, column, where) {
574
- this.validateTable(table);
575
- validateColumnName(column);
576
- const qualifiedTable = `"${this.pgSchemaName}"."${table}"`;
577
- const whereClause = where ? `WHERE ${buildWhereClause(where).clause}` : "";
578
- const { rows } = await sql.raw(`SELECT COALESCE(SUM("${column}"), 0) AS total FROM ${qualifiedTable} ${whereClause}`).execute(this.db);
579
- return BigInt(rows[0]?.total?.toString() ?? "0");
580
- }
581
- async min(table, column, where) {
582
- this.validateTable(table);
583
- validateColumnName(column);
584
- const qualifiedTable = `"${this.pgSchemaName}"."${table}"`;
585
- const whereClause = where ? `WHERE ${buildWhereClause(where).clause}` : "";
586
- const { rows } = await sql.raw(`SELECT MIN("${column}") AS val FROM ${qualifiedTable} ${whereClause}`).execute(this.db);
587
- const val = rows[0]?.val;
588
- return val != null ? BigInt(val.toString()) : null;
589
- }
590
- async max(table, column, where) {
591
- this.validateTable(table);
592
- validateColumnName(column);
593
- const qualifiedTable = `"${this.pgSchemaName}"."${table}"`;
594
- const whereClause = where ? `WHERE ${buildWhereClause(where).clause}` : "";
595
- const { rows } = await sql.raw(`SELECT MAX("${column}") AS val FROM ${qualifiedTable} ${whereClause}`).execute(this.db);
596
- const val = rows[0]?.val;
597
- return val != null ? BigInt(val.toString()) : null;
598
- }
599
- async countDistinct(table, column, where) {
600
- this.validateTable(table);
601
- validateColumnName(column);
602
- const qualifiedTable = `"${this.pgSchemaName}"."${table}"`;
603
- const whereClause = where ? `WHERE ${buildWhereClause(where).clause}` : "";
604
- const { rows } = await sql.raw(`SELECT COUNT(DISTINCT "${column}")::int AS count FROM ${qualifiedTable} ${whereClause}`).execute(this.db);
605
- return Number(rows[0]?.count ?? 0);
606
- }
607
541
  coerceRow(table, row) {
608
542
  const tableDef = this.subgraphSchema[table];
609
543
  if (!tableDef)
@@ -928,528 +862,172 @@ function buildWhereClause(where) {
928
862
  return { clause: parts.join(" AND "), values: [] };
929
863
  }
930
864
 
931
- // src/runtime/clarity.ts
932
- import { cvToValue, deserializeCV as deserializeCV2 } from "@secondlayer/stacks/clarity";
933
- function decodeClarityValue(hex) {
934
- try {
935
- const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
936
- const cv = deserializeCV2(cleanHex);
937
- return cvToValue(cv);
938
- } catch {
939
- return hex;
940
- }
865
+ // src/runtime/runner.ts
866
+ import { getErrorMessage } from "@secondlayer/shared";
867
+ import { logger as logger4 } from "@secondlayer/shared/logger";
868
+ import {
869
+ clarityValueToJS,
870
+ deserializeCV as deserializeCV4,
871
+ toCamelCase as toCamelCase2
872
+ } from "@secondlayer/stacks/clarity";
873
+
874
+ // src/print-schema.ts
875
+ import {
876
+ deserializeCV as deserializeCV2
877
+ } from "@secondlayer/stacks/clarity";
878
+ function camelizeDataKey(str) {
879
+ return str.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
941
880
  }
942
- function decodeEventData(data) {
943
- if (typeof data === "string" && data.startsWith("0x") && data.length > 10) {
944
- return decodeClarityValue(data);
945
- }
946
- if (Array.isArray(data)) {
947
- return data.map(decodeEventData);
881
+ function camelizeKeys(obj) {
882
+ if (obj === null || obj === undefined)
883
+ return obj;
884
+ if (typeof obj !== "object")
885
+ return obj;
886
+ if (Array.isArray(obj))
887
+ return obj.map(camelizeKeys);
888
+ const result = {};
889
+ for (const [k, v] of Object.entries(obj)) {
890
+ result[camelizeDataKey(k)] = camelizeKeys(v);
948
891
  }
949
- if (typeof data === "object" && data !== null) {
950
- const decoded = {};
951
- for (const [key, value] of Object.entries(data)) {
952
- decoded[key] = decodeEventData(value);
892
+ return result;
893
+ }
894
+ function cvToTree(cv) {
895
+ switch (cv.type) {
896
+ case "uint":
897
+ case "int":
898
+ return { kind: cv.type };
899
+ case "true":
900
+ case "false":
901
+ return { kind: "bool" };
902
+ case "address":
903
+ case "contract":
904
+ return { kind: "principal" };
905
+ case "buffer":
906
+ return { kind: "buffer", len: cv.value.length / 2 };
907
+ case "ascii":
908
+ return { kind: "ascii", len: cv.value.length };
909
+ case "utf8":
910
+ return { kind: "utf8", len: new TextEncoder().encode(cv.value).length };
911
+ case "none":
912
+ return { kind: "optional", inner: null };
913
+ case "some":
914
+ return { kind: "optional", inner: cvToTree(cv.value) };
915
+ case "ok":
916
+ return { kind: "response", ok: cvToTree(cv.value), err: null };
917
+ case "err":
918
+ return { kind: "response", ok: null, err: cvToTree(cv.value) };
919
+ case "list": {
920
+ let inner = null;
921
+ for (const el of cv.value) {
922
+ const t = cvToTree(el);
923
+ inner = inner ? unify(inner, t) : t;
924
+ }
925
+ return { kind: "list", inner };
926
+ }
927
+ case "tuple": {
928
+ const entries = new Map;
929
+ for (const [k, v] of Object.entries(cv.value)) {
930
+ entries.set(k, { tree: cvToTree(v), present: 1 });
931
+ }
932
+ return { kind: "tuple", count: 1, entries };
953
933
  }
954
- return decoded;
955
934
  }
956
- return data;
957
935
  }
958
- function decodeFunctionArgs(args) {
959
- return args.map(decodeClarityValue);
936
+ function unifyNullable(a, b) {
937
+ if (!a)
938
+ return b;
939
+ if (!b)
940
+ return a;
941
+ return unify(a, b);
960
942
  }
961
-
962
- // src/runtime/source-matcher.ts
963
- var patternCache = new Map;
964
- function matchAny(value, pattern) {
965
- return Array.isArray(pattern) ? pattern.some((p) => matchPattern(value, p)) : matchPattern(value, pattern);
943
+ var UNION_KIND_ORDER = {
944
+ uint: 0,
945
+ int: 1,
946
+ bool: 2,
947
+ principal: 3,
948
+ buffer: 4,
949
+ ascii: 5,
950
+ utf8: 6,
951
+ list: 7,
952
+ tuple: 8,
953
+ response: 9
954
+ };
955
+ function makeUnion(members) {
956
+ const sorted = [...members].sort((a, b) => (UNION_KIND_ORDER[a.kind] ?? 99) - (UNION_KIND_ORDER[b.kind] ?? 99));
957
+ return { kind: "union", members: sorted };
966
958
  }
967
- function matchPattern(value, pattern) {
968
- if (!pattern.includes("*"))
969
- return value === pattern;
970
- let re = patternCache.get(pattern);
971
- if (!re) {
972
- const regex = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
973
- re = new RegExp(`^${regex}$`);
974
- patternCache.set(pattern, re);
959
+ function unify(a, b) {
960
+ if (a.kind === "optional" || b.kind === "optional") {
961
+ const ai = a.kind === "optional" ? a.inner : a;
962
+ const bi = b.kind === "optional" ? b.inner : b;
963
+ return { kind: "optional", inner: unifyNullable(ai, bi) };
975
964
  }
976
- return re.test(value);
977
- }
978
- var EMPTY_SET = new Set;
979
- function factoryAllows(filter, contractId, factoryContracts) {
980
- if (!filter.factory)
981
- return true;
982
- if (!contractId)
983
- return false;
984
- return (factoryContracts.get(filter.factory.from) ?? EMPTY_SET).has(contractId);
985
- }
986
- function readPath(payload, path) {
987
- let cur = payload;
988
- for (const key of path.split(".")) {
989
- if (cur === null || typeof cur !== "object")
990
- return;
991
- cur = cur[key];
965
+ if (a.kind === "union")
966
+ return unionAdd(a.members, b);
967
+ if (b.kind === "union")
968
+ return unionAdd(b.members, a);
969
+ if (a.kind !== b.kind)
970
+ return makeUnion([a, b]);
971
+ switch (a.kind) {
972
+ case "uint":
973
+ case "int":
974
+ case "bool":
975
+ case "principal":
976
+ return a;
977
+ case "buffer":
978
+ case "ascii":
979
+ case "utf8":
980
+ return { kind: a.kind, len: Math.max(a.len, b.len) };
981
+ case "list":
982
+ return {
983
+ kind: "list",
984
+ inner: unifyNullable(a.inner, b.inner)
985
+ };
986
+ case "response": {
987
+ const rb = b;
988
+ return {
989
+ kind: "response",
990
+ ok: unifyNullable(a.ok, rb.ok),
991
+ err: unifyNullable(a.err, rb.err)
992
+ };
993
+ }
994
+ case "tuple": {
995
+ const tb = b;
996
+ const entries = new Map([...a.entries].map(([k, e]) => [k, { ...e }]));
997
+ for (const [k, e] of tb.entries) {
998
+ const existing = entries.get(k);
999
+ entries.set(k, existing ? {
1000
+ tree: unify(existing.tree, e.tree),
1001
+ present: existing.present + e.present
1002
+ } : { ...e });
1003
+ }
1004
+ return { kind: "tuple", count: a.count + tb.count, entries };
1005
+ }
992
1006
  }
993
- return cur;
994
- }
995
- function traitAllows(filter, contractId, traitContracts) {
996
- const trait = filter.trait;
997
- if (!trait)
998
- return true;
999
- if (!contractId)
1000
- return false;
1001
- return (traitContracts.get(trait) ?? EMPTY_SET).has(contractId);
1002
1007
  }
1003
- function assetContract(assetId) {
1004
- return assetId?.split("::")[0];
1008
+ function unionAdd(members, t) {
1009
+ if (t.kind === "union") {
1010
+ let acc = { kind: "union", members };
1011
+ for (const m of t.members)
1012
+ acc = unify(acc, m);
1013
+ return acc;
1014
+ }
1015
+ const next = [...members];
1016
+ for (let i = 0;i < next.length; i++) {
1017
+ const member = next[i];
1018
+ if (!member)
1019
+ continue;
1020
+ const merged = unify(member, t);
1021
+ if (merged.kind !== "union") {
1022
+ next[i] = merged;
1023
+ return makeUnion(next);
1024
+ }
1025
+ }
1026
+ next.push(t);
1027
+ return makeUnion(next);
1005
1028
  }
1006
- function printContractId(data) {
1007
- if (!data)
1008
- return;
1009
- const id = (typeof data.contract_identifier === "string" ? data.contract_identifier : undefined) ?? (typeof data.contract_id === "string" ? data.contract_id : undefined);
1010
- return id || undefined;
1011
- }
1012
- function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts = new Map, vmEventsByTx = new Map) {
1013
- const results = [];
1014
- switch (filter.type) {
1015
- case "stx_transfer":
1016
- case "stx_mint":
1017
- case "stx_burn":
1018
- case "stx_lock": {
1019
- const eventType = `${filter.type}_event`;
1020
- for (const tx of transactions) {
1021
- const txEvents = eventsByTx.get(tx.tx_id) ?? [];
1022
- const matched = txEvents.filter((e) => e.type === eventType);
1023
- if (matched.length === 0)
1024
- continue;
1025
- const filtered = matched.filter((e) => {
1026
- const data = e.data;
1027
- if (!data)
1028
- return false;
1029
- if ("sender" in filter && filter.sender) {
1030
- if (!matchPattern(data.sender, filter.sender))
1031
- return false;
1032
- }
1033
- if ("recipient" in filter && filter.recipient) {
1034
- if (!matchPattern(data.recipient, filter.recipient))
1035
- return false;
1036
- }
1037
- if ("lockedAddress" in filter && filter.lockedAddress) {
1038
- if (!matchPattern(data.locked_address, filter.lockedAddress))
1039
- return false;
1040
- }
1041
- if ("minAmount" in filter && filter.minAmount !== undefined) {
1042
- const amount = BigInt(data.amount ?? data.locked_amount ?? "0");
1043
- if (amount < filter.minAmount)
1044
- return false;
1045
- }
1046
- if ("maxAmount" in filter && filter.maxAmount !== undefined) {
1047
- const amount = BigInt(data.amount ?? "0");
1048
- if (amount > filter.maxAmount)
1049
- return false;
1050
- }
1051
- return true;
1052
- });
1053
- if (filtered.length > 0) {
1054
- results.push({ tx, events: filtered });
1055
- }
1056
- }
1057
- break;
1058
- }
1059
- case "ft_transfer":
1060
- case "ft_mint":
1061
- case "ft_burn": {
1062
- const eventType = `${filter.type}_event`;
1063
- for (const tx of transactions) {
1064
- const txEvents = eventsByTx.get(tx.tx_id) ?? [];
1065
- const matched = txEvents.filter((e) => {
1066
- if (e.type !== eventType)
1067
- return false;
1068
- const data = e.data;
1069
- if (!data)
1070
- return false;
1071
- if (filter.assetIdentifier) {
1072
- const assetId = data.asset_identifier;
1073
- if (!assetId || !matchPattern(assetId, filter.assetIdentifier))
1074
- return false;
1075
- }
1076
- if (!traitAllows(filter, assetContract(data.asset_identifier), traitContracts))
1077
- return false;
1078
- if ("sender" in filter && filter.sender) {
1079
- if (!matchPattern(data.sender, filter.sender))
1080
- return false;
1081
- }
1082
- if ("recipient" in filter && filter.recipient) {
1083
- if (!matchPattern(data.recipient, filter.recipient))
1084
- return false;
1085
- }
1086
- if (filter.minAmount !== undefined) {
1087
- const amount = BigInt(data.amount ?? "0");
1088
- if (amount < filter.minAmount)
1089
- return false;
1090
- }
1091
- return true;
1092
- });
1093
- if (matched.length > 0) {
1094
- results.push({ tx, events: matched });
1095
- }
1096
- }
1097
- break;
1098
- }
1099
- case "nft_transfer":
1100
- case "nft_mint":
1101
- case "nft_burn": {
1102
- const eventType = `${filter.type}_event`;
1103
- for (const tx of transactions) {
1104
- const txEvents = eventsByTx.get(tx.tx_id) ?? [];
1105
- const matched = txEvents.filter((e) => {
1106
- if (e.type !== eventType)
1107
- return false;
1108
- const data = e.data;
1109
- if (!data)
1110
- return false;
1111
- if (filter.assetIdentifier) {
1112
- const assetId = data.asset_identifier;
1113
- if (!assetId || !matchPattern(assetId, filter.assetIdentifier))
1114
- return false;
1115
- }
1116
- if (!traitAllows(filter, assetContract(data.asset_identifier), traitContracts))
1117
- return false;
1118
- if ("sender" in filter && filter.sender) {
1119
- if (!matchPattern(data.sender, filter.sender))
1120
- return false;
1121
- }
1122
- if ("recipient" in filter && filter.recipient) {
1123
- if (!matchPattern(data.recipient, filter.recipient))
1124
- return false;
1125
- }
1126
- return true;
1127
- });
1128
- if (matched.length > 0) {
1129
- results.push({ tx, events: matched });
1130
- }
1131
- }
1132
- break;
1133
- }
1134
- case "contract_call": {
1135
- for (const tx of transactions) {
1136
- if (tx.type !== "contract_call")
1137
- continue;
1138
- if (filter.contractId) {
1139
- if (!tx.contract_id || !matchAny(tx.contract_id, filter.contractId))
1140
- continue;
1141
- }
1142
- if (!factoryAllows(filter, tx.contract_id, factoryContracts))
1143
- continue;
1144
- if (filter.functionName) {
1145
- if (!tx.function_name || !matchPattern(tx.function_name, filter.functionName))
1146
- continue;
1147
- }
1148
- if (filter.caller) {
1149
- if (!matchPattern(tx.sender, filter.caller))
1150
- continue;
1151
- }
1152
- if (!traitAllows(filter, tx.contract_id, traitContracts))
1153
- continue;
1154
- const txEvents = eventsByTx.get(tx.tx_id) ?? [];
1155
- results.push({ tx, events: txEvents });
1156
- }
1157
- break;
1158
- }
1159
- case "contract_deploy": {
1160
- for (const tx of transactions) {
1161
- if (tx.type !== "smart_contract")
1162
- continue;
1163
- if (filter.deployer) {
1164
- if (!matchPattern(tx.sender, filter.deployer))
1165
- continue;
1166
- }
1167
- if (filter.contractName) {
1168
- const name = tx.contract_id?.split(".")[1] ?? "";
1169
- if (!matchPattern(name, filter.contractName))
1170
- continue;
1171
- }
1172
- const txEvents = eventsByTx.get(tx.tx_id) ?? [];
1173
- results.push({ tx, events: txEvents });
1174
- }
1175
- break;
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
- }
1228
- case "print_event": {
1229
- for (const tx of transactions) {
1230
- const txEvents = eventsByTx.get(tx.tx_id) ?? [];
1231
- const matched = txEvents.filter((e) => {
1232
- if (e.type !== "smart_contract_event" && e.type !== "contract_event")
1233
- return false;
1234
- const data = e.data;
1235
- if (!data)
1236
- return false;
1237
- if (data.topic !== "print")
1238
- return false;
1239
- const contractId = printContractId(data);
1240
- if (filter.contractId) {
1241
- if (!contractId || !matchAny(contractId, filter.contractId))
1242
- return false;
1243
- }
1244
- if (!traitAllows(filter, contractId, traitContracts))
1245
- return false;
1246
- if (!factoryAllows(filter, contractId, factoryContracts))
1247
- return false;
1248
- return true;
1249
- });
1250
- if (matched.length > 0) {
1251
- results.push({ tx, events: matched });
1252
- }
1253
- }
1254
- break;
1255
- }
1256
- }
1257
- return results;
1258
- }
1259
- function matchSources(sources, transactions, events, traitContracts = new Map, factoryContracts = new Map, vmEvents = []) {
1260
- const eventsByTx = new Map;
1261
- for (const event of events) {
1262
- const list = eventsByTx.get(event.tx_id) ?? [];
1263
- list.push(event);
1264
- eventsByTx.set(event.tx_id, list);
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
- }
1272
- const seen = new Set;
1273
- const results = [];
1274
- for (const [sourceName, filter] of Object.entries(sources)) {
1275
- const matches = matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts, vmEventsByTx);
1276
- for (const match of matches) {
1277
- const dedupeKey = `${match.tx.tx_id}:${sourceName}`;
1278
- if (!seen.has(dedupeKey)) {
1279
- seen.add(dedupeKey);
1280
- results.push({ ...match, sourceName });
1281
- }
1282
- }
1283
- }
1284
- return results;
1285
- }
1286
-
1287
- // src/runtime/runner.ts
1288
- import { getErrorMessage } from "@secondlayer/shared";
1289
- import { logger as logger4 } from "@secondlayer/shared/logger";
1290
- import {
1291
- clarityValueToJS,
1292
- deserializeCV as deserializeCV4,
1293
- toCamelCase as toCamelCase2
1294
- } from "@secondlayer/stacks/clarity";
1295
-
1296
- // src/print-schema.ts
1297
- import {
1298
- deserializeCV as deserializeCV3
1299
- } from "@secondlayer/stacks/clarity";
1300
- function camelizeDataKey(str) {
1301
- return str.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
1302
- }
1303
- function camelizeKeys(obj) {
1304
- if (obj === null || obj === undefined)
1305
- return obj;
1306
- if (typeof obj !== "object")
1307
- return obj;
1308
- if (Array.isArray(obj))
1309
- return obj.map(camelizeKeys);
1310
- const result = {};
1311
- for (const [k, v] of Object.entries(obj)) {
1312
- result[camelizeDataKey(k)] = camelizeKeys(v);
1313
- }
1314
- return result;
1315
- }
1316
- function cvToTree(cv) {
1317
- switch (cv.type) {
1318
- case "uint":
1319
- case "int":
1320
- return { kind: cv.type };
1321
- case "true":
1322
- case "false":
1323
- return { kind: "bool" };
1324
- case "address":
1325
- case "contract":
1326
- return { kind: "principal" };
1327
- case "buffer":
1328
- return { kind: "buffer", len: cv.value.length / 2 };
1329
- case "ascii":
1330
- return { kind: "ascii", len: cv.value.length };
1331
- case "utf8":
1332
- return { kind: "utf8", len: new TextEncoder().encode(cv.value).length };
1333
- case "none":
1334
- return { kind: "optional", inner: null };
1335
- case "some":
1336
- return { kind: "optional", inner: cvToTree(cv.value) };
1337
- case "ok":
1338
- return { kind: "response", ok: cvToTree(cv.value), err: null };
1339
- case "err":
1340
- return { kind: "response", ok: null, err: cvToTree(cv.value) };
1341
- case "list": {
1342
- let inner = null;
1343
- for (const el of cv.value) {
1344
- const t = cvToTree(el);
1345
- inner = inner ? unify(inner, t) : t;
1346
- }
1347
- return { kind: "list", inner };
1348
- }
1349
- case "tuple": {
1350
- const entries = new Map;
1351
- for (const [k, v] of Object.entries(cv.value)) {
1352
- entries.set(k, { tree: cvToTree(v), present: 1 });
1353
- }
1354
- return { kind: "tuple", count: 1, entries };
1355
- }
1356
- }
1357
- }
1358
- function unifyNullable(a, b) {
1359
- if (!a)
1360
- return b;
1361
- if (!b)
1362
- return a;
1363
- return unify(a, b);
1364
- }
1365
- var UNION_KIND_ORDER = {
1366
- uint: 0,
1367
- int: 1,
1368
- bool: 2,
1369
- principal: 3,
1370
- buffer: 4,
1371
- ascii: 5,
1372
- utf8: 6,
1373
- list: 7,
1374
- tuple: 8,
1375
- response: 9
1376
- };
1377
- function makeUnion(members) {
1378
- const sorted = [...members].sort((a, b) => (UNION_KIND_ORDER[a.kind] ?? 99) - (UNION_KIND_ORDER[b.kind] ?? 99));
1379
- return { kind: "union", members: sorted };
1380
- }
1381
- function unify(a, b) {
1382
- if (a.kind === "optional" || b.kind === "optional") {
1383
- const ai = a.kind === "optional" ? a.inner : a;
1384
- const bi = b.kind === "optional" ? b.inner : b;
1385
- return { kind: "optional", inner: unifyNullable(ai, bi) };
1386
- }
1387
- if (a.kind === "union")
1388
- return unionAdd(a.members, b);
1389
- if (b.kind === "union")
1390
- return unionAdd(b.members, a);
1391
- if (a.kind !== b.kind)
1392
- return makeUnion([a, b]);
1393
- switch (a.kind) {
1394
- case "uint":
1395
- case "int":
1396
- case "bool":
1397
- case "principal":
1398
- return a;
1399
- case "buffer":
1400
- case "ascii":
1401
- case "utf8":
1402
- return { kind: a.kind, len: Math.max(a.len, b.len) };
1403
- case "list":
1404
- return {
1405
- kind: "list",
1406
- inner: unifyNullable(a.inner, b.inner)
1407
- };
1408
- case "response": {
1409
- const rb = b;
1410
- return {
1411
- kind: "response",
1412
- ok: unifyNullable(a.ok, rb.ok),
1413
- err: unifyNullable(a.err, rb.err)
1414
- };
1415
- }
1416
- case "tuple": {
1417
- const tb = b;
1418
- const entries = new Map([...a.entries].map(([k, e]) => [k, { ...e }]));
1419
- for (const [k, e] of tb.entries) {
1420
- const existing = entries.get(k);
1421
- entries.set(k, existing ? {
1422
- tree: unify(existing.tree, e.tree),
1423
- present: existing.present + e.present
1424
- } : { ...e });
1425
- }
1426
- return { kind: "tuple", count: a.count + tb.count, entries };
1427
- }
1428
- }
1429
- }
1430
- function unionAdd(members, t) {
1431
- if (t.kind === "union") {
1432
- let acc = { kind: "union", members };
1433
- for (const m of t.members)
1434
- acc = unify(acc, m);
1435
- return acc;
1436
- }
1437
- const next = [...members];
1438
- for (let i = 0;i < next.length; i++) {
1439
- const member = next[i];
1440
- if (!member)
1441
- continue;
1442
- const merged = unify(member, t);
1443
- if (merged.kind !== "union") {
1444
- next[i] = merged;
1445
- return makeUnion(next);
1446
- }
1447
- }
1448
- next.push(t);
1449
- return makeUnion(next);
1450
- }
1451
- function wrapOptional(t) {
1452
- return t.kind === "optional" ? t : { kind: "optional", inner: t };
1029
+ function wrapOptional(t) {
1030
+ return t.kind === "optional" ? t : { kind: "optional", inner: t };
1453
1031
  }
1454
1032
  function renderClarity(t) {
1455
1033
  if (!t)
@@ -1576,7 +1154,7 @@ function inferPrintTopics(samples) {
1576
1154
  let decoded = 0;
1577
1155
  for (const p of picked) {
1578
1156
  try {
1579
- const cv = deserializeCV3(p.rawHex);
1157
+ const cv = deserializeCV2(p.rawHex);
1580
1158
  decoded++;
1581
1159
  if (cv.type === "tuple")
1582
1160
  tuples.push(cv);
@@ -1610,221 +1188,395 @@ function inferPrintTopics(samples) {
1610
1188
  }
1611
1189
  }
1612
1190
  }
1613
- for (const [name, st] of [...stats].sort(([a], [b]) => a.localeCompare(b))) {
1614
- const field = {
1615
- name,
1616
- camel_name: camelizeDataKey(name),
1617
- clarity_type: renderClarity(st.tree),
1618
- ts_type: renderTs(st.tree),
1619
- column_type: toColumnType(st.tree),
1620
- always_present: st.present === tuples.length
1621
- };
1622
- if (st.optionalSeen) {
1623
- field.optional_some_rate = (st.present - st.noneCount) / st.present;
1191
+ for (const [name, st] of [...stats].sort(([a], [b]) => a.localeCompare(b))) {
1192
+ const field = {
1193
+ name,
1194
+ camel_name: camelizeDataKey(name),
1195
+ clarity_type: renderClarity(st.tree),
1196
+ ts_type: renderTs(st.tree),
1197
+ column_type: toColumnType(st.tree),
1198
+ always_present: st.present === tuples.length
1199
+ };
1200
+ if (st.optionalSeen) {
1201
+ field.optional_some_rate = (st.present - st.noneCount) / st.present;
1202
+ }
1203
+ fields.push(field);
1204
+ }
1205
+ }
1206
+ out.push({
1207
+ topic,
1208
+ count: rows.length,
1209
+ first_height: first,
1210
+ last_height: last,
1211
+ non_tuple: nonTuple,
1212
+ fields
1213
+ });
1214
+ }
1215
+ return out.sort((a, b) => b.count - a.count);
1216
+ }
1217
+
1218
+ // src/runtime/clarity.ts
1219
+ import { cvToValue, deserializeCV as deserializeCV3 } from "@secondlayer/stacks/clarity";
1220
+ function decodeClarityValue(hex) {
1221
+ try {
1222
+ const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
1223
+ const cv = deserializeCV3(cleanHex);
1224
+ return cvToValue(cv);
1225
+ } catch {
1226
+ return hex;
1227
+ }
1228
+ }
1229
+ function decodeEventData(data) {
1230
+ if (typeof data === "string" && data.startsWith("0x") && data.length > 10) {
1231
+ return decodeClarityValue(data);
1232
+ }
1233
+ if (Array.isArray(data)) {
1234
+ return data.map(decodeEventData);
1235
+ }
1236
+ if (typeof data === "object" && data !== null) {
1237
+ const decoded = {};
1238
+ for (const [key, value] of Object.entries(data)) {
1239
+ decoded[key] = decodeEventData(value);
1240
+ }
1241
+ return decoded;
1242
+ }
1243
+ return data;
1244
+ }
1245
+
1246
+ // src/runtime/print-validate.ts
1247
+ var COLUMN_TYPES = new Set([
1248
+ "text",
1249
+ "uint",
1250
+ "int",
1251
+ "principal",
1252
+ "boolean",
1253
+ "timestamp",
1254
+ "jsonb"
1255
+ ]);
1256
+
1257
+ // src/runtime/source-matcher.ts
1258
+ var patternCache = new Map;
1259
+ function matchAny(value, pattern) {
1260
+ return Array.isArray(pattern) ? pattern.some((p) => matchPattern(value, p)) : matchPattern(value, pattern);
1261
+ }
1262
+ function matchPattern(value, pattern) {
1263
+ if (!pattern.includes("*"))
1264
+ return value === pattern;
1265
+ let re = patternCache.get(pattern);
1266
+ if (!re) {
1267
+ const regex = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
1268
+ re = new RegExp(`^${regex}$`);
1269
+ patternCache.set(pattern, re);
1270
+ }
1271
+ return re.test(value);
1272
+ }
1273
+ var EMPTY_SET = new Set;
1274
+ function factoryAllows(filter, contractId, factoryContracts) {
1275
+ if (!filter.factory)
1276
+ return true;
1277
+ if (!contractId)
1278
+ return false;
1279
+ return (factoryContracts.get(filter.factory.from) ?? EMPTY_SET).has(contractId);
1280
+ }
1281
+ function traitAllows(filter, contractId, traitContracts) {
1282
+ const trait = filter.trait;
1283
+ if (!trait)
1284
+ return true;
1285
+ if (!contractId)
1286
+ return false;
1287
+ return (traitContracts.get(trait) ?? EMPTY_SET).has(contractId);
1288
+ }
1289
+ function assetContract(assetId) {
1290
+ return assetId?.split("::")[0];
1291
+ }
1292
+ function printContractId(data) {
1293
+ if (!data)
1294
+ return;
1295
+ const id = (typeof data.contract_identifier === "string" ? data.contract_identifier : undefined) ?? (typeof data.contract_id === "string" ? data.contract_id : undefined);
1296
+ return id || undefined;
1297
+ }
1298
+ function matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts = new Map, vmEventsByTx = new Map) {
1299
+ const results = [];
1300
+ switch (filter.type) {
1301
+ case "stx_transfer":
1302
+ case "stx_mint":
1303
+ case "stx_burn":
1304
+ case "stx_lock": {
1305
+ const eventType = `${filter.type}_event`;
1306
+ for (const tx of transactions) {
1307
+ const txEvents = eventsByTx.get(tx.tx_id) ?? [];
1308
+ const matched = txEvents.filter((e) => e.type === eventType);
1309
+ if (matched.length === 0)
1310
+ continue;
1311
+ const filtered = matched.filter((e) => {
1312
+ const data = e.data;
1313
+ if (!data)
1314
+ return false;
1315
+ if ("sender" in filter && filter.sender) {
1316
+ if (!matchPattern(data.sender, filter.sender))
1317
+ return false;
1318
+ }
1319
+ if ("recipient" in filter && filter.recipient) {
1320
+ if (!matchPattern(data.recipient, filter.recipient))
1321
+ return false;
1322
+ }
1323
+ if ("lockedAddress" in filter && filter.lockedAddress) {
1324
+ if (!matchPattern(data.locked_address, filter.lockedAddress))
1325
+ return false;
1326
+ }
1327
+ if ("minAmount" in filter && filter.minAmount !== undefined) {
1328
+ const amount = BigInt(data.amount ?? data.locked_amount ?? "0");
1329
+ if (amount < filter.minAmount)
1330
+ return false;
1331
+ }
1332
+ if ("maxAmount" in filter && filter.maxAmount !== undefined) {
1333
+ const amount = BigInt(data.amount ?? "0");
1334
+ if (amount > filter.maxAmount)
1335
+ return false;
1336
+ }
1337
+ return true;
1338
+ });
1339
+ if (filtered.length > 0) {
1340
+ results.push({ tx, events: filtered });
1341
+ }
1342
+ }
1343
+ break;
1344
+ }
1345
+ case "ft_transfer":
1346
+ case "ft_mint":
1347
+ case "ft_burn": {
1348
+ const eventType = `${filter.type}_event`;
1349
+ for (const tx of transactions) {
1350
+ const txEvents = eventsByTx.get(tx.tx_id) ?? [];
1351
+ const matched = txEvents.filter((e) => {
1352
+ if (e.type !== eventType)
1353
+ return false;
1354
+ const data = e.data;
1355
+ if (!data)
1356
+ return false;
1357
+ if (filter.assetIdentifier) {
1358
+ const assetId = data.asset_identifier;
1359
+ if (!assetId || !matchPattern(assetId, filter.assetIdentifier))
1360
+ return false;
1361
+ }
1362
+ if (!traitAllows(filter, assetContract(data.asset_identifier), traitContracts))
1363
+ return false;
1364
+ if ("sender" in filter && filter.sender) {
1365
+ if (!matchPattern(data.sender, filter.sender))
1366
+ return false;
1367
+ }
1368
+ if ("recipient" in filter && filter.recipient) {
1369
+ if (!matchPattern(data.recipient, filter.recipient))
1370
+ return false;
1371
+ }
1372
+ if (filter.minAmount !== undefined) {
1373
+ const amount = BigInt(data.amount ?? "0");
1374
+ if (amount < filter.minAmount)
1375
+ return false;
1376
+ }
1377
+ return true;
1378
+ });
1379
+ if (matched.length > 0) {
1380
+ results.push({ tx, events: matched });
1381
+ }
1382
+ }
1383
+ break;
1384
+ }
1385
+ case "nft_transfer":
1386
+ case "nft_mint":
1387
+ case "nft_burn": {
1388
+ const eventType = `${filter.type}_event`;
1389
+ for (const tx of transactions) {
1390
+ const txEvents = eventsByTx.get(tx.tx_id) ?? [];
1391
+ const matched = txEvents.filter((e) => {
1392
+ if (e.type !== eventType)
1393
+ return false;
1394
+ const data = e.data;
1395
+ if (!data)
1396
+ return false;
1397
+ if (filter.assetIdentifier) {
1398
+ const assetId = data.asset_identifier;
1399
+ if (!assetId || !matchPattern(assetId, filter.assetIdentifier))
1400
+ return false;
1401
+ }
1402
+ if (!traitAllows(filter, assetContract(data.asset_identifier), traitContracts))
1403
+ return false;
1404
+ if ("sender" in filter && filter.sender) {
1405
+ if (!matchPattern(data.sender, filter.sender))
1406
+ return false;
1407
+ }
1408
+ if ("recipient" in filter && filter.recipient) {
1409
+ if (!matchPattern(data.recipient, filter.recipient))
1410
+ return false;
1411
+ }
1412
+ return true;
1413
+ });
1414
+ if (matched.length > 0) {
1415
+ results.push({ tx, events: matched });
1416
+ }
1417
+ }
1418
+ break;
1419
+ }
1420
+ case "contract_call": {
1421
+ for (const tx of transactions) {
1422
+ if (tx.type !== "contract_call")
1423
+ continue;
1424
+ if (filter.contractId) {
1425
+ if (!tx.contract_id || !matchAny(tx.contract_id, filter.contractId))
1426
+ continue;
1427
+ }
1428
+ if (!factoryAllows(filter, tx.contract_id, factoryContracts))
1429
+ continue;
1430
+ if (filter.functionName) {
1431
+ if (!tx.function_name || !matchPattern(tx.function_name, filter.functionName))
1432
+ continue;
1433
+ }
1434
+ if (filter.caller) {
1435
+ if (!matchPattern(tx.sender, filter.caller))
1436
+ continue;
1437
+ }
1438
+ if (!traitAllows(filter, tx.contract_id, traitContracts))
1439
+ continue;
1440
+ const txEvents = eventsByTx.get(tx.tx_id) ?? [];
1441
+ results.push({ tx, events: txEvents });
1442
+ }
1443
+ break;
1444
+ }
1445
+ case "contract_deploy": {
1446
+ for (const tx of transactions) {
1447
+ if (tx.type !== "smart_contract")
1448
+ continue;
1449
+ if (filter.deployer) {
1450
+ if (!matchPattern(tx.sender, filter.deployer))
1451
+ continue;
1624
1452
  }
1625
- fields.push(field);
1453
+ if (filter.contractName) {
1454
+ const name = tx.contract_id?.split(".")[1] ?? "";
1455
+ if (!matchPattern(name, filter.contractName))
1456
+ continue;
1457
+ }
1458
+ const txEvents = eventsByTx.get(tx.tx_id) ?? [];
1459
+ results.push({ tx, events: txEvents });
1626
1460
  }
1461
+ break;
1627
1462
  }
1628
- out.push({
1629
- topic,
1630
- count: rows.length,
1631
- first_height: first,
1632
- last_height: last,
1633
- non_tuple: nonTuple,
1634
- fields
1635
- });
1636
- }
1637
- return out.sort((a, b) => b.count - a.count);
1638
- }
1639
-
1640
- // src/runtime/materialize.ts
1641
- function resolveColumn(col, event, tx, block) {
1642
- if ("fromTx" in col) {
1643
- return { ok: true, value: tx[col.fromTx] };
1644
- }
1645
- if ("fromBlock" in col) {
1646
- return { ok: true, value: block[col.fromBlock] };
1647
- }
1648
- const data = event.data;
1649
- const dataObj = data !== null && typeof data === "object" && !Array.isArray(data) ? data : undefined;
1650
- if (dataObj && Object.prototype.hasOwnProperty.call(dataObj, col.from)) {
1651
- return { ok: true, value: dataObj[col.from] };
1652
- }
1653
- if (col.from === "topic" && "topic" in event) {
1654
- return { ok: true, value: event.topic };
1655
- }
1656
- if (Object.prototype.hasOwnProperty.call(event, col.from)) {
1657
- return { ok: true, value: event[col.from] };
1658
- }
1659
- return { ok: false, missing: col.from };
1660
- }
1661
- function buildMaterializeRow(spec, event, ctx, tableColumns) {
1662
- const row = {};
1663
- for (const [colName, mapping] of Object.entries(spec.columns)) {
1664
- const resolved = resolveColumn(mapping, event, ctx.tx, ctx.block);
1665
- if (!resolved.ok) {
1666
- const colDef = tableColumns[colName];
1667
- if (colDef?.nullable) {
1668
- row[colName] = null;
1669
- continue;
1463
+ case "nested_contract_call":
1464
+ case "var_set":
1465
+ case "map_set":
1466
+ case "map_insert":
1467
+ case "map_delete": {
1468
+ for (const tx of transactions) {
1469
+ const txEvents = vmEventsByTx.get(tx.tx_id) ?? [];
1470
+ const matched = txEvents.filter((e) => {
1471
+ if (e.type !== filter.type)
1472
+ return false;
1473
+ const data = e.data;
1474
+ if (!data)
1475
+ return false;
1476
+ const contractId = printContractId(data);
1477
+ if ("contractId" in filter && filter.contractId) {
1478
+ if (!contractId || !matchAny(contractId, filter.contractId))
1479
+ return false;
1480
+ }
1481
+ if (!traitAllows(filter, contractId, traitContracts))
1482
+ return false;
1483
+ if (!factoryAllows(filter, contractId, factoryContracts))
1484
+ return false;
1485
+ if (filter.type === "nested_contract_call") {
1486
+ if (filter.functionName) {
1487
+ if (typeof data.function_name !== "string" || !matchPattern(data.function_name, filter.functionName))
1488
+ return false;
1489
+ }
1490
+ if (filter.caller) {
1491
+ if (typeof data.caller !== "string" || !matchPattern(data.caller, filter.caller))
1492
+ return false;
1493
+ }
1494
+ if (filter.sender) {
1495
+ if (typeof data.sender !== "string" || !matchPattern(data.sender, filter.sender))
1496
+ return false;
1497
+ }
1498
+ }
1499
+ if (filter.type === "var_set" && filter.varName) {
1500
+ if (typeof data.var_name !== "string" || !matchPattern(data.var_name, filter.varName))
1501
+ return false;
1502
+ }
1503
+ if ((filter.type === "map_set" || filter.type === "map_insert" || filter.type === "map_delete") && filter.map) {
1504
+ if (typeof data.map_name !== "string" || !matchPattern(data.map_name, filter.map))
1505
+ return false;
1506
+ }
1507
+ return true;
1508
+ });
1509
+ if (matched.length > 0)
1510
+ results.push({ tx, events: matched });
1670
1511
  }
1671
- return {
1672
- ok: false,
1673
- reason: `required materialize field "${resolved.missing}" missing for column "${colName}"`
1674
- };
1512
+ break;
1513
+ }
1514
+ case "print_event": {
1515
+ for (const tx of transactions) {
1516
+ const txEvents = eventsByTx.get(tx.tx_id) ?? [];
1517
+ const matched = txEvents.filter((e) => {
1518
+ if (e.type !== "smart_contract_event" && e.type !== "contract_event")
1519
+ return false;
1520
+ const data = e.data;
1521
+ if (!data)
1522
+ return false;
1523
+ if (data.topic !== "print")
1524
+ return false;
1525
+ const contractId = printContractId(data);
1526
+ if (filter.contractId) {
1527
+ if (!contractId || !matchAny(contractId, filter.contractId))
1528
+ return false;
1529
+ }
1530
+ if (!traitAllows(filter, contractId, traitContracts))
1531
+ return false;
1532
+ if (!factoryAllows(filter, contractId, factoryContracts))
1533
+ return false;
1534
+ return true;
1535
+ });
1536
+ if (matched.length > 0) {
1537
+ results.push({ tx, events: matched });
1538
+ }
1539
+ }
1540
+ break;
1675
1541
  }
1676
- row[colName] = resolved.value ?? null;
1677
- }
1678
- return { ok: true, row };
1679
- }
1680
- function applyMaterializeInsert(spec, event, ctx, schema) {
1681
- const table = schema[spec.table];
1682
- if (!table) {
1683
- return { ok: false, reason: `materialize table "${spec.table}" missing` };
1684
1542
  }
1685
- const built = buildMaterializeRow(spec, event, ctx, table.columns);
1686
- if (!built.ok)
1687
- return built;
1688
- ctx.insert(spec.table, built.row);
1689
- return { ok: true };
1543
+ return results;
1690
1544
  }
1691
-
1692
- // src/runtime/print-validate.ts
1693
- var COLUMN_TYPES = new Set([
1694
- "text",
1695
- "uint",
1696
- "int",
1697
- "principal",
1698
- "boolean",
1699
- "timestamp",
1700
- "jsonb"
1701
- ]);
1702
- function isColumnType(field) {
1703
- return typeof field === "string" && COLUMN_TYPES.has(field);
1704
- }
1705
- function matchesField(field, value) {
1706
- if (isColumnType(field)) {
1707
- switch (field) {
1708
- case "uint":
1709
- case "int":
1710
- return typeof value === "bigint" || typeof value === "number";
1711
- case "boolean":
1712
- return typeof value === "boolean";
1713
- case "text":
1714
- case "principal":
1715
- case "timestamp":
1716
- return typeof value === "string" || typeof value === "number" || typeof value === "bigint";
1717
- case "jsonb":
1718
- return value !== undefined;
1719
- }
1720
- }
1721
- if (typeof field !== "object" || field === null)
1722
- return false;
1723
- if ("optional" in field) {
1724
- return value === undefined || value === null || matchesField(field.type, value);
1725
- }
1726
- if ("tuple" in field) {
1727
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
1728
- return false;
1729
- }
1730
- return matchesTopic(field.tuple, value).ok;
1545
+ function matchSources(sources, transactions, events, traitContracts = new Map, factoryContracts = new Map, vmEvents = []) {
1546
+ const eventsByTx = new Map;
1547
+ for (const event of events) {
1548
+ const list = eventsByTx.get(event.tx_id) ?? [];
1549
+ list.push(event);
1550
+ eventsByTx.set(event.tx_id, list);
1731
1551
  }
1732
- if ("list" in field) {
1733
- return Array.isArray(value) && value.every((item) => matchesField(field.list, item));
1552
+ const vmEventsByTx = new Map;
1553
+ for (const event of vmEvents) {
1554
+ const list = vmEventsByTx.get(event.tx_id) ?? [];
1555
+ list.push(event);
1556
+ vmEventsByTx.set(event.tx_id, list);
1734
1557
  }
1735
- return false;
1736
- }
1737
- function matchesTopic(declared, data) {
1738
- for (const [name, field] of Object.entries(declared)) {
1739
- const present = name in data;
1740
- const optional = typeof field === "object" && field !== null && "optional" in field;
1741
- if (!present) {
1742
- if (optional)
1743
- continue;
1744
- return { ok: false, reason: `missing declared field "${name}"` };
1745
- }
1746
- if (!matchesField(field, data[name])) {
1747
- return {
1748
- ok: false,
1749
- reason: `field "${name}" does not match its declared type (got ${describe(data[name])})`
1750
- };
1558
+ const seen = new Set;
1559
+ const results = [];
1560
+ for (const [sourceName, filter] of Object.entries(sources)) {
1561
+ const matches = matchFilter(filter, transactions, eventsByTx, traitContracts, factoryContracts, vmEventsByTx);
1562
+ for (const match of matches) {
1563
+ const dedupeKey = `${match.tx.tx_id}:${sourceName}`;
1564
+ if (!seen.has(dedupeKey)) {
1565
+ seen.add(dedupeKey);
1566
+ results.push({ ...match, sourceName });
1567
+ }
1751
1568
  }
1752
1569
  }
1753
- return { ok: true };
1754
- }
1755
- function describe(value) {
1756
- if (value === null)
1757
- return "null";
1758
- if (Array.isArray(value))
1759
- return "array";
1760
- return typeof value;
1761
- }
1762
- function validatePrintPayload(prints, topic, data) {
1763
- if (!prints)
1764
- return { ok: true };
1765
- const declared = prints[topic];
1766
- if (!declared)
1767
- return { ok: true };
1768
- return matchesTopic(declared, data);
1570
+ return results;
1769
1571
  }
1770
1572
 
1771
1573
  // src/runtime/violations.ts
1772
1574
  import { getTargetDb } from "@secondlayer/shared/db";
1773
1575
  import { logger as logger3 } from "@secondlayer/shared/logger";
1774
1576
  import { sql as sql2 } from "kysely";
1775
- var VIOLATIONS_CAP_PER_SUBGRAPH = 100;
1776
- function jsonSafe2(value) {
1777
- if (typeof value === "bigint")
1778
- return value.toString();
1779
- if (value === null || value === undefined)
1780
- return value;
1781
- if (Array.isArray(value))
1782
- return value.map(jsonSafe2);
1783
- if (typeof value === "object") {
1784
- const out = {};
1785
- for (const [k, v] of Object.entries(value)) {
1786
- out[k] = jsonSafe2(v);
1787
- }
1788
- return out;
1789
- }
1790
- return value;
1791
- }
1792
- async function defaultRecordPrintViolation(input) {
1793
- try {
1794
- const db = getTargetDb();
1795
- const sample = jsonSafe2(input.samplePayload);
1796
- await db.insertInto("subgraph_violations").values({
1797
- subgraph_name: input.subgraphName,
1798
- source_name: input.sourceName,
1799
- block_height: input.blockHeight,
1800
- tx_id: input.txId,
1801
- reason: input.reason,
1802
- sample_payload: sample
1803
- }).execute();
1804
- await sql2`
1805
- DELETE FROM subgraph_violations
1806
- WHERE id IN (
1807
- SELECT id FROM subgraph_violations
1808
- WHERE subgraph_name = ${input.subgraphName}
1809
- ORDER BY seen_at DESC
1810
- OFFSET ${VIOLATIONS_CAP_PER_SUBGRAPH}
1811
- )
1812
- `.execute(db);
1813
- } catch (err) {
1814
- logger3.warn("Failed to record print violation", {
1815
- subgraph: input.subgraphName,
1816
- error: err instanceof Error ? err.message : String(err)
1817
- });
1818
- }
1819
- }
1820
- var recorder = defaultRecordPrintViolation;
1821
- async function recordPrintViolation(input) {
1822
- await recorder(input);
1823
- }
1824
1577
 
1825
1578
  // src/runtime/runner.ts
1826
- var DEFAULT_ERROR_THRESHOLD = 50;
1827
- function decodeFunctionArgs2(args) {
1579
+ function decodeFunctionArgs(args) {
1828
1580
  let parsed = args;
1829
1581
  if (typeof parsed === "string") {
1830
1582
  try {
@@ -1907,7 +1659,7 @@ function buildEventPayload(filter, tx, event) {
1907
1659
  contractId: tx.contract_id ?? null,
1908
1660
  functionName: tx.function_name ?? null
1909
1661
  };
1910
- const decodedArgs = decodeFunctionArgs2(tx.function_args);
1662
+ const decodedArgs = decodeFunctionArgs(tx.function_args);
1911
1663
  const decodedResult = decodeRawResult(tx.raw_result);
1912
1664
  if (!event) {
1913
1665
  switch (filter.type) {
@@ -2054,7 +1806,7 @@ function buildEventPayload(filter, tx, event) {
2054
1806
  sender: typeof data.sender === "string" ? data.sender : null,
2055
1807
  caller: typeof data.caller === "string" ? data.caller : "",
2056
1808
  functionName: typeof data.function_name === "string" ? data.function_name : "",
2057
- args: decodeFunctionArgs2(argsHex),
1809
+ args: decodeFunctionArgs(argsHex),
2058
1810
  arguments: argsHex,
2059
1811
  rawResult: typeof data.raw_result === "string" ? data.raw_result : "",
2060
1812
  result: decodeRawResult(data.raw_result),
@@ -2106,152 +1858,8 @@ function buildEventPayload(filter, tx, event) {
2106
1858
  };
2107
1859
  }
2108
1860
  }
2109
- async function runHandlers(subgraph, matched, ctx, opts) {
2110
- let processed = 0;
2111
- let errors = 0;
2112
- let skipped = 0;
2113
- const threshold = opts?.errorThreshold ?? DEFAULT_ERROR_THRESHOLD;
2114
- const filterLookup = new Map;
2115
- if (!Array.isArray(subgraph.sources)) {
2116
- for (const [name, filter] of Object.entries(subgraph.sources)) {
2117
- filterLookup.set(name, filter);
2118
- }
2119
- }
2120
- const units = [];
2121
- for (const { tx, events, sourceName } of matched) {
2122
- if (events.length === 0) {
2123
- units.push({ tx, sourceName, event: null });
2124
- } else {
2125
- for (const event of events)
2126
- units.push({ tx, sourceName, event });
2127
- }
2128
- }
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));
2131
- for (const { tx, event, sourceName } of units) {
2132
- if (errors >= threshold) {
2133
- logger4.error("Subgraph error threshold reached, skipping remaining events", {
2134
- subgraph: subgraph.name,
2135
- errors,
2136
- threshold
2137
- });
2138
- return { processed, errors, ...skipped > 0 ? { skipped } : {} };
2139
- }
2140
- const filter = filterLookup.get(sourceName);
2141
- const materialize = filter && "materialize" in filter && filter.materialize !== undefined ? filter.materialize : undefined;
2142
- const handler = subgraph.handlers[sourceName] ?? subgraph.handlers["*"] ?? null;
2143
- if (!handler && !materialize) {
2144
- logger4.warn("No handler found for source", {
2145
- subgraph: subgraph.name,
2146
- sourceName,
2147
- txId: tx.tx_id
2148
- });
2149
- continue;
2150
- }
2151
- ctx.setTx({
2152
- txId: tx.tx_id,
2153
- sender: tx.sender,
2154
- type: tx.type,
2155
- status: tx.status,
2156
- contractId: tx.contract_id ?? null,
2157
- functionName: tx.function_name ?? null
2158
- });
2159
- const checkpoint = ctx.opsCheckpoint();
2160
- try {
2161
- let payload;
2162
- if (event === null) {
2163
- payload = filter ? buildEventPayload(filter, tx, null) : {
2164
- tx: {
2165
- txId: tx.tx_id,
2166
- sender: tx.sender,
2167
- type: tx.type,
2168
- status: tx.status,
2169
- contractId: tx.contract_id,
2170
- functionName: tx.function_name
2171
- }
2172
- };
2173
- } else if (filter) {
2174
- payload = buildEventPayload(filter, tx, event);
2175
- } else {
2176
- const decoded = decodeEventData(event.data);
2177
- payload = {
2178
- ...decoded,
2179
- _eventId: event.id,
2180
- _eventType: event.type,
2181
- _eventIndex: event.event_index,
2182
- tx: {
2183
- txId: tx.tx_id,
2184
- sender: tx.sender,
2185
- type: tx.type,
2186
- status: tx.status,
2187
- contractId: tx.contract_id,
2188
- functionName: tx.function_name
2189
- }
2190
- };
2191
- }
2192
- if (event !== null && filter?.type === "print_event" && filter.topic && payload.topic !== filter.topic) {
2193
- continue;
2194
- }
2195
- if (event !== null && filter?.type === "print_event" && filter.prints) {
2196
- const printPayload = payload;
2197
- const verdict = validatePrintPayload(filter.prints, printPayload.topic ?? "", printPayload.data ?? {});
2198
- if (!verdict.ok) {
2199
- skipped++;
2200
- logger4.warn("Print payload does not match declared prints schema", {
2201
- subgraph: subgraph.name,
2202
- sourceName,
2203
- topic: printPayload.topic,
2204
- txId: tx.tx_id,
2205
- reason: verdict.reason
2206
- });
2207
- recordPrintViolation({
2208
- subgraphName: subgraph.name,
2209
- sourceName,
2210
- blockHeight: ctx.block.height,
2211
- txId: tx.tx_id,
2212
- reason: verdict.reason,
2213
- samplePayload: {
2214
- topic: printPayload.topic ?? "",
2215
- data: printPayload.data ?? {}
2216
- }
2217
- });
2218
- continue;
2219
- }
2220
- }
2221
- if (materialize) {
2222
- const result = applyMaterializeInsert(materialize, payload, ctx, subgraph.schema);
2223
- if (!result.ok) {
2224
- skipped++;
2225
- logger4.warn("Materialize skipped: required field missing", {
2226
- subgraph: subgraph.name,
2227
- sourceName,
2228
- txId: tx.tx_id,
2229
- reason: result.reason
2230
- });
2231
- continue;
2232
- }
2233
- processed++;
2234
- } else if (handler) {
2235
- await handler(payload, ctx);
2236
- processed++;
2237
- }
2238
- } catch (err) {
2239
- ctx.rollbackTo(checkpoint);
2240
- errors++;
2241
- logger4.error("Subgraph handler error", {
2242
- subgraph: subgraph.name,
2243
- sourceName,
2244
- txId: tx.tx_id,
2245
- ...event !== null ? { eventId: event.id, eventType: event.type } : {},
2246
- error: getErrorMessage(err)
2247
- });
2248
- }
2249
- }
2250
- return { processed, errors, ...skipped > 0 ? { skipped } : {} };
2251
- }
2252
1861
 
2253
1862
  // src/testing/harness.ts
2254
- import { normalizeAbi as normalizeAbi2, toCamelCase as toCamelCase3 } from "@secondlayer/stacks/clarity";
2255
1863
  var TEST_SCHEMA_NAME = "subgraph_test";
2256
1864
  function defaultBlock(overrides = {}) {
2257
1865
  return {
@@ -2457,17 +2065,17 @@ function toContractCallPayload(row) {
2457
2065
  }
2458
2066
  };
2459
2067
  }
2460
- function jsonSafe3(value) {
2068
+ function jsonSafe2(value) {
2461
2069
  if (typeof value === "bigint")
2462
2070
  return value.toString();
2463
2071
  if (value === null || value === undefined)
2464
2072
  return value;
2465
2073
  if (Array.isArray(value))
2466
- return value.map(jsonSafe3);
2074
+ return value.map(jsonSafe2);
2467
2075
  if (typeof value === "object") {
2468
2076
  const out = {};
2469
2077
  for (const [k, v] of Object.entries(value)) {
2470
- out[k] = jsonSafe3(v);
2078
+ out[k] = jsonSafe2(v);
2471
2079
  }
2472
2080
  return out;
2473
2081
  }
@@ -2533,9 +2141,8 @@ async function runSubgraphTest(input) {
2533
2141
  const traces = [];
2534
2142
  for (const [name, rows] of Object.entries(events)) {
2535
2143
  const filter = sources[name];
2536
- const handler = handlers[name] ?? handlers["*"];
2537
- const materialize = filter && "materialize" in filter && filter.materialize !== undefined ? filter.materialize : undefined;
2538
- if (typeof handler !== "function" && !materialize)
2144
+ const handler = handlers[name];
2145
+ if (typeof handler !== "function")
2539
2146
  continue;
2540
2147
  for (const row of rows) {
2541
2148
  const payload = filter?.type === "contract_call" ? toContractCallPayload(row) : toHandlerPayload(filter, row);
@@ -2556,17 +2163,7 @@ async function runSubgraphTest(input) {
2556
2163
  try {
2557
2164
  ctx.setTx(txFromRow(row));
2558
2165
  const event = buildEvent(filter, payload, { tx: ctx.tx });
2559
- if (materialize) {
2560
- applyMaterializeInsert(materialize, event, {
2561
- tx: ctx.tx,
2562
- block: ctx.block,
2563
- insert: (table, insertRow) => {
2564
- ctx.insert(table, insertRow);
2565
- }
2566
- }, schema);
2567
- } else {
2568
- await handler(event, ctx);
2569
- }
2166
+ await handler(event, ctx);
2570
2167
  } catch {}
2571
2168
  if (trace) {
2572
2169
  const inserts = ctx.pendingInsertsSince(checkpoint);
@@ -2589,7 +2186,7 @@ async function runSubgraphTest(input) {
2589
2186
  tables.push({
2590
2187
  name: table,
2591
2188
  rows: tableRows.length,
2592
- ...sample ? { sampleRow: jsonSafe3(sample) } : {}
2189
+ ...sample ? { sampleRow: jsonSafe2(sample) } : {}
2593
2190
  });
2594
2191
  }
2595
2192
  const fetched = Object.values(events).reduce((n, r) => n + r.length, 0);
@@ -2618,7 +2215,7 @@ async function runSubgraphTest(input) {
2618
2215
  matched,
2619
2216
  written: 0,
2620
2217
  tables,
2621
- firstEvent: firstEvent ? { ...firstEvent, data: jsonSafe3(firstEvent.data) } : undefined,
2218
+ firstEvent: firstEvent ? { ...firstEvent, data: jsonSafe2(firstEvent.data) } : undefined,
2622
2219
  hint: `${matched} event${matched === 1 ? "" : "s"} matched, but NO rows were written — the shape of the field-mapping bug that ships a 0-row subgraph.${keyPart} Map only observed keys; do not invent fields.`,
2623
2220
  ...traceFields
2624
2221
  };
@@ -2632,7 +2229,7 @@ async function runSubgraphTest(input) {
2632
2229
  matched,
2633
2230
  written,
2634
2231
  tables,
2635
- firstEvent: firstEvent ? { ...firstEvent, data: jsonSafe3(firstEvent.data) } : undefined,
2232
+ firstEvent: firstEvent ? { ...firstEvent, data: jsonSafe2(firstEvent.data) } : undefined,
2636
2233
  hint: `At least one matched event wrote 0 rows.${keyPart}`,
2637
2234
  ...traceFields
2638
2235
  };
@@ -2642,7 +2239,7 @@ async function runSubgraphTest(input) {
2642
2239
  matched,
2643
2240
  written,
2644
2241
  tables,
2645
- firstEvent: firstEvent ? { ...firstEvent, data: jsonSafe3(firstEvent.data) } : undefined,
2242
+ firstEvent: firstEvent ? { ...firstEvent, data: jsonSafe2(firstEvent.data) } : undefined,
2646
2243
  ...traceFields
2647
2244
  };
2648
2245
  }
@@ -2654,9 +2251,8 @@ async function probeHandlers(def, samples) {
2654
2251
  const filter = def.sources[sample.source];
2655
2252
  if (!filter)
2656
2253
  continue;
2657
- const handler = def.handlers[sample.source] ?? def.handlers["*"];
2658
- const materialize = "materialize" in filter && filter.materialize !== undefined ? filter.materialize : undefined;
2659
- if (typeof handler !== "function" && !materialize)
2254
+ const handler = def.handlers[sample.source];
2255
+ if (typeof handler !== "function")
2660
2256
  continue;
2661
2257
  if (firstEventKeys === undefined) {
2662
2258
  firstEventKeys = dataKeysOf(sample.event.data);
@@ -2664,17 +2260,7 @@ async function probeHandlers(def, samples) {
2664
2260
  matched++;
2665
2261
  try {
2666
2262
  const event = buildEvent(filter, sample.event);
2667
- if (materialize) {
2668
- applyMaterializeInsert(materialize, event, {
2669
- tx: ctx.tx,
2670
- block: ctx.block,
2671
- insert: (table, row) => {
2672
- ctx.insert(table, row);
2673
- }
2674
- }, def.schema);
2675
- } else {
2676
- await handler(event, ctx);
2677
- }
2263
+ await handler(event, ctx);
2678
2264
  } catch {}
2679
2265
  }
2680
2266
  const tables = Object.keys(def.schema);
@@ -2690,14 +2276,14 @@ async function probeHandlers(def, samples) {
2690
2276
  };
2691
2277
  }
2692
2278
  export {
2693
- toHandlerPayload,
2694
- toContractCallPayload,
2695
- runSubgraphTest,
2696
- probeHandlers,
2697
- createTestContext,
2279
+ buildEvent,
2698
2280
  buildEventPayload,
2699
- buildEvent
2281
+ createTestContext,
2282
+ probeHandlers,
2283
+ runSubgraphTest,
2284
+ toContractCallPayload,
2285
+ toHandlerPayload
2700
2286
  };
2701
2287
 
2702
- //# debugId=BBBAFF796E747D6364756E2164756E21
2288
+ //# debugId=73BD3E2068CDEA0464756E2164756E21
2703
2289
  //# sourceMappingURL=index.js.map