@secondlayer/subgraphs 0.8.0 → 0.9.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.
- package/dist/src/index.d.ts +113 -32
- package/dist/src/index.js +458 -103
- package/dist/src/index.js.map +10 -11
- package/dist/src/runtime/block-processor.d.ts +110 -20
- package/dist/src/runtime/block-processor.js +419 -90
- package/dist/src/runtime/block-processor.js.map +7 -8
- package/dist/src/runtime/catchup.d.ts +110 -20
- package/dist/src/runtime/catchup.js +424 -94
- package/dist/src/runtime/catchup.js.map +8 -9
- package/dist/src/runtime/clarity.js +3 -3
- package/dist/src/runtime/clarity.js.map +3 -3
- package/dist/src/runtime/context.d.ts +23 -5
- package/dist/src/runtime/context.js +57 -1
- package/dist/src/runtime/context.js.map +3 -3
- package/dist/src/runtime/processor.js +424 -94
- package/dist/src/runtime/processor.js.map +8 -9
- package/dist/src/runtime/reindex.d.ts +110 -20
- package/dist/src/runtime/reindex.js +424 -94
- package/dist/src/runtime/reindex.js.map +8 -9
- package/dist/src/runtime/reorg.d.ts +110 -20
- package/dist/src/runtime/reorg.js +419 -90
- package/dist/src/runtime/reorg.js.map +7 -8
- package/dist/src/runtime/runner.d.ts +150 -42
- package/dist/src/runtime/runner.js +193 -30
- package/dist/src/runtime/runner.js.map +4 -4
- package/dist/src/runtime/source-matcher.d.ts +86 -31
- package/dist/src/runtime/source-matcher.js +171 -61
- package/dist/src/runtime/source-matcher.js.map +4 -5
- package/dist/src/schema/index.d.ts +110 -20
- package/dist/src/schema/index.js +34 -9
- package/dist/src/schema/index.js.map +3 -3
- package/dist/src/service.js +424 -94
- package/dist/src/service.js.map +8 -9
- package/dist/src/templates.js +52 -51
- package/dist/src/templates.js.map +3 -3
- package/dist/src/types.d.ts +111 -29
- package/dist/src/types.js +1 -20
- package/dist/src/types.js.map +3 -4
- package/dist/src/validate.d.ts +112 -22
- package/dist/src/validate.js +35 -10
- package/dist/src/validate.js.map +3 -3
- package/package.json +2 -2
|
@@ -2,12 +2,12 @@ import { createRequire } from "node:module";
|
|
|
2
2
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
3
|
|
|
4
4
|
// src/runtime/clarity.ts
|
|
5
|
-
import {
|
|
5
|
+
import { cvToValue, deserializeCV } from "@secondlayer/stacks/clarity";
|
|
6
6
|
function decodeClarityValue(hex) {
|
|
7
7
|
try {
|
|
8
8
|
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
9
9
|
const cv = deserializeCV(cleanHex);
|
|
10
|
-
return
|
|
10
|
+
return cvToValue(cv);
|
|
11
11
|
} catch {
|
|
12
12
|
return hex;
|
|
13
13
|
}
|
|
@@ -36,19 +36,177 @@ function decodeFunctionArgs(args) {
|
|
|
36
36
|
import { getErrorMessage } from "@secondlayer/shared";
|
|
37
37
|
import { logger } from "@secondlayer/shared/logger";
|
|
38
38
|
var DEFAULT_ERROR_THRESHOLD = 50;
|
|
39
|
-
function
|
|
40
|
-
return
|
|
39
|
+
function camelCase(str) {
|
|
40
|
+
return str.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
41
|
+
}
|
|
42
|
+
function camelizeKeys(obj) {
|
|
43
|
+
if (obj === null || obj === undefined)
|
|
44
|
+
return obj;
|
|
45
|
+
if (typeof obj !== "object")
|
|
46
|
+
return obj;
|
|
47
|
+
if (Array.isArray(obj))
|
|
48
|
+
return obj.map(camelizeKeys);
|
|
49
|
+
const result = {};
|
|
50
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
51
|
+
result[camelCase(k)] = camelizeKeys(v);
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
function buildEventPayload(filter, tx, event) {
|
|
56
|
+
const txMeta = {
|
|
57
|
+
txId: tx.tx_id,
|
|
58
|
+
sender: tx.sender,
|
|
59
|
+
type: tx.type,
|
|
60
|
+
status: tx.status,
|
|
61
|
+
contractId: tx.contract_id ?? null,
|
|
62
|
+
functionName: tx.function_name ?? null
|
|
63
|
+
};
|
|
64
|
+
if (!event) {
|
|
65
|
+
switch (filter.type) {
|
|
66
|
+
case "contract_call":
|
|
67
|
+
return {
|
|
68
|
+
contractId: tx.contract_id ?? "",
|
|
69
|
+
functionName: tx.function_name ?? "",
|
|
70
|
+
caller: tx.sender,
|
|
71
|
+
args: {},
|
|
72
|
+
result: null,
|
|
73
|
+
tx: txMeta
|
|
74
|
+
};
|
|
75
|
+
case "contract_deploy":
|
|
76
|
+
return {
|
|
77
|
+
contractId: tx.contract_id ?? "",
|
|
78
|
+
deployer: tx.sender,
|
|
79
|
+
tx: txMeta
|
|
80
|
+
};
|
|
81
|
+
default:
|
|
82
|
+
return { tx: txMeta };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const decoded = decodeEventData(event.data);
|
|
86
|
+
switch (filter.type) {
|
|
87
|
+
case "ft_transfer":
|
|
88
|
+
return {
|
|
89
|
+
sender: decoded.sender,
|
|
90
|
+
recipient: decoded.recipient,
|
|
91
|
+
amount: decoded.amount,
|
|
92
|
+
assetIdentifier: decoded.asset_identifier,
|
|
93
|
+
tx: txMeta
|
|
94
|
+
};
|
|
95
|
+
case "ft_mint":
|
|
96
|
+
return {
|
|
97
|
+
recipient: decoded.recipient,
|
|
98
|
+
amount: decoded.amount,
|
|
99
|
+
assetIdentifier: decoded.asset_identifier,
|
|
100
|
+
tx: txMeta
|
|
101
|
+
};
|
|
102
|
+
case "ft_burn":
|
|
103
|
+
return {
|
|
104
|
+
sender: decoded.sender,
|
|
105
|
+
amount: decoded.amount,
|
|
106
|
+
assetIdentifier: decoded.asset_identifier,
|
|
107
|
+
tx: txMeta
|
|
108
|
+
};
|
|
109
|
+
case "nft_transfer":
|
|
110
|
+
return {
|
|
111
|
+
sender: decoded.sender,
|
|
112
|
+
recipient: decoded.recipient,
|
|
113
|
+
tokenId: decoded.value,
|
|
114
|
+
assetIdentifier: decoded.asset_identifier,
|
|
115
|
+
tx: txMeta
|
|
116
|
+
};
|
|
117
|
+
case "nft_mint":
|
|
118
|
+
return {
|
|
119
|
+
recipient: decoded.recipient,
|
|
120
|
+
tokenId: decoded.value,
|
|
121
|
+
assetIdentifier: decoded.asset_identifier,
|
|
122
|
+
tx: txMeta
|
|
123
|
+
};
|
|
124
|
+
case "nft_burn":
|
|
125
|
+
return {
|
|
126
|
+
sender: decoded.sender,
|
|
127
|
+
tokenId: decoded.value,
|
|
128
|
+
assetIdentifier: decoded.asset_identifier,
|
|
129
|
+
tx: txMeta
|
|
130
|
+
};
|
|
131
|
+
case "stx_transfer":
|
|
132
|
+
return {
|
|
133
|
+
sender: decoded.sender,
|
|
134
|
+
recipient: decoded.recipient,
|
|
135
|
+
amount: decoded.amount,
|
|
136
|
+
memo: decoded.memo ?? "",
|
|
137
|
+
tx: txMeta
|
|
138
|
+
};
|
|
139
|
+
case "stx_mint":
|
|
140
|
+
return {
|
|
141
|
+
recipient: decoded.recipient,
|
|
142
|
+
amount: decoded.amount,
|
|
143
|
+
tx: txMeta
|
|
144
|
+
};
|
|
145
|
+
case "stx_burn":
|
|
146
|
+
return {
|
|
147
|
+
sender: decoded.sender,
|
|
148
|
+
amount: decoded.amount,
|
|
149
|
+
tx: txMeta
|
|
150
|
+
};
|
|
151
|
+
case "stx_lock":
|
|
152
|
+
return {
|
|
153
|
+
lockedAddress: decoded.locked_address,
|
|
154
|
+
lockedAmount: decoded.locked_amount,
|
|
155
|
+
unlockHeight: decoded.unlock_height,
|
|
156
|
+
tx: txMeta
|
|
157
|
+
};
|
|
158
|
+
case "print_event": {
|
|
159
|
+
const topic = decoded.topic ?? "";
|
|
160
|
+
const rawValue = decoded.value;
|
|
161
|
+
const data = rawValue && typeof rawValue === "object" ? camelizeKeys(rawValue) : rawValue;
|
|
162
|
+
return {
|
|
163
|
+
contractId: decoded.contract_identifier ?? tx.contract_id ?? "",
|
|
164
|
+
topic,
|
|
165
|
+
data: data ?? {},
|
|
166
|
+
tx: txMeta
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
case "contract_call":
|
|
170
|
+
return {
|
|
171
|
+
...decoded,
|
|
172
|
+
_eventType: event.type,
|
|
173
|
+
contractId: tx.contract_id ?? "",
|
|
174
|
+
functionName: tx.function_name ?? "",
|
|
175
|
+
caller: tx.sender,
|
|
176
|
+
args: {},
|
|
177
|
+
result: null,
|
|
178
|
+
tx: txMeta
|
|
179
|
+
};
|
|
180
|
+
case "contract_deploy":
|
|
181
|
+
return {
|
|
182
|
+
contractId: tx.contract_id ?? "",
|
|
183
|
+
deployer: tx.sender,
|
|
184
|
+
tx: txMeta
|
|
185
|
+
};
|
|
186
|
+
default:
|
|
187
|
+
return {
|
|
188
|
+
...decoded,
|
|
189
|
+
_eventType: event.type,
|
|
190
|
+
tx: txMeta
|
|
191
|
+
};
|
|
192
|
+
}
|
|
41
193
|
}
|
|
42
194
|
async function runHandlers(subgraph, matched, ctx, opts) {
|
|
43
195
|
let processed = 0;
|
|
44
196
|
let errors = 0;
|
|
45
197
|
const threshold = opts?.errorThreshold ?? DEFAULT_ERROR_THRESHOLD;
|
|
46
|
-
|
|
47
|
-
|
|
198
|
+
const filterLookup = new Map;
|
|
199
|
+
if (!Array.isArray(subgraph.sources)) {
|
|
200
|
+
for (const [name, filter] of Object.entries(subgraph.sources)) {
|
|
201
|
+
filterLookup.set(name, filter);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
for (const { tx, events, sourceName } of matched) {
|
|
205
|
+
const handler = subgraph.handlers[sourceName] ?? subgraph.handlers["*"] ?? null;
|
|
48
206
|
if (!handler) {
|
|
49
|
-
logger.warn("No handler found for source
|
|
207
|
+
logger.warn("No handler found for source", {
|
|
50
208
|
subgraph: subgraph.name,
|
|
51
|
-
|
|
209
|
+
sourceName,
|
|
52
210
|
txId: tx.tx_id
|
|
53
211
|
});
|
|
54
212
|
continue;
|
|
@@ -57,11 +215,14 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
57
215
|
txId: tx.tx_id,
|
|
58
216
|
sender: tx.sender,
|
|
59
217
|
type: tx.type,
|
|
60
|
-
status: tx.status
|
|
218
|
+
status: tx.status,
|
|
219
|
+
contractId: tx.contract_id ?? null,
|
|
220
|
+
functionName: tx.function_name ?? null
|
|
61
221
|
});
|
|
222
|
+
const filter = filterLookup.get(sourceName);
|
|
62
223
|
if (events.length === 0) {
|
|
63
224
|
try {
|
|
64
|
-
const
|
|
225
|
+
const payload = filter ? buildEventPayload(filter, tx, null) : {
|
|
65
226
|
tx: {
|
|
66
227
|
txId: tx.tx_id,
|
|
67
228
|
sender: tx.sender,
|
|
@@ -71,13 +232,13 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
71
232
|
functionName: tx.function_name
|
|
72
233
|
}
|
|
73
234
|
};
|
|
74
|
-
await handler(
|
|
235
|
+
await handler(payload, ctx);
|
|
75
236
|
processed++;
|
|
76
237
|
} catch (err) {
|
|
77
238
|
errors++;
|
|
78
239
|
logger.error("Subgraph handler error", {
|
|
79
240
|
subgraph: subgraph.name,
|
|
80
|
-
|
|
241
|
+
sourceName,
|
|
81
242
|
txId: tx.tx_id,
|
|
82
243
|
error: getErrorMessage(err)
|
|
83
244
|
});
|
|
@@ -94,28 +255,30 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
94
255
|
return { processed, errors };
|
|
95
256
|
}
|
|
96
257
|
try {
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
258
|
+
const payload = filter ? buildEventPayload(filter, tx, event) : (() => {
|
|
259
|
+
const decoded = decodeEventData(event.data);
|
|
260
|
+
return {
|
|
261
|
+
...decoded,
|
|
262
|
+
_eventId: event.id,
|
|
263
|
+
_eventType: event.type,
|
|
264
|
+
_eventIndex: event.event_index,
|
|
265
|
+
tx: {
|
|
266
|
+
txId: tx.tx_id,
|
|
267
|
+
sender: tx.sender,
|
|
268
|
+
type: tx.type,
|
|
269
|
+
status: tx.status,
|
|
270
|
+
contractId: tx.contract_id,
|
|
271
|
+
functionName: tx.function_name
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
})();
|
|
275
|
+
await handler(payload, ctx);
|
|
113
276
|
processed++;
|
|
114
277
|
} catch (err) {
|
|
115
278
|
errors++;
|
|
116
279
|
logger.error("Subgraph handler error", {
|
|
117
280
|
subgraph: subgraph.name,
|
|
118
|
-
|
|
281
|
+
sourceName,
|
|
119
282
|
txId: tx.tx_id,
|
|
120
283
|
eventId: event.id,
|
|
121
284
|
eventType: event.type,
|
|
@@ -130,5 +293,5 @@ export {
|
|
|
130
293
|
runHandlers
|
|
131
294
|
};
|
|
132
295
|
|
|
133
|
-
//# debugId=
|
|
296
|
+
//# debugId=7008E1755DAEF1C564756E2164756E21
|
|
134
297
|
//# sourceMappingURL=runner.js.map
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/runtime/clarity.ts", "../src/runtime/runner.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import {
|
|
6
|
-
"import { getErrorMessage } from \"@secondlayer/shared\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport type { SubgraphDefinition } from \"../types.ts\";\nimport { decodeEventData } from \"./clarity.ts\";\nimport type { SubgraphContext } from \"./context.ts\";\nimport type { MatchedTx } from \"./source-matcher.ts\";\n\n/** Max consecutive handler errors before marking subgraph as error */\nconst DEFAULT_ERROR_THRESHOLD = 50;\n\nexport interface RunResult {\n\tprocessed: number;\n\terrors: number;\n}\n\n/**\n *
|
|
5
|
+
"import { cvToValue, deserializeCV } from \"@secondlayer/stacks/clarity\";\n\n/**\n * Decode a hex-encoded Clarity value to a JS object.\n * Returns original value on failure.\n */\nexport function decodeClarityValue(hex: string): unknown {\n\ttry {\n\t\tconst cleanHex = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n\t\tconst cv = deserializeCV(cleanHex);\n\t\treturn cvToValue(cv);\n\t} catch {\n\t\treturn hex;\n\t}\n}\n\n/**\n * Recursively decode all hex-encoded Clarity values in an object.\n * Any string starting with \"0x\" and longer than 10 chars is attempted.\n */\nexport function decodeEventData(data: unknown): unknown {\n\tif (typeof data === \"string\" && data.startsWith(\"0x\") && data.length > 10) {\n\t\treturn decodeClarityValue(data);\n\t}\n\n\tif (Array.isArray(data)) {\n\t\treturn data.map(decodeEventData);\n\t}\n\n\tif (typeof data === \"object\" && data !== null) {\n\t\tconst decoded: Record<string, unknown> = {};\n\t\tfor (const [key, value] of Object.entries(data)) {\n\t\t\tdecoded[key] = decodeEventData(value);\n\t\t}\n\t\treturn decoded;\n\t}\n\n\treturn data;\n}\n\n/**\n * Decode function args array (hex-encoded Clarity values).\n */\nexport function decodeFunctionArgs(args: string[]): unknown[] {\n\treturn args.map(decodeClarityValue);\n}\n",
|
|
6
|
+
"import { getErrorMessage } from \"@secondlayer/shared\";\nimport { logger } from \"@secondlayer/shared/logger\";\nimport type { SubgraphDefinition, SubgraphFilter } from \"../types.ts\";\nimport { decodeEventData } from \"./clarity.ts\";\nimport type { SubgraphContext } from \"./context.ts\";\nimport type { MatchedTx } from \"./source-matcher.ts\";\n\n/** Max consecutive handler errors before marking subgraph as error */\nconst DEFAULT_ERROR_THRESHOLD = 50;\n\nexport interface RunResult {\n\tprocessed: number;\n\terrors: number;\n}\n\n/** Convert kebab-case to camelCase: \"bitcoin-txid\" → \"bitcoinTxid\" */\nfunction camelCase(str: string): string {\n\treturn str.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());\n}\n\n/** Recursively camelize all object keys */\nfunction camelizeKeys(obj: unknown): unknown {\n\tif (obj === null || obj === undefined) return obj;\n\tif (typeof obj !== \"object\") return obj;\n\tif (Array.isArray(obj)) return obj.map(camelizeKeys);\n\tconst result: Record<string, unknown> = {};\n\tfor (const [k, v] of Object.entries(obj as Record<string, unknown>)) {\n\t\tresult[camelCase(k)] = camelizeKeys(v);\n\t}\n\treturn result;\n}\n\n/**\n * Build a typed event payload based on the source filter type.\n * Returns the payload the handler will receive.\n */\nfunction buildEventPayload(\n\tfilter: SubgraphFilter,\n\ttx: MatchedTx[\"tx\"],\n\tevent: MatchedTx[\"events\"][0] | null,\n): Record<string, unknown> {\n\tconst txMeta = {\n\t\ttxId: tx.tx_id,\n\t\tsender: tx.sender,\n\t\ttype: tx.type,\n\t\tstatus: tx.status,\n\t\tcontractId: tx.contract_id ?? null,\n\t\tfunctionName: tx.function_name ?? null,\n\t};\n\n\t// No event — tx-level match (contract_call or contract_deploy)\n\tif (!event) {\n\t\tswitch (filter.type) {\n\t\t\tcase \"contract_call\":\n\t\t\t\treturn {\n\t\t\t\t\tcontractId: tx.contract_id ?? \"\",\n\t\t\t\t\tfunctionName: tx.function_name ?? \"\",\n\t\t\t\t\tcaller: tx.sender,\n\t\t\t\t\targs: {}, // TODO: decode from ABI when available\n\t\t\t\t\tresult: null,\n\t\t\t\t\ttx: txMeta,\n\t\t\t\t};\n\t\t\tcase \"contract_deploy\":\n\t\t\t\treturn {\n\t\t\t\t\tcontractId: tx.contract_id ?? \"\",\n\t\t\t\t\tdeployer: tx.sender,\n\t\t\t\t\ttx: txMeta,\n\t\t\t\t};\n\t\t\tdefault:\n\t\t\t\treturn { tx: txMeta };\n\t\t}\n\t}\n\n\t// Decode event data (Clarity values auto-unwrapped via cvToValue)\n\tconst decoded = decodeEventData(event.data) as Record<string, unknown>;\n\n\tswitch (filter.type) {\n\t\t// ── FT events ──\n\t\tcase \"ft_transfer\":\n\t\t\treturn {\n\t\t\t\tsender: decoded.sender as string,\n\t\t\t\trecipient: decoded.recipient as string,\n\t\t\t\tamount: decoded.amount,\n\t\t\t\tassetIdentifier: decoded.asset_identifier as string,\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\t\tcase \"ft_mint\":\n\t\t\treturn {\n\t\t\t\trecipient: decoded.recipient as string,\n\t\t\t\tamount: decoded.amount,\n\t\t\t\tassetIdentifier: decoded.asset_identifier as string,\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\t\tcase \"ft_burn\":\n\t\t\treturn {\n\t\t\t\tsender: decoded.sender as string,\n\t\t\t\tamount: decoded.amount,\n\t\t\t\tassetIdentifier: decoded.asset_identifier as string,\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\n\t\t// ── NFT events ──\n\t\tcase \"nft_transfer\":\n\t\t\treturn {\n\t\t\t\tsender: decoded.sender as string,\n\t\t\t\trecipient: decoded.recipient as string,\n\t\t\t\ttokenId: decoded.value,\n\t\t\t\tassetIdentifier: decoded.asset_identifier as string,\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\t\tcase \"nft_mint\":\n\t\t\treturn {\n\t\t\t\trecipient: decoded.recipient as string,\n\t\t\t\ttokenId: decoded.value,\n\t\t\t\tassetIdentifier: decoded.asset_identifier as string,\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\t\tcase \"nft_burn\":\n\t\t\treturn {\n\t\t\t\tsender: decoded.sender as string,\n\t\t\t\ttokenId: decoded.value,\n\t\t\t\tassetIdentifier: decoded.asset_identifier as string,\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\n\t\t// ── STX events ──\n\t\tcase \"stx_transfer\":\n\t\t\treturn {\n\t\t\t\tsender: decoded.sender as string,\n\t\t\t\trecipient: decoded.recipient as string,\n\t\t\t\tamount: decoded.amount,\n\t\t\t\tmemo: decoded.memo ?? \"\",\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\t\tcase \"stx_mint\":\n\t\t\treturn {\n\t\t\t\trecipient: decoded.recipient as string,\n\t\t\t\tamount: decoded.amount,\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\t\tcase \"stx_burn\":\n\t\t\treturn {\n\t\t\t\tsender: decoded.sender as string,\n\t\t\t\tamount: decoded.amount,\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\t\tcase \"stx_lock\":\n\t\t\treturn {\n\t\t\t\tlockedAddress: decoded.locked_address as string,\n\t\t\t\tlockedAmount: decoded.locked_amount,\n\t\t\t\tunlockHeight: decoded.unlock_height,\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\n\t\t// ── Print event ──\n\t\tcase \"print_event\": {\n\t\t\tconst topic = decoded.topic as string ?? \"\";\n\t\t\tconst rawValue = decoded.value;\n\t\t\t// Camelize keys for developer convenience\n\t\t\tconst data =\n\t\t\t\trawValue && typeof rawValue === \"object\"\n\t\t\t\t\t? (camelizeKeys(rawValue) as Record<string, unknown>)\n\t\t\t\t\t: rawValue;\n\t\t\treturn {\n\t\t\t\tcontractId: decoded.contract_identifier as string ?? tx.contract_id ?? \"\",\n\t\t\t\ttopic,\n\t\t\t\tdata: data ?? {},\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\t\t}\n\n\t\t// ── Contract call (with events) ──\n\t\tcase \"contract_call\":\n\t\t\treturn {\n\t\t\t\t...decoded,\n\t\t\t\t_eventType: event.type,\n\t\t\t\tcontractId: tx.contract_id ?? \"\",\n\t\t\t\tfunctionName: tx.function_name ?? \"\",\n\t\t\t\tcaller: tx.sender,\n\t\t\t\targs: {}, // TODO: decode from ABI\n\t\t\t\tresult: null,\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\n\t\t// ── Contract deploy ──\n\t\tcase \"contract_deploy\":\n\t\t\treturn {\n\t\t\t\tcontractId: tx.contract_id ?? \"\",\n\t\t\t\tdeployer: tx.sender,\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\n\t\tdefault:\n\t\t\t// Fallback: spread decoded data with tx metadata\n\t\t\treturn {\n\t\t\t\t...decoded,\n\t\t\t\t_eventType: event.type,\n\t\t\t\ttx: txMeta,\n\t\t\t};\n\t}\n}\n\n/**\n * Run a subgraph's keyed handlers against all matched transactions/events.\n *\n * Each MatchedTx carries a sourceName from the matcher. The runner looks up\n * the corresponding handler in subgraph.handlers, falling back to \"*\".\n *\n * Does NOT flush — caller is responsible for flushing ctx after run.\n */\nexport async function runHandlers(\n\tsubgraph: SubgraphDefinition,\n\tmatched: MatchedTx[],\n\tctx: SubgraphContext,\n\topts?: { errorThreshold?: number },\n): Promise<RunResult> {\n\tlet processed = 0;\n\tlet errors = 0;\n\tconst threshold = opts?.errorThreshold ?? DEFAULT_ERROR_THRESHOLD;\n\n\t// Build filter lookup from sources (supports both array and named object)\n\tconst filterLookup = new Map<string, SubgraphFilter>();\n\tif (!Array.isArray(subgraph.sources)) {\n\t\tfor (const [name, filter] of Object.entries(\n\t\t\tsubgraph.sources as Record<string, SubgraphFilter>,\n\t\t)) {\n\t\t\tfilterLookup.set(name, filter);\n\t\t}\n\t}\n\n\tfor (const { tx, events, sourceName } of matched) {\n\t\tconst handler =\n\t\t\tsubgraph.handlers[sourceName] ?? subgraph.handlers[\"*\"] ?? null;\n\t\tif (!handler) {\n\t\t\tlogger.warn(\"No handler found for source\", {\n\t\t\t\tsubgraph: subgraph.name,\n\t\t\t\tsourceName,\n\t\t\t\ttxId: tx.tx_id,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tctx.setTx({\n\t\t\ttxId: tx.tx_id,\n\t\t\tsender: tx.sender,\n\t\t\ttype: tx.type,\n\t\t\tstatus: tx.status,\n\t\t\tcontractId: tx.contract_id ?? null,\n\t\t\tfunctionName: tx.function_name ?? null,\n\t\t});\n\n\t\tconst filter = filterLookup.get(sourceName);\n\n\t\t// If no events but tx matched, call handler with tx-level data\n\t\tif (events.length === 0) {\n\t\t\ttry {\n\t\t\t\tconst payload = filter\n\t\t\t\t\t? buildEventPayload(filter, tx, null)\n\t\t\t\t\t: {\n\t\t\t\t\t\t\ttx: {\n\t\t\t\t\t\t\t\ttxId: tx.tx_id,\n\t\t\t\t\t\t\t\tsender: tx.sender,\n\t\t\t\t\t\t\t\ttype: tx.type,\n\t\t\t\t\t\t\t\tstatus: tx.status,\n\t\t\t\t\t\t\t\tcontractId: tx.contract_id,\n\t\t\t\t\t\t\t\tfunctionName: tx.function_name,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\tawait handler(payload, ctx);\n\t\t\t\tprocessed++;\n\t\t\t} catch (err) {\n\t\t\t\terrors++;\n\t\t\t\tlogger.error(\"Subgraph handler error\", {\n\t\t\t\t\tsubgraph: subgraph.name,\n\t\t\t\t\tsourceName,\n\t\t\t\t\ttxId: tx.tx_id,\n\t\t\t\t\terror: getErrorMessage(err),\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (const event of events) {\n\t\t\tif (errors >= threshold) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Subgraph error threshold reached, skipping remaining events\",\n\t\t\t\t\t{\n\t\t\t\t\t\tsubgraph: subgraph.name,\n\t\t\t\t\t\terrors,\n\t\t\t\t\t\tthreshold,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\treturn { processed, errors };\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst payload = filter\n\t\t\t\t\t? buildEventPayload(filter, tx, event)\n\t\t\t\t\t: (() => {\n\t\t\t\t\t\t\tconst decoded = decodeEventData(event.data) as Record<\n\t\t\t\t\t\t\t\tstring,\n\t\t\t\t\t\t\t\tunknown\n\t\t\t\t\t\t\t>;\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t...decoded,\n\t\t\t\t\t\t\t\t_eventId: event.id,\n\t\t\t\t\t\t\t\t_eventType: event.type,\n\t\t\t\t\t\t\t\t_eventIndex: event.event_index,\n\t\t\t\t\t\t\t\ttx: {\n\t\t\t\t\t\t\t\t\ttxId: tx.tx_id,\n\t\t\t\t\t\t\t\t\tsender: tx.sender,\n\t\t\t\t\t\t\t\t\ttype: tx.type,\n\t\t\t\t\t\t\t\t\tstatus: tx.status,\n\t\t\t\t\t\t\t\t\tcontractId: tx.contract_id,\n\t\t\t\t\t\t\t\t\tfunctionName: tx.function_name,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t})();\n\n\t\t\t\tawait handler(payload, ctx);\n\t\t\t\tprocessed++;\n\t\t\t} catch (err) {\n\t\t\t\terrors++;\n\t\t\t\tlogger.error(\"Subgraph handler error\", {\n\t\t\t\t\tsubgraph: subgraph.name,\n\t\t\t\t\tsourceName,\n\t\t\t\t\ttxId: tx.tx_id,\n\t\t\t\t\teventId: event.id,\n\t\t\t\t\teventType: event.type,\n\t\t\t\t\terror: getErrorMessage(err),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { processed, errors };\n}\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": ";;;;AAAA;AAMO,SAAS,kBAAkB,CAAC,KAAsB;AAAA,EACxD,IAAI;AAAA,IACH,MAAM,WAAW,IAAI,WAAW,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI;AAAA,IACvD,MAAM,KAAK,cAAc,QAAQ;AAAA,IACjC,OAAO,
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "7008E1755DAEF1C564756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
|
@@ -1,34 +1,89 @@
|
|
|
1
|
-
/**
|
|
2
|
-
interface
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
event?: string;
|
|
7
|
-
/** Function name to filter on */
|
|
8
|
-
function?: string;
|
|
9
|
-
/** Transaction type filter (e.g., "stx_transfer", "contract_call") */
|
|
10
|
-
type?: string;
|
|
11
|
-
/** Minimum amount filter (for stx_transfer sources) */
|
|
1
|
+
/** STX event filters */
|
|
2
|
+
interface StxTransferFilter {
|
|
3
|
+
type: "stx_transfer";
|
|
4
|
+
sender?: string;
|
|
5
|
+
recipient?: string;
|
|
12
6
|
minAmount?: bigint;
|
|
7
|
+
maxAmount?: bigint;
|
|
13
8
|
}
|
|
9
|
+
interface StxMintFilter {
|
|
10
|
+
type: "stx_mint";
|
|
11
|
+
recipient?: string;
|
|
12
|
+
minAmount?: bigint;
|
|
13
|
+
}
|
|
14
|
+
interface StxBurnFilter {
|
|
15
|
+
type: "stx_burn";
|
|
16
|
+
sender?: string;
|
|
17
|
+
minAmount?: bigint;
|
|
18
|
+
}
|
|
19
|
+
interface StxLockFilter {
|
|
20
|
+
type: "stx_lock";
|
|
21
|
+
lockedAddress?: string;
|
|
22
|
+
minAmount?: bigint;
|
|
23
|
+
}
|
|
24
|
+
/** FT event filters */
|
|
25
|
+
interface FtTransferFilter {
|
|
26
|
+
type: "ft_transfer";
|
|
27
|
+
assetIdentifier?: string;
|
|
28
|
+
sender?: string;
|
|
29
|
+
recipient?: string;
|
|
30
|
+
minAmount?: bigint;
|
|
31
|
+
}
|
|
32
|
+
interface FtMintFilter {
|
|
33
|
+
type: "ft_mint";
|
|
34
|
+
assetIdentifier?: string;
|
|
35
|
+
recipient?: string;
|
|
36
|
+
minAmount?: bigint;
|
|
37
|
+
}
|
|
38
|
+
interface FtBurnFilter {
|
|
39
|
+
type: "ft_burn";
|
|
40
|
+
assetIdentifier?: string;
|
|
41
|
+
sender?: string;
|
|
42
|
+
minAmount?: bigint;
|
|
43
|
+
}
|
|
44
|
+
/** NFT event filters */
|
|
45
|
+
interface NftTransferFilter {
|
|
46
|
+
type: "nft_transfer";
|
|
47
|
+
assetIdentifier?: string;
|
|
48
|
+
sender?: string;
|
|
49
|
+
recipient?: string;
|
|
50
|
+
}
|
|
51
|
+
interface NftMintFilter {
|
|
52
|
+
type: "nft_mint";
|
|
53
|
+
assetIdentifier?: string;
|
|
54
|
+
recipient?: string;
|
|
55
|
+
}
|
|
56
|
+
interface NftBurnFilter {
|
|
57
|
+
type: "nft_burn";
|
|
58
|
+
assetIdentifier?: string;
|
|
59
|
+
sender?: string;
|
|
60
|
+
}
|
|
61
|
+
/** Contract event filters */
|
|
62
|
+
interface ContractCallFilter {
|
|
63
|
+
type: "contract_call";
|
|
64
|
+
contractId?: string;
|
|
65
|
+
functionName?: string;
|
|
66
|
+
caller?: string;
|
|
67
|
+
/** ABI for typed event.args. If omitted, auto-fetched at deploy time. */
|
|
68
|
+
abi?: Record<string, unknown>;
|
|
69
|
+
}
|
|
70
|
+
interface ContractDeployFilter {
|
|
71
|
+
type: "contract_deploy";
|
|
72
|
+
deployer?: string;
|
|
73
|
+
contractName?: string;
|
|
74
|
+
}
|
|
75
|
+
interface PrintEventFilter {
|
|
76
|
+
type: "print_event";
|
|
77
|
+
contractId?: string;
|
|
78
|
+
topic?: string;
|
|
79
|
+
}
|
|
80
|
+
/** All subgraph filter types — discriminated on `type` */
|
|
81
|
+
type SubgraphFilter = StxTransferFilter | StxMintFilter | StxBurnFilter | StxLockFilter | FtTransferFilter | FtMintFilter | FtBurnFilter | NftTransferFilter | NftMintFilter | NftBurnFilter | ContractCallFilter | ContractDeployFilter | PrintEventFilter;
|
|
14
82
|
interface MatchedTx {
|
|
15
|
-
tx:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
status: string
|
|
20
|
-
contract_id?: string | null
|
|
21
|
-
function_name?: string | null
|
|
22
|
-
};
|
|
23
|
-
events: {
|
|
24
|
-
id: string
|
|
25
|
-
tx_id: string
|
|
26
|
-
type: string
|
|
27
|
-
event_index: number
|
|
28
|
-
data: unknown
|
|
29
|
-
}[];
|
|
30
|
-
/** Which source produced this match — used for handler dispatch */
|
|
31
|
-
sourceKey: string;
|
|
83
|
+
tx: TxRecord;
|
|
84
|
+
events: EventRecord[];
|
|
85
|
+
/** Source object key — used for handler dispatch */
|
|
86
|
+
sourceName: string;
|
|
32
87
|
}
|
|
33
88
|
type TxRecord = {
|
|
34
89
|
tx_id: string
|
|
@@ -46,8 +101,8 @@ type EventRecord = {
|
|
|
46
101
|
data: unknown
|
|
47
102
|
};
|
|
48
103
|
/**
|
|
49
|
-
* Match
|
|
50
|
-
*
|
|
104
|
+
* Match named filters against a block's transactions and events.
|
|
105
|
+
* Returns matches with sourceName = the object key from sources.
|
|
51
106
|
*/
|
|
52
|
-
declare function matchSources(sources:
|
|
107
|
+
declare function matchSources(sources: Record<string, SubgraphFilter>, transactions: TxRecord[], events: EventRecord[]): MatchedTx[];
|
|
53
108
|
export { matchSources, MatchedTx };
|