@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.
Files changed (42) hide show
  1. package/dist/src/index.d.ts +113 -32
  2. package/dist/src/index.js +458 -103
  3. package/dist/src/index.js.map +10 -11
  4. package/dist/src/runtime/block-processor.d.ts +110 -20
  5. package/dist/src/runtime/block-processor.js +419 -90
  6. package/dist/src/runtime/block-processor.js.map +7 -8
  7. package/dist/src/runtime/catchup.d.ts +110 -20
  8. package/dist/src/runtime/catchup.js +424 -94
  9. package/dist/src/runtime/catchup.js.map +8 -9
  10. package/dist/src/runtime/clarity.js +3 -3
  11. package/dist/src/runtime/clarity.js.map +3 -3
  12. package/dist/src/runtime/context.d.ts +23 -5
  13. package/dist/src/runtime/context.js +57 -1
  14. package/dist/src/runtime/context.js.map +3 -3
  15. package/dist/src/runtime/processor.js +424 -94
  16. package/dist/src/runtime/processor.js.map +8 -9
  17. package/dist/src/runtime/reindex.d.ts +110 -20
  18. package/dist/src/runtime/reindex.js +424 -94
  19. package/dist/src/runtime/reindex.js.map +8 -9
  20. package/dist/src/runtime/reorg.d.ts +110 -20
  21. package/dist/src/runtime/reorg.js +419 -90
  22. package/dist/src/runtime/reorg.js.map +7 -8
  23. package/dist/src/runtime/runner.d.ts +150 -42
  24. package/dist/src/runtime/runner.js +193 -30
  25. package/dist/src/runtime/runner.js.map +4 -4
  26. package/dist/src/runtime/source-matcher.d.ts +86 -31
  27. package/dist/src/runtime/source-matcher.js +171 -61
  28. package/dist/src/runtime/source-matcher.js.map +4 -5
  29. package/dist/src/schema/index.d.ts +110 -20
  30. package/dist/src/schema/index.js +34 -9
  31. package/dist/src/schema/index.js.map +3 -3
  32. package/dist/src/service.js +424 -94
  33. package/dist/src/service.js.map +8 -9
  34. package/dist/src/templates.js +52 -51
  35. package/dist/src/templates.js.map +3 -3
  36. package/dist/src/types.d.ts +111 -29
  37. package/dist/src/types.js +1 -20
  38. package/dist/src/types.js.map +3 -4
  39. package/dist/src/validate.d.ts +112 -22
  40. package/dist/src/validate.js +35 -10
  41. package/dist/src/validate.js.map +3 -3
  42. 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 { cvToJSON, deserializeCV } from "@secondlayer/stacks/clarity";
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 cvToJSON(cv);
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 resolveHandler(handlers, key) {
279
- return handlers[key] ?? handlers["*"] ?? null;
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
- for (const { tx, events, sourceKey: sourceKey2 } of matched) {
286
- const handler = resolveHandler(subgraph.handlers, sourceKey2);
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 key", {
488
+ logger2.warn("No handler found for source", {
289
489
  subgraph: subgraph.name,
290
- sourceKey: sourceKey2,
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 txPayload = {
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(txPayload, ctx);
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
- sourceKey: sourceKey2,
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 decoded = decodeEventData(event.data);
337
- const eventPayload = {
338
- ...decoded,
339
- _eventId: event.id,
340
- _eventType: event.type,
341
- _eventIndex: event.event_index,
342
- tx: {
343
- txId: tx.tx_id,
344
- sender: tx.sender,
345
- type: tx.type,
346
- status: tx.status,
347
- contractId: tx.contract_id,
348
- functionName: tx.function_name
349
- }
350
- };
351
- await handler(eventPayload, ctx);
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
- sourceKey: sourceKey2,
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 matchSource(source, transactions, eventsByTx) {
587
+ function matchFilter(filter, transactions, eventsByTx) {
383
588
  const results = [];
384
- const key = sourceKey(source);
385
- for (const tx of transactions) {
386
- if (source.type) {
387
- if (!matchPattern(tx.type, source.type))
388
- continue;
389
- const txEvents = eventsByTx.get(tx.tx_id) ?? [];
390
- let matchedEvents = txEvents;
391
- if (source.minAmount !== undefined) {
392
- const amountEvents = matchedEvents.filter((e) => {
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
- const rawAmount = data?.amount;
395
- if (rawAmount === undefined)
602
+ if (!data)
396
603
  return false;
397
- const amount = BigInt(rawAmount);
398
- return amount >= source.minAmount;
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 (amountEvents.length === 0)
401
- continue;
402
- matchedEvents = amountEvents;
628
+ if (filtered.length > 0) {
629
+ results.push({ tx, events: filtered });
630
+ }
403
631
  }
404
- results.push({ tx, events: matchedEvents, sourceKey: key });
405
- continue;
632
+ break;
406
633
  }
407
- if (source.contract) {
408
- const txContractMatch = tx.contract_id && matchPattern(tx.contract_id, source.contract);
409
- if (source.function && tx.function_name) {
410
- if (!matchPattern(tx.function_name, source.function))
411
- continue;
412
- } else if (source.function && !tx.function_name) {
413
- continue;
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
- const txEvents = eventsByTx.get(tx.tx_id) ?? [];
416
- let matchedEvents = txEvents;
417
- if (!txContractMatch) {
418
- matchedEvents = txEvents.filter((e) => {
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
- const contractIdentifier = data?.contract_identifier;
421
- return contractIdentifier && matchPattern(contractIdentifier, source.contract);
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 (matchedEvents.length === 0)
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
- if (source.event) {
427
- matchedEvents = matchedEvents.filter((e) => {
428
- if (matchPattern(e.type, source.event))
429
- return true;
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
- const topic = data?.topic;
432
- return topic ? matchPattern(topic, source.event) : false;
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
- if (txContractMatch || matchedEvents.length > 0) {
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 source of sources) {
452
- const matches = matchSource(source, transactions, eventsByTx);
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}:${match.sourceKey}`;
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
  }
@@ -766,7 +1095,8 @@ async function catchUpSubgraph(subgraph, subgraphName) {
766
1095
  let processed = 0;
767
1096
  let batchSize = DEFAULT_BATCH_SIZE;
768
1097
  let currentHeight = startBlock;
769
- let nextBatchPromise = loadBlockRange(db, currentHeight, Math.min(currentHeight + batchSize - 1, chainTip));
1098
+ let nextBatchEnd = Math.min(currentHeight + batchSize - 1, chainTip);
1099
+ let nextBatchPromise = loadBlockRange(db, currentHeight, nextBatchEnd);
770
1100
  while (currentHeight <= chainTip) {
771
1101
  const currentRow = await getSubgraph(db, subgraphName);
772
1102
  if (!currentRow || currentRow.status !== "active") {
@@ -777,11 +1107,11 @@ async function catchUpSubgraph(subgraph, subgraphName) {
777
1107
  break;
778
1108
  }
779
1109
  const batch = await nextBatchPromise;
780
- const batchEnd = Math.min(currentHeight + batchSize - 1, chainTip);
1110
+ const batchEnd = nextBatchEnd;
781
1111
  const nextStart = batchEnd + 1;
782
1112
  if (nextStart <= chainTip) {
783
- const nextEnd = Math.min(nextStart + batchSize - 1, chainTip);
784
- nextBatchPromise = loadBlockRange(db, nextStart, nextEnd);
1113
+ nextBatchEnd = Math.min(nextStart + batchSize - 1, chainTip);
1114
+ nextBatchPromise = loadBlockRange(db, nextStart, nextBatchEnd);
785
1115
  }
786
1116
  const batchFailedBlocks = [];
787
1117
  for (let height = currentHeight;height <= batchEnd; height++) {
@@ -852,5 +1182,5 @@ export {
852
1182
  catchUpSubgraph
853
1183
  };
854
1184
 
855
- //# debugId=C68A82347E5B495264756E2164756E21
1185
+ //# debugId=726A46CF193F6AC864756E2164756E21
856
1186
  //# sourceMappingURL=catchup.js.map