envio 3.6.1 → 3.7.0-subgraph
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 +18 -2
- package/src/Config.res.mjs +9 -6
- package/src/Core.res +20 -0
- package/src/Core.res.mjs +11 -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 +10 -14
- package/src/EventProcessing.res.mjs +12 -10
- package/src/EventUtils.res +3 -47
- package/src/FetchState.res +124 -104
- package/src/FetchState.res.mjs +116 -100
- package/src/HandlerLoader.res +20 -8
- package/src/HandlerLoader.res.mjs +11 -2
- package/src/HandlerRegister.res +108 -2
- package/src/HandlerRegister.res.mjs +59 -10
- package/src/HandlerRegister.resi +4 -0
- package/src/InMemoryStore.res +1 -6
- package/src/InMemoryStore.res.mjs +1 -3
- 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 +756 -0
- package/src/MemoryStorage.res.mjs +623 -0
- package/src/Persistence.res +4 -2
- package/src/PgStorage.res +24 -8
- package/src/PgStorage.res.mjs +15 -12
- 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/UserContext.res +358 -51
- package/src/UserContext.res.mjs +271 -35
- 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/src/subgraph/blocks.ts +176 -0
- package/src/subgraph/calls.ts +217 -0
- package/src/subgraph/conformance.ts +99 -0
- package/src/subgraph/division.ts +110 -0
- package/src/subgraph/errors.ts +90 -0
- package/src/subgraph/graph-ts-types/VERSION +2 -0
- package/src/subgraph/graph-ts-types/chain/arweave.d.ts +70 -0
- package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +327 -0
- package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +233 -0
- package/src/subgraph/graph-ts-types/chain/near.d.ts +253 -0
- package/src/subgraph/graph-ts-types/chain/starknet.d.ts +32 -0
- package/src/subgraph/graph-ts-types/common/collections.d.ts +136 -0
- package/src/subgraph/graph-ts-types/common/conversion.d.ts +11 -0
- package/src/subgraph/graph-ts-types/common/datasource.d.ts +30 -0
- package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
- package/src/subgraph/graph-ts-types/common/json.d.ts +17 -0
- package/src/subgraph/graph-ts-types/common/numbers.d.ts +120 -0
- package/src/subgraph/graph-ts-types/common/value.d.ts +120 -0
- package/src/subgraph/graph-ts-types/common/yaml.d.ts +90 -0
- package/src/subgraph/graph-ts-types/global/global.d.ts +194 -0
- package/src/subgraph/graph-ts-types/helper-functions.d.ts +22 -0
- package/src/subgraph/graph-ts-types/index.d.ts +102 -0
- package/src/subgraph/graph-ts.ts +1871 -0
- package/src/subgraph/hosts.ts +148 -0
- package/src/subgraph/runtime.ts +845 -0
- package/src/subgraph/scope.ts +63 -0
- 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
|
@@ -119,6 +119,9 @@ type t = {
|
|
|
119
119
|
userEntities: array<Internal.entityConfig>,
|
|
120
120
|
allEntities: array<Internal.entityConfig>,
|
|
121
121
|
allEnums: array<Table.enumConfig<Table.enum>>,
|
|
122
|
+
// Set only in subgraph mode: the translated manifest, which is what makes
|
|
123
|
+
// the subgraph runtime take over handler registration.
|
|
124
|
+
subgraph: option<JSON.t>,
|
|
122
125
|
}
|
|
123
126
|
|
|
124
127
|
module EnvioAddresses = {
|
|
@@ -613,6 +616,7 @@ let publicConfigSchema = S.schema(s =>
|
|
|
613
616
|
"svm": s.matches(S.option(publicConfigEcosystemSchema)),
|
|
614
617
|
"enums": s.matches(S.option(S.dict(S.array(S.string)))),
|
|
615
618
|
"entities": s.matches(S.option(S.array(entityJsonSchema))),
|
|
619
|
+
"subgraph": s.matches(S.option(S.json(~validate=false))),
|
|
616
620
|
}
|
|
617
621
|
)
|
|
618
622
|
|
|
@@ -1016,8 +1020,15 @@ let fromPublic = (publicConfigJson: JSON.t) => {
|
|
|
1016
1020
|
endBlock: ?publicChainConfig["endBlock"],
|
|
1017
1021
|
maxReorgDepth: switch ecosystemName {
|
|
1018
1022
|
| Ecosystem.Evm => publicChainConfig["maxReorgDepth"]->Option.getOr(200)
|
|
1019
|
-
|
|
1020
|
-
|
|
1023
|
+
// Tower BFT roots a block once 32 votes lock it in (MAX_LOCKOUT_HISTORY
|
|
1024
|
+
// is 31, plus the slot itself), which is what `finalized` waits for — so
|
|
1025
|
+
// 32 is the protocol's own bound on how far a fork can be replaced. That
|
|
1026
|
+
// bound counts *blocks* while the threshold here is measured in slot
|
|
1027
|
+
// numbers, and skipped slots make the slot distance the larger of the
|
|
1028
|
+
// two, so the default keeps a wide margin over it. Slots are ~0.4s, so
|
|
1029
|
+
// even this spans well under two minutes of chain.
|
|
1030
|
+
| Ecosystem.Svm => publicChainConfig["maxReorgDepth"]->Option.getOr(200)
|
|
1031
|
+
| Ecosystem.Fuel => 0
|
|
1021
1032
|
},
|
|
1022
1033
|
blockLag: publicChainConfig["blockLag"]->Option.getOr(0),
|
|
1023
1034
|
contracts,
|
|
@@ -1110,6 +1121,7 @@ let fromPublic = (publicConfigJson: JSON.t) => {
|
|
|
1110
1121
|
userEntities,
|
|
1111
1122
|
allEntities,
|
|
1112
1123
|
allEnums,
|
|
1124
|
+
subgraph: publicConfig["subgraph"],
|
|
1113
1125
|
}
|
|
1114
1126
|
}
|
|
1115
1127
|
|
|
@@ -1246,6 +1258,10 @@ let stripSensitiveData = (json: JSON.t): JSON.t => {
|
|
|
1246
1258
|
stripChains(obj->Dict.get("evm"))
|
|
1247
1259
|
stripChains(obj->Dict.get("fuel"))
|
|
1248
1260
|
stripChains(obj->Dict.get("svm"))
|
|
1261
|
+
// The subgraph blob is how the runtime finds mappings. None of it
|
|
1262
|
+
// describes stored data — that's already in `evm` / `entities` — so a
|
|
1263
|
+
// specVersion bump or a mapping-path edit must not force a reset.
|
|
1264
|
+
obj->Utils.Dict.deleteInPlace("subgraph")
|
|
1249
1265
|
}
|
|
1250
1266
|
| _ => ()
|
|
1251
1267
|
}
|
package/src/Config.res.mjs
CHANGED
|
@@ -433,7 +433,8 @@ let publicConfigSchema = S$RescriptSchema.schema(s => ({
|
|
|
433
433
|
fuel: s.m(S$RescriptSchema.option(publicConfigEcosystemSchema)),
|
|
434
434
|
svm: s.m(S$RescriptSchema.option(publicConfigEcosystemSchema)),
|
|
435
435
|
enums: s.m(S$RescriptSchema.option(S$RescriptSchema.dict(S$RescriptSchema.array(S$RescriptSchema.string)))),
|
|
436
|
-
entities: s.m(S$RescriptSchema.option(S$RescriptSchema.array(entityJsonSchema)))
|
|
436
|
+
entities: s.m(S$RescriptSchema.option(S$RescriptSchema.array(entityJsonSchema))),
|
|
437
|
+
subgraph: s.m(S$RescriptSchema.option(S$RescriptSchema.json(false)))
|
|
437
438
|
}));
|
|
438
439
|
|
|
439
440
|
function fromPublic(publicConfigJson) {
|
|
@@ -685,13 +686,13 @@ function fromPublic(publicConfigJson) {
|
|
|
685
686
|
}
|
|
686
687
|
let tmp;
|
|
687
688
|
switch (ecosystemName) {
|
|
688
|
-
case "evm" :
|
|
689
|
-
tmp = Stdlib_Option.getOr(publicChainConfig.maxReorgDepth, 200);
|
|
690
|
-
break;
|
|
691
689
|
case "fuel" :
|
|
692
|
-
case "svm" :
|
|
693
690
|
tmp = 0;
|
|
694
691
|
break;
|
|
692
|
+
case "evm" :
|
|
693
|
+
case "svm" :
|
|
694
|
+
tmp = Stdlib_Option.getOr(publicChainConfig.maxReorgDepth, 200);
|
|
695
|
+
break;
|
|
695
696
|
}
|
|
696
697
|
return {
|
|
697
698
|
name: chainName,
|
|
@@ -757,7 +758,8 @@ function fromPublic(publicConfigJson) {
|
|
|
757
758
|
userEntitiesByName: userEntitiesByName,
|
|
758
759
|
userEntities: userEntities,
|
|
759
760
|
allEntities: allEntities,
|
|
760
|
-
allEnums: allEnums
|
|
761
|
+
allEnums: allEnums,
|
|
762
|
+
subgraph: publicConfig.subgraph
|
|
761
763
|
};
|
|
762
764
|
}
|
|
763
765
|
|
|
@@ -902,6 +904,7 @@ function stripSensitiveData(json) {
|
|
|
902
904
|
stripChains(cloned["evm"]);
|
|
903
905
|
stripChains(cloned["fuel"]);
|
|
904
906
|
stripChains(cloned["svm"]);
|
|
907
|
+
Utils.Dict.deleteInPlace(cloned, "subgraph");
|
|
905
908
|
}
|
|
906
909
|
return cloned;
|
|
907
910
|
}
|
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>,
|
|
@@ -24,8 +26,16 @@ type fromUserApiResult = {
|
|
|
24
26
|
indexerCode: Null.t<string>,
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
type fromSubgraphOptions = {
|
|
30
|
+
name?: string,
|
|
31
|
+
env?: dict<string>,
|
|
32
|
+
files?: dict<string>,
|
|
33
|
+
root?: string,
|
|
34
|
+
}
|
|
35
|
+
|
|
27
36
|
type addon = {
|
|
28
37
|
getConfigJson: (~configPath: Null.t<string>, ~directory: Null.t<string>) => string,
|
|
38
|
+
fromSubgraph: (string, string, fromSubgraphOptions) => fromUserApiResult,
|
|
29
39
|
encodeIndexedTopic: (~abiType: string, ~value: unknown) => EvmTypes.Hex.t,
|
|
30
40
|
fromUserApi: (string, fromUserApiOptions) => fromUserApiResult,
|
|
31
41
|
runCli: (~args: array<string>, ~envioPackageDir: Null.t<string>) => promise<Null.t<string>>,
|
|
@@ -43,6 +53,8 @@ type addon = {
|
|
|
43
53
|
blockStore: blockStoreCtor,
|
|
44
54
|
@as("AddressStore")
|
|
45
55
|
addressStore: addressStoreCtor,
|
|
56
|
+
@as("MockHyperSyncServer")
|
|
57
|
+
mockHyperSyncServer: mockHyperSyncServerCtor,
|
|
46
58
|
// Ordered transaction-field names exposed for the field-code contract test
|
|
47
59
|
// (the ReScript `transactionFields` arrays must match the Rust ordinals).
|
|
48
60
|
evmTransactionFieldNames: unit => array<string>,
|
|
@@ -51,6 +63,7 @@ type addon = {
|
|
|
51
63
|
// must match the Rust ordinals).
|
|
52
64
|
evmBlockFieldNames: unit => array<string>,
|
|
53
65
|
svmBlockFieldNames: unit => array<string>,
|
|
66
|
+
fuelBlockFieldNames: unit => array<string>,
|
|
54
67
|
}
|
|
55
68
|
|
|
56
69
|
@module("node:module") external createRequire: string => {..} = "createRequire"
|
|
@@ -232,6 +245,13 @@ let fromUserApi = (~schema=?, ~env=?, ~files=?, ~withIndexerTypes=false, yaml) =
|
|
|
232
245
|
)
|
|
233
246
|
}
|
|
234
247
|
|
|
248
|
+
/// Parses a subgraph project without touching the filesystem: subgraph.yaml and
|
|
249
|
+
/// its schema inline, ABI bodies through `files`.
|
|
250
|
+
let fromSubgraph = (~name=?, ~env=?, ~files=?, ~root=?, ~manifest, ~schema) => {
|
|
251
|
+
let addon = getAddon()
|
|
252
|
+
addon.fromSubgraph(manifest, schema, {?name, ?env, ?files, ?root})
|
|
253
|
+
}
|
|
254
|
+
|
|
235
255
|
let runCli = args => {
|
|
236
256
|
let addon = getAddon()
|
|
237
257
|
addon.runCli(~args, ~envioPackageDir=Null.make(envioPackageDir))
|
package/src/Core.res.mjs
CHANGED
|
@@ -191,6 +191,16 @@ function fromUserApi(schema, env, files, withIndexerTypesOpt, yaml) {
|
|
|
191
191
|
});
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
function fromSubgraph(name, env, files, root, manifest, schema) {
|
|
195
|
+
let addon = getAddon();
|
|
196
|
+
return addon.fromSubgraph(manifest, schema, {
|
|
197
|
+
name: name,
|
|
198
|
+
env: env,
|
|
199
|
+
files: files,
|
|
200
|
+
root: root
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
194
204
|
function runCli(args) {
|
|
195
205
|
let addon = getAddon();
|
|
196
206
|
return addon.runCli(args, envioPackageDir);
|
|
@@ -208,6 +218,7 @@ export {
|
|
|
208
218
|
getAddon,
|
|
209
219
|
getConfigJson,
|
|
210
220
|
fromUserApi,
|
|
221
|
+
fromSubgraph,
|
|
211
222
|
runCli,
|
|
212
223
|
}
|
|
213
224
|
/* envioPackageDir Not a pure module */
|
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
|
|