ponder 0.8.24 → 0.8.26

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.
@@ -2413,6 +2413,7 @@ var MetricsService = class {
2413
2413
  ponder_historical_cached_blocks;
2414
2414
  ponder_historical_completed_blocks;
2415
2415
  ponder_realtime_reorg_total;
2416
+ ponder_realtime_latency;
2416
2417
  ponder_database_method_duration;
2417
2418
  ponder_database_method_error_total;
2418
2419
  ponder_http_server_port;
@@ -2511,10 +2512,17 @@ var MetricsService = class {
2511
2512
  });
2512
2513
  this.ponder_realtime_reorg_total = new prometheus.Counter({
2513
2514
  name: "ponder_realtime_reorg_total",
2514
- help: "Count of how many re-orgs have occurred.",
2515
+ help: "Count of how many re-orgs have occurred",
2515
2516
  labelNames: ["network"],
2516
2517
  registers: [this.registry]
2517
2518
  });
2519
+ this.ponder_realtime_latency = new prometheus.Histogram({
2520
+ name: "ponder_realtime_latency",
2521
+ help: "Time elapsed between receiving a block and fully processing it",
2522
+ labelNames: ["network"],
2523
+ buckets: httpRequestDurationMs,
2524
+ registers: [this.registry]
2525
+ });
2518
2526
  this.ponder_database_method_duration = new prometheus.Histogram({
2519
2527
  name: "ponder_database_method_duration",
2520
2528
  help: "Duration of database operations",
@@ -6378,74 +6386,93 @@ var methods = {
6378
6386
  var createIndexingService = extend(create, methods);
6379
6387
 
6380
6388
  // src/sync/fragments.ts
6381
- var getFragmentIds = (filter) => {
6389
+ var getFragments = (filter) => {
6382
6390
  switch (filter.type) {
6383
6391
  case "block":
6384
- return getBlockFilterFragmentId(filter);
6392
+ return getBlockFilterFragment(filter);
6385
6393
  case "transaction":
6386
- return getTransactionFilterFragmentIds(filter);
6394
+ return getTransactionFilterFragments(filter);
6387
6395
  case "trace":
6388
- return getTraceFilterFragmentIds(filter);
6396
+ return getTraceFilterFragments(filter);
6389
6397
  case "log":
6390
- return getLogFilterFragmentIds(filter);
6398
+ return getLogFilterFragments(filter);
6391
6399
  case "transfer":
6392
- return getTransferFilterFragmentIds(filter);
6400
+ return getTransferFilterFragments(filter);
6393
6401
  }
6394
6402
  };
6395
- var getAddressFragmentIds = (address) => {
6403
+ var getAddressFragments = (address) => {
6396
6404
  const fragments = [];
6397
6405
  if (isAddressFactory(address)) {
6398
6406
  for (const fragmentAddress of Array.isArray(address.address) ? address.address : [address.address]) {
6399
- const id = `${fragmentAddress}_${address.eventSelector}_${address.childAddressLocation}`;
6400
- fragments.push({ id, adjacent: [id] });
6407
+ const fragment = {
6408
+ address: fragmentAddress,
6409
+ eventSelector: address.eventSelector,
6410
+ childAddressLocation: address.childAddressLocation
6411
+ };
6412
+ fragments.push({
6413
+ fragment,
6414
+ adjacentIds: [
6415
+ `${fragmentAddress}_${address.eventSelector}_${address.childAddressLocation}`
6416
+ ]
6417
+ });
6401
6418
  }
6402
6419
  } else {
6403
6420
  for (const fragmentAddress of Array.isArray(address) ? address : [address ?? null]) {
6404
6421
  fragments.push({
6405
- id: fragmentAddress,
6406
- adjacent: fragmentAddress ? [fragmentAddress, null] : [fragmentAddress]
6422
+ fragment: fragmentAddress,
6423
+ adjacentIds: fragmentAddress ? [fragmentAddress, null] : [fragmentAddress]
6407
6424
  });
6408
6425
  }
6409
6426
  }
6410
6427
  return fragments;
6411
6428
  };
6412
- var getBlockFilterFragmentId = ({
6429
+ var getBlockFilterFragment = ({
6413
6430
  chainId,
6414
6431
  interval,
6415
6432
  offset
6416
6433
  }) => {
6417
6434
  return [
6418
6435
  {
6419
- id: `block_${chainId}_${interval}_${offset}`,
6420
- adjacent: [`block_${chainId}_${interval}_${offset}`]
6436
+ fragment: {
6437
+ type: "block",
6438
+ chainId,
6439
+ interval,
6440
+ offset
6441
+ },
6442
+ adjacentIds: [`block_${chainId}_${interval}_${offset}`]
6421
6443
  }
6422
6444
  ];
6423
6445
  };
6424
- var getTransactionFilterFragmentIds = ({
6446
+ var getTransactionFilterFragments = ({
6425
6447
  chainId,
6426
6448
  fromAddress,
6427
6449
  toAddress
6428
6450
  }) => {
6429
6451
  const fragments = [];
6430
- const fromAddressFragmentIds = getAddressFragmentIds(fromAddress);
6431
- const toAddressFragmentIds = getAddressFragmentIds(toAddress);
6432
- for (const fragmentFromAddress of fromAddressFragmentIds) {
6433
- for (const fragmentToAddress of toAddressFragmentIds) {
6434
- const id = `transaction_${chainId}_${fragmentFromAddress.id}_${fragmentToAddress.id}`;
6435
- const adjacent = [];
6436
- for (const adjacentFromAddress of fragmentFromAddress.adjacent) {
6437
- for (const adjacentToAddress of fragmentToAddress.adjacent) {
6438
- adjacent.push(
6439
- `transaction_${chainId}_${adjacentFromAddress}_${adjacentToAddress}`
6452
+ const fromAddressFragments = getAddressFragments(fromAddress);
6453
+ const toAddressFragments = getAddressFragments(toAddress);
6454
+ for (const fromAddressFragment of fromAddressFragments) {
6455
+ for (const toAddressFragment of toAddressFragments) {
6456
+ const fragment = {
6457
+ type: "transaction",
6458
+ chainId,
6459
+ fromAddress: fromAddressFragment.fragment,
6460
+ toAddress: toAddressFragment.fragment
6461
+ };
6462
+ const adjacentIds = [];
6463
+ for (const fromAddressAdjacentId of fromAddressFragment.adjacentIds) {
6464
+ for (const toAddressAdjacentId of toAddressFragment.adjacentIds) {
6465
+ adjacentIds.push(
6466
+ `transaction_${chainId}_${fromAddressAdjacentId}_${toAddressAdjacentId}`
6440
6467
  );
6441
6468
  }
6442
6469
  }
6443
- fragments.push({ id, adjacent });
6470
+ fragments.push({ fragment, adjacentIds });
6444
6471
  }
6445
6472
  }
6446
6473
  return fragments;
6447
6474
  };
6448
- var getTraceFilterFragmentIds = ({
6475
+ var getTraceFilterFragments = ({
6449
6476
  chainId,
6450
6477
  fromAddress,
6451
6478
  toAddress,
@@ -6454,32 +6481,39 @@ var getTraceFilterFragmentIds = ({
6454
6481
  ...filter
6455
6482
  }) => {
6456
6483
  const fragments = [];
6457
- const fromAddressFragmentIds = getAddressFragmentIds(fromAddress);
6458
- const toAddressFragmentIds = getAddressFragmentIds(toAddress);
6484
+ const fromAddressFragments = getAddressFragments(fromAddress);
6485
+ const toAddressFragments = getAddressFragments(toAddress);
6459
6486
  const includeTransactionReceipts = shouldGetTransactionReceipt(filter);
6460
- for (const fragmentFromAddress of fromAddressFragmentIds) {
6461
- for (const fragmentToAddress of toAddressFragmentIds) {
6487
+ for (const fromAddressFragment of fromAddressFragments) {
6488
+ for (const toAddressFragment of toAddressFragments) {
6462
6489
  for (const fragmentFunctionSelector of Array.isArray(functionSelector) ? functionSelector : [functionSelector]) {
6463
- const id = `trace_${chainId}_${fragmentFromAddress.id}_${fragmentToAddress.id}_${fragmentFunctionSelector ?? null}_${includeTransactionReceipts ? 1 : 0}`;
6464
- const adjacent = [];
6465
- for (const adjacentFromAddress of fragmentFromAddress.adjacent) {
6466
- for (const adjacentToAddress of fragmentToAddress.adjacent) {
6490
+ const fragment = {
6491
+ type: "trace",
6492
+ chainId,
6493
+ fromAddress: fromAddressFragment.fragment,
6494
+ toAddress: toAddressFragment.fragment,
6495
+ functionSelector: fragmentFunctionSelector ?? null,
6496
+ includeTransactionReceipts
6497
+ };
6498
+ const adjacentIds = [];
6499
+ for (const fromAddressAdjacentId of fromAddressFragment.adjacentIds) {
6500
+ for (const toAddressAdjacentId of toAddressFragment.adjacentIds) {
6467
6501
  for (const adjacentFunctionSelector of fragmentFunctionSelector ? [fragmentFunctionSelector, null] : [null]) {
6468
6502
  for (const adjacentTxr of includeTransactionReceipts ? [1] : [0, 1]) {
6469
- adjacent.push(
6470
- `trace_${chainId}_${adjacentFromAddress}_${adjacentToAddress}_${adjacentFunctionSelector}_${adjacentTxr}`
6503
+ adjacentIds.push(
6504
+ `trace_${chainId}_${fromAddressAdjacentId}_${toAddressAdjacentId}_${adjacentFunctionSelector}_${adjacentTxr}`
6471
6505
  );
6472
6506
  }
6473
6507
  }
6474
6508
  }
6475
6509
  }
6476
- fragments.push({ id, adjacent });
6510
+ fragments.push({ fragment, adjacentIds });
6477
6511
  }
6478
6512
  }
6479
6513
  }
6480
6514
  return fragments;
6481
6515
  };
6482
- var getLogFilterFragmentIds = ({
6516
+ var getLogFilterFragments = ({
6483
6517
  chainId,
6484
6518
  address,
6485
6519
  topic0,
@@ -6489,23 +6523,32 @@ var getLogFilterFragmentIds = ({
6489
6523
  ...filter
6490
6524
  }) => {
6491
6525
  const fragments = [];
6492
- const addressFragmentIds = getAddressFragmentIds(address);
6526
+ const addressFragments = getAddressFragments(address);
6493
6527
  const includeTransactionReceipts = shouldGetTransactionReceipt(filter);
6494
- for (const fragmentAddress of addressFragmentIds) {
6528
+ for (const addressFragment of addressFragments) {
6495
6529
  for (const fragmentTopic0 of Array.isArray(topic0) ? topic0 : [topic0]) {
6496
6530
  for (const fragmentTopic1 of Array.isArray(topic1) ? topic1 : [topic1]) {
6497
6531
  for (const fragmentTopic2 of Array.isArray(topic2) ? topic2 : [topic2]) {
6498
6532
  for (const fragmentTopic3 of Array.isArray(topic3) ? topic3 : [topic3]) {
6499
- const id = `log_${chainId}_${fragmentAddress.id}_${fragmentTopic0 ?? null}_${fragmentTopic1 ?? null}_${fragmentTopic2 ?? null}_${fragmentTopic3 ?? null}_${includeTransactionReceipts ? 1 : 0}`;
6500
- const adjacent = [];
6501
- for (const adjacentAddress of fragmentAddress.adjacent) {
6533
+ const fragment = {
6534
+ type: "log",
6535
+ chainId,
6536
+ address: addressFragment.fragment,
6537
+ topic0: fragmentTopic0 ?? null,
6538
+ topic1: fragmentTopic1 ?? null,
6539
+ topic2: fragmentTopic2 ?? null,
6540
+ topic3: fragmentTopic3 ?? null,
6541
+ includeTransactionReceipts
6542
+ };
6543
+ const adjacentIds = [];
6544
+ for (const addressAdjacentId of addressFragment.adjacentIds) {
6502
6545
  for (const adjacentTopic0 of fragmentTopic0 ? [fragmentTopic0, null] : [null]) {
6503
6546
  for (const adjacentTopic1 of fragmentTopic1 ? [fragmentTopic1, null] : [null]) {
6504
6547
  for (const adjacentTopic2 of fragmentTopic2 ? [fragmentTopic2, null] : [null]) {
6505
6548
  for (const adjacentTopic3 of fragmentTopic3 ? [fragmentTopic3, null] : [null]) {
6506
6549
  for (const adjacentTxr of includeTransactionReceipts ? [1] : [0, 1]) {
6507
- adjacent.push(
6508
- `log_${chainId}_${adjacentAddress}_${adjacentTopic0}_${adjacentTopic1}_${adjacentTopic2}_${adjacentTopic3}_${adjacentTxr}`
6550
+ adjacentIds.push(
6551
+ `log_${chainId}_${addressAdjacentId}_${adjacentTopic0}_${adjacentTopic1}_${adjacentTopic2}_${adjacentTopic3}_${adjacentTxr}`
6509
6552
  );
6510
6553
  }
6511
6554
  }
@@ -6513,7 +6556,7 @@ var getLogFilterFragmentIds = ({
6513
6556
  }
6514
6557
  }
6515
6558
  }
6516
- fragments.push({ id, adjacent });
6559
+ fragments.push({ fragment, adjacentIds });
6517
6560
  }
6518
6561
  }
6519
6562
  }
@@ -6521,149 +6564,197 @@ var getLogFilterFragmentIds = ({
6521
6564
  }
6522
6565
  return fragments;
6523
6566
  };
6524
- var getTransferFilterFragmentIds = ({
6567
+ var getTransferFilterFragments = ({
6525
6568
  chainId,
6526
6569
  fromAddress,
6527
6570
  toAddress,
6528
6571
  ...filter
6529
6572
  }) => {
6530
6573
  const fragments = [];
6531
- const fromAddressFragmentIds = getAddressFragmentIds(fromAddress);
6532
- const toAddressFragmentIds = getAddressFragmentIds(toAddress);
6574
+ const fromAddressFragments = getAddressFragments(fromAddress);
6575
+ const toAddressFragments = getAddressFragments(toAddress);
6533
6576
  const includeTransactionReceipts = shouldGetTransactionReceipt(filter);
6534
- for (const fragmentFromAddress of fromAddressFragmentIds) {
6535
- for (const fragmentToAddress of toAddressFragmentIds) {
6536
- const id = `transfer_${chainId}_${fragmentFromAddress.id}_${fragmentToAddress.id}_${includeTransactionReceipts ? 1 : 0}`;
6537
- const adjacent = [];
6538
- for (const adjacentFromAddress of fragmentFromAddress.adjacent) {
6539
- for (const adjacentToAddress of fragmentToAddress.adjacent) {
6577
+ for (const fromAddressFragment of fromAddressFragments) {
6578
+ for (const toAddressFragment of toAddressFragments) {
6579
+ const fragment = {
6580
+ type: "transfer",
6581
+ chainId,
6582
+ fromAddress: fromAddressFragment.fragment,
6583
+ toAddress: toAddressFragment.fragment,
6584
+ includeTransactionReceipts
6585
+ };
6586
+ const adjacentIds = [];
6587
+ for (const fromAddressAdjacentId of fromAddressFragment.adjacentIds) {
6588
+ for (const toAddressAdjacentId of toAddressFragment.adjacentIds) {
6540
6589
  for (const adjacentTxr of includeTransactionReceipts ? [1] : [0, 1]) {
6541
- adjacent.push(
6542
- `transfer_${chainId}_${adjacentFromAddress}_${adjacentToAddress}_${adjacentTxr}`
6590
+ adjacentIds.push(
6591
+ `transfer_${chainId}_${fromAddressAdjacentId}_${toAddressAdjacentId}_${adjacentTxr}`
6543
6592
  );
6544
6593
  }
6545
6594
  }
6546
6595
  }
6547
- fragments.push({ id, adjacent });
6596
+ fragments.push({ fragment, adjacentIds });
6548
6597
  }
6549
6598
  }
6550
6599
  return fragments;
6551
6600
  };
6552
-
6553
- // src/utils/range.ts
6554
- var range = (start2, stop) => Array.from({ length: stop - start2 }, (_, i) => start2 + i);
6555
-
6556
- // src/utils/interval.ts
6557
- function intervalSum(intervals) {
6558
- let totalSum = 0;
6559
- for (const [start2, end] of intervals) {
6560
- totalSum += end - start2 + 1;
6601
+ var fragmentAddressToId = (fragmentAddress) => {
6602
+ if (fragmentAddress === null)
6603
+ return null;
6604
+ if (typeof fragmentAddress === "string")
6605
+ return fragmentAddress;
6606
+ return `${fragmentAddress.address}_${fragmentAddress.eventSelector}_${fragmentAddress.childAddressLocation}`;
6607
+ };
6608
+ var fragmentToId = (fragment) => {
6609
+ switch (fragment.type) {
6610
+ case "block":
6611
+ return `block_${fragment.chainId}_${fragment.interval}_${fragment.offset}`;
6612
+ case "transaction":
6613
+ return `transaction_${fragment.chainId}_${fragmentAddressToId(fragment.fromAddress)}_${fragmentAddressToId(fragment.toAddress)}`;
6614
+ case "trace":
6615
+ return `trace_${fragment.chainId}_${fragmentAddressToId(fragment.fromAddress)}_${fragmentAddressToId(fragment.toAddress)}_${fragment.functionSelector}_${fragment.includeTransactionReceipts ? 1 : 0}`;
6616
+ case "log":
6617
+ return `log_${fragment.chainId}_${fragmentAddressToId(fragment.address)}_${fragment.topic0}_${fragment.topic1}_${fragment.topic2}_${fragment.topic3}_${fragment.includeTransactionReceipts ? 1 : 0}`;
6618
+ case "transfer":
6619
+ return `transfer_${fragment.chainId}_${fragmentAddressToId(fragment.fromAddress)}_${fragmentAddressToId(fragment.toAddress)}_${fragment.includeTransactionReceipts ? 1 : 0}`;
6561
6620
  }
6562
- return totalSum;
6563
- }
6564
- function intervalUnion(intervals_) {
6565
- if (intervals_.length === 0)
6566
- return [];
6567
- const intervals = intervals_.map((interval) => [...interval]);
6568
- intervals.sort((a, b) => a[0] - b[0]);
6569
- const result = [];
6570
- let currentInterval = intervals[0];
6571
- for (let i = 1; i < intervals.length; i++) {
6572
- const nextInterval = intervals[i];
6573
- if (currentInterval[1] >= nextInterval[0] - 1) {
6574
- currentInterval[1] = Math.max(currentInterval[1], nextInterval[1]);
6575
- } else {
6576
- result.push(currentInterval);
6577
- currentInterval = nextInterval;
6621
+ };
6622
+ var recoverAddress = (baseAddress, fragmentAddresses) => {
6623
+ if (baseAddress === void 0)
6624
+ return void 0;
6625
+ if (typeof baseAddress === "string")
6626
+ return baseAddress;
6627
+ if (Array.isArray(baseAddress))
6628
+ return dedupe(fragmentAddresses);
6629
+ if (typeof baseAddress.address === "string")
6630
+ return baseAddress;
6631
+ const address = {
6632
+ type: "log",
6633
+ chainId: baseAddress.chainId,
6634
+ address: [],
6635
+ eventSelector: baseAddress.eventSelector,
6636
+ childAddressLocation: baseAddress.childAddressLocation
6637
+ };
6638
+ address.address = dedupe(
6639
+ fragmentAddresses.map(
6640
+ ({ address: address2 }) => address2
6641
+ )
6642
+ );
6643
+ return address;
6644
+ };
6645
+ var recoverSelector = (base, fragments) => {
6646
+ if (base === void 0)
6647
+ return void 0;
6648
+ if (typeof base === "string")
6649
+ return base;
6650
+ return dedupe(fragments);
6651
+ };
6652
+ var recoverTopic = (base, fragments) => {
6653
+ if (base === null)
6654
+ return null;
6655
+ if (typeof base === "string")
6656
+ return base;
6657
+ return dedupe(fragments);
6658
+ };
6659
+ var recoverFilter = (baseFilter, fragments) => {
6660
+ switch (baseFilter.type) {
6661
+ case "block": {
6662
+ return baseFilter;
6578
6663
  }
6579
- }
6580
- result.push(currentInterval);
6581
- return result;
6582
- }
6583
- function intervalIntersection(list1, list2) {
6584
- const result = [];
6585
- let i = 0;
6586
- let j = 0;
6587
- while (i < list1.length && j < list2.length) {
6588
- const [start1, end1] = list1[i];
6589
- const [start2, end2] = list2[j];
6590
- const intersectionStart = Math.max(start1, start2);
6591
- const intersectionEnd = Math.min(end1, end2);
6592
- if (intersectionStart <= intersectionEnd) {
6593
- result.push([intersectionStart, intersectionEnd]);
6664
+ case "transaction": {
6665
+ return {
6666
+ ...baseFilter,
6667
+ fromAddress: recoverAddress(
6668
+ baseFilter.fromAddress,
6669
+ fragments.map(
6670
+ (fragment) => fragment.fromAddress
6671
+ )
6672
+ ),
6673
+ toAddress: recoverAddress(
6674
+ baseFilter.toAddress,
6675
+ fragments.map(
6676
+ (fragment) => fragment.toAddress
6677
+ )
6678
+ )
6679
+ };
6594
6680
  }
6595
- if (end1 < end2) {
6596
- i++;
6597
- } else {
6598
- j++;
6681
+ case "trace": {
6682
+ return {
6683
+ ...baseFilter,
6684
+ fromAddress: recoverAddress(
6685
+ baseFilter.fromAddress,
6686
+ fragments.map(
6687
+ (fragment) => fragment.fromAddress
6688
+ )
6689
+ ),
6690
+ toAddress: recoverAddress(
6691
+ baseFilter.toAddress,
6692
+ fragments.map(
6693
+ (fragment) => fragment.toAddress
6694
+ )
6695
+ ),
6696
+ functionSelector: recoverSelector(
6697
+ baseFilter.functionSelector,
6698
+ fragments.map(
6699
+ (fragment) => fragment.functionSelector
6700
+ )
6701
+ )
6702
+ };
6599
6703
  }
6600
- }
6601
- return intervalUnion(result);
6602
- }
6603
- function intervalIntersectionMany(lists) {
6604
- if (lists.length === 0)
6605
- return [];
6606
- if (lists.length === 1)
6607
- return lists[0];
6608
- let result = lists[0];
6609
- for (let i = 1; i < lists.length; i++) {
6610
- result = intervalIntersection(result, lists[i]);
6611
- }
6612
- return intervalUnion(result);
6613
- }
6614
- function intervalDifference(initial, remove) {
6615
- const initial_ = initial.map((interval) => [...interval]);
6616
- const remove_ = remove.map((interval) => [...interval]);
6617
- const result = [];
6618
- let i = 0;
6619
- let j = 0;
6620
- while (i < initial.length && j < remove.length) {
6621
- const interval1 = initial_[i];
6622
- const interval2 = remove_[j];
6623
- if (interval1[1] < interval2[0]) {
6624
- result.push(interval1);
6625
- i++;
6626
- } else if (interval2[1] < interval1[0]) {
6627
- j++;
6628
- } else {
6629
- if (interval1[0] < interval2[0]) {
6630
- result.push([interval1[0], interval2[0] - 1]);
6631
- }
6632
- if (interval1[1] > interval2[1]) {
6633
- interval1[0] = interval2[1] + 1;
6634
- j++;
6635
- } else {
6636
- i++;
6637
- }
6704
+ case "log": {
6705
+ return {
6706
+ ...baseFilter,
6707
+ address: recoverAddress(
6708
+ baseFilter.address,
6709
+ fragments.map(
6710
+ (fragment) => fragment.address
6711
+ )
6712
+ ),
6713
+ topic0: recoverTopic(
6714
+ baseFilter.topic0,
6715
+ fragments.map(
6716
+ (fragment) => fragment.topic0
6717
+ )
6718
+ ),
6719
+ topic1: recoverTopic(
6720
+ baseFilter.topic1,
6721
+ fragments.map(
6722
+ (fragment) => fragment.topic1
6723
+ )
6724
+ ),
6725
+ topic2: recoverTopic(
6726
+ baseFilter.topic2,
6727
+ fragments.map(
6728
+ (fragment) => fragment.topic2
6729
+ )
6730
+ ),
6731
+ topic3: recoverTopic(
6732
+ baseFilter.topic3,
6733
+ fragments.map(
6734
+ (fragment) => fragment.topic3
6735
+ )
6736
+ )
6737
+ };
6738
+ }
6739
+ case "transfer": {
6740
+ return {
6741
+ ...baseFilter,
6742
+ fromAddress: recoverAddress(
6743
+ baseFilter.fromAddress,
6744
+ fragments.map(
6745
+ (fragment) => fragment.fromAddress
6746
+ )
6747
+ ),
6748
+ toAddress: recoverAddress(
6749
+ baseFilter.toAddress,
6750
+ fragments.map(
6751
+ (fragment) => fragment.toAddress
6752
+ )
6753
+ )
6754
+ };
6638
6755
  }
6639
6756
  }
6640
- while (i < initial_.length) {
6641
- result.push(initial_[i]);
6642
- i++;
6643
- }
6644
- return result;
6645
- }
6646
- function sortIntervals(intervals) {
6647
- return intervals.sort((a, b) => a[0] < b[0] ? -1 : 1);
6648
- }
6649
- function getChunks({
6650
- interval,
6651
- maxChunkSize
6652
- }) {
6653
- const _chunks = [];
6654
- const [startBlock, endBlock] = interval;
6655
- let fromBlock = startBlock;
6656
- let toBlock = Math.min(fromBlock + maxChunkSize - 1, endBlock);
6657
- while (fromBlock <= endBlock) {
6658
- _chunks.push([fromBlock, toBlock]);
6659
- fromBlock = toBlock + 1;
6660
- toBlock = Math.min(fromBlock + maxChunkSize - 1, endBlock);
6661
- }
6662
- return _chunks;
6663
- }
6664
- function intervalRange(interval) {
6665
- return range(interval[0], interval[1] + 1);
6666
- }
6757
+ };
6667
6758
 
6668
6759
  // src/sync-store/index.ts
6669
6760
  import { sql as ksql } from "kysely";
@@ -6866,11 +6957,12 @@ var createSyncStore = ({
6866
6957
  const perFragmentIntervals = /* @__PURE__ */ new Map();
6867
6958
  const values = [];
6868
6959
  for (const { filter, interval } of intervals) {
6869
- for (const fragment of getFragmentIds(filter)) {
6870
- if (perFragmentIntervals.has(fragment.id) === false) {
6871
- perFragmentIntervals.set(fragment.id, []);
6960
+ for (const fragment of getFragments(filter)) {
6961
+ const fragmentId = fragmentToId(fragment.fragment);
6962
+ if (perFragmentIntervals.has(fragmentId) === false) {
6963
+ perFragmentIntervals.set(fragmentId, []);
6872
6964
  }
6873
- perFragmentIntervals.get(fragment.id).push(interval);
6965
+ perFragmentIntervals.get(fragmentId).push(interval);
6874
6966
  }
6875
6967
  }
6876
6968
  for (const [fragmentId, intervals2] of perFragmentIntervals) {
@@ -6896,13 +6988,15 @@ var createSyncStore = ({
6896
6988
  let query2;
6897
6989
  for (let i = 0; i < filters.length; i++) {
6898
6990
  const filter = filters[i];
6899
- const fragments = getFragmentIds(filter);
6900
- for (const fragment of fragments) {
6991
+ const fragments = getFragments(filter);
6992
+ for (let j = 0; j < fragments.length; j++) {
6993
+ const fragment = fragments[j];
6901
6994
  const _query = db.selectFrom(
6902
- db.selectFrom("intervals").select(ksql`unnest(blocks)`.as("blocks")).where("fragment_id", "in", fragment.adjacent).as("unnested")
6995
+ db.selectFrom("intervals").select(ksql`unnest(blocks)`.as("blocks")).where("fragment_id", "in", fragment.adjacentIds).as("unnested")
6903
6996
  ).select([
6904
6997
  ksql`range_agg(unnested.blocks)`.as("merged_blocks"),
6905
- ksql.raw(`'${i}'`).as("filter")
6998
+ ksql.raw(`'${i}'`).as("filter"),
6999
+ ksql.raw(`'${j}'`).as("fragment")
6906
7000
  ]);
6907
7001
  query2 = query2 === void 0 ? _query : query2.unionAll(_query);
6908
7002
  }
@@ -6911,12 +7005,17 @@ var createSyncStore = ({
6911
7005
  const result = /* @__PURE__ */ new Map();
6912
7006
  for (let i = 0; i < filters.length; i++) {
6913
7007
  const filter = filters[i];
6914
- const intervals = rows.filter((row) => row.filter === `${i}`).map(
6915
- (row) => (row.merged_blocks ? JSON.parse(
6916
- `[${row.merged_blocks.slice(1, -1)}]`
6917
- ) : []).map((interval) => [interval[0], interval[1] - 1])
6918
- );
6919
- result.set(filter, intervalIntersectionMany(intervals));
7008
+ const fragments = getFragments(filter);
7009
+ result.set(filter, []);
7010
+ for (let j = 0; j < fragments.length; j++) {
7011
+ const fragment = fragments[j];
7012
+ const intervals = rows.filter((row) => row.filter === `${i}`).filter((row) => row.fragment === `${j}`).map(
7013
+ (row) => (row.merged_blocks ? JSON.parse(
7014
+ `[${row.merged_blocks.slice(1, -1)}]`
7015
+ ) : []).map((interval) => [interval[0], interval[1] - 1])
7016
+ )[0];
7017
+ result.get(filter).push({ fragment: fragment.fragment, intervals });
7018
+ }
6920
7019
  }
6921
7020
  return result;
6922
7021
  }),
@@ -8238,6 +8337,126 @@ var convertTrace = (trace) => ({
8238
8337
  subcalls: trace.trace.subcalls
8239
8338
  });
8240
8339
 
8340
+ // src/utils/range.ts
8341
+ var range = (start2, stop) => Array.from({ length: stop - start2 }, (_, i) => start2 + i);
8342
+
8343
+ // src/utils/interval.ts
8344
+ function intervalSum(intervals) {
8345
+ let totalSum = 0;
8346
+ for (const [start2, end] of intervals) {
8347
+ totalSum += end - start2 + 1;
8348
+ }
8349
+ return totalSum;
8350
+ }
8351
+ function intervalUnion(intervals_) {
8352
+ if (intervals_.length === 0)
8353
+ return [];
8354
+ const intervals = intervals_.map((interval) => [...interval]);
8355
+ intervals.sort((a, b) => a[0] - b[0]);
8356
+ const result = [];
8357
+ let currentInterval = intervals[0];
8358
+ for (let i = 1; i < intervals.length; i++) {
8359
+ const nextInterval = intervals[i];
8360
+ if (currentInterval[1] >= nextInterval[0] - 1) {
8361
+ currentInterval[1] = Math.max(currentInterval[1], nextInterval[1]);
8362
+ } else {
8363
+ result.push(currentInterval);
8364
+ currentInterval = nextInterval;
8365
+ }
8366
+ }
8367
+ result.push(currentInterval);
8368
+ return result;
8369
+ }
8370
+ function intervalIntersection(list1, list2) {
8371
+ const result = [];
8372
+ let i = 0;
8373
+ let j = 0;
8374
+ while (i < list1.length && j < list2.length) {
8375
+ const [start1, end1] = list1[i];
8376
+ const [start2, end2] = list2[j];
8377
+ const intersectionStart = Math.max(start1, start2);
8378
+ const intersectionEnd = Math.min(end1, end2);
8379
+ if (intersectionStart <= intersectionEnd) {
8380
+ result.push([intersectionStart, intersectionEnd]);
8381
+ }
8382
+ if (end1 < end2) {
8383
+ i++;
8384
+ } else {
8385
+ j++;
8386
+ }
8387
+ }
8388
+ return intervalUnion(result);
8389
+ }
8390
+ function intervalIntersectionMany(lists) {
8391
+ if (lists.length === 0)
8392
+ return [];
8393
+ if (lists.length === 1)
8394
+ return lists[0];
8395
+ let result = lists[0];
8396
+ for (let i = 1; i < lists.length; i++) {
8397
+ result = intervalIntersection(result, lists[i]);
8398
+ }
8399
+ return intervalUnion(result);
8400
+ }
8401
+ function intervalDifference(initial, remove) {
8402
+ const initial_ = initial.map((interval) => [...interval]);
8403
+ const remove_ = remove.map((interval) => [...interval]);
8404
+ const result = [];
8405
+ let i = 0;
8406
+ let j = 0;
8407
+ while (i < initial.length && j < remove.length) {
8408
+ const interval1 = initial_[i];
8409
+ const interval2 = remove_[j];
8410
+ if (interval1[1] < interval2[0]) {
8411
+ result.push(interval1);
8412
+ i++;
8413
+ } else if (interval2[1] < interval1[0]) {
8414
+ j++;
8415
+ } else {
8416
+ if (interval1[0] < interval2[0]) {
8417
+ result.push([interval1[0], interval2[0] - 1]);
8418
+ }
8419
+ if (interval1[1] > interval2[1]) {
8420
+ interval1[0] = interval2[1] + 1;
8421
+ j++;
8422
+ } else {
8423
+ i++;
8424
+ }
8425
+ }
8426
+ }
8427
+ while (i < initial_.length) {
8428
+ result.push(initial_[i]);
8429
+ i++;
8430
+ }
8431
+ return result;
8432
+ }
8433
+ function intervalBounds(intervals) {
8434
+ const start2 = Math.min(...intervals.map((interval) => interval[0]));
8435
+ const end = Math.max(...intervals.map((interval) => interval[1]));
8436
+ return [start2, end];
8437
+ }
8438
+ function sortIntervals(intervals) {
8439
+ return intervals.sort((a, b) => a[0] < b[0] ? -1 : 1);
8440
+ }
8441
+ function getChunks({
8442
+ interval,
8443
+ maxChunkSize
8444
+ }) {
8445
+ const _chunks = [];
8446
+ const [startBlock, endBlock] = interval;
8447
+ let fromBlock = startBlock;
8448
+ let toBlock = Math.min(fromBlock + maxChunkSize - 1, endBlock);
8449
+ while (fromBlock <= endBlock) {
8450
+ _chunks.push([fromBlock, toBlock]);
8451
+ fromBlock = toBlock + 1;
8452
+ toBlock = Math.min(fromBlock + maxChunkSize - 1, endBlock);
8453
+ }
8454
+ return _chunks;
8455
+ }
8456
+ function intervalRange(interval) {
8457
+ return range(interval[0], interval[1] + 1);
8458
+ }
8459
+
8241
8460
  // src/utils/rpc.ts
8242
8461
  import {
8243
8462
  BlockNotFoundError,
@@ -8825,51 +9044,75 @@ var createHistoricalSync = async (args) => {
8825
9044
  return {
8826
9045
  intervalsCache,
8827
9046
  async sync(_interval) {
8828
- const syncedIntervals = [];
8829
- await Promise.all(
8830
- args.sources.map(async (source) => {
8831
- const filter = source.filter;
8832
- if (filter.fromBlock !== void 0 && filter.fromBlock > _interval[1] || filter.toBlock !== void 0 && filter.toBlock < _interval[0]) {
8833
- return;
8834
- }
8835
- const interval = [
8836
- Math.max(filter.fromBlock ?? 0, _interval[0]),
8837
- Math.min(filter.toBlock ?? Number.POSITIVE_INFINITY, _interval[1])
8838
- ];
8839
- const completedIntervals = intervalsCache.get(filter);
8840
- const requiredIntervals = intervalDifference(
9047
+ const intervalsToSync = [];
9048
+ for (const { filter } of args.sources) {
9049
+ if (filter.fromBlock !== void 0 && filter.fromBlock > _interval[1] || filter.toBlock !== void 0 && filter.toBlock < _interval[0]) {
9050
+ continue;
9051
+ }
9052
+ const interval = [
9053
+ Math.max(filter.fromBlock ?? 0, _interval[0]),
9054
+ Math.min(filter.toBlock ?? Number.POSITIVE_INFINITY, _interval[1])
9055
+ ];
9056
+ const completedIntervals = intervalsCache.get(filter);
9057
+ const requiredIntervals = [];
9058
+ for (const {
9059
+ fragment,
9060
+ intervals: fragmentIntervals
9061
+ } of completedIntervals) {
9062
+ const requiredFragmentIntervals = intervalDifference(
8841
9063
  [interval],
8842
- completedIntervals
9064
+ fragmentIntervals
8843
9065
  );
8844
- if (requiredIntervals.length === 0)
8845
- return;
9066
+ if (requiredFragmentIntervals.length > 0) {
9067
+ requiredIntervals.push({
9068
+ fragment,
9069
+ intervals: requiredFragmentIntervals
9070
+ });
9071
+ }
9072
+ }
9073
+ if (requiredIntervals.length > 0) {
9074
+ const requiredInterval = intervalBounds(
9075
+ requiredIntervals.flatMap(({ intervals }) => intervals)
9076
+ );
9077
+ const requiredFilter = recoverFilter(
9078
+ filter,
9079
+ requiredIntervals.map(({ fragment }) => fragment)
9080
+ );
9081
+ intervalsToSync.push({
9082
+ filter: requiredFilter,
9083
+ interval: requiredInterval
9084
+ });
9085
+ }
9086
+ }
9087
+ await Promise.all(
9088
+ intervalsToSync.map(async ({ filter, interval }) => {
8846
9089
  const blockPromise = syncBlock(interval[1]);
8847
9090
  try {
8848
- await Promise.all(
8849
- requiredIntervals.map(async (interval2) => {
8850
- switch (filter.type) {
8851
- case "log": {
8852
- await syncLogFilter(filter, interval2);
8853
- break;
8854
- }
8855
- case "block": {
8856
- await syncBlockFilter(filter, interval2);
8857
- break;
8858
- }
8859
- case "transaction": {
8860
- await syncTransactionFilter(filter, interval2);
8861
- break;
8862
- }
8863
- case "trace":
8864
- case "transfer": {
8865
- await syncTraceOrTransferFilter(filter, interval2);
8866
- break;
8867
- }
8868
- default:
8869
- never(filter);
8870
- }
8871
- })
8872
- );
9091
+ switch (filter.type) {
9092
+ case "log": {
9093
+ await syncLogFilter(filter, interval);
9094
+ break;
9095
+ }
9096
+ case "block": {
9097
+ await syncBlockFilter(filter, interval);
9098
+ break;
9099
+ }
9100
+ case "transaction": {
9101
+ await syncTransactionFilter(
9102
+ filter,
9103
+ interval
9104
+ );
9105
+ break;
9106
+ }
9107
+ case "trace":
9108
+ case "transfer": {
9109
+ await syncTraceOrTransferFilter(
9110
+ filter,
9111
+ interval
9112
+ );
9113
+ break;
9114
+ }
9115
+ }
8873
9116
  } catch (_error) {
8874
9117
  const error = _error;
8875
9118
  args.common.logger.error({
@@ -8883,9 +9126,10 @@ var createHistoricalSync = async (args) => {
8883
9126
  if (isKilled)
8884
9127
  return;
8885
9128
  await blockPromise;
8886
- syncedIntervals.push({ filter, interval });
8887
9129
  })
8888
9130
  );
9131
+ if (isKilled)
9132
+ return;
8889
9133
  const blocks = await Promise.all(blockCache.values());
8890
9134
  await Promise.all([
8891
9135
  args.syncStore.insertBlocks({ blocks, chainId: args.network.chainId }),
@@ -8899,9 +9143,11 @@ var createHistoricalSync = async (args) => {
8899
9143
  chainId: args.network.chainId
8900
9144
  })
8901
9145
  ]);
9146
+ if (isKilled)
9147
+ return;
8902
9148
  if (args.network.disableCache === false) {
8903
9149
  await args.syncStore.insertIntervals({
8904
- intervals: syncedIntervals,
9150
+ intervals: intervalsToSync,
8905
9151
  chainId: args.network.chainId
8906
9152
  });
8907
9153
  }
@@ -9062,7 +9308,8 @@ var createRealtimeSync = (args) => {
9062
9308
  factoryLogs,
9063
9309
  traces,
9064
9310
  transactions,
9065
- transactionReceipts
9311
+ transactionReceipts,
9312
+ endClock
9066
9313
  }) => {
9067
9314
  args.common.logger.debug({
9068
9315
  service: "realtime",
@@ -9219,7 +9466,8 @@ var createRealtimeSync = (args) => {
9219
9466
  logs,
9220
9467
  traces,
9221
9468
  transactions,
9222
- transactionReceipts
9469
+ transactionReceipts,
9470
+ endClock
9223
9471
  });
9224
9472
  const blockMovesFinality = hexToNumber6(block.number) >= hexToNumber6(finalizedBlock.number) + 2 * args.network.finalityBlockCount;
9225
9473
  if (blockMovesFinality) {
@@ -9632,9 +9880,10 @@ var createRealtimeSync = (args) => {
9632
9880
  });
9633
9881
  return;
9634
9882
  }
9883
+ const endClock = startClock();
9635
9884
  const blockWithEventData = await fetchBlockEventData(block);
9636
9885
  consecutiveErrors = 0;
9637
- return queue.add(blockWithEventData);
9886
+ return queue.add({ ...blockWithEventData, endClock });
9638
9887
  } catch (_error) {
9639
9888
  if (isKilled)
9640
9889
  return;
@@ -10352,6 +10601,19 @@ var createSync = async (args) => {
10352
10601
  msg: `Indexed ${events.length} events`
10353
10602
  });
10354
10603
  }
10604
+ for (const network2 of args.networks) {
10605
+ for (const { block, endClock } of perNetworkSync.get(network2).unfinalizedBlocks) {
10606
+ const checkpoint = encodeCheckpoint(
10607
+ blockToCheckpoint(block, network2.chainId, "up")
10608
+ );
10609
+ if (checkpoint > from && checkpoint <= to && endClock) {
10610
+ args.common.metrics.ponder_realtime_latency.observe(
10611
+ { network: network2.name },
10612
+ endClock()
10613
+ );
10614
+ }
10615
+ }
10616
+ }
10355
10617
  });
10356
10618
  }
10357
10619
  break;
@@ -10608,9 +10870,14 @@ var getCachedBlock = ({
10608
10870
  filter.fromBlock ?? 0,
10609
10871
  filter.toBlock ?? Number.POSITIVE_INFINITY
10610
10872
  ];
10611
- const cachedIntervals = historicalSync.intervalsCache.get(filter);
10873
+ const fragmentIntervals = historicalSync.intervalsCache.get(filter);
10612
10874
  const completedIntervals = sortIntervals(
10613
- intervalIntersection([requiredInterval], cachedIntervals)
10875
+ intervalIntersection(
10876
+ [requiredInterval],
10877
+ intervalIntersectionMany(
10878
+ fragmentIntervals.map(({ intervals }) => intervals)
10879
+ )
10880
+ )
10614
10881
  );
10615
10882
  if (completedIntervals.length === 0)
10616
10883
  return void 0;
@@ -10666,7 +10933,7 @@ async function* localHistoricalSyncGenerator({
10666
10933
  const requiredIntervals = Array.from(
10667
10934
  historicalSync.intervalsCache.entries()
10668
10935
  ).flatMap(
10669
- ([filter, interval]) => intervalDifference(
10936
+ ([filter, fragmentIntervals]) => intervalDifference(
10670
10937
  [
10671
10938
  [
10672
10939
  filter.fromBlock ?? 0,
@@ -10676,7 +10943,9 @@ async function* localHistoricalSyncGenerator({
10676
10943
  )
10677
10944
  ]
10678
10945
  ],
10679
- interval
10946
+ intervalIntersectionMany(
10947
+ fragmentIntervals.map(({ intervals }) => intervals)
10948
+ )
10680
10949
  )
10681
10950
  );
10682
10951
  const required = intervalSum(intervalUnion(requiredIntervals));
@@ -10731,7 +11000,7 @@ async function* localHistoricalSyncGenerator({
10731
11000
  }
10732
11001
  const duration = endClock();
10733
11002
  common.metrics.ponder_sync_block.set(
10734
- { network: network.name },
11003
+ label,
10735
11004
  hexToNumber7(syncProgress.current.number)
10736
11005
  );
10737
11006
  common.metrics.ponder_historical_duration.observe(label, duration);