envio 3.6.1 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +197 -9
- package/package.json +6 -6
- package/src/Batch.res +64 -25
- package/src/Batch.res.mjs +69 -46
- package/src/ChainFetching.res +13 -17
- package/src/ChainFetching.res.mjs +9 -14
- package/src/ChainState.res +160 -119
- package/src/ChainState.res.mjs +75 -46
- package/src/ChainState.resi +15 -12
- package/src/Config.res +9 -2
- package/src/Config.res.mjs +4 -4
- package/src/Core.res +5 -0
- package/src/Ecosystem.res +0 -1
- package/src/Envio.res +16 -3
- package/src/EventConfigBuilder.res +155 -40
- package/src/EventConfigBuilder.res.mjs +76 -24
- package/src/EventProcessing.res +4 -8
- package/src/EventProcessing.res.mjs +4 -4
- package/src/EventUtils.res +3 -47
- package/src/FetchState.res +124 -104
- package/src/FetchState.res.mjs +116 -100
- package/src/HandlerRegister.res +108 -2
- package/src/HandlerRegister.res.mjs +59 -10
- package/src/HandlerRegister.resi +4 -0
- package/src/Internal.res +84 -24
- package/src/Internal.res.mjs +33 -2
- package/src/LazyLoader.res +12 -11
- package/src/LazyLoader.res.mjs +13 -7
- package/src/Main.res +22 -9
- package/src/Main.res.mjs +18 -5
- package/src/MemoryStorage.res +724 -0
- package/src/MemoryStorage.res.mjs +601 -0
- package/src/PgStorage.res +18 -7
- package/src/PgStorage.res.mjs +14 -11
- package/src/ReorgDetection.res +0 -222
- package/src/ReorgDetection.res.mjs +0 -163
- package/src/Rollback.res +14 -15
- package/src/Rollback.res.mjs +4 -5
- package/src/SimulateItems.res +2 -2
- package/src/Utils.res +3 -0
- package/src/bindings/ClickHouse.res +16 -11
- package/src/bindings/ClickHouse.res.mjs +10 -10
- package/src/bindings/Vitest.res +1 -1
- package/src/sources/BlockStore.res +115 -5
- package/src/sources/BlockStore.res.mjs +25 -0
- package/src/sources/Evm.res +0 -1
- package/src/sources/Evm.res.mjs +0 -1
- package/src/sources/EvmHyperSyncSource.res +19 -84
- package/src/sources/EvmHyperSyncSource.res.mjs +24 -60
- package/src/sources/Fuel.res +24 -4
- package/src/sources/Fuel.res.mjs +23 -3
- package/src/sources/FuelHyperSync.res +8 -3
- package/src/sources/FuelHyperSync.res.mjs +5 -4
- package/src/sources/FuelHyperSync.resi +3 -1
- package/src/sources/FuelHyperSyncClient.res +7 -10
- package/src/sources/FuelHyperSyncSource.res +18 -45
- package/src/sources/FuelHyperSyncSource.res.mjs +18 -35
- package/src/sources/HyperSync.res +49 -229
- package/src/sources/HyperSync.res.mjs +74 -191
- package/src/sources/HyperSync.resi +11 -35
- package/src/sources/HyperSyncClient.res +9 -79
- package/src/sources/HyperSyncClient.res.mjs +2 -6
- package/src/sources/RequestStat.res +5 -0
- package/src/sources/RequestStat.res.mjs +2 -0
- package/src/sources/RpcSource.res +149 -43
- package/src/sources/RpcSource.res.mjs +104 -41
- package/src/sources/SimulateSource.res +8 -5
- package/src/sources/SimulateSource.res.mjs +6 -6
- package/src/sources/Source.res +89 -16
- package/src/sources/Source.res.mjs +50 -1
- package/src/sources/SourceManager.res +255 -50
- package/src/sources/SourceManager.res.mjs +149 -55
- package/src/sources/SourceManager.resi +2 -6
- package/src/sources/Svm.res +0 -7
- package/src/sources/Svm.res.mjs +0 -8
- package/src/sources/SvmHyperSyncClient.res +21 -16
- package/src/sources/SvmHyperSyncClient.res.mjs +3 -4
- package/src/sources/SvmHyperSyncSource.res +25 -117
- package/src/sources/SvmHyperSyncSource.res.mjs +8 -121
- package/svm.schema.json +3 -2
package/src/ChainState.res.mjs
CHANGED
|
@@ -18,7 +18,6 @@ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
|
18
18
|
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
19
19
|
import * as SourceManager from "./sources/SourceManager.res.mjs";
|
|
20
20
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
21
|
-
import * as ReorgDetection from "./ReorgDetection.res.mjs";
|
|
22
21
|
import * as SimulateSource from "./sources/SimulateSource.res.mjs";
|
|
23
22
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
24
23
|
import * as Primitive_float from "@rescript/runtime/lib/es6/Primitive_float.js";
|
|
@@ -50,7 +49,7 @@ function validateOnEventRegistrations(chainId, registrations) {
|
|
|
50
49
|
});
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
function make(chainConfig, fetchState, onEventRegistrationsOpt, addressStore, sourceManager,
|
|
52
|
+
function make(chainConfig, fetchState, onEventRegistrationsOpt, addressStore, sourceManager, committedProgressBlockNumber, safeCheckpointTrackingOpt, shouldRollbackOnReorg, maxReorgDepth, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt, transactionStoreOpt, chainDensityOpt, blockStoreOpt, reorgThresholdReadyToleranceOpt, perChainEntitiesOpt, logger) {
|
|
54
53
|
let onEventRegistrations = onEventRegistrationsOpt !== undefined ? onEventRegistrationsOpt : [];
|
|
55
54
|
let safeCheckpointTracking = safeCheckpointTrackingOpt !== undefined ? Primitive_option.valFromOption(safeCheckpointTrackingOpt) : undefined;
|
|
56
55
|
let numEventsProcessed = numEventsProcessedOpt !== undefined ? numEventsProcessedOpt : 0;
|
|
@@ -77,8 +76,9 @@ function make(chainConfig, fetchState, onEventRegistrationsOpt, addressStore, so
|
|
|
77
76
|
pendingBudget: 0,
|
|
78
77
|
chainDensity: chainDensity,
|
|
79
78
|
entities: EntityTables.make(perChainEntities),
|
|
80
|
-
reorgDetection: reorgDetection,
|
|
81
79
|
safeCheckpointTracking: safeCheckpointTracking,
|
|
80
|
+
shouldRollbackOnReorg: shouldRollbackOnReorg,
|
|
81
|
+
maxReorgDepth: maxReorgDepth,
|
|
82
82
|
transactionStore: transactionStore,
|
|
83
83
|
blockStore: blockStore,
|
|
84
84
|
reorgThresholdReadyTolerance: reorgThresholdReadyTolerance,
|
|
@@ -132,7 +132,7 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
|
|
|
132
132
|
tmp = undefined;
|
|
133
133
|
break;
|
|
134
134
|
}
|
|
135
|
-
let fetchState = FetchState.make(startBlock, endBlock, onEventRegistrations, addressStore, indexingAddresses, config.maxAddrInPartition, chainConfig.id, (config.batchSize << 1), knownHeight, progressBlockNumber, match.onBlockRegistrations, Primitive_int.max(!config.shouldRollbackOnReorg || isInReorgThreshold ? 0 :
|
|
135
|
+
let fetchState = FetchState.make(startBlock, endBlock, onEventRegistrations, addressStore, indexingAddresses, config.maxAddrInPartition, chainConfig.id, (config.batchSize << 1), knownHeight, progressBlockNumber, match.onBlockRegistrations, Primitive_int.max(!config.shouldRollbackOnReorg || isInReorgThreshold ? 0 : maxReorgDepth, chainConfig.blockLag), Primitive_option.some(firstEventBlock), Primitive_option.some(tmp), isResumed);
|
|
136
136
|
let chainReorgCheckpoints = Stdlib_Array.filterMap(reorgCheckpoints, reorgCheckpoint => {
|
|
137
137
|
if (reorgCheckpoint.chain_id === chainConfig.id) {
|
|
138
138
|
return reorgCheckpoint;
|
|
@@ -181,15 +181,23 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
|
|
|
181
181
|
);
|
|
182
182
|
break;
|
|
183
183
|
case "SimulateSourceConfig" :
|
|
184
|
-
sources$1 = [SimulateSource.make(sources.items, sources.endBlock, chainId, addressStore)];
|
|
184
|
+
sources$1 = [SimulateSource.make(sources.items, sources.endBlock, chainId, addressStore, config.ecosystem.name)];
|
|
185
185
|
break;
|
|
186
186
|
case "CustomSources" :
|
|
187
187
|
sources$1 = sources._0;
|
|
188
188
|
break;
|
|
189
189
|
}
|
|
190
|
+
let blockStore = BlockStore.make(config.ecosystem.name, !lowercaseAddresses);
|
|
191
|
+
if (Utils.$$Array.notEmpty(chainReorgCheckpoints)) {
|
|
192
|
+
let seedPage = BlockStore.fromJs(chainReorgCheckpoints.map(cp => ({
|
|
193
|
+
blockNumber: cp.block_number,
|
|
194
|
+
blockHash: cp.block_hash
|
|
195
|
+
})), config.ecosystem.name, !lowercaseAddresses);
|
|
196
|
+
blockStore.merge(seedPage, 0, false);
|
|
197
|
+
}
|
|
190
198
|
let firstEventBlock$1 = fetchState.firstEventBlock;
|
|
191
199
|
let chainDensity = firstEventBlock$1 !== undefined && progressBlockNumber > firstEventBlock$1 && numEventsProcessed > 0 ? numEventsProcessed / (progressBlockNumber - firstEventBlock$1 | 0) : undefined;
|
|
192
|
-
return make(chainConfig, fetchState, onEventRegistrations, addressStore, SourceManager.make(sources$1, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined),
|
|
200
|
+
return make(chainConfig, fetchState, onEventRegistrations, addressStore, SourceManager.make(sources$1, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined), progressBlockNumber, Primitive_option.some(SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)), config.shouldRollbackOnReorg, maxReorgDepth, numEventsProcessed, Primitive_option.some(timestampCaughtUpToHeadOrEndblock), undefined, Primitive_option.some(TransactionStore.make(config.ecosystem.name, !lowercaseAddresses)), Primitive_option.some(chainDensity), Primitive_option.some(blockStore), config.reorgThresholdReadyTolerance, EntityTables.perChain(config.allEntities), logger);
|
|
193
201
|
}
|
|
194
202
|
|
|
195
203
|
function makeFromConfig(chainConfig, config, registrationsByChainId, knownHeight) {
|
|
@@ -212,6 +220,10 @@ function logger(cs) {
|
|
|
212
220
|
return cs.logger;
|
|
213
221
|
}
|
|
214
222
|
|
|
223
|
+
function blockStore(cs) {
|
|
224
|
+
return cs.blockStore;
|
|
225
|
+
}
|
|
226
|
+
|
|
215
227
|
function entities(cs) {
|
|
216
228
|
return cs.entities;
|
|
217
229
|
}
|
|
@@ -228,8 +240,16 @@ function chainConfig(cs) {
|
|
|
228
240
|
return cs.chainConfig;
|
|
229
241
|
}
|
|
230
242
|
|
|
231
|
-
function
|
|
232
|
-
return cs.
|
|
243
|
+
function shouldRollbackOnReorg(cs) {
|
|
244
|
+
return cs.shouldRollbackOnReorg;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function getReorgThresholdBlockNumbersBelow(cs, blockNumber) {
|
|
248
|
+
return cs.blockStore.getHashedBlockNumbers(Primitive_int.max(cs.fetchState.knownHeight - cs.maxReorgDepth | 0, 0), blockNumber);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function getLatestValidScannedBlock(cs, blockStore, blockNumbers) {
|
|
252
|
+
return Primitive_option.fromNull(cs.blockStore.latestValidBlockFromStore(blockStore, blockNumbers));
|
|
233
253
|
}
|
|
234
254
|
|
|
235
255
|
function safeCheckpointTracking(cs) {
|
|
@@ -447,7 +467,7 @@ function isDurablyCaughtUp(cs) {
|
|
|
447
467
|
}
|
|
448
468
|
|
|
449
469
|
function getHighestBlockBelowThreshold(cs) {
|
|
450
|
-
let highestBlockBelowThreshold = cs.fetchState.knownHeight - cs.
|
|
470
|
+
let highestBlockBelowThreshold = cs.fetchState.knownHeight - cs.maxReorgDepth | 0;
|
|
451
471
|
if (highestBlockBelowThreshold < 0) {
|
|
452
472
|
return 0;
|
|
453
473
|
} else {
|
|
@@ -471,7 +491,7 @@ function isAtHeadWithoutEndBlock(cs) {
|
|
|
471
491
|
}
|
|
472
492
|
}
|
|
473
493
|
|
|
474
|
-
function groupBatchItems(items
|
|
494
|
+
function groupBatchItems(items) {
|
|
475
495
|
let txBlockNumbers = [];
|
|
476
496
|
let transactionIndices = [];
|
|
477
497
|
let transactionMasks = [];
|
|
@@ -490,7 +510,7 @@ function groupBatchItems(items, includeBlocks) {
|
|
|
490
510
|
let match = item.payload.transaction;
|
|
491
511
|
if (match == null) {
|
|
492
512
|
let transactionIndex = item.transactionIndex;
|
|
493
|
-
let mask = item.onEventRegistration.
|
|
513
|
+
let mask = item.onEventRegistration.fieldSelection.transactionMask;
|
|
494
514
|
if (mask !== 0) {
|
|
495
515
|
anyTransactionFieldSelected.contents = true;
|
|
496
516
|
}
|
|
@@ -505,14 +525,11 @@ function groupBatchItems(items, includeBlocks) {
|
|
|
505
525
|
payloadGroups.push([item.payload]);
|
|
506
526
|
}
|
|
507
527
|
}
|
|
508
|
-
if (!includeBlocks) {
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
511
528
|
let match$1 = item.payload.block;
|
|
512
529
|
if (!(match$1 == null)) {
|
|
513
530
|
return;
|
|
514
531
|
}
|
|
515
|
-
let mask$1 = item.onEventRegistration.
|
|
532
|
+
let mask$1 = item.onEventRegistration.fieldSelection.blockMask;
|
|
516
533
|
let last$1 = blockItemGroups.length - 1 | 0;
|
|
517
534
|
if (last$1 >= 0 && blockBlockNumbers[last$1] === blockNumber) {
|
|
518
535
|
blockItemGroups[last$1].push(item);
|
|
@@ -573,48 +590,50 @@ async function applyBlockGroups(store, g) {
|
|
|
573
590
|
});
|
|
574
591
|
}
|
|
575
592
|
|
|
576
|
-
function
|
|
577
|
-
|
|
578
|
-
case "fuel" :
|
|
579
|
-
return false;
|
|
580
|
-
case "evm" :
|
|
581
|
-
case "svm" :
|
|
582
|
-
return true;
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
async function materializeBatchItems(cs, items, ecosystem) {
|
|
587
|
-
let match = groupBatchItems(items, includeBlocksForEcosystem(ecosystem));
|
|
593
|
+
async function materializeBatchItems(cs, items) {
|
|
594
|
+
let match = groupBatchItems(items);
|
|
588
595
|
await Promise.all([
|
|
589
596
|
applyTransactionGroups(cs.transactionStore, match[0]),
|
|
590
597
|
applyBlockGroups(cs.blockStore, match[1])
|
|
591
598
|
]);
|
|
592
599
|
}
|
|
593
600
|
|
|
594
|
-
async function materializePageItems(items, transactionStore, blockStore
|
|
595
|
-
let match = groupBatchItems(items
|
|
601
|
+
async function materializePageItems(items, transactionStore, blockStore) {
|
|
602
|
+
let match = groupBatchItems(items);
|
|
596
603
|
await Promise.all([
|
|
597
604
|
transactionStore !== undefined ? applyTransactionGroups(Primitive_option.valFromOption(transactionStore), match[0]) : Promise.resolve(),
|
|
598
|
-
|
|
605
|
+
applyBlockGroups(blockStore, match[1])
|
|
599
606
|
]);
|
|
600
607
|
}
|
|
601
608
|
|
|
602
|
-
function handleQueryResult(cs, query, newItems, newRegistrations, latestFetchedBlock, knownHeight, txPage
|
|
609
|
+
function handleQueryResult(cs, query, newItems, newRegistrations, latestFetchedBlock, knownHeight, txPage) {
|
|
603
610
|
if (txPage !== undefined) {
|
|
604
611
|
cs.transactionStore.merge(Primitive_option.valFromOption(txPage));
|
|
605
612
|
}
|
|
606
|
-
|
|
607
|
-
cs.blockStore.merge(Primitive_option.valFromOption(blockPage));
|
|
608
|
-
}
|
|
609
|
-
let fs = newRegistrations.length !== 0 ? FetchState.registerDynamicContracts(cs.fetchState, cs.addressStore, Primitive_int.max(knownHeight, latestFetchedBlock.blockNumber), newRegistrations) : cs.fetchState;
|
|
613
|
+
let fs = newRegistrations.length !== 0 ? FetchState.registerDynamicContracts(cs.fetchState, cs.addressStore, Primitive_int.max(knownHeight, latestFetchedBlock), newRegistrations) : cs.fetchState;
|
|
610
614
|
cs.fetchState = FetchState.updateKnownHeight(FetchState.handleQueryResult(fs, query, latestFetchedBlock, newItems), knownHeight);
|
|
611
615
|
cs.pendingBudget = Primitive_float.max(0, cs.pendingBudget - query.itemsEst);
|
|
612
616
|
}
|
|
613
617
|
|
|
614
|
-
function registerReorgGuard(cs,
|
|
615
|
-
let match =
|
|
616
|
-
|
|
617
|
-
|
|
618
|
+
function registerReorgGuard(cs, blockStore, knownHeight) {
|
|
619
|
+
let match = cs.blockStore.merge(blockStore, Primitive_int.max(knownHeight - cs.maxReorgDepth | 0, 0), !cs.shouldRollbackOnReorg);
|
|
620
|
+
if (match === null) {
|
|
621
|
+
return "NoReorg";
|
|
622
|
+
}
|
|
623
|
+
let blockNumber = match.blockNumber;
|
|
624
|
+
return {
|
|
625
|
+
TAG: "ReorgDetected",
|
|
626
|
+
_0: {
|
|
627
|
+
scannedBlock: {
|
|
628
|
+
blockHash: match.storedHash,
|
|
629
|
+
blockNumber: blockNumber
|
|
630
|
+
},
|
|
631
|
+
receivedBlock: {
|
|
632
|
+
blockHash: match.receivedHash,
|
|
633
|
+
blockNumber: blockNumber
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
};
|
|
618
637
|
}
|
|
619
638
|
|
|
620
639
|
function prepareReorg(cs, eventsProcessedDiff) {
|
|
@@ -720,9 +739,20 @@ function toMetrics(cs) {
|
|
|
720
739
|
}
|
|
721
740
|
|
|
722
741
|
function toChainBeforeBatch(cs) {
|
|
742
|
+
let match = cs.blockStore.getHashes(Primitive_int.max(cs.fetchState.knownHeight - cs.maxReorgDepth | 0, 0), cs.fetchState.knownHeight + 1 | 0);
|
|
743
|
+
let hashes = match.hashes;
|
|
744
|
+
let blockNumbers = match.blockNumbers;
|
|
745
|
+
let hashByBlockNumber = {};
|
|
746
|
+
blockNumbers.forEach((blockNumber, idx) => {
|
|
747
|
+
hashByBlockNumber[blockNumber] = hashes[idx];
|
|
748
|
+
});
|
|
723
749
|
return {
|
|
724
750
|
fetchState: cs.fetchState,
|
|
725
|
-
|
|
751
|
+
scannedHashes: {
|
|
752
|
+
blockNumbers: blockNumbers,
|
|
753
|
+
hashByBlockNumber: hashByBlockNumber
|
|
754
|
+
},
|
|
755
|
+
shouldRollbackOnReorg: cs.shouldRollbackOnReorg,
|
|
726
756
|
progressBlockNumber: cs.committedProgressBlockNumber,
|
|
727
757
|
sourceBlockNumber: cs.fetchState.knownHeight,
|
|
728
758
|
totalEventsProcessed: cs.numEventsProcessed,
|
|
@@ -804,7 +834,7 @@ function applyBatchProgress(cs, batch, blockTimestampName) {
|
|
|
804
834
|
cs.processingBlockNumber = Primitive_int.max(cs.processingBlockNumber, chainAfterBatch.progressBlockNumber);
|
|
805
835
|
cs.numEventsProcessed = chainAfterBatch.totalEventsProcessed;
|
|
806
836
|
cs.transactionStore.prune(chainAfterBatch.progressBlockNumber);
|
|
807
|
-
cs.blockStore.prune(chainAfterBatch.progressBlockNumber);
|
|
837
|
+
cs.blockStore.prune(chainAfterBatch.progressBlockNumber, cs.fetchState.knownHeight - cs.maxReorgDepth | 0);
|
|
808
838
|
cs.isProgressAtHead = cs.isProgressAtHead || chainAfterBatch.isProgressAtHeadWhenBatchCreated;
|
|
809
839
|
let safeCheckpointTracking = cs.safeCheckpointTracking;
|
|
810
840
|
if (safeCheckpointTracking !== undefined) {
|
|
@@ -823,7 +853,6 @@ function markReady(cs, readyAt) {
|
|
|
823
853
|
function rollback(cs, newProgressBlockNumber, eventsProcessedDiff, rollbackTargetBlockNumber, isReorgChain) {
|
|
824
854
|
if (newProgressBlockNumber === undefined) {
|
|
825
855
|
if (isReorgChain) {
|
|
826
|
-
cs.reorgDetection = ReorgDetection.rollbackToValidBlockNumber(cs.reorgDetection, rollbackTargetBlockNumber);
|
|
827
856
|
cs.fetchState = FetchState.rollback(cs.fetchState, cs.addressStore, rollbackTargetBlockNumber);
|
|
828
857
|
cs.transactionStore.rollback(rollbackTargetBlockNumber);
|
|
829
858
|
cs.blockStore.rollback(rollbackTargetBlockNumber);
|
|
@@ -835,9 +864,6 @@ function rollback(cs, newProgressBlockNumber, eventsProcessedDiff, rollbackTarge
|
|
|
835
864
|
}
|
|
836
865
|
}
|
|
837
866
|
let newTotalEventsProcessed = cs.numEventsProcessed - Stdlib_Option.getOrThrow(eventsProcessedDiff, "Missing events-processed diff for rolled-back chain");
|
|
838
|
-
if (isReorgChain) {
|
|
839
|
-
cs.reorgDetection = ReorgDetection.rollbackToValidBlockNumber(cs.reorgDetection, rollbackTargetBlockNumber);
|
|
840
|
-
}
|
|
841
867
|
let safeCheckpointTracking = cs.safeCheckpointTracking;
|
|
842
868
|
if (safeCheckpointTracking !== undefined) {
|
|
843
869
|
cs.safeCheckpointTracking = SafeCheckpointTracking.rollback(safeCheckpointTracking, newProgressBlockNumber);
|
|
@@ -856,11 +882,14 @@ export {
|
|
|
856
882
|
makeFromConfig,
|
|
857
883
|
makeFromDbState,
|
|
858
884
|
logger,
|
|
885
|
+
blockStore,
|
|
859
886
|
entities,
|
|
860
887
|
resetEntities,
|
|
861
888
|
sourceManager,
|
|
862
889
|
chainConfig,
|
|
863
|
-
|
|
890
|
+
shouldRollbackOnReorg,
|
|
891
|
+
getReorgThresholdBlockNumbersBelow,
|
|
892
|
+
getLatestValidScannedBlock,
|
|
864
893
|
safeCheckpointTracking,
|
|
865
894
|
isProgressAtHead,
|
|
866
895
|
committedProgressBlockNumber,
|
package/src/ChainState.resi
CHANGED
|
@@ -11,9 +11,10 @@ let make: (
|
|
|
11
11
|
~onEventRegistrations: array<Internal.onEventRegistration>=?,
|
|
12
12
|
~addressStore: AddressStore.t,
|
|
13
13
|
~sourceManager: SourceManager.t,
|
|
14
|
-
~reorgDetection: ReorgDetection.t,
|
|
15
14
|
~committedProgressBlockNumber: int,
|
|
16
15
|
~safeCheckpointTracking: option<SafeCheckpointTracking.t>=?,
|
|
16
|
+
~shouldRollbackOnReorg: bool,
|
|
17
|
+
~maxReorgDepth: int,
|
|
17
18
|
~numEventsProcessed: float=?,
|
|
18
19
|
~timestampCaughtUpToHeadOrEndblock: option<Date.t>=?,
|
|
19
20
|
~isProgressAtHead: bool=?,
|
|
@@ -45,11 +46,19 @@ let makeFromDbState: (
|
|
|
45
46
|
|
|
46
47
|
// Accessors.
|
|
47
48
|
let logger: t => Pino.t
|
|
49
|
+
let blockStore: t => BlockStore.t
|
|
48
50
|
let entities: t => EntityTables.t
|
|
49
51
|
let resetEntities: (t, ~perChainEntities: array<Internal.entityConfig>) => unit
|
|
50
52
|
let sourceManager: t => SourceManager.t
|
|
51
53
|
let chainConfig: t => Config.chain
|
|
52
|
-
let
|
|
54
|
+
let shouldRollbackOnReorg: t => bool
|
|
55
|
+
// Reorg-scan reads over the chain's block store, for the rollback flow.
|
|
56
|
+
let getReorgThresholdBlockNumbersBelow: (t, ~blockNumber: int) => array<int>
|
|
57
|
+
let getLatestValidScannedBlock: (
|
|
58
|
+
t,
|
|
59
|
+
~blockStore: BlockStore.t,
|
|
60
|
+
~blockNumbers: array<int>,
|
|
61
|
+
) => option<int>
|
|
53
62
|
let safeCheckpointTracking: t => option<SafeCheckpointTracking.t>
|
|
54
63
|
let isProgressAtHead: t => bool
|
|
55
64
|
let committedProgressBlockNumber: t => int
|
|
@@ -120,25 +129,19 @@ let handleQueryResult: (
|
|
|
120
129
|
~query: FetchState.query,
|
|
121
130
|
~newItems: array<Internal.item>,
|
|
122
131
|
~newRegistrations: array<AddressStore.registration>,
|
|
123
|
-
~latestFetchedBlock:
|
|
132
|
+
~latestFetchedBlock: int,
|
|
124
133
|
~knownHeight: int,
|
|
125
134
|
~transactionStore: option<TransactionStore.t>,
|
|
126
|
-
~blockStore: option<BlockStore.t>,
|
|
127
135
|
) => unit
|
|
128
|
-
let materializeBatchItems: (
|
|
129
|
-
t,
|
|
130
|
-
~items: array<Internal.item>,
|
|
131
|
-
~ecosystem: Ecosystem.name,
|
|
132
|
-
) => promise<unit>
|
|
136
|
+
let materializeBatchItems: (t, ~items: array<Internal.item>) => promise<unit>
|
|
133
137
|
let materializePageItems: (
|
|
134
138
|
~items: array<Internal.item>,
|
|
135
139
|
~transactionStore: option<TransactionStore.t>,
|
|
136
|
-
~blockStore:
|
|
137
|
-
~ecosystem: Ecosystem.name,
|
|
140
|
+
~blockStore: BlockStore.t,
|
|
138
141
|
) => promise<unit>
|
|
139
142
|
let registerReorgGuard: (
|
|
140
143
|
t,
|
|
141
|
-
~
|
|
144
|
+
~blockStore: BlockStore.t,
|
|
142
145
|
~knownHeight: int,
|
|
143
146
|
) => ReorgDetection.reorgResult
|
|
144
147
|
let prepareReorg: (t, ~eventsProcessedDiff: option<float>) => unit
|
package/src/Config.res
CHANGED
|
@@ -1016,8 +1016,15 @@ let fromPublic = (publicConfigJson: JSON.t) => {
|
|
|
1016
1016
|
endBlock: ?publicChainConfig["endBlock"],
|
|
1017
1017
|
maxReorgDepth: switch ecosystemName {
|
|
1018
1018
|
| Ecosystem.Evm => publicChainConfig["maxReorgDepth"]->Option.getOr(200)
|
|
1019
|
-
|
|
1020
|
-
|
|
1019
|
+
// Tower BFT roots a block once 32 votes lock it in (MAX_LOCKOUT_HISTORY
|
|
1020
|
+
// is 31, plus the slot itself), which is what `finalized` waits for — so
|
|
1021
|
+
// 32 is the protocol's own bound on how far a fork can be replaced. That
|
|
1022
|
+
// bound counts *blocks* while the threshold here is measured in slot
|
|
1023
|
+
// numbers, and skipped slots make the slot distance the larger of the
|
|
1024
|
+
// two, so the default keeps a wide margin over it. Slots are ~0.4s, so
|
|
1025
|
+
// even this spans well under two minutes of chain.
|
|
1026
|
+
| Ecosystem.Svm => publicChainConfig["maxReorgDepth"]->Option.getOr(200)
|
|
1027
|
+
| Ecosystem.Fuel => 0
|
|
1021
1028
|
},
|
|
1022
1029
|
blockLag: publicChainConfig["blockLag"]->Option.getOr(0),
|
|
1023
1030
|
contracts,
|
package/src/Config.res.mjs
CHANGED
|
@@ -685,13 +685,13 @@ function fromPublic(publicConfigJson) {
|
|
|
685
685
|
}
|
|
686
686
|
let tmp;
|
|
687
687
|
switch (ecosystemName) {
|
|
688
|
-
case "evm" :
|
|
689
|
-
tmp = Stdlib_Option.getOr(publicChainConfig.maxReorgDepth, 200);
|
|
690
|
-
break;
|
|
691
688
|
case "fuel" :
|
|
692
|
-
case "svm" :
|
|
693
689
|
tmp = 0;
|
|
694
690
|
break;
|
|
691
|
+
case "evm" :
|
|
692
|
+
case "svm" :
|
|
693
|
+
tmp = Stdlib_Option.getOr(publicChainConfig.maxReorgDepth, 200);
|
|
694
|
+
break;
|
|
695
695
|
}
|
|
696
696
|
return {
|
|
697
697
|
name: chainName,
|
package/src/Core.res
CHANGED
|
@@ -11,6 +11,8 @@ type fuelHyperSyncClientCtor
|
|
|
11
11
|
type transactionStoreCtor
|
|
12
12
|
type blockStoreCtor
|
|
13
13
|
type addressStoreCtor
|
|
14
|
+
// Test-only: a local HyperSync server, bound by MockHyperSyncServer in envio-tests.
|
|
15
|
+
type mockHyperSyncServerCtor
|
|
14
16
|
type fromUserApiOptions = {
|
|
15
17
|
schema?: string,
|
|
16
18
|
env?: dict<string>,
|
|
@@ -43,6 +45,8 @@ type addon = {
|
|
|
43
45
|
blockStore: blockStoreCtor,
|
|
44
46
|
@as("AddressStore")
|
|
45
47
|
addressStore: addressStoreCtor,
|
|
48
|
+
@as("MockHyperSyncServer")
|
|
49
|
+
mockHyperSyncServer: mockHyperSyncServerCtor,
|
|
46
50
|
// Ordered transaction-field names exposed for the field-code contract test
|
|
47
51
|
// (the ReScript `transactionFields` arrays must match the Rust ordinals).
|
|
48
52
|
evmTransactionFieldNames: unit => array<string>,
|
|
@@ -51,6 +55,7 @@ type addon = {
|
|
|
51
55
|
// must match the Rust ordinals).
|
|
52
56
|
evmBlockFieldNames: unit => array<string>,
|
|
53
57
|
svmBlockFieldNames: unit => array<string>,
|
|
58
|
+
fuelBlockFieldNames: unit => array<string>,
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
@module("node:module") external createRequire: string => {..} = "createRequire"
|
package/src/Ecosystem.res
CHANGED
|
@@ -5,7 +5,6 @@ type t = {
|
|
|
5
5
|
blockNumberName: string,
|
|
6
6
|
blockTimestampName: string,
|
|
7
7
|
blockHashName: string,
|
|
8
|
-
cleanUpRawEventFieldsInPlace: JSON.t => unit,
|
|
9
8
|
/** Method name that the block handler is exposed under on the public
|
|
10
9
|
`indexer` object — `"onBlock"` for chain-based ecosystems, `"onSlot"`
|
|
11
10
|
for SVM. Centralised here so adding a new ecosystem only requires a
|
package/src/Envio.res
CHANGED
|
@@ -42,14 +42,24 @@ type svmInstructionParams = {
|
|
|
42
42
|
type svmTokenBalance = {
|
|
43
43
|
account?: SvmTypes.Pubkey.t,
|
|
44
44
|
mint?: SvmTypes.Pubkey.t,
|
|
45
|
+
/** Owner at the end of the transaction, falling back to the owner on entry
|
|
46
|
+
when the account was closed during it. Pre and post owners differ only when
|
|
47
|
+
a `SetAuthority(AccountOwner)` runs mid-transaction. */
|
|
45
48
|
owner?: SvmTypes.Pubkey.t,
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
/** Mint decimals, for scaling the raw amounts below. */
|
|
50
|
+
decimals?: int,
|
|
51
|
+
/** Raw amount in base units before the transaction. Absent when the token
|
|
52
|
+
account was created during it. */
|
|
53
|
+
preAmount?: bigint,
|
|
54
|
+
/** Raw amount in base units after the transaction. Absent when the token
|
|
55
|
+
account was closed during it. */
|
|
56
|
+
postAmount?: bigint,
|
|
48
57
|
}
|
|
49
58
|
|
|
50
59
|
type svmTransaction = {
|
|
51
60
|
transactionIndex?: int,
|
|
52
|
-
|
|
61
|
+
/** The transaction's identifying signature (`allSignatures[0]`). */
|
|
62
|
+
signature: string,
|
|
53
63
|
feePayer?: SvmTypes.Pubkey.t,
|
|
54
64
|
success?: bool,
|
|
55
65
|
err?: string,
|
|
@@ -58,6 +68,9 @@ type svmTransaction = {
|
|
|
58
68
|
accountKeys: array<SvmTypes.Pubkey.t>,
|
|
59
69
|
recentBlockhash?: string,
|
|
60
70
|
version?: string,
|
|
71
|
+
/** Every signature on the transaction, in message order; the first is
|
|
72
|
+
`signature`. Longer than one element only for a multi-signer transaction. */
|
|
73
|
+
allSignatures: array<string>,
|
|
61
74
|
tokenBalances?: array<svmTokenBalance>,
|
|
62
75
|
}
|
|
63
76
|
|