@secondlayer/subgraphs 0.8.1 → 0.9.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.
- package/dist/src/index.d.ts +113 -32
- package/dist/src/index.js +486 -99
- package/dist/src/index.js.map +9 -10
- package/dist/src/runtime/block-processor.d.ts +110 -20
- package/dist/src/runtime/block-processor.js +452 -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 +457 -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 +457 -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 +452 -90
- package/dist/src/runtime/reindex.js.map +7 -8
- package/dist/src/runtime/reorg.d.ts +110 -20
- package/dist/src/runtime/reorg.js +452 -90
- package/dist/src/runtime/reorg.js.map +7 -8
- package/dist/src/runtime/runner.d.ts +152 -42
- package/dist/src/runtime/runner.js +226 -30
- package/dist/src/runtime/runner.js.map +4 -4
- package/dist/src/runtime/source-matcher.d.ts +88 -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 +457 -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
|
@@ -1,22 +1,9 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
3
|
|
|
4
|
-
// src/types.ts
|
|
5
|
-
function sourceKey(source) {
|
|
6
|
-
if (source.contract) {
|
|
7
|
-
if (source.function)
|
|
8
|
-
return `${source.contract}::${source.function}`;
|
|
9
|
-
if (source.event)
|
|
10
|
-
return `${source.contract}::${source.event}`;
|
|
11
|
-
return source.contract;
|
|
12
|
-
}
|
|
13
|
-
if (source.type)
|
|
14
|
-
return source.type;
|
|
15
|
-
return "*";
|
|
16
|
-
}
|
|
17
|
-
|
|
18
4
|
// src/runtime/context.ts
|
|
19
5
|
import { logger } from "@secondlayer/shared/logger";
|
|
6
|
+
import { formatUnits } from "@secondlayer/stacks/utils";
|
|
20
7
|
import { sql } from "kysely";
|
|
21
8
|
function validateColumnName(name) {
|
|
22
9
|
if (!/^[a-z_][a-z0-9_]*$/i.test(name)) {
|
|
@@ -84,6 +71,20 @@ class SubgraphContext {
|
|
|
84
71
|
this.validateTable(table);
|
|
85
72
|
this.ops.push({ kind: "delete", table, data: where });
|
|
86
73
|
}
|
|
74
|
+
patch(table, where, set) {
|
|
75
|
+
this.update(table, where, set);
|
|
76
|
+
}
|
|
77
|
+
async patchOrInsert(table, key, row) {
|
|
78
|
+
const existing = await this.findOne(table, key);
|
|
79
|
+
const resolved = {};
|
|
80
|
+
for (const [k, v] of Object.entries(row)) {
|
|
81
|
+
resolved[k] = typeof v === "function" ? v(existing) : v;
|
|
82
|
+
}
|
|
83
|
+
this.upsert(table, key, resolved);
|
|
84
|
+
}
|
|
85
|
+
formatUnits(value, decimals) {
|
|
86
|
+
return formatUnits(value, decimals);
|
|
87
|
+
}
|
|
87
88
|
async findOne(table, where) {
|
|
88
89
|
this.validateTable(table);
|
|
89
90
|
const qualifiedTable = `"${this.pgSchemaName}"."${table}"`;
|
|
@@ -101,6 +102,47 @@ class SubgraphContext {
|
|
|
101
102
|
const { rows } = await sql.raw(query).execute(this.db);
|
|
102
103
|
return rows.map((r) => this.coerceRow(table, r));
|
|
103
104
|
}
|
|
105
|
+
async count(table, where) {
|
|
106
|
+
this.validateTable(table);
|
|
107
|
+
const qualifiedTable = `"${this.pgSchemaName}"."${table}"`;
|
|
108
|
+
const whereClause = where ? `WHERE ${buildWhereClause(where).clause}` : "";
|
|
109
|
+
const { rows } = await sql.raw(`SELECT COUNT(*)::int AS count FROM ${qualifiedTable} ${whereClause}`).execute(this.db);
|
|
110
|
+
return Number(rows[0]?.count ?? 0);
|
|
111
|
+
}
|
|
112
|
+
async sum(table, column, where) {
|
|
113
|
+
this.validateTable(table);
|
|
114
|
+
validateColumnName(column);
|
|
115
|
+
const qualifiedTable = `"${this.pgSchemaName}"."${table}"`;
|
|
116
|
+
const whereClause = where ? `WHERE ${buildWhereClause(where).clause}` : "";
|
|
117
|
+
const { rows } = await sql.raw(`SELECT COALESCE(SUM("${column}"), 0) AS total FROM ${qualifiedTable} ${whereClause}`).execute(this.db);
|
|
118
|
+
return BigInt(rows[0]?.total?.toString() ?? "0");
|
|
119
|
+
}
|
|
120
|
+
async min(table, column, where) {
|
|
121
|
+
this.validateTable(table);
|
|
122
|
+
validateColumnName(column);
|
|
123
|
+
const qualifiedTable = `"${this.pgSchemaName}"."${table}"`;
|
|
124
|
+
const whereClause = where ? `WHERE ${buildWhereClause(where).clause}` : "";
|
|
125
|
+
const { rows } = await sql.raw(`SELECT MIN("${column}") AS val FROM ${qualifiedTable} ${whereClause}`).execute(this.db);
|
|
126
|
+
const val = rows[0]?.val;
|
|
127
|
+
return val != null ? BigInt(val.toString()) : null;
|
|
128
|
+
}
|
|
129
|
+
async max(table, column, where) {
|
|
130
|
+
this.validateTable(table);
|
|
131
|
+
validateColumnName(column);
|
|
132
|
+
const qualifiedTable = `"${this.pgSchemaName}"."${table}"`;
|
|
133
|
+
const whereClause = where ? `WHERE ${buildWhereClause(where).clause}` : "";
|
|
134
|
+
const { rows } = await sql.raw(`SELECT MAX("${column}") AS val FROM ${qualifiedTable} ${whereClause}`).execute(this.db);
|
|
135
|
+
const val = rows[0]?.val;
|
|
136
|
+
return val != null ? BigInt(val.toString()) : null;
|
|
137
|
+
}
|
|
138
|
+
async countDistinct(table, column, where) {
|
|
139
|
+
this.validateTable(table);
|
|
140
|
+
validateColumnName(column);
|
|
141
|
+
const qualifiedTable = `"${this.pgSchemaName}"."${table}"`;
|
|
142
|
+
const whereClause = where ? `WHERE ${buildWhereClause(where).clause}` : "";
|
|
143
|
+
const { rows } = await sql.raw(`SELECT COUNT(DISTINCT "${column}")::int AS count FROM ${qualifiedTable} ${whereClause}`).execute(this.db);
|
|
144
|
+
return Number(rows[0]?.count ?? 0);
|
|
145
|
+
}
|
|
104
146
|
coerceRow(table, row) {
|
|
105
147
|
const tableDef = this.subgraphSchema[table];
|
|
106
148
|
if (!tableDef)
|
|
@@ -241,12 +283,12 @@ function buildWhereClause(where) {
|
|
|
241
283
|
}
|
|
242
284
|
|
|
243
285
|
// src/runtime/clarity.ts
|
|
244
|
-
import {
|
|
286
|
+
import { cvToValue, deserializeCV } from "@secondlayer/stacks/clarity";
|
|
245
287
|
function decodeClarityValue(hex) {
|
|
246
288
|
try {
|
|
247
289
|
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
248
290
|
const cv = deserializeCV(cleanHex);
|
|
249
|
-
return
|
|
291
|
+
return cvToValue(cv);
|
|
250
292
|
} catch {
|
|
251
293
|
return hex;
|
|
252
294
|
}
|
|
@@ -275,19 +317,210 @@ function decodeFunctionArgs(args) {
|
|
|
275
317
|
import { getErrorMessage } from "@secondlayer/shared";
|
|
276
318
|
import { logger as logger2 } from "@secondlayer/shared/logger";
|
|
277
319
|
var DEFAULT_ERROR_THRESHOLD = 50;
|
|
278
|
-
function
|
|
279
|
-
return
|
|
320
|
+
function camelCase(str) {
|
|
321
|
+
return str.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
322
|
+
}
|
|
323
|
+
function camelizeKeys(obj) {
|
|
324
|
+
if (obj === null || obj === undefined)
|
|
325
|
+
return obj;
|
|
326
|
+
if (typeof obj !== "object")
|
|
327
|
+
return obj;
|
|
328
|
+
if (Array.isArray(obj))
|
|
329
|
+
return obj.map(camelizeKeys);
|
|
330
|
+
const result = {};
|
|
331
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
332
|
+
result[camelCase(k)] = camelizeKeys(v);
|
|
333
|
+
}
|
|
334
|
+
return result;
|
|
335
|
+
}
|
|
336
|
+
function decodeFunctionArgs2(args) {
|
|
337
|
+
if (!Array.isArray(args))
|
|
338
|
+
return [];
|
|
339
|
+
return args.map((arg) => {
|
|
340
|
+
if (typeof arg === "string")
|
|
341
|
+
return decodeClarityValue(arg);
|
|
342
|
+
return arg;
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
function decodeRawResult(raw) {
|
|
346
|
+
if (typeof raw === "string" && raw.length > 2) {
|
|
347
|
+
return decodeClarityValue(raw);
|
|
348
|
+
}
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
function safeBigInt(val) {
|
|
352
|
+
if (typeof val === "bigint")
|
|
353
|
+
return val;
|
|
354
|
+
if (typeof val === "number")
|
|
355
|
+
return BigInt(val);
|
|
356
|
+
if (typeof val === "string") {
|
|
357
|
+
try {
|
|
358
|
+
return BigInt(val);
|
|
359
|
+
} catch {
|
|
360
|
+
return 0n;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return 0n;
|
|
364
|
+
}
|
|
365
|
+
function buildEventPayload(filter, tx, event) {
|
|
366
|
+
const txMeta = {
|
|
367
|
+
txId: tx.tx_id,
|
|
368
|
+
sender: tx.sender,
|
|
369
|
+
type: tx.type,
|
|
370
|
+
status: tx.status,
|
|
371
|
+
contractId: tx.contract_id ?? null,
|
|
372
|
+
functionName: tx.function_name ?? null
|
|
373
|
+
};
|
|
374
|
+
const decodedArgs = decodeFunctionArgs2(tx.function_args);
|
|
375
|
+
const decodedResult = decodeRawResult(tx.raw_result);
|
|
376
|
+
if (!event) {
|
|
377
|
+
switch (filter.type) {
|
|
378
|
+
case "contract_call":
|
|
379
|
+
return {
|
|
380
|
+
contractId: tx.contract_id ?? "",
|
|
381
|
+
functionName: tx.function_name ?? "",
|
|
382
|
+
caller: tx.sender,
|
|
383
|
+
args: decodedArgs,
|
|
384
|
+
result: decodedResult,
|
|
385
|
+
tx: txMeta
|
|
386
|
+
};
|
|
387
|
+
case "contract_deploy":
|
|
388
|
+
return {
|
|
389
|
+
contractId: tx.contract_id ?? "",
|
|
390
|
+
deployer: tx.sender,
|
|
391
|
+
tx: txMeta
|
|
392
|
+
};
|
|
393
|
+
default:
|
|
394
|
+
return { tx: txMeta };
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
const decoded = decodeEventData(event.data);
|
|
398
|
+
switch (filter.type) {
|
|
399
|
+
case "ft_transfer":
|
|
400
|
+
return {
|
|
401
|
+
sender: decoded.sender,
|
|
402
|
+
recipient: decoded.recipient,
|
|
403
|
+
amount: safeBigInt(decoded.amount),
|
|
404
|
+
assetIdentifier: decoded.asset_identifier,
|
|
405
|
+
tx: txMeta
|
|
406
|
+
};
|
|
407
|
+
case "ft_mint":
|
|
408
|
+
return {
|
|
409
|
+
recipient: decoded.recipient,
|
|
410
|
+
amount: safeBigInt(decoded.amount),
|
|
411
|
+
assetIdentifier: decoded.asset_identifier,
|
|
412
|
+
tx: txMeta
|
|
413
|
+
};
|
|
414
|
+
case "ft_burn":
|
|
415
|
+
return {
|
|
416
|
+
sender: decoded.sender,
|
|
417
|
+
amount: safeBigInt(decoded.amount),
|
|
418
|
+
assetIdentifier: decoded.asset_identifier,
|
|
419
|
+
tx: txMeta
|
|
420
|
+
};
|
|
421
|
+
case "nft_transfer":
|
|
422
|
+
return {
|
|
423
|
+
sender: decoded.sender,
|
|
424
|
+
recipient: decoded.recipient,
|
|
425
|
+
tokenId: decoded.value,
|
|
426
|
+
assetIdentifier: decoded.asset_identifier,
|
|
427
|
+
tx: txMeta
|
|
428
|
+
};
|
|
429
|
+
case "nft_mint":
|
|
430
|
+
return {
|
|
431
|
+
recipient: decoded.recipient,
|
|
432
|
+
tokenId: decoded.value,
|
|
433
|
+
assetIdentifier: decoded.asset_identifier,
|
|
434
|
+
tx: txMeta
|
|
435
|
+
};
|
|
436
|
+
case "nft_burn":
|
|
437
|
+
return {
|
|
438
|
+
sender: decoded.sender,
|
|
439
|
+
tokenId: decoded.value,
|
|
440
|
+
assetIdentifier: decoded.asset_identifier,
|
|
441
|
+
tx: txMeta
|
|
442
|
+
};
|
|
443
|
+
case "stx_transfer":
|
|
444
|
+
return {
|
|
445
|
+
sender: decoded.sender,
|
|
446
|
+
recipient: decoded.recipient,
|
|
447
|
+
amount: safeBigInt(decoded.amount),
|
|
448
|
+
memo: decoded.memo ?? "",
|
|
449
|
+
tx: txMeta
|
|
450
|
+
};
|
|
451
|
+
case "stx_mint":
|
|
452
|
+
return {
|
|
453
|
+
recipient: decoded.recipient,
|
|
454
|
+
amount: safeBigInt(decoded.amount),
|
|
455
|
+
tx: txMeta
|
|
456
|
+
};
|
|
457
|
+
case "stx_burn":
|
|
458
|
+
return {
|
|
459
|
+
sender: decoded.sender,
|
|
460
|
+
amount: safeBigInt(decoded.amount),
|
|
461
|
+
tx: txMeta
|
|
462
|
+
};
|
|
463
|
+
case "stx_lock":
|
|
464
|
+
return {
|
|
465
|
+
lockedAddress: decoded.locked_address,
|
|
466
|
+
lockedAmount: safeBigInt(decoded.locked_amount),
|
|
467
|
+
unlockHeight: safeBigInt(decoded.unlock_height),
|
|
468
|
+
tx: txMeta
|
|
469
|
+
};
|
|
470
|
+
case "print_event": {
|
|
471
|
+
const rawValue = decoded.value;
|
|
472
|
+
const clarityObj = rawValue && typeof rawValue === "object" && !Array.isArray(rawValue) ? rawValue : null;
|
|
473
|
+
const topic = clarityObj?.topic ? String(clarityObj.topic) : decoded.topic ?? "";
|
|
474
|
+
const { topic: _, ...rest } = clarityObj ?? {};
|
|
475
|
+
const data = Object.keys(rest).length > 0 ? camelizeKeys(rest) : rawValue && typeof rawValue !== "object" ? rawValue : {};
|
|
476
|
+
return {
|
|
477
|
+
contractId: decoded.contract_identifier ?? tx.contract_id ?? "",
|
|
478
|
+
topic,
|
|
479
|
+
data: data ?? {},
|
|
480
|
+
tx: txMeta
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
case "contract_call":
|
|
484
|
+
return {
|
|
485
|
+
...decoded,
|
|
486
|
+
_eventType: event.type,
|
|
487
|
+
contractId: tx.contract_id ?? "",
|
|
488
|
+
functionName: tx.function_name ?? "",
|
|
489
|
+
caller: tx.sender,
|
|
490
|
+
args: decodedArgs,
|
|
491
|
+
result: decodedResult,
|
|
492
|
+
tx: txMeta
|
|
493
|
+
};
|
|
494
|
+
case "contract_deploy":
|
|
495
|
+
return {
|
|
496
|
+
contractId: tx.contract_id ?? "",
|
|
497
|
+
deployer: tx.sender,
|
|
498
|
+
tx: txMeta
|
|
499
|
+
};
|
|
500
|
+
default:
|
|
501
|
+
return {
|
|
502
|
+
...decoded,
|
|
503
|
+
_eventType: event.type,
|
|
504
|
+
tx: txMeta
|
|
505
|
+
};
|
|
506
|
+
}
|
|
280
507
|
}
|
|
281
508
|
async function runHandlers(subgraph, matched, ctx, opts) {
|
|
282
509
|
let processed = 0;
|
|
283
510
|
let errors = 0;
|
|
284
511
|
const threshold = opts?.errorThreshold ?? DEFAULT_ERROR_THRESHOLD;
|
|
285
|
-
|
|
286
|
-
|
|
512
|
+
const filterLookup = new Map;
|
|
513
|
+
if (!Array.isArray(subgraph.sources)) {
|
|
514
|
+
for (const [name, filter] of Object.entries(subgraph.sources)) {
|
|
515
|
+
filterLookup.set(name, filter);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
for (const { tx, events, sourceName } of matched) {
|
|
519
|
+
const handler = subgraph.handlers[sourceName] ?? subgraph.handlers["*"] ?? null;
|
|
287
520
|
if (!handler) {
|
|
288
|
-
logger2.warn("No handler found for source
|
|
521
|
+
logger2.warn("No handler found for source", {
|
|
289
522
|
subgraph: subgraph.name,
|
|
290
|
-
|
|
523
|
+
sourceName,
|
|
291
524
|
txId: tx.tx_id
|
|
292
525
|
});
|
|
293
526
|
continue;
|
|
@@ -296,11 +529,14 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
296
529
|
txId: tx.tx_id,
|
|
297
530
|
sender: tx.sender,
|
|
298
531
|
type: tx.type,
|
|
299
|
-
status: tx.status
|
|
532
|
+
status: tx.status,
|
|
533
|
+
contractId: tx.contract_id ?? null,
|
|
534
|
+
functionName: tx.function_name ?? null
|
|
300
535
|
});
|
|
536
|
+
const filter = filterLookup.get(sourceName);
|
|
301
537
|
if (events.length === 0) {
|
|
302
538
|
try {
|
|
303
|
-
const
|
|
539
|
+
const payload = filter ? buildEventPayload(filter, tx, null) : {
|
|
304
540
|
tx: {
|
|
305
541
|
txId: tx.tx_id,
|
|
306
542
|
sender: tx.sender,
|
|
@@ -310,13 +546,13 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
310
546
|
functionName: tx.function_name
|
|
311
547
|
}
|
|
312
548
|
};
|
|
313
|
-
await handler(
|
|
549
|
+
await handler(payload, ctx);
|
|
314
550
|
processed++;
|
|
315
551
|
} catch (err) {
|
|
316
552
|
errors++;
|
|
317
553
|
logger2.error("Subgraph handler error", {
|
|
318
554
|
subgraph: subgraph.name,
|
|
319
|
-
|
|
555
|
+
sourceName,
|
|
320
556
|
txId: tx.tx_id,
|
|
321
557
|
error: getErrorMessage(err)
|
|
322
558
|
});
|
|
@@ -333,28 +569,30 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
333
569
|
return { processed, errors };
|
|
334
570
|
}
|
|
335
571
|
try {
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
572
|
+
const payload = filter ? buildEventPayload(filter, tx, event) : (() => {
|
|
573
|
+
const decoded = decodeEventData(event.data);
|
|
574
|
+
return {
|
|
575
|
+
...decoded,
|
|
576
|
+
_eventId: event.id,
|
|
577
|
+
_eventType: event.type,
|
|
578
|
+
_eventIndex: event.event_index,
|
|
579
|
+
tx: {
|
|
580
|
+
txId: tx.tx_id,
|
|
581
|
+
sender: tx.sender,
|
|
582
|
+
type: tx.type,
|
|
583
|
+
status: tx.status,
|
|
584
|
+
contractId: tx.contract_id,
|
|
585
|
+
functionName: tx.function_name
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
})();
|
|
589
|
+
await handler(payload, ctx);
|
|
352
590
|
processed++;
|
|
353
591
|
} catch (err) {
|
|
354
592
|
errors++;
|
|
355
593
|
logger2.error("Subgraph handler error", {
|
|
356
594
|
subgraph: subgraph.name,
|
|
357
|
-
|
|
595
|
+
sourceName,
|
|
358
596
|
txId: tx.tx_id,
|
|
359
597
|
eventId: event.id,
|
|
360
598
|
eventType: event.type,
|
|
@@ -379,62 +617,186 @@ function matchPattern(value, pattern) {
|
|
|
379
617
|
}
|
|
380
618
|
return re.test(value);
|
|
381
619
|
}
|
|
382
|
-
function
|
|
620
|
+
function matchFilter(filter, transactions, eventsByTx) {
|
|
383
621
|
const results = [];
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
const
|
|
622
|
+
switch (filter.type) {
|
|
623
|
+
case "stx_transfer":
|
|
624
|
+
case "stx_mint":
|
|
625
|
+
case "stx_burn":
|
|
626
|
+
case "stx_lock": {
|
|
627
|
+
const eventType = `${filter.type}_event`;
|
|
628
|
+
for (const tx of transactions) {
|
|
629
|
+
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
630
|
+
const matched = txEvents.filter((e) => e.type === eventType);
|
|
631
|
+
if (matched.length === 0)
|
|
632
|
+
continue;
|
|
633
|
+
const filtered = matched.filter((e) => {
|
|
393
634
|
const data = e.data;
|
|
394
|
-
|
|
395
|
-
if (rawAmount === undefined)
|
|
635
|
+
if (!data)
|
|
396
636
|
return false;
|
|
397
|
-
|
|
398
|
-
|
|
637
|
+
if ("sender" in filter && filter.sender) {
|
|
638
|
+
if (!matchPattern(data.sender, filter.sender))
|
|
639
|
+
return false;
|
|
640
|
+
}
|
|
641
|
+
if ("recipient" in filter && filter.recipient) {
|
|
642
|
+
if (!matchPattern(data.recipient, filter.recipient))
|
|
643
|
+
return false;
|
|
644
|
+
}
|
|
645
|
+
if ("lockedAddress" in filter && filter.lockedAddress) {
|
|
646
|
+
if (!matchPattern(data.locked_address, filter.lockedAddress))
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
if ("minAmount" in filter && filter.minAmount !== undefined) {
|
|
650
|
+
const amount = BigInt(data.amount ?? data.locked_amount ?? "0");
|
|
651
|
+
if (amount < filter.minAmount)
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
if ("maxAmount" in filter && filter.maxAmount !== undefined) {
|
|
655
|
+
const amount = BigInt(data.amount ?? "0");
|
|
656
|
+
if (amount > filter.maxAmount)
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
return true;
|
|
399
660
|
});
|
|
400
|
-
if (
|
|
401
|
-
|
|
402
|
-
|
|
661
|
+
if (filtered.length > 0) {
|
|
662
|
+
results.push({ tx, events: filtered });
|
|
663
|
+
}
|
|
403
664
|
}
|
|
404
|
-
|
|
405
|
-
continue;
|
|
665
|
+
break;
|
|
406
666
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
667
|
+
case "ft_transfer":
|
|
668
|
+
case "ft_mint":
|
|
669
|
+
case "ft_burn": {
|
|
670
|
+
const eventType = `${filter.type}_event`;
|
|
671
|
+
for (const tx of transactions) {
|
|
672
|
+
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
673
|
+
const matched = txEvents.filter((e) => {
|
|
674
|
+
if (e.type !== eventType)
|
|
675
|
+
return false;
|
|
676
|
+
const data = e.data;
|
|
677
|
+
if (!data)
|
|
678
|
+
return false;
|
|
679
|
+
if (filter.assetIdentifier) {
|
|
680
|
+
const assetId = data.asset_identifier;
|
|
681
|
+
if (!assetId || !matchPattern(assetId, filter.assetIdentifier))
|
|
682
|
+
return false;
|
|
683
|
+
}
|
|
684
|
+
if ("sender" in filter && filter.sender) {
|
|
685
|
+
if (!matchPattern(data.sender, filter.sender))
|
|
686
|
+
return false;
|
|
687
|
+
}
|
|
688
|
+
if ("recipient" in filter && filter.recipient) {
|
|
689
|
+
if (!matchPattern(data.recipient, filter.recipient))
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
if (filter.minAmount !== undefined) {
|
|
693
|
+
const amount = BigInt(data.amount ?? "0");
|
|
694
|
+
if (amount < filter.minAmount)
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
return true;
|
|
698
|
+
});
|
|
699
|
+
if (matched.length > 0) {
|
|
700
|
+
results.push({ tx, events: matched });
|
|
701
|
+
}
|
|
414
702
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
703
|
+
break;
|
|
704
|
+
}
|
|
705
|
+
case "nft_transfer":
|
|
706
|
+
case "nft_mint":
|
|
707
|
+
case "nft_burn": {
|
|
708
|
+
const eventType = `${filter.type}_event`;
|
|
709
|
+
for (const tx of transactions) {
|
|
710
|
+
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
711
|
+
const matched = txEvents.filter((e) => {
|
|
712
|
+
if (e.type !== eventType)
|
|
713
|
+
return false;
|
|
419
714
|
const data = e.data;
|
|
420
|
-
|
|
421
|
-
|
|
715
|
+
if (!data)
|
|
716
|
+
return false;
|
|
717
|
+
if (filter.assetIdentifier) {
|
|
718
|
+
const assetId = data.asset_identifier;
|
|
719
|
+
if (!assetId || !matchPattern(assetId, filter.assetIdentifier))
|
|
720
|
+
return false;
|
|
721
|
+
}
|
|
722
|
+
if ("sender" in filter && filter.sender) {
|
|
723
|
+
if (!matchPattern(data.sender, filter.sender))
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
if ("recipient" in filter && filter.recipient) {
|
|
727
|
+
if (!matchPattern(data.recipient, filter.recipient))
|
|
728
|
+
return false;
|
|
729
|
+
}
|
|
730
|
+
return true;
|
|
422
731
|
});
|
|
423
|
-
if (
|
|
732
|
+
if (matched.length > 0) {
|
|
733
|
+
results.push({ tx, events: matched });
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
break;
|
|
737
|
+
}
|
|
738
|
+
case "contract_call": {
|
|
739
|
+
for (const tx of transactions) {
|
|
740
|
+
if (tx.type !== "contract_call")
|
|
741
|
+
continue;
|
|
742
|
+
if (filter.contractId) {
|
|
743
|
+
if (!tx.contract_id || !matchPattern(tx.contract_id, filter.contractId))
|
|
744
|
+
continue;
|
|
745
|
+
}
|
|
746
|
+
if (filter.functionName) {
|
|
747
|
+
if (!tx.function_name || !matchPattern(tx.function_name, filter.functionName))
|
|
748
|
+
continue;
|
|
749
|
+
}
|
|
750
|
+
if (filter.caller) {
|
|
751
|
+
if (!matchPattern(tx.sender, filter.caller))
|
|
752
|
+
continue;
|
|
753
|
+
}
|
|
754
|
+
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
755
|
+
results.push({ tx, events: txEvents });
|
|
756
|
+
}
|
|
757
|
+
break;
|
|
758
|
+
}
|
|
759
|
+
case "contract_deploy": {
|
|
760
|
+
for (const tx of transactions) {
|
|
761
|
+
if (tx.type !== "smart_contract")
|
|
424
762
|
continue;
|
|
763
|
+
if (filter.deployer) {
|
|
764
|
+
if (!matchPattern(tx.sender, filter.deployer))
|
|
765
|
+
continue;
|
|
766
|
+
}
|
|
767
|
+
if (filter.contractName) {
|
|
768
|
+
const name = tx.contract_id?.split(".")[1] ?? "";
|
|
769
|
+
if (!matchPattern(name, filter.contractName))
|
|
770
|
+
continue;
|
|
771
|
+
}
|
|
772
|
+
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
773
|
+
results.push({ tx, events: txEvents });
|
|
425
774
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
775
|
+
break;
|
|
776
|
+
}
|
|
777
|
+
case "print_event": {
|
|
778
|
+
for (const tx of transactions) {
|
|
779
|
+
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
780
|
+
const matched = txEvents.filter((e) => {
|
|
781
|
+
if (e.type !== "smart_contract_event")
|
|
782
|
+
return false;
|
|
430
783
|
const data = e.data;
|
|
431
|
-
|
|
432
|
-
|
|
784
|
+
if (!data)
|
|
785
|
+
return false;
|
|
786
|
+
if (data.topic !== "print")
|
|
787
|
+
return false;
|
|
788
|
+
if (filter.contractId) {
|
|
789
|
+
const contractId = data.contract_identifier;
|
|
790
|
+
if (!contractId || !matchPattern(contractId, filter.contractId))
|
|
791
|
+
return false;
|
|
792
|
+
}
|
|
793
|
+
return true;
|
|
433
794
|
});
|
|
795
|
+
if (matched.length > 0) {
|
|
796
|
+
results.push({ tx, events: matched });
|
|
797
|
+
}
|
|
434
798
|
}
|
|
435
|
-
|
|
436
|
-
results.push({ tx, events: matchedEvents, sourceKey: key });
|
|
437
|
-
}
|
|
799
|
+
break;
|
|
438
800
|
}
|
|
439
801
|
}
|
|
440
802
|
return results;
|
|
@@ -448,13 +810,13 @@ function matchSources(sources, transactions, events) {
|
|
|
448
810
|
}
|
|
449
811
|
const seen = new Set;
|
|
450
812
|
const results = [];
|
|
451
|
-
for (const
|
|
452
|
-
const matches =
|
|
813
|
+
for (const [sourceName, filter] of Object.entries(sources)) {
|
|
814
|
+
const matches = matchFilter(filter, transactions, eventsByTx);
|
|
453
815
|
for (const match of matches) {
|
|
454
|
-
const dedupeKey = `${match.tx.tx_id}:${
|
|
816
|
+
const dedupeKey = `${match.tx.tx_id}:${sourceName}`;
|
|
455
817
|
if (!seen.has(dedupeKey)) {
|
|
456
818
|
seen.add(dedupeKey);
|
|
457
|
-
results.push(match);
|
|
819
|
+
results.push({ ...match, sourceName });
|
|
458
820
|
}
|
|
459
821
|
}
|
|
460
822
|
}
|
|
@@ -1137,5 +1499,5 @@ export {
|
|
|
1137
1499
|
backfillSubgraph
|
|
1138
1500
|
};
|
|
1139
1501
|
|
|
1140
|
-
//# debugId=
|
|
1502
|
+
//# debugId=3D0636EE08B11F5164756E2164756E21
|
|
1141
1503
|
//# sourceMappingURL=reindex.js.map
|