envio 3.1.0 → 3.1.2
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/package.json +6 -6
- package/src/FetchState.res +103 -57
- package/src/FetchState.res.mjs +52 -36
- package/src/InMemoryStore.res +12 -3
- package/src/InMemoryStore.res.mjs +14 -3
- package/src/LoadLayer.res +2 -2
- package/src/LoadLayer.res.mjs +1 -2
- package/src/sources/EvmChain.res +9 -16
- package/src/sources/EvmChain.res.mjs +7 -15
- package/src/sources/HyperSyncClient.res +8 -2
- package/src/sources/HyperSyncSource.res +17 -14
- package/src/sources/HyperSyncSource.res.mjs +21 -21
- package/src/sources/RpcSource.res +6 -4
- package/src/sources/RpcSource.res.mjs +47 -42
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envio",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
|
|
6
6
|
"bin": "./bin.mjs",
|
|
@@ -70,10 +70,10 @@
|
|
|
70
70
|
"tsx": "4.21.0"
|
|
71
71
|
},
|
|
72
72
|
"optionalDependencies": {
|
|
73
|
-
"envio-linux-x64": "3.1.
|
|
74
|
-
"envio-linux-x64-musl": "3.1.
|
|
75
|
-
"envio-linux-arm64": "3.1.
|
|
76
|
-
"envio-darwin-x64": "3.1.
|
|
77
|
-
"envio-darwin-arm64": "3.1.
|
|
73
|
+
"envio-linux-x64": "3.1.2",
|
|
74
|
+
"envio-linux-x64-musl": "3.1.2",
|
|
75
|
+
"envio-linux-arm64": "3.1.2",
|
|
76
|
+
"envio-darwin-x64": "3.1.2",
|
|
77
|
+
"envio-darwin-arm64": "3.1.2"
|
|
78
78
|
}
|
|
79
79
|
}
|
package/src/FetchState.res
CHANGED
|
@@ -555,6 +555,63 @@ let blockItemLogIndex = 16777216
|
|
|
555
555
|
|
|
556
556
|
let numAddresses = fetchState => fetchState.indexingAddresses->Utils.Dict.size
|
|
557
557
|
|
|
558
|
+
// Appends Block items produced by the onBlock handlers for every block in
|
|
559
|
+
// (fromBlock, maxBlockNumber] into mutItems and returns the new
|
|
560
|
+
// latestOnBlockBlockNumber pointer. targetBufferSize bounds how many items
|
|
561
|
+
// are generated at once to prevent OOM.
|
|
562
|
+
let appendOnBlockItems = (
|
|
563
|
+
~mutItems: array<Internal.item>,
|
|
564
|
+
~onBlockConfigs: array<Internal.onBlockConfig>,
|
|
565
|
+
~indexerStartBlock,
|
|
566
|
+
~fromBlock,
|
|
567
|
+
~maxBlockNumber,
|
|
568
|
+
~targetBufferSize,
|
|
569
|
+
) => {
|
|
570
|
+
let newItemsCounter = ref(0)
|
|
571
|
+
let latestOnBlockBlockNumber = ref(fromBlock)
|
|
572
|
+
|
|
573
|
+
// Simply iterate over every block
|
|
574
|
+
// could have a better algorithm to iterate over blocks in a more efficient way
|
|
575
|
+
// but raw loops are fast enough
|
|
576
|
+
while (
|
|
577
|
+
latestOnBlockBlockNumber.contents < maxBlockNumber &&
|
|
578
|
+
// Additional safeguard to prevent OOM
|
|
579
|
+
newItemsCounter.contents <= targetBufferSize
|
|
580
|
+
) {
|
|
581
|
+
let blockNumber = latestOnBlockBlockNumber.contents + 1
|
|
582
|
+
latestOnBlockBlockNumber := blockNumber
|
|
583
|
+
|
|
584
|
+
for configIdx in 0 to onBlockConfigs->Array.length - 1 {
|
|
585
|
+
let onBlockConfig = onBlockConfigs->Array.getUnsafe(configIdx)
|
|
586
|
+
|
|
587
|
+
let handlerStartBlock = switch onBlockConfig.startBlock {
|
|
588
|
+
| Some(startBlock) => startBlock
|
|
589
|
+
| None => indexerStartBlock
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
if (
|
|
593
|
+
blockNumber >= handlerStartBlock &&
|
|
594
|
+
switch onBlockConfig.endBlock {
|
|
595
|
+
| Some(endBlock) => blockNumber <= endBlock
|
|
596
|
+
| None => true
|
|
597
|
+
} &&
|
|
598
|
+
(blockNumber - handlerStartBlock)->Pervasives.mod(onBlockConfig.interval) === 0
|
|
599
|
+
) {
|
|
600
|
+
mutItems->Array.push(
|
|
601
|
+
Block({
|
|
602
|
+
onBlockConfig,
|
|
603
|
+
blockNumber,
|
|
604
|
+
logIndex: blockItemLogIndex + onBlockConfig.index,
|
|
605
|
+
}),
|
|
606
|
+
)
|
|
607
|
+
newItemsCounter := newItemsCounter.contents + 1
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
latestOnBlockBlockNumber.contents
|
|
613
|
+
}
|
|
614
|
+
|
|
558
615
|
/*
|
|
559
616
|
Update fetchState, merge registers and recompute derived values.
|
|
560
617
|
Runs partition optimization when partitions change.
|
|
@@ -597,49 +654,14 @@ let updateInternal = (
|
|
|
597
654
|
}
|
|
598
655
|
mutItemsRef := Some(mutItems)
|
|
599
656
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
// Additional safeguard to prevent OOM
|
|
609
|
-
newItemsCounter.contents <= fetchState.targetBufferSize
|
|
610
|
-
) {
|
|
611
|
-
let blockNumber = latestOnBlockBlockNumber.contents + 1
|
|
612
|
-
latestOnBlockBlockNumber := blockNumber
|
|
613
|
-
|
|
614
|
-
for configIdx in 0 to onBlockConfigs->Array.length - 1 {
|
|
615
|
-
let onBlockConfig = onBlockConfigs->Array.getUnsafe(configIdx)
|
|
616
|
-
|
|
617
|
-
let handlerStartBlock = switch onBlockConfig.startBlock {
|
|
618
|
-
| Some(startBlock) => startBlock
|
|
619
|
-
| None => fetchState.startBlock
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
if (
|
|
623
|
-
blockNumber >= handlerStartBlock &&
|
|
624
|
-
switch onBlockConfig.endBlock {
|
|
625
|
-
| Some(endBlock) => blockNumber <= endBlock
|
|
626
|
-
| None => true
|
|
627
|
-
} &&
|
|
628
|
-
(blockNumber - handlerStartBlock)->Pervasives.mod(onBlockConfig.interval) === 0
|
|
629
|
-
) {
|
|
630
|
-
mutItems->Array.push(
|
|
631
|
-
Block({
|
|
632
|
-
onBlockConfig,
|
|
633
|
-
blockNumber,
|
|
634
|
-
logIndex: blockItemLogIndex + onBlockConfig.index,
|
|
635
|
-
}),
|
|
636
|
-
)
|
|
637
|
-
newItemsCounter := newItemsCounter.contents + 1
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
latestOnBlockBlockNumber.contents
|
|
657
|
+
appendOnBlockItems(
|
|
658
|
+
~mutItems,
|
|
659
|
+
~onBlockConfigs,
|
|
660
|
+
~indexerStartBlock=fetchState.startBlock,
|
|
661
|
+
~fromBlock=fetchState.latestOnBlockBlockNumber,
|
|
662
|
+
~maxBlockNumber,
|
|
663
|
+
~targetBufferSize=fetchState.targetBufferSize,
|
|
664
|
+
)
|
|
643
665
|
}
|
|
644
666
|
}
|
|
645
667
|
|
|
@@ -1661,35 +1683,59 @@ let make = (
|
|
|
1661
1683
|
)
|
|
1662
1684
|
}
|
|
1663
1685
|
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1686
|
+
// On resume knownHeight is restored from the DB but the buffer starts empty.
|
|
1687
|
+
// For onBlock-only indexers (e.g. SVM onSlot) there are no partitions to drive
|
|
1688
|
+
// fetching, so without seeding the buffer here getNextQuery would return
|
|
1689
|
+
// NothingToQuery and the indexer would get stuck.
|
|
1690
|
+
let buffer = []
|
|
1691
|
+
let latestOnBlockBlockNumber = if knownHeight > 0 && onBlockConfigs->Utils.Array.notEmpty {
|
|
1692
|
+
let maxBlockNumber = switch optimizedPartitions->OptimizedPartitions.getLatestFullyFetchedBlock {
|
|
1693
|
+
| None => knownHeight
|
|
1694
|
+
| Some(latestFullyFetchedBlock) => latestFullyFetchedBlock.blockNumber
|
|
1695
|
+
}
|
|
1696
|
+
appendOnBlockItems(
|
|
1697
|
+
~mutItems=buffer,
|
|
1698
|
+
~onBlockConfigs,
|
|
1699
|
+
~indexerStartBlock=startBlock,
|
|
1700
|
+
~fromBlock=progressBlockNumber,
|
|
1701
|
+
~maxBlockNumber,
|
|
1702
|
+
~targetBufferSize,
|
|
1703
|
+
)
|
|
1704
|
+
} else {
|
|
1705
|
+
progressBlockNumber
|
|
1675
1706
|
}
|
|
1676
1707
|
|
|
1677
|
-
{
|
|
1708
|
+
let fetchState = {
|
|
1678
1709
|
optimizedPartitions,
|
|
1679
1710
|
contractConfigs,
|
|
1680
1711
|
chainId,
|
|
1681
1712
|
startBlock,
|
|
1682
1713
|
endBlock,
|
|
1683
|
-
latestOnBlockBlockNumber
|
|
1714
|
+
latestOnBlockBlockNumber,
|
|
1684
1715
|
normalSelection,
|
|
1685
1716
|
indexingAddresses,
|
|
1686
1717
|
blockLag,
|
|
1687
1718
|
onBlockConfigs,
|
|
1688
1719
|
targetBufferSize,
|
|
1689
1720
|
knownHeight,
|
|
1690
|
-
buffer
|
|
1721
|
+
buffer,
|
|
1691
1722
|
firstEventBlock,
|
|
1692
1723
|
}
|
|
1724
|
+
|
|
1725
|
+
let numAddresses = indexingAddresses->Utils.Dict.size
|
|
1726
|
+
Prometheus.IndexingAddresses.set(~addressesCount=numAddresses, ~chainId)
|
|
1727
|
+
Prometheus.IndexingPartitions.set(
|
|
1728
|
+
~partitionsCount=optimizedPartitions->OptimizedPartitions.count,
|
|
1729
|
+
~chainId,
|
|
1730
|
+
)
|
|
1731
|
+
Prometheus.IndexingBufferSize.set(~bufferSize=buffer->Array.length, ~chainId)
|
|
1732
|
+
Prometheus.IndexingBufferBlockNumber.set(~blockNumber=fetchState->bufferBlockNumber, ~chainId)
|
|
1733
|
+
switch endBlock {
|
|
1734
|
+
| Some(endBlock) => Prometheus.IndexingEndBlock.set(~endBlock, ~chainId)
|
|
1735
|
+
| None => ()
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
fetchState
|
|
1693
1739
|
}
|
|
1694
1740
|
|
|
1695
1741
|
let bufferSize = ({buffer}: t) => buffer->Array.length
|
package/src/FetchState.res.mjs
CHANGED
|
@@ -450,6 +450,35 @@ function numAddresses(fetchState) {
|
|
|
450
450
|
return Utils.Dict.size(fetchState.indexingAddresses);
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
+
function appendOnBlockItems(mutItems, onBlockConfigs, indexerStartBlock, fromBlock, maxBlockNumber, targetBufferSize) {
|
|
454
|
+
let newItemsCounter = 0;
|
|
455
|
+
let latestOnBlockBlockNumber = fromBlock;
|
|
456
|
+
while (latestOnBlockBlockNumber < maxBlockNumber && newItemsCounter <= targetBufferSize) {
|
|
457
|
+
let blockNumber = latestOnBlockBlockNumber + 1 | 0;
|
|
458
|
+
latestOnBlockBlockNumber = blockNumber;
|
|
459
|
+
for (let configIdx = 0, configIdx_finish = onBlockConfigs.length; configIdx < configIdx_finish; ++configIdx) {
|
|
460
|
+
let onBlockConfig = onBlockConfigs[configIdx];
|
|
461
|
+
let startBlock = onBlockConfig.startBlock;
|
|
462
|
+
let handlerStartBlock = startBlock !== undefined ? startBlock : indexerStartBlock;
|
|
463
|
+
let tmp = false;
|
|
464
|
+
if (blockNumber >= handlerStartBlock) {
|
|
465
|
+
let endBlock = onBlockConfig.endBlock;
|
|
466
|
+
tmp = endBlock !== undefined ? blockNumber <= endBlock : true;
|
|
467
|
+
}
|
|
468
|
+
if (tmp && Primitive_int.mod_(blockNumber - handlerStartBlock | 0, onBlockConfig.interval) === 0) {
|
|
469
|
+
mutItems.push({
|
|
470
|
+
kind: 1,
|
|
471
|
+
onBlockConfig: onBlockConfig,
|
|
472
|
+
blockNumber: blockNumber,
|
|
473
|
+
logIndex: 16777216 + onBlockConfig.index | 0
|
|
474
|
+
});
|
|
475
|
+
newItemsCounter = newItemsCounter + 1 | 0;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
return latestOnBlockBlockNumber;
|
|
480
|
+
}
|
|
481
|
+
|
|
453
482
|
function updateInternal(fetchState, optimizedPartitionsOpt, indexingAddressesOpt, mutItems, blockLagOpt, knownHeightOpt) {
|
|
454
483
|
let optimizedPartitions = optimizedPartitionsOpt !== undefined ? optimizedPartitionsOpt : fetchState.optimizedPartitions;
|
|
455
484
|
let indexingAddresses = indexingAddressesOpt !== undefined ? indexingAddressesOpt : fetchState.indexingAddresses;
|
|
@@ -472,32 +501,7 @@ function updateInternal(fetchState, optimizedPartitionsOpt, indexingAddressesOpt
|
|
|
472
501
|
let mutItems$2 = mutItemsRef;
|
|
473
502
|
let mutItems$3 = mutItems$2 !== undefined ? mutItems$2 : fetchState.buffer.slice();
|
|
474
503
|
mutItemsRef = mutItems$3;
|
|
475
|
-
|
|
476
|
-
let latestOnBlockBlockNumber$1 = fetchState.latestOnBlockBlockNumber;
|
|
477
|
-
while (latestOnBlockBlockNumber$1 < maxBlockNumber && newItemsCounter <= fetchState.targetBufferSize) {
|
|
478
|
-
let blockNumber = latestOnBlockBlockNumber$1 + 1 | 0;
|
|
479
|
-
latestOnBlockBlockNumber$1 = blockNumber;
|
|
480
|
-
for (let configIdx = 0, configIdx_finish = onBlockConfigs.length; configIdx < configIdx_finish; ++configIdx) {
|
|
481
|
-
let onBlockConfig = onBlockConfigs[configIdx];
|
|
482
|
-
let startBlock = onBlockConfig.startBlock;
|
|
483
|
-
let handlerStartBlock = startBlock !== undefined ? startBlock : fetchState.startBlock;
|
|
484
|
-
let tmp = false;
|
|
485
|
-
if (blockNumber >= handlerStartBlock) {
|
|
486
|
-
let endBlock = onBlockConfig.endBlock;
|
|
487
|
-
tmp = endBlock !== undefined ? blockNumber <= endBlock : true;
|
|
488
|
-
}
|
|
489
|
-
if (tmp && Primitive_int.mod_(blockNumber - handlerStartBlock | 0, onBlockConfig.interval) === 0) {
|
|
490
|
-
mutItems$3.push({
|
|
491
|
-
kind: 1,
|
|
492
|
-
onBlockConfig: onBlockConfig,
|
|
493
|
-
blockNumber: blockNumber,
|
|
494
|
-
logIndex: 16777216 + onBlockConfig.index | 0
|
|
495
|
-
});
|
|
496
|
-
newItemsCounter = newItemsCounter + 1 | 0;
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
};
|
|
500
|
-
latestOnBlockBlockNumber = latestOnBlockBlockNumber$1;
|
|
504
|
+
latestOnBlockBlockNumber = appendOnBlockItems(mutItems$3, onBlockConfigs, fetchState.startBlock, fetchState.latestOnBlockBlockNumber, maxBlockNumber, fetchState.targetBufferSize);
|
|
501
505
|
} else {
|
|
502
506
|
latestOnBlockBlockNumber = knownHeight;
|
|
503
507
|
}
|
|
@@ -1299,15 +1303,17 @@ function make$1(startBlock, endBlock, eventConfigs, addresses, maxAddrInPartitio
|
|
|
1299
1303
|
if (optimizedPartitions.idsInAscOrder.length === 0 && Utils.$$Array.isEmpty(onBlockConfigs)) {
|
|
1300
1304
|
Stdlib_JsError.throwWithMessage(`Invalid configuration: Nothing to fetch on chain ` + chainId.toString() + `. ` + (`addresses=` + addresses.length.toString() + `, `) + (`eventConfigs=` + eventConfigs.length.toString() + `, `) + (`normalEventConfigs=` + normalEventConfigs.length.toString() + `. `) + `Make sure that you provided at least one contract address to index, or have events with Wildcard mode enabled, or have onBlock handlers.`);
|
|
1301
1305
|
}
|
|
1302
|
-
let
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1306
|
+
let buffer = [];
|
|
1307
|
+
let latestOnBlockBlockNumber;
|
|
1308
|
+
if (knownHeight > 0 && Utils.$$Array.notEmpty(onBlockConfigs)) {
|
|
1309
|
+
let id = optimizedPartitions.idsInAscOrder[0];
|
|
1310
|
+
let latestFullyFetchedBlock = id !== undefined ? optimizedPartitions.entities[id].latestFetchedBlock : undefined;
|
|
1311
|
+
let maxBlockNumber = latestFullyFetchedBlock !== undefined ? latestFullyFetchedBlock.blockNumber : knownHeight;
|
|
1312
|
+
latestOnBlockBlockNumber = appendOnBlockItems(buffer, onBlockConfigs, startBlock, progressBlockNumber, maxBlockNumber, targetBufferSize);
|
|
1313
|
+
} else {
|
|
1314
|
+
latestOnBlockBlockNumber = progressBlockNumber;
|
|
1309
1315
|
}
|
|
1310
|
-
|
|
1316
|
+
let fetchState = {
|
|
1311
1317
|
optimizedPartitions: optimizedPartitions,
|
|
1312
1318
|
startBlock: startBlock,
|
|
1313
1319
|
endBlock: endBlock,
|
|
@@ -1315,14 +1321,23 @@ function make$1(startBlock, endBlock, eventConfigs, addresses, maxAddrInPartitio
|
|
|
1315
1321
|
indexingAddresses: indexingAddresses,
|
|
1316
1322
|
contractConfigs: contractConfigs,
|
|
1317
1323
|
chainId: chainId,
|
|
1318
|
-
latestOnBlockBlockNumber:
|
|
1324
|
+
latestOnBlockBlockNumber: latestOnBlockBlockNumber,
|
|
1319
1325
|
blockLag: blockLag,
|
|
1320
|
-
buffer:
|
|
1326
|
+
buffer: buffer,
|
|
1321
1327
|
targetBufferSize: targetBufferSize,
|
|
1322
1328
|
onBlockConfigs: onBlockConfigs,
|
|
1323
1329
|
knownHeight: knownHeight,
|
|
1324
1330
|
firstEventBlock: firstEventBlock
|
|
1325
1331
|
};
|
|
1332
|
+
let numAddresses = Utils.Dict.size(indexingAddresses);
|
|
1333
|
+
Prometheus.IndexingAddresses.set(numAddresses, chainId);
|
|
1334
|
+
Prometheus.IndexingPartitions.set(optimizedPartitions.idsInAscOrder.length, chainId);
|
|
1335
|
+
Prometheus.IndexingBufferSize.set(buffer.length, chainId);
|
|
1336
|
+
Prometheus.IndexingBufferBlockNumber.set(bufferBlockNumber(fetchState), chainId);
|
|
1337
|
+
if (endBlock !== undefined) {
|
|
1338
|
+
Prometheus.IndexingEndBlock.set(endBlock, chainId);
|
|
1339
|
+
}
|
|
1340
|
+
return fetchState;
|
|
1326
1341
|
}
|
|
1327
1342
|
|
|
1328
1343
|
function bufferSize(param) {
|
|
@@ -1607,6 +1622,7 @@ export {
|
|
|
1607
1622
|
compareBufferItem,
|
|
1608
1623
|
blockItemLogIndex,
|
|
1609
1624
|
numAddresses,
|
|
1625
|
+
appendOnBlockItems,
|
|
1610
1626
|
updateInternal,
|
|
1611
1627
|
warnDifferentContractType,
|
|
1612
1628
|
addressesByContractNameCount,
|
package/src/InMemoryStore.res
CHANGED
|
@@ -124,10 +124,19 @@ let getEffectInMemTable = (inMemoryStore: t, ~effect: Internal.effect) => {
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
let
|
|
127
|
+
let hasEffectOutput = (inMemTable: effectCacheInMemTable, key) =>
|
|
128
128
|
switch inMemTable.dict->Utils.Dict.dangerouslyGetNonOption(key) {
|
|
129
|
-
| Some(Set(
|
|
130
|
-
| Some(Delete(_)) | None =>
|
|
129
|
+
| Some(Set(_)) => true
|
|
130
|
+
| Some(Delete(_)) | None => false
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Returns the raw output. The output is itself an option for effects with an
|
|
134
|
+
// optional output, so it must never be wrapped in another option here: Some(None)
|
|
135
|
+
// is encoded as the nested-option sentinel and would leak to the handler.
|
|
136
|
+
let getEffectOutputUnsafe = (inMemTable: effectCacheInMemTable, key): Internal.effectOutput =>
|
|
137
|
+
switch inMemTable.dict->Utils.Dict.dangerouslyGetNonOption(key) {
|
|
138
|
+
| Some(Set({entity: output})) => output
|
|
139
|
+
| Some(Delete(_)) | None => %raw(`undefined`)
|
|
131
140
|
}
|
|
132
141
|
|
|
133
142
|
// Records a handler output. Persisted on the next write only when shouldCache;
|
|
@@ -90,11 +90,21 @@ function getEffectInMemTable(inMemoryStore, effect) {
|
|
|
90
90
|
return table$1;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
function
|
|
93
|
+
function hasEffectOutput(inMemTable, key) {
|
|
94
|
+
let match = inMemTable.dict[key];
|
|
95
|
+
if (match !== undefined) {
|
|
96
|
+
return match.type === "SET";
|
|
97
|
+
} else {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function getEffectOutputUnsafe(inMemTable, key) {
|
|
94
103
|
let match = inMemTable.dict[key];
|
|
95
104
|
if (match !== undefined && match.type === "SET") {
|
|
96
|
-
return
|
|
105
|
+
return match.entity;
|
|
97
106
|
}
|
|
107
|
+
return undefined;
|
|
98
108
|
}
|
|
99
109
|
|
|
100
110
|
function setEffectOutput(inMemTable, checkpointId, cacheKey, output, shouldCache) {
|
|
@@ -487,7 +497,8 @@ export {
|
|
|
487
497
|
make$1 as make,
|
|
488
498
|
keepLatestChangesLimit,
|
|
489
499
|
getEffectInMemTable,
|
|
490
|
-
|
|
500
|
+
hasEffectOutput,
|
|
501
|
+
getEffectOutputUnsafe,
|
|
491
502
|
setEffectOutput,
|
|
492
503
|
initEffectOutputFromDb,
|
|
493
504
|
dropCommittedEffects,
|
package/src/LoadLayer.res
CHANGED
|
@@ -336,8 +336,8 @@ let loadEffect = (
|
|
|
336
336
|
~load,
|
|
337
337
|
~shouldGroup,
|
|
338
338
|
~hasher=args => args.cacheKey,
|
|
339
|
-
~getUnsafeInMemory=hash => inMemTable->InMemoryStore.
|
|
340
|
-
~hasInMemory=hash => inMemTable->InMemoryStore.
|
|
339
|
+
~getUnsafeInMemory=hash => inMemTable->InMemoryStore.getEffectOutputUnsafe(hash),
|
|
340
|
+
~hasInMemory=hash => inMemTable->InMemoryStore.hasEffectOutput(hash),
|
|
341
341
|
~input=effectArgs,
|
|
342
342
|
)
|
|
343
343
|
}
|
package/src/LoadLayer.res.mjs
CHANGED
|
@@ -12,7 +12,6 @@ import * as TableIndices from "./TableIndices.res.mjs";
|
|
|
12
12
|
import * as ErrorHandling from "./ErrorHandling.res.mjs";
|
|
13
13
|
import * as InMemoryStore from "./InMemoryStore.res.mjs";
|
|
14
14
|
import * as InMemoryTable from "./InMemoryTable.res.mjs";
|
|
15
|
-
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
16
15
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
17
16
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
18
17
|
|
|
@@ -187,7 +186,7 @@ function loadEffect(loadManager, persistence, effect, effectArgs, inMemoryStore,
|
|
|
187
186
|
return await executeWithRateLimit(effect, argsToCall, inMemTable, onError, false);
|
|
188
187
|
}
|
|
189
188
|
};
|
|
190
|
-
return LoadManager.call(loadManager, effectArgs, key, load, args => args.cacheKey, shouldGroup, hash =>
|
|
189
|
+
return LoadManager.call(loadManager, effectArgs, key, load, args => args.cacheKey, shouldGroup, hash => InMemoryStore.hasEffectOutput(inMemTable, hash), hash => InMemoryStore.getEffectOutputUnsafe(inMemTable, hash));
|
|
191
190
|
}
|
|
192
191
|
|
|
193
192
|
function loadByField(loadManager, persistence, operator, entityConfig, inMemoryStore, fieldName, fieldValueSchema, shouldGroup, item, fieldValue) {
|
package/src/sources/EvmChain.res
CHANGED
|
@@ -41,25 +41,18 @@ let getSyncConfig = (
|
|
|
41
41
|
let collectEventParams = (contracts: array<Internal.evmContractConfig>): array<
|
|
42
42
|
HyperSyncClient.Decoder.eventParamsInput,
|
|
43
43
|
> => {
|
|
44
|
-
let seen = Dict.make()
|
|
45
44
|
let result = []
|
|
46
45
|
contracts->Array.forEach(contract => {
|
|
47
46
|
contract.events->Array.forEach(event => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
eventName: event.name,
|
|
58
|
-
params: event.paramsMetadata,
|
|
59
|
-
})
|
|
60
|
-
->ignore
|
|
61
|
-
}
|
|
62
|
-
}
|
|
47
|
+
result
|
|
48
|
+
->Array.push({
|
|
49
|
+
HyperSyncClient.Decoder.sighash: event.sighash,
|
|
50
|
+
topicCount: event.topicCount,
|
|
51
|
+
eventName: event.name,
|
|
52
|
+
contractName: contract.name,
|
|
53
|
+
params: event.paramsMetadata,
|
|
54
|
+
})
|
|
55
|
+
->ignore
|
|
63
56
|
})
|
|
64
57
|
})
|
|
65
58
|
result
|
|
@@ -22,24 +22,16 @@ function getSyncConfig(param) {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function collectEventParams(contracts) {
|
|
25
|
-
let seen = {};
|
|
26
25
|
let result = [];
|
|
27
26
|
contracts.forEach(contract => {
|
|
28
27
|
contract.events.forEach(event => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
sighash: event.sighash,
|
|
37
|
-
topicCount: event.topicCount,
|
|
38
|
-
eventName: event.name,
|
|
39
|
-
params: event.paramsMetadata
|
|
40
|
-
});
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
28
|
+
result.push({
|
|
29
|
+
sighash: event.sighash,
|
|
30
|
+
topicCount: event.topicCount,
|
|
31
|
+
eventName: event.name,
|
|
32
|
+
contractName: contract.name,
|
|
33
|
+
params: event.paramsMetadata
|
|
34
|
+
});
|
|
43
35
|
});
|
|
44
36
|
});
|
|
45
37
|
return result;
|
|
@@ -322,11 +322,17 @@ module Decoder = {
|
|
|
322
322
|
sighash: string,
|
|
323
323
|
topicCount: int,
|
|
324
324
|
eventName: string,
|
|
325
|
+
contractName: string,
|
|
325
326
|
params: array<Internal.paramMeta>,
|
|
326
327
|
}
|
|
327
328
|
|
|
329
|
+
// Decoded params keyed by contract name. Contracts that emit the same-signature
|
|
330
|
+
// event share one decode but get their own param names, so the caller picks the
|
|
331
|
+
// entry for the contract its router resolved the log to.
|
|
328
332
|
type tWithParams = {
|
|
329
|
-
decodeLogs: array<ResponseTypes.event> => promise<
|
|
333
|
+
decodeLogs: array<ResponseTypes.event> => promise<
|
|
334
|
+
array<Nullable.t<dict<Internal.eventParams>>>,
|
|
335
|
+
>,
|
|
330
336
|
}
|
|
331
337
|
|
|
332
338
|
@send
|
|
@@ -348,7 +354,7 @@ module EventItems = {
|
|
|
348
354
|
topicCount: int,
|
|
349
355
|
block: ResponseTypes.block,
|
|
350
356
|
transaction: ResponseTypes.transaction,
|
|
351
|
-
params: Nullable.t<Internal.eventParams
|
|
357
|
+
params: Nullable.t<dict<Internal.eventParams>>,
|
|
352
358
|
}
|
|
353
359
|
|
|
354
360
|
type response = {
|
|
@@ -351,20 +351,23 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`)
|
|
|
351
351
|
~blockNumber=item.block.number->Belt.Option.getUnsafe,
|
|
352
352
|
)
|
|
353
353
|
|
|
354
|
-
switch
|
|
355
|
-
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
->
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
~eventConfig
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
354
|
+
switch maybeEventConfig {
|
|
355
|
+
| None => () //ignore events that aren't registered
|
|
356
|
+
| Some(eventConfig) =>
|
|
357
|
+
switch item.params
|
|
358
|
+
->Nullable.toOption
|
|
359
|
+
->Option.flatMap(Dict.get(_, eventConfig.contractName)) {
|
|
360
|
+
| Some(params) =>
|
|
361
|
+
parsedQueueItems->Array.push(makeEventBatchQueueItem(item, ~params, ~eventConfig))->ignore
|
|
362
|
+
| None =>
|
|
363
|
+
handleDecodeFailure(
|
|
364
|
+
~eventConfig,
|
|
365
|
+
~logIndex=item.logIndex,
|
|
366
|
+
~blockNumber=item.block.number->Belt.Option.getUnsafe,
|
|
367
|
+
~chainId,
|
|
368
|
+
~exn=UndefinedValue,
|
|
369
|
+
)
|
|
370
|
+
}
|
|
368
371
|
}
|
|
369
372
|
})
|
|
370
373
|
|
|
@@ -14,6 +14,7 @@ import * as ErrorHandling from "../ErrorHandling.res.mjs";
|
|
|
14
14
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
15
15
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
16
16
|
import * as HyperSyncClient from "./HyperSyncClient.res.mjs";
|
|
17
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
17
18
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
18
19
|
import * as HyperSyncHeightStream from "./HyperSyncHeightStream.res.mjs";
|
|
19
20
|
|
|
@@ -215,32 +216,31 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`);
|
|
|
215
216
|
let parsedQueueItems = [];
|
|
216
217
|
Belt_Array.forEach(pageUnsafe.items, item => {
|
|
217
218
|
let maybeEventConfig = EventRouter.get(eventRouter, EventRouter.getEvmEventId(item.topic0, item.topicCount), item.srcAddress, item.block.number, indexingAddresses);
|
|
218
|
-
let match = item.params;
|
|
219
219
|
if (maybeEventConfig === undefined) {
|
|
220
220
|
return;
|
|
221
221
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
parsedQueueItems.push(makeEventBatchQueueItem(item, match, maybeEventConfig));
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
let logIndex = item.logIndex;
|
|
229
|
-
let blockNumber = item.block.number;
|
|
230
|
-
let exn = {
|
|
231
|
-
RE_EXN_ID: UndefinedValue
|
|
232
|
-
};
|
|
233
|
-
if (maybeEventConfig.isWildcard) {
|
|
222
|
+
let params = Stdlib_Option.flatMap(Primitive_option.fromNullable(item.params), __x => __x[maybeEventConfig.contractName]);
|
|
223
|
+
if (params !== undefined) {
|
|
224
|
+
parsedQueueItems.push(makeEventBatchQueueItem(item, Primitive_option.valFromOption(params), maybeEventConfig));
|
|
234
225
|
return;
|
|
226
|
+
} else {
|
|
227
|
+
let logIndex = item.logIndex;
|
|
228
|
+
let blockNumber = item.block.number;
|
|
229
|
+
let exn = {
|
|
230
|
+
RE_EXN_ID: UndefinedValue
|
|
231
|
+
};
|
|
232
|
+
if (maybeEventConfig.isWildcard) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
let msg = `Event ` + maybeEventConfig.name + ` was unexpectedly parsed as undefined`;
|
|
236
|
+
let logger$1 = Logging.createChildFrom(logger, {
|
|
237
|
+
chainId: chain,
|
|
238
|
+
blockNumber: blockNumber,
|
|
239
|
+
logIndex: logIndex,
|
|
240
|
+
decoder: "hypersync-client"
|
|
241
|
+
});
|
|
242
|
+
return ErrorHandling.mkLogAndRaise(logger$1, msg, exn);
|
|
235
243
|
}
|
|
236
|
-
let msg = `Event ` + maybeEventConfig.name + ` was unexpectedly parsed as undefined`;
|
|
237
|
-
let logger$1 = Logging.createChildFrom(logger, {
|
|
238
|
-
chainId: chain,
|
|
239
|
-
blockNumber: blockNumber,
|
|
240
|
-
logIndex: logIndex,
|
|
241
|
-
decoder: "hypersync-client"
|
|
242
|
-
});
|
|
243
|
-
ErrorHandling.mkLogAndRaise(logger$1, msg, exn);
|
|
244
244
|
});
|
|
245
245
|
let parsingTimeElapsed = Hrtime.toSecondsFloat(Hrtime.timeSince(parsingTimeRef));
|
|
246
246
|
let blockHashes = [];
|
|
@@ -1115,7 +1115,7 @@ let make = (
|
|
|
1115
1115
|
->Array.zip(parsedEvents)
|
|
1116
1116
|
->Array.filterMap(((
|
|
1117
1117
|
log: Rpc.GetLogs.log,
|
|
1118
|
-
maybeDecodedEvent: Nullable.t<Internal.eventParams
|
|
1118
|
+
maybeDecodedEvent: Nullable.t<dict<Internal.eventParams>>,
|
|
1119
1119
|
)) => {
|
|
1120
1120
|
let topic0 = log.topics[0]->Option.getOr("0x0")
|
|
1121
1121
|
let routedAddress = if lowercaseAddresses {
|
|
@@ -1132,8 +1132,10 @@ let make = (
|
|
|
1132
1132
|
) {
|
|
1133
1133
|
| None => None
|
|
1134
1134
|
| Some(eventConfig) =>
|
|
1135
|
-
switch maybeDecodedEvent
|
|
1136
|
-
|
|
1135
|
+
switch maybeDecodedEvent
|
|
1136
|
+
->Nullable.toOption
|
|
1137
|
+
->Option.flatMap(Dict.get(_, eventConfig.contractName)) {
|
|
1138
|
+
| Some(decoded) =>
|
|
1137
1139
|
Some(
|
|
1138
1140
|
(
|
|
1139
1141
|
async () => {
|
|
@@ -1176,7 +1178,7 @@ let make = (
|
|
|
1176
1178
|
}
|
|
1177
1179
|
)(),
|
|
1178
1180
|
)
|
|
1179
|
-
|
|
|
1181
|
+
| None => None
|
|
1180
1182
|
}
|
|
1181
1183
|
}
|
|
1182
1184
|
})
|
|
@@ -1064,54 +1064,59 @@ function make(param) {
|
|
|
1064
1064
|
};
|
|
1065
1065
|
}
|
|
1066
1066
|
let parsedQueueItems = await Promise.all(Stdlib_Array.filterMap(Stdlib_Array.zip(logs, parsedEvents), param => {
|
|
1067
|
-
let maybeDecodedEvent = param[1];
|
|
1068
1067
|
let log = param[0];
|
|
1069
1068
|
let topic0 = Stdlib_Option.getOr(log.topics[0], "0x0");
|
|
1070
1069
|
let routedAddress = lowercaseAddresses ? Address.Evm.fromAddressLowercaseOrThrow(log.address) : Address.Evm.fromAddressOrThrow(log.address);
|
|
1071
1070
|
let eventConfig = EventRouter.get(eventRouter, EventRouter.getEvmEventId(topic0, log.topics.length), routedAddress, log.blockNumber, indexingAddresses);
|
|
1072
|
-
if (eventConfig
|
|
1073
|
-
return
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
return {
|
|
1096
|
-
kind: 0,
|
|
1097
|
-
eventConfig: eventConfig,
|
|
1098
|
-
timestamp: block.timestamp,
|
|
1099
|
-
chain: chain,
|
|
1100
|
-
blockNumber: block.number,
|
|
1101
|
-
logIndex: log.logIndex,
|
|
1102
|
-
event: {
|
|
1103
|
-
contractName: eventConfig.contractName,
|
|
1104
|
-
eventName: eventConfig.name,
|
|
1105
|
-
params: maybeDecodedEvent,
|
|
1106
|
-
chainId: chain,
|
|
1107
|
-
srcAddress: routedAddress,
|
|
1071
|
+
if (eventConfig === undefined) {
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
let decoded = Stdlib_Option.flatMap(Primitive_option.fromNullable(param[1]), __x => __x[eventConfig.contractName]);
|
|
1075
|
+
if (decoded === undefined) {
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
1078
|
+
let decoded$1 = Primitive_option.valFromOption(decoded);
|
|
1079
|
+
return (async () => {
|
|
1080
|
+
let match;
|
|
1081
|
+
try {
|
|
1082
|
+
match = await Promise.all([
|
|
1083
|
+
getEventBlockOrThrow(log, eventConfig.selectedBlockFields),
|
|
1084
|
+
getEventTransactionOrThrow(log, eventConfig.selectedTransactionFields)
|
|
1085
|
+
]);
|
|
1086
|
+
} catch (raw_exn) {
|
|
1087
|
+
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
1088
|
+
throw {
|
|
1089
|
+
RE_EXN_ID: Source.GetItemsError,
|
|
1090
|
+
_1: {
|
|
1091
|
+
TAG: "FailedGettingFieldSelection",
|
|
1092
|
+
exn: exn,
|
|
1093
|
+
blockNumber: log.blockNumber,
|
|
1108
1094
|
logIndex: log.logIndex,
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1095
|
+
message: "Failed getting selected fields. Please double-check your RPC provider returns correct data."
|
|
1096
|
+
},
|
|
1097
|
+
Error: new Error()
|
|
1112
1098
|
};
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1099
|
+
}
|
|
1100
|
+
let block = match[0];
|
|
1101
|
+
return {
|
|
1102
|
+
kind: 0,
|
|
1103
|
+
eventConfig: eventConfig,
|
|
1104
|
+
timestamp: block.timestamp,
|
|
1105
|
+
chain: chain,
|
|
1106
|
+
blockNumber: block.number,
|
|
1107
|
+
logIndex: log.logIndex,
|
|
1108
|
+
event: {
|
|
1109
|
+
contractName: eventConfig.contractName,
|
|
1110
|
+
eventName: eventConfig.name,
|
|
1111
|
+
params: decoded$1,
|
|
1112
|
+
chainId: chain,
|
|
1113
|
+
srcAddress: routedAddress,
|
|
1114
|
+
logIndex: log.logIndex,
|
|
1115
|
+
transaction: match[1],
|
|
1116
|
+
block: block
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
1119
|
+
})();
|
|
1115
1120
|
}));
|
|
1116
1121
|
let optFirstBlockParent = await firstBlockParentPromise;
|
|
1117
1122
|
let totalTimeElapsed = Hrtime.toSecondsFloat(Hrtime.timeSince(startFetchingBatchTimeRef));
|