@secondlayer/subgraphs 0.8.1 → 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 +453 -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 +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 +419 -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 +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
|
@@ -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,177 @@ 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 buildEventPayload(filter, tx, event) {
|
|
337
|
+
const txMeta = {
|
|
338
|
+
txId: tx.tx_id,
|
|
339
|
+
sender: tx.sender,
|
|
340
|
+
type: tx.type,
|
|
341
|
+
status: tx.status,
|
|
342
|
+
contractId: tx.contract_id ?? null,
|
|
343
|
+
functionName: tx.function_name ?? null
|
|
344
|
+
};
|
|
345
|
+
if (!event) {
|
|
346
|
+
switch (filter.type) {
|
|
347
|
+
case "contract_call":
|
|
348
|
+
return {
|
|
349
|
+
contractId: tx.contract_id ?? "",
|
|
350
|
+
functionName: tx.function_name ?? "",
|
|
351
|
+
caller: tx.sender,
|
|
352
|
+
args: {},
|
|
353
|
+
result: null,
|
|
354
|
+
tx: txMeta
|
|
355
|
+
};
|
|
356
|
+
case "contract_deploy":
|
|
357
|
+
return {
|
|
358
|
+
contractId: tx.contract_id ?? "",
|
|
359
|
+
deployer: tx.sender,
|
|
360
|
+
tx: txMeta
|
|
361
|
+
};
|
|
362
|
+
default:
|
|
363
|
+
return { tx: txMeta };
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const decoded = decodeEventData(event.data);
|
|
367
|
+
switch (filter.type) {
|
|
368
|
+
case "ft_transfer":
|
|
369
|
+
return {
|
|
370
|
+
sender: decoded.sender,
|
|
371
|
+
recipient: decoded.recipient,
|
|
372
|
+
amount: decoded.amount,
|
|
373
|
+
assetIdentifier: decoded.asset_identifier,
|
|
374
|
+
tx: txMeta
|
|
375
|
+
};
|
|
376
|
+
case "ft_mint":
|
|
377
|
+
return {
|
|
378
|
+
recipient: decoded.recipient,
|
|
379
|
+
amount: decoded.amount,
|
|
380
|
+
assetIdentifier: decoded.asset_identifier,
|
|
381
|
+
tx: txMeta
|
|
382
|
+
};
|
|
383
|
+
case "ft_burn":
|
|
384
|
+
return {
|
|
385
|
+
sender: decoded.sender,
|
|
386
|
+
amount: decoded.amount,
|
|
387
|
+
assetIdentifier: decoded.asset_identifier,
|
|
388
|
+
tx: txMeta
|
|
389
|
+
};
|
|
390
|
+
case "nft_transfer":
|
|
391
|
+
return {
|
|
392
|
+
sender: decoded.sender,
|
|
393
|
+
recipient: decoded.recipient,
|
|
394
|
+
tokenId: decoded.value,
|
|
395
|
+
assetIdentifier: decoded.asset_identifier,
|
|
396
|
+
tx: txMeta
|
|
397
|
+
};
|
|
398
|
+
case "nft_mint":
|
|
399
|
+
return {
|
|
400
|
+
recipient: decoded.recipient,
|
|
401
|
+
tokenId: decoded.value,
|
|
402
|
+
assetIdentifier: decoded.asset_identifier,
|
|
403
|
+
tx: txMeta
|
|
404
|
+
};
|
|
405
|
+
case "nft_burn":
|
|
406
|
+
return {
|
|
407
|
+
sender: decoded.sender,
|
|
408
|
+
tokenId: decoded.value,
|
|
409
|
+
assetIdentifier: decoded.asset_identifier,
|
|
410
|
+
tx: txMeta
|
|
411
|
+
};
|
|
412
|
+
case "stx_transfer":
|
|
413
|
+
return {
|
|
414
|
+
sender: decoded.sender,
|
|
415
|
+
recipient: decoded.recipient,
|
|
416
|
+
amount: decoded.amount,
|
|
417
|
+
memo: decoded.memo ?? "",
|
|
418
|
+
tx: txMeta
|
|
419
|
+
};
|
|
420
|
+
case "stx_mint":
|
|
421
|
+
return {
|
|
422
|
+
recipient: decoded.recipient,
|
|
423
|
+
amount: decoded.amount,
|
|
424
|
+
tx: txMeta
|
|
425
|
+
};
|
|
426
|
+
case "stx_burn":
|
|
427
|
+
return {
|
|
428
|
+
sender: decoded.sender,
|
|
429
|
+
amount: decoded.amount,
|
|
430
|
+
tx: txMeta
|
|
431
|
+
};
|
|
432
|
+
case "stx_lock":
|
|
433
|
+
return {
|
|
434
|
+
lockedAddress: decoded.locked_address,
|
|
435
|
+
lockedAmount: decoded.locked_amount,
|
|
436
|
+
unlockHeight: decoded.unlock_height,
|
|
437
|
+
tx: txMeta
|
|
438
|
+
};
|
|
439
|
+
case "print_event": {
|
|
440
|
+
const topic = decoded.topic ?? "";
|
|
441
|
+
const rawValue = decoded.value;
|
|
442
|
+
const data = rawValue && typeof rawValue === "object" ? camelizeKeys(rawValue) : rawValue;
|
|
443
|
+
return {
|
|
444
|
+
contractId: decoded.contract_identifier ?? tx.contract_id ?? "",
|
|
445
|
+
topic,
|
|
446
|
+
data: data ?? {},
|
|
447
|
+
tx: txMeta
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
case "contract_call":
|
|
451
|
+
return {
|
|
452
|
+
...decoded,
|
|
453
|
+
_eventType: event.type,
|
|
454
|
+
contractId: tx.contract_id ?? "",
|
|
455
|
+
functionName: tx.function_name ?? "",
|
|
456
|
+
caller: tx.sender,
|
|
457
|
+
args: {},
|
|
458
|
+
result: null,
|
|
459
|
+
tx: txMeta
|
|
460
|
+
};
|
|
461
|
+
case "contract_deploy":
|
|
462
|
+
return {
|
|
463
|
+
contractId: tx.contract_id ?? "",
|
|
464
|
+
deployer: tx.sender,
|
|
465
|
+
tx: txMeta
|
|
466
|
+
};
|
|
467
|
+
default:
|
|
468
|
+
return {
|
|
469
|
+
...decoded,
|
|
470
|
+
_eventType: event.type,
|
|
471
|
+
tx: txMeta
|
|
472
|
+
};
|
|
473
|
+
}
|
|
280
474
|
}
|
|
281
475
|
async function runHandlers(subgraph, matched, ctx, opts) {
|
|
282
476
|
let processed = 0;
|
|
283
477
|
let errors = 0;
|
|
284
478
|
const threshold = opts?.errorThreshold ?? DEFAULT_ERROR_THRESHOLD;
|
|
285
|
-
|
|
286
|
-
|
|
479
|
+
const filterLookup = new Map;
|
|
480
|
+
if (!Array.isArray(subgraph.sources)) {
|
|
481
|
+
for (const [name, filter] of Object.entries(subgraph.sources)) {
|
|
482
|
+
filterLookup.set(name, filter);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
for (const { tx, events, sourceName } of matched) {
|
|
486
|
+
const handler = subgraph.handlers[sourceName] ?? subgraph.handlers["*"] ?? null;
|
|
287
487
|
if (!handler) {
|
|
288
|
-
logger2.warn("No handler found for source
|
|
488
|
+
logger2.warn("No handler found for source", {
|
|
289
489
|
subgraph: subgraph.name,
|
|
290
|
-
|
|
490
|
+
sourceName,
|
|
291
491
|
txId: tx.tx_id
|
|
292
492
|
});
|
|
293
493
|
continue;
|
|
@@ -296,11 +496,14 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
296
496
|
txId: tx.tx_id,
|
|
297
497
|
sender: tx.sender,
|
|
298
498
|
type: tx.type,
|
|
299
|
-
status: tx.status
|
|
499
|
+
status: tx.status,
|
|
500
|
+
contractId: tx.contract_id ?? null,
|
|
501
|
+
functionName: tx.function_name ?? null
|
|
300
502
|
});
|
|
503
|
+
const filter = filterLookup.get(sourceName);
|
|
301
504
|
if (events.length === 0) {
|
|
302
505
|
try {
|
|
303
|
-
const
|
|
506
|
+
const payload = filter ? buildEventPayload(filter, tx, null) : {
|
|
304
507
|
tx: {
|
|
305
508
|
txId: tx.tx_id,
|
|
306
509
|
sender: tx.sender,
|
|
@@ -310,13 +513,13 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
310
513
|
functionName: tx.function_name
|
|
311
514
|
}
|
|
312
515
|
};
|
|
313
|
-
await handler(
|
|
516
|
+
await handler(payload, ctx);
|
|
314
517
|
processed++;
|
|
315
518
|
} catch (err) {
|
|
316
519
|
errors++;
|
|
317
520
|
logger2.error("Subgraph handler error", {
|
|
318
521
|
subgraph: subgraph.name,
|
|
319
|
-
|
|
522
|
+
sourceName,
|
|
320
523
|
txId: tx.tx_id,
|
|
321
524
|
error: getErrorMessage(err)
|
|
322
525
|
});
|
|
@@ -333,28 +536,30 @@ async function runHandlers(subgraph, matched, ctx, opts) {
|
|
|
333
536
|
return { processed, errors };
|
|
334
537
|
}
|
|
335
538
|
try {
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
539
|
+
const payload = filter ? buildEventPayload(filter, tx, event) : (() => {
|
|
540
|
+
const decoded = decodeEventData(event.data);
|
|
541
|
+
return {
|
|
542
|
+
...decoded,
|
|
543
|
+
_eventId: event.id,
|
|
544
|
+
_eventType: event.type,
|
|
545
|
+
_eventIndex: event.event_index,
|
|
546
|
+
tx: {
|
|
547
|
+
txId: tx.tx_id,
|
|
548
|
+
sender: tx.sender,
|
|
549
|
+
type: tx.type,
|
|
550
|
+
status: tx.status,
|
|
551
|
+
contractId: tx.contract_id,
|
|
552
|
+
functionName: tx.function_name
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
})();
|
|
556
|
+
await handler(payload, ctx);
|
|
352
557
|
processed++;
|
|
353
558
|
} catch (err) {
|
|
354
559
|
errors++;
|
|
355
560
|
logger2.error("Subgraph handler error", {
|
|
356
561
|
subgraph: subgraph.name,
|
|
357
|
-
|
|
562
|
+
sourceName,
|
|
358
563
|
txId: tx.tx_id,
|
|
359
564
|
eventId: event.id,
|
|
360
565
|
eventType: event.type,
|
|
@@ -379,62 +584,186 @@ function matchPattern(value, pattern) {
|
|
|
379
584
|
}
|
|
380
585
|
return re.test(value);
|
|
381
586
|
}
|
|
382
|
-
function
|
|
587
|
+
function matchFilter(filter, transactions, eventsByTx) {
|
|
383
588
|
const results = [];
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
const
|
|
589
|
+
switch (filter.type) {
|
|
590
|
+
case "stx_transfer":
|
|
591
|
+
case "stx_mint":
|
|
592
|
+
case "stx_burn":
|
|
593
|
+
case "stx_lock": {
|
|
594
|
+
const eventType = `${filter.type}_event`;
|
|
595
|
+
for (const tx of transactions) {
|
|
596
|
+
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
597
|
+
const matched = txEvents.filter((e) => e.type === eventType);
|
|
598
|
+
if (matched.length === 0)
|
|
599
|
+
continue;
|
|
600
|
+
const filtered = matched.filter((e) => {
|
|
393
601
|
const data = e.data;
|
|
394
|
-
|
|
395
|
-
if (rawAmount === undefined)
|
|
602
|
+
if (!data)
|
|
396
603
|
return false;
|
|
397
|
-
|
|
398
|
-
|
|
604
|
+
if ("sender" in filter && filter.sender) {
|
|
605
|
+
if (!matchPattern(data.sender, filter.sender))
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
608
|
+
if ("recipient" in filter && filter.recipient) {
|
|
609
|
+
if (!matchPattern(data.recipient, filter.recipient))
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
if ("lockedAddress" in filter && filter.lockedAddress) {
|
|
613
|
+
if (!matchPattern(data.locked_address, filter.lockedAddress))
|
|
614
|
+
return false;
|
|
615
|
+
}
|
|
616
|
+
if ("minAmount" in filter && filter.minAmount !== undefined) {
|
|
617
|
+
const amount = BigInt(data.amount ?? data.locked_amount ?? "0");
|
|
618
|
+
if (amount < filter.minAmount)
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
621
|
+
if ("maxAmount" in filter && filter.maxAmount !== undefined) {
|
|
622
|
+
const amount = BigInt(data.amount ?? "0");
|
|
623
|
+
if (amount > filter.maxAmount)
|
|
624
|
+
return false;
|
|
625
|
+
}
|
|
626
|
+
return true;
|
|
399
627
|
});
|
|
400
|
-
if (
|
|
401
|
-
|
|
402
|
-
|
|
628
|
+
if (filtered.length > 0) {
|
|
629
|
+
results.push({ tx, events: filtered });
|
|
630
|
+
}
|
|
403
631
|
}
|
|
404
|
-
|
|
405
|
-
continue;
|
|
632
|
+
break;
|
|
406
633
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
634
|
+
case "ft_transfer":
|
|
635
|
+
case "ft_mint":
|
|
636
|
+
case "ft_burn": {
|
|
637
|
+
const eventType = `${filter.type}_event`;
|
|
638
|
+
for (const tx of transactions) {
|
|
639
|
+
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
640
|
+
const matched = txEvents.filter((e) => {
|
|
641
|
+
if (e.type !== eventType)
|
|
642
|
+
return false;
|
|
643
|
+
const data = e.data;
|
|
644
|
+
if (!data)
|
|
645
|
+
return false;
|
|
646
|
+
if (filter.assetIdentifier) {
|
|
647
|
+
const assetId = data.asset_identifier;
|
|
648
|
+
if (!assetId || !matchPattern(assetId, filter.assetIdentifier))
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
651
|
+
if ("sender" in filter && filter.sender) {
|
|
652
|
+
if (!matchPattern(data.sender, filter.sender))
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
if ("recipient" in filter && filter.recipient) {
|
|
656
|
+
if (!matchPattern(data.recipient, filter.recipient))
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
if (filter.minAmount !== undefined) {
|
|
660
|
+
const amount = BigInt(data.amount ?? "0");
|
|
661
|
+
if (amount < filter.minAmount)
|
|
662
|
+
return false;
|
|
663
|
+
}
|
|
664
|
+
return true;
|
|
665
|
+
});
|
|
666
|
+
if (matched.length > 0) {
|
|
667
|
+
results.push({ tx, events: matched });
|
|
668
|
+
}
|
|
414
669
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
670
|
+
break;
|
|
671
|
+
}
|
|
672
|
+
case "nft_transfer":
|
|
673
|
+
case "nft_mint":
|
|
674
|
+
case "nft_burn": {
|
|
675
|
+
const eventType = `${filter.type}_event`;
|
|
676
|
+
for (const tx of transactions) {
|
|
677
|
+
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
678
|
+
const matched = txEvents.filter((e) => {
|
|
679
|
+
if (e.type !== eventType)
|
|
680
|
+
return false;
|
|
419
681
|
const data = e.data;
|
|
420
|
-
|
|
421
|
-
|
|
682
|
+
if (!data)
|
|
683
|
+
return false;
|
|
684
|
+
if (filter.assetIdentifier) {
|
|
685
|
+
const assetId = data.asset_identifier;
|
|
686
|
+
if (!assetId || !matchPattern(assetId, filter.assetIdentifier))
|
|
687
|
+
return false;
|
|
688
|
+
}
|
|
689
|
+
if ("sender" in filter && filter.sender) {
|
|
690
|
+
if (!matchPattern(data.sender, filter.sender))
|
|
691
|
+
return false;
|
|
692
|
+
}
|
|
693
|
+
if ("recipient" in filter && filter.recipient) {
|
|
694
|
+
if (!matchPattern(data.recipient, filter.recipient))
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
return true;
|
|
422
698
|
});
|
|
423
|
-
if (
|
|
699
|
+
if (matched.length > 0) {
|
|
700
|
+
results.push({ tx, events: matched });
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
break;
|
|
704
|
+
}
|
|
705
|
+
case "contract_call": {
|
|
706
|
+
for (const tx of transactions) {
|
|
707
|
+
if (tx.type !== "contract_call")
|
|
424
708
|
continue;
|
|
709
|
+
if (filter.contractId) {
|
|
710
|
+
if (!tx.contract_id || !matchPattern(tx.contract_id, filter.contractId))
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
if (filter.functionName) {
|
|
714
|
+
if (!tx.function_name || !matchPattern(tx.function_name, filter.functionName))
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
if (filter.caller) {
|
|
718
|
+
if (!matchPattern(tx.sender, filter.caller))
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
721
|
+
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
722
|
+
results.push({ tx, events: txEvents });
|
|
425
723
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
724
|
+
break;
|
|
725
|
+
}
|
|
726
|
+
case "contract_deploy": {
|
|
727
|
+
for (const tx of transactions) {
|
|
728
|
+
if (tx.type !== "smart_contract")
|
|
729
|
+
continue;
|
|
730
|
+
if (filter.deployer) {
|
|
731
|
+
if (!matchPattern(tx.sender, filter.deployer))
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
if (filter.contractName) {
|
|
735
|
+
const name = tx.contract_id?.split(".")[1] ?? "";
|
|
736
|
+
if (!matchPattern(name, filter.contractName))
|
|
737
|
+
continue;
|
|
738
|
+
}
|
|
739
|
+
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
740
|
+
results.push({ tx, events: txEvents });
|
|
741
|
+
}
|
|
742
|
+
break;
|
|
743
|
+
}
|
|
744
|
+
case "print_event": {
|
|
745
|
+
for (const tx of transactions) {
|
|
746
|
+
const txEvents = eventsByTx.get(tx.tx_id) ?? [];
|
|
747
|
+
const matched = txEvents.filter((e) => {
|
|
748
|
+
if (e.type !== "smart_contract_event")
|
|
749
|
+
return false;
|
|
430
750
|
const data = e.data;
|
|
431
|
-
|
|
432
|
-
|
|
751
|
+
if (!data)
|
|
752
|
+
return false;
|
|
753
|
+
if (data.topic !== "print")
|
|
754
|
+
return false;
|
|
755
|
+
if (filter.contractId) {
|
|
756
|
+
const contractId = data.contract_identifier;
|
|
757
|
+
if (!contractId || !matchPattern(contractId, filter.contractId))
|
|
758
|
+
return false;
|
|
759
|
+
}
|
|
760
|
+
return true;
|
|
433
761
|
});
|
|
762
|
+
if (matched.length > 0) {
|
|
763
|
+
results.push({ tx, events: matched });
|
|
764
|
+
}
|
|
434
765
|
}
|
|
435
|
-
|
|
436
|
-
results.push({ tx, events: matchedEvents, sourceKey: key });
|
|
437
|
-
}
|
|
766
|
+
break;
|
|
438
767
|
}
|
|
439
768
|
}
|
|
440
769
|
return results;
|
|
@@ -448,13 +777,13 @@ function matchSources(sources, transactions, events) {
|
|
|
448
777
|
}
|
|
449
778
|
const seen = new Set;
|
|
450
779
|
const results = [];
|
|
451
|
-
for (const
|
|
452
|
-
const matches =
|
|
780
|
+
for (const [sourceName, filter] of Object.entries(sources)) {
|
|
781
|
+
const matches = matchFilter(filter, transactions, eventsByTx);
|
|
453
782
|
for (const match of matches) {
|
|
454
|
-
const dedupeKey = `${match.tx.tx_id}:${
|
|
783
|
+
const dedupeKey = `${match.tx.tx_id}:${sourceName}`;
|
|
455
784
|
if (!seen.has(dedupeKey)) {
|
|
456
785
|
seen.add(dedupeKey);
|
|
457
|
-
results.push(match);
|
|
786
|
+
results.push({ ...match, sourceName });
|
|
458
787
|
}
|
|
459
788
|
}
|
|
460
789
|
}
|
|
@@ -1137,5 +1466,5 @@ export {
|
|
|
1137
1466
|
backfillSubgraph
|
|
1138
1467
|
};
|
|
1139
1468
|
|
|
1140
|
-
//# debugId=
|
|
1469
|
+
//# debugId=6179C8B152DFE4D464756E2164756E21
|
|
1141
1470
|
//# sourceMappingURL=reindex.js.map
|