envio 3.3.0-alpha.6 → 3.3.0-alpha.8
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 +23 -5
- package/package.json +6 -6
- package/src/Address.res +5 -2
- package/src/Address.res.mjs +3 -1
- package/src/Api.res +1 -1
- package/src/Api.res.mjs +1 -1
- package/src/ChainFetching.res +34 -34
- package/src/ChainFetching.res.mjs +29 -29
- package/src/ChainState.res +328 -165
- package/src/ChainState.res.mjs +205 -100
- package/src/ChainState.resi +16 -7
- package/src/Config.res +55 -27
- package/src/Config.res.mjs +46 -7
- package/src/ContractRegisterContext.res +2 -12
- package/src/ContractRegisterContext.res.mjs +3 -5
- package/src/Core.res +7 -0
- package/src/CrossChainState.res +54 -79
- package/src/CrossChainState.res.mjs +45 -60
- package/src/CrossChainState.resi +1 -1
- package/src/Ecosystem.res +3 -3
- package/src/Ecosystem.res.mjs +3 -3
- package/src/Envio.res +14 -9
- package/src/EventConfigBuilder.res +105 -56
- package/src/EventConfigBuilder.res.mjs +69 -33
- package/src/EventProcessing.res +19 -15
- package/src/EventProcessing.res.mjs +13 -12
- package/src/FetchState.res +383 -182
- package/src/FetchState.res.mjs +260 -264
- package/src/HandlerLoader.res +7 -112
- package/src/HandlerLoader.res.mjs +1 -87
- package/src/HandlerRegister.res +209 -6
- package/src/HandlerRegister.res.mjs +90 -5
- package/src/HandlerRegister.resi +13 -2
- package/src/IndexerState.res +6 -3
- package/src/IndexerState.res.mjs +3 -3
- package/src/IndexerState.resi +1 -1
- package/src/IndexingAddresses.res +10 -7
- package/src/IndexingAddresses.res.mjs +8 -7
- package/src/IndexingAddresses.resi +3 -1
- package/src/Internal.res +82 -36
- package/src/Internal.res.mjs +11 -1
- package/src/Main.res +22 -23
- package/src/Main.res.mjs +15 -17
- package/src/Metrics.res +43 -2
- package/src/Metrics.res.mjs +39 -3
- package/src/Prometheus.res +0 -35
- package/src/Prometheus.res.mjs +33 -68
- package/src/RawEvent.res +7 -2
- package/src/RawEvent.res.mjs +4 -4
- package/src/SimulateItems.res +26 -8
- package/src/SimulateItems.res.mjs +11 -14
- package/src/TestIndexer.res +1 -1
- package/src/TestIndexer.res.mjs +1 -1
- package/src/sources/BlockStore.res +46 -0
- package/src/sources/BlockStore.res.mjs +24 -0
- package/src/sources/EventRouter.res +19 -12
- package/src/sources/EventRouter.res.mjs +7 -5
- package/src/sources/Evm.res +54 -4
- package/src/sources/Evm.res.mjs +43 -4
- package/src/sources/EvmChain.res +14 -18
- package/src/sources/EvmChain.res.mjs +12 -13
- package/src/sources/FieldMask.res +39 -0
- package/src/sources/FieldMask.res.mjs +42 -0
- package/src/sources/Fuel.res +5 -2
- package/src/sources/Fuel.res.mjs +4 -3
- package/src/sources/HyperFuelSource.res +32 -40
- package/src/sources/HyperFuelSource.res.mjs +53 -45
- package/src/sources/HyperSync.res +35 -9
- package/src/sources/HyperSync.res.mjs +52 -35
- package/src/sources/HyperSync.resi +11 -3
- package/src/sources/HyperSyncClient.res +15 -4
- package/src/sources/HyperSyncHeightStream.res +1 -8
- package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
- package/src/sources/HyperSyncSource.res +39 -58
- package/src/sources/HyperSyncSource.res.mjs +44 -44
- package/src/sources/RpcSource.res +114 -92
- package/src/sources/RpcSource.res.mjs +77 -46
- package/src/sources/RpcWebSocketHeightStream.res +0 -5
- package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
- package/src/sources/SimulateSource.res +6 -3
- package/src/sources/SimulateSource.res.mjs +13 -5
- package/src/sources/Source.res +25 -5
- package/src/sources/SourceManager.res +66 -3
- package/src/sources/SourceManager.res.mjs +55 -7
- package/src/sources/SourceManager.resi +10 -0
- package/src/sources/Svm.res +15 -10
- package/src/sources/Svm.res.mjs +24 -7
- package/src/sources/SvmHyperSyncClient.res +5 -6
- package/src/sources/SvmHyperSyncSource.res +84 -41
- package/src/sources/SvmHyperSyncSource.res.mjs +90 -43
- package/src/sources/TransactionStore.res +6 -107
- package/src/sources/TransactionStore.res.mjs +5 -86
- package/svm.schema.json +19 -0
package/src/ChainState.res.mjs
CHANGED
|
@@ -7,9 +7,10 @@ import * as Utils from "./Utils.res.mjs";
|
|
|
7
7
|
import * as Logging from "./Logging.res.mjs";
|
|
8
8
|
import * as ChainMap from "./ChainMap.res.mjs";
|
|
9
9
|
import * as EvmChain from "./sources/EvmChain.res.mjs";
|
|
10
|
+
import * as FieldMask from "./sources/FieldMask.res.mjs";
|
|
11
|
+
import * as BlockStore from "./sources/BlockStore.res.mjs";
|
|
10
12
|
import * as FetchState from "./FetchState.res.mjs";
|
|
11
13
|
import * as Prometheus from "./Prometheus.res.mjs";
|
|
12
|
-
import * as EventRouter from "./sources/EventRouter.res.mjs";
|
|
13
14
|
import * as Stdlib_Null from "@rescript/runtime/lib/es6/Stdlib_Null.js";
|
|
14
15
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
15
16
|
import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
|
|
@@ -39,12 +40,14 @@ function configAddresses(chainConfig) {
|
|
|
39
40
|
return addresses;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
function make(chainConfig, fetchState, indexingAddresses, sourceManager, reorgDetection, committedProgressBlockNumber, safeCheckpointTrackingOpt, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt, transactionStoreOpt, logger) {
|
|
43
|
+
function make(chainConfig, fetchState, indexingAddresses, sourceManager, reorgDetection, committedProgressBlockNumber, safeCheckpointTrackingOpt, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt, transactionStoreOpt, chainDensityOpt, blockStoreOpt, logger) {
|
|
43
44
|
let safeCheckpointTracking = safeCheckpointTrackingOpt !== undefined ? Primitive_option.valFromOption(safeCheckpointTrackingOpt) : undefined;
|
|
44
45
|
let numEventsProcessed = numEventsProcessedOpt !== undefined ? numEventsProcessedOpt : 0;
|
|
45
46
|
let timestampCaughtUpToHeadOrEndblock = timestampCaughtUpToHeadOrEndblockOpt !== undefined ? Primitive_option.valFromOption(timestampCaughtUpToHeadOrEndblockOpt) : undefined;
|
|
46
47
|
let isProgressAtHead = isProgressAtHeadOpt !== undefined ? isProgressAtHeadOpt : false;
|
|
47
48
|
let transactionStore = transactionStoreOpt !== undefined ? Primitive_option.valFromOption(transactionStoreOpt) : TransactionStore.make("evm", false);
|
|
49
|
+
let chainDensity = chainDensityOpt !== undefined ? Primitive_option.valFromOption(chainDensityOpt) : undefined;
|
|
50
|
+
let blockStore = blockStoreOpt !== undefined ? Primitive_option.valFromOption(blockStoreOpt) : BlockStore.make("evm", false);
|
|
48
51
|
return {
|
|
49
52
|
logger: logger,
|
|
50
53
|
fetchState: fetchState,
|
|
@@ -56,74 +59,40 @@ function make(chainConfig, fetchState, indexingAddresses, sourceManager, reorgDe
|
|
|
56
59
|
committedProgressBlockNumber: committedProgressBlockNumber,
|
|
57
60
|
numEventsProcessed: numEventsProcessed,
|
|
58
61
|
pendingBudget: 0,
|
|
62
|
+
chainDensity: chainDensity,
|
|
59
63
|
reorgDetection: reorgDetection,
|
|
60
64
|
safeCheckpointTracking: safeCheckpointTracking,
|
|
61
|
-
transactionStore: transactionStore
|
|
65
|
+
transactionStore: transactionStore,
|
|
66
|
+
blockStore: blockStore
|
|
62
67
|
};
|
|
63
68
|
}
|
|
64
69
|
|
|
65
|
-
function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firstEventBlockOpt, progressBlockNumber, config,
|
|
70
|
+
function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firstEventBlockOpt, progressBlockNumber, config, registrationsByChainId, logger, timestampCaughtUpToHeadOrEndblock, numEventsProcessed, isInReorgThreshold, isRealtime, reorgCheckpoints, maxReorgDepth, knownHeightOpt, reducedPollingInterval) {
|
|
66
71
|
let firstEventBlock = firstEventBlockOpt !== undefined ? Primitive_option.valFromOption(firstEventBlockOpt) : undefined;
|
|
67
72
|
let knownHeight = knownHeightOpt !== undefined ? knownHeightOpt : 0;
|
|
68
|
-
let
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
let match = Stdlib_Option.getOr(registrationsByChainId[chainConfig.id.toString()], {
|
|
74
|
+
onEventRegistrations: [],
|
|
75
|
+
onBlockRegistrations: []
|
|
76
|
+
});
|
|
77
|
+
let onBlockRegistrations = match.onBlockRegistrations;
|
|
78
|
+
let onEventRegistrations = match.onEventRegistrations;
|
|
71
79
|
chainConfig.contracts.forEach(contract => {
|
|
72
|
-
let contractName = contract.name;
|
|
73
|
-
contract.events.forEach(eventConfig => {
|
|
74
|
-
let hasContractRegister = Stdlib_Option.isSome(eventConfig.contractRegister);
|
|
75
|
-
EventRouter.addOrThrow(eventRouter, eventConfig.id, undefined, contractName, eventConfig.isWildcard, eventConfig.name, ChainMap.Chain.makeUnsafe(chainConfig.id));
|
|
76
|
-
let shouldBeIncluded;
|
|
77
|
-
if (config.enableRawEvents) {
|
|
78
|
-
shouldBeIncluded = true;
|
|
79
|
-
} else {
|
|
80
|
-
let isRegistered = hasContractRegister || Stdlib_Option.isSome(eventConfig.handler);
|
|
81
|
-
if (!isRegistered) {
|
|
82
|
-
notRegisteredEvents.push(eventConfig);
|
|
83
|
-
}
|
|
84
|
-
shouldBeIncluded = isRegistered;
|
|
85
|
-
}
|
|
86
|
-
let shouldSkip;
|
|
87
|
-
try {
|
|
88
|
-
let getEventFiltersOrThrow = eventConfig.getEventFiltersOrThrow;
|
|
89
|
-
if (getEventFiltersOrThrow) {
|
|
90
|
-
let match = getEventFiltersOrThrow(ChainMap.Chain.makeUnsafe(chainConfig.id));
|
|
91
|
-
shouldSkip = match.TAG === "Static" ? match._0.length === 0 : false;
|
|
92
|
-
} else {
|
|
93
|
-
shouldSkip = false;
|
|
94
|
-
}
|
|
95
|
-
} catch (exn) {
|
|
96
|
-
shouldSkip = false;
|
|
97
|
-
}
|
|
98
|
-
if (shouldBeIncluded && !shouldSkip) {
|
|
99
|
-
eventConfigs.push(eventConfig);
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
80
|
let startBlock = contract.startBlock;
|
|
104
81
|
if (startBlock !== undefined && startBlock < chainConfig.startBlock) {
|
|
105
|
-
return Stdlib_JsError.throwWithMessage(`The start block for contract "` +
|
|
82
|
+
return Stdlib_JsError.throwWithMessage(`The start block for contract "` + contract.name + `" is less than the chain start block. This is not supported yet.`);
|
|
106
83
|
}
|
|
107
84
|
});
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
Stdlib_JsError.throwWithMessage(`The start block for onBlock handler "` + onBlockConfig.name + `" is less than the chain start block (` + startBlock.toString() + `). This is not supported yet.`);
|
|
118
|
-
}
|
|
119
|
-
if (endBlock !== undefined && Stdlib_Option.getOr(onBlockConfig.endBlock, endBlock) > endBlock) {
|
|
120
|
-
return Stdlib_JsError.throwWithMessage(`The end block for onBlock handler "` + onBlockConfig.name + `" is greater than the chain end block (` + endBlock.toString() + `). This is not supported yet.`);
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
let contractConfigs = IndexingAddresses.makeContractConfigs(eventConfigs);
|
|
85
|
+
onBlockRegistrations.forEach(onBlockRegistration => {
|
|
86
|
+
if (Stdlib_Option.getOr(onBlockRegistration.startBlock, startBlock) < startBlock) {
|
|
87
|
+
Stdlib_JsError.throwWithMessage(`The start block for onBlock handler "` + onBlockRegistration.name + `" is less than the chain start block (` + startBlock.toString() + `). This is not supported yet.`);
|
|
88
|
+
}
|
|
89
|
+
if (endBlock !== undefined && Stdlib_Option.getOr(onBlockRegistration.endBlock, endBlock) > endBlock) {
|
|
90
|
+
return Stdlib_JsError.throwWithMessage(`The end block for onBlock handler "` + onBlockRegistration.name + `" is greater than the chain end block (` + endBlock.toString() + `). This is not supported yet.`);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
let contractConfigs = IndexingAddresses.makeContractConfigs(onEventRegistrations);
|
|
125
94
|
let indexingAddressIndex = IndexingAddresses.make(contractConfigs, indexingAddresses);
|
|
126
|
-
let fetchState = FetchState.make(startBlock, endBlock,
|
|
95
|
+
let fetchState = FetchState.make(startBlock, endBlock, onEventRegistrations, contractConfigs, indexingAddresses, config.maxAddrInPartition, chainConfig.id, (config.batchSize << 1), knownHeight, progressBlockNumber, onBlockRegistrations, Primitive_int.max(!config.shouldRollbackOnReorg || isInReorgThreshold ? 0 : chainConfig.maxReorgDepth, chainConfig.blockLag), Primitive_option.some(firstEventBlock));
|
|
127
96
|
let chainReorgCheckpoints = Stdlib_Array.filterMap(reorgCheckpoints, reorgCheckpoint => {
|
|
128
97
|
if (reorgCheckpoint.chain_id === chainConfig.id) {
|
|
129
98
|
return reorgCheckpoint;
|
|
@@ -135,11 +104,6 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
|
|
|
135
104
|
let sources$1;
|
|
136
105
|
switch (sources.TAG) {
|
|
137
106
|
case "EvmSourceConfig" :
|
|
138
|
-
let evmContracts = chainConfig.contracts.map(contract => ({
|
|
139
|
-
name: contract.name,
|
|
140
|
-
abi: contract.abi,
|
|
141
|
-
events: contract.events
|
|
142
|
-
}));
|
|
143
107
|
let evmRpcs = sources.rpcs.map(rpc => {
|
|
144
108
|
let syncConfig = rpc.syncConfig;
|
|
145
109
|
let ws = rpc.ws;
|
|
@@ -152,7 +116,7 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
|
|
|
152
116
|
headers: headers
|
|
153
117
|
};
|
|
154
118
|
});
|
|
155
|
-
sources$1 = EvmChain.makeSources(chain,
|
|
119
|
+
sources$1 = EvmChain.makeSources(chain, onEventRegistrations, sources.hypersync, evmRpcs, lowercaseAddresses);
|
|
156
120
|
break;
|
|
157
121
|
case "FuelSourceConfig" :
|
|
158
122
|
sources$1 = [HyperFuelSource.make({
|
|
@@ -164,41 +128,40 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
|
|
|
164
128
|
case "SvmSourceConfig" :
|
|
165
129
|
let rpc = sources.rpc;
|
|
166
130
|
let hypersync = sources.hypersync;
|
|
167
|
-
|
|
168
|
-
let svmEventConfigs = chainConfig.contracts.flatMap(contract => contract.events);
|
|
169
|
-
sources$1 = [SvmHyperSyncSource.make({
|
|
131
|
+
sources$1 = hypersync !== undefined ? [SvmHyperSyncSource.make({
|
|
170
132
|
chain: chain,
|
|
171
133
|
endpointUrl: hypersync,
|
|
172
134
|
apiToken: Env.envioApiToken,
|
|
173
|
-
|
|
135
|
+
onEventRegistrations: onEventRegistrations,
|
|
174
136
|
clientTimeoutMillis: Env.hyperSyncClientTimeoutMillis
|
|
175
|
-
})]
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
137
|
+
})] : (
|
|
138
|
+
rpc !== undefined ? [Svm.makeRPCSource(chain, rpc, undefined)] : Stdlib_JsError.throwWithMessage(`Chain ` + chain.toString() + ` has no SVM data source`)
|
|
139
|
+
);
|
|
179
140
|
break;
|
|
180
141
|
case "CustomSources" :
|
|
181
142
|
sources$1 = sources._0;
|
|
182
143
|
break;
|
|
183
144
|
}
|
|
184
|
-
|
|
145
|
+
let firstEventBlock$1 = fetchState.firstEventBlock;
|
|
146
|
+
let chainDensity = firstEventBlock$1 !== undefined && progressBlockNumber > firstEventBlock$1 && numEventsProcessed > 0 ? numEventsProcessed / (progressBlockNumber - firstEventBlock$1 | 0) : undefined;
|
|
147
|
+
return make(chainConfig, fetchState, indexingAddressIndex, SourceManager.make(sources$1, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined), ReorgDetection.make(chainReorgCheckpoints, maxReorgDepth, config.shouldRollbackOnReorg), progressBlockNumber, Primitive_option.some(SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)), numEventsProcessed, Primitive_option.some(timestampCaughtUpToHeadOrEndblock), undefined, Primitive_option.some(TransactionStore.make(config.ecosystem.name, !lowercaseAddresses)), Primitive_option.some(chainDensity), Primitive_option.some(BlockStore.make(config.ecosystem.name, !lowercaseAddresses)), logger);
|
|
185
148
|
}
|
|
186
149
|
|
|
187
|
-
function makeFromConfig(chainConfig, config,
|
|
150
|
+
function makeFromConfig(chainConfig, config, registrationsByChainId, knownHeight) {
|
|
188
151
|
let logger = Logging.createChild({
|
|
189
152
|
chainId: chainConfig.id
|
|
190
153
|
});
|
|
191
|
-
return makeInternal(chainConfig, configAddresses(chainConfig), chainConfig.startBlock, chainConfig.endBlock, undefined, -1, config,
|
|
154
|
+
return makeInternal(chainConfig, configAddresses(chainConfig), chainConfig.startBlock, chainConfig.endBlock, undefined, -1, config, registrationsByChainId, logger, undefined, 0, false, false, [], chainConfig.maxReorgDepth, knownHeight, undefined);
|
|
192
155
|
}
|
|
193
156
|
|
|
194
|
-
function makeFromDbState(chainConfig, resumedChainState, reorgCheckpoints, isInReorgThreshold, isRealtime, config,
|
|
157
|
+
function makeFromDbState(chainConfig, resumedChainState, reorgCheckpoints, isInReorgThreshold, isRealtime, config, registrationsByChainId, reducedPollingInterval) {
|
|
195
158
|
let chainId = chainConfig.id;
|
|
196
159
|
let logger = Logging.createChild({
|
|
197
160
|
chainId: chainId
|
|
198
161
|
});
|
|
199
162
|
Prometheus.ProgressEventsCount.set(resumedChainState.numEventsProcessed, chainId);
|
|
200
163
|
let progressBlockNumber = resumedChainState.progressBlockNumber >= 0 ? resumedChainState.progressBlockNumber : resumedChainState.startBlock - 1 | 0;
|
|
201
|
-
return makeInternal(chainConfig, resumedChainState.indexingAddresses, resumedChainState.startBlock, resumedChainState.endBlock, Primitive_option.some(resumedChainState.firstEventBlockNumber), progressBlockNumber, config,
|
|
164
|
+
return makeInternal(chainConfig, resumedChainState.indexingAddresses, resumedChainState.startBlock, resumedChainState.endBlock, Primitive_option.some(resumedChainState.firstEventBlockNumber), progressBlockNumber, config, registrationsByChainId, logger, Env.updateSyncTimeOnRestart ? undefined : resumedChainState.timestampCaughtUpToHeadOrEndblock, resumedChainState.numEventsProcessed, isInReorgThreshold, isRealtime, reorgCheckpoints, resumedChainState.maxReorgDepth, resumedChainState.sourceBlockNumber, reducedPollingInterval);
|
|
202
165
|
}
|
|
203
166
|
|
|
204
167
|
function logger(cs) {
|
|
@@ -261,8 +224,8 @@ function getProgressPercentage(cs) {
|
|
|
261
224
|
return FetchState.getProgressPercentage(cs.fetchState);
|
|
262
225
|
}
|
|
263
226
|
|
|
264
|
-
function
|
|
265
|
-
return
|
|
227
|
+
function chainDensity(cs) {
|
|
228
|
+
return cs.chainDensity;
|
|
266
229
|
}
|
|
267
230
|
|
|
268
231
|
function hasReadyItem(cs) {
|
|
@@ -279,11 +242,16 @@ function isReadyToEnterReorgThreshold(cs) {
|
|
|
279
242
|
|
|
280
243
|
function startFetchingQueries(cs, queries) {
|
|
281
244
|
FetchState.startFetchingQueries(cs.fetchState, queries);
|
|
282
|
-
cs.pendingBudget = cs.pendingBudget + Stdlib_Array.reduce(queries, 0, (acc, query) => acc + query.
|
|
245
|
+
cs.pendingBudget = cs.pendingBudget + Stdlib_Array.reduce(queries, 0, (acc, query) => acc + query.itemsTarget);
|
|
283
246
|
}
|
|
284
247
|
|
|
285
|
-
function getNextQuery(cs,
|
|
286
|
-
|
|
248
|
+
function getNextQuery(cs, chainTargetItems) {
|
|
249
|
+
let fetchState = cs.fetchState;
|
|
250
|
+
let knownHeight = fetchState.knownHeight;
|
|
251
|
+
let bufferBlockNumber = FetchState.bufferBlockNumber(fetchState);
|
|
252
|
+
let density = cs.chainDensity;
|
|
253
|
+
let chainTargetBlock = density !== undefined && density > 0 ? Primitive_int.min(knownHeight, bufferBlockNumber + (Math.ceil(chainTargetItems / density) | 0) | 0) : knownHeight;
|
|
254
|
+
return FetchState.getNextQuery(fetchState, chainTargetBlock, chainTargetItems);
|
|
287
255
|
}
|
|
288
256
|
|
|
289
257
|
function dispatch(cs, executeQuery, waitForNewBlock, onNewBlock, action, stateId) {
|
|
@@ -330,25 +298,144 @@ function isAtHeadWithoutEndBlock(cs) {
|
|
|
330
298
|
}
|
|
331
299
|
}
|
|
332
300
|
|
|
333
|
-
function
|
|
334
|
-
|
|
301
|
+
function groupBatchItems(items, includeBlocks) {
|
|
302
|
+
let txBlockNumbers = [];
|
|
303
|
+
let transactionIndices = [];
|
|
304
|
+
let transactionMasks = [];
|
|
305
|
+
let payloadGroups = [];
|
|
306
|
+
let anyTransactionFieldSelected = {
|
|
307
|
+
contents: false
|
|
308
|
+
};
|
|
309
|
+
let blockBlockNumbers = [];
|
|
310
|
+
let blockMasks = [];
|
|
311
|
+
let blockItemGroups = [];
|
|
312
|
+
items.forEach(item => {
|
|
313
|
+
if (item.kind !== 0) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
let blockNumber = item.blockNumber;
|
|
317
|
+
let match = item.payload.transaction;
|
|
318
|
+
if (match == null) {
|
|
319
|
+
let transactionIndex = item.transactionIndex;
|
|
320
|
+
let mask = item.onEventRegistration.eventConfig.transactionFieldMask;
|
|
321
|
+
if (mask !== 0) {
|
|
322
|
+
anyTransactionFieldSelected.contents = true;
|
|
323
|
+
}
|
|
324
|
+
let last = payloadGroups.length - 1 | 0;
|
|
325
|
+
if (last >= 0 && txBlockNumbers[last] === blockNumber && transactionIndices[last] === transactionIndex) {
|
|
326
|
+
payloadGroups[last].push(item.payload);
|
|
327
|
+
transactionMasks[last] = FieldMask.orMask(transactionMasks[last], mask);
|
|
328
|
+
} else {
|
|
329
|
+
txBlockNumbers.push(blockNumber);
|
|
330
|
+
transactionIndices.push(transactionIndex);
|
|
331
|
+
transactionMasks.push(mask);
|
|
332
|
+
payloadGroups.push([item.payload]);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (!includeBlocks) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
let match$1 = item.payload.block;
|
|
339
|
+
if (!(match$1 == null)) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
let mask$1 = item.onEventRegistration.eventConfig.blockFieldMask;
|
|
343
|
+
let last$1 = blockItemGroups.length - 1 | 0;
|
|
344
|
+
if (last$1 >= 0 && blockBlockNumbers[last$1] === blockNumber) {
|
|
345
|
+
blockItemGroups[last$1].push(item);
|
|
346
|
+
blockMasks[last$1] = FieldMask.orMask(blockMasks[last$1], mask$1);
|
|
347
|
+
} else {
|
|
348
|
+
blockBlockNumbers.push(blockNumber);
|
|
349
|
+
blockMasks.push(mask$1);
|
|
350
|
+
blockItemGroups.push([item]);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
return [
|
|
354
|
+
{
|
|
355
|
+
txBlockNumbers: txBlockNumbers,
|
|
356
|
+
transactionIndices: transactionIndices,
|
|
357
|
+
transactionMasks: transactionMasks,
|
|
358
|
+
payloadGroups: payloadGroups,
|
|
359
|
+
anyTransactionFieldSelected: anyTransactionFieldSelected.contents
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
blockBlockNumbers: blockBlockNumbers,
|
|
363
|
+
blockMasks: blockMasks,
|
|
364
|
+
blockItemGroups: blockItemGroups
|
|
365
|
+
}
|
|
366
|
+
];
|
|
335
367
|
}
|
|
336
368
|
|
|
337
|
-
function
|
|
338
|
-
if (
|
|
339
|
-
return
|
|
340
|
-
}
|
|
341
|
-
|
|
369
|
+
async function applyTransactionGroups(store, g) {
|
|
370
|
+
if (!Utils.$$Array.notEmpty(g.payloadGroups)) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (g.anyTransactionFieldSelected) {
|
|
374
|
+
let txs = await store.materialize(g.txBlockNumbers, g.transactionIndices, g.transactionMasks);
|
|
375
|
+
g.payloadGroups.forEach((payloads, i) => {
|
|
376
|
+
let tx = txs[i];
|
|
377
|
+
payloads.forEach(payload => {
|
|
378
|
+
payload.transaction = tx;
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
g.payloadGroups.forEach(payloads => {
|
|
384
|
+
payloads.forEach(payload => {
|
|
385
|
+
payload.transaction = {};
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
async function applyBlockGroups(store, g) {
|
|
391
|
+
if (!Utils.$$Array.notEmpty(g.blockItemGroups)) {
|
|
392
|
+
return;
|
|
342
393
|
}
|
|
394
|
+
let blocks = await store.materialize(g.blockBlockNumbers, g.blockMasks);
|
|
395
|
+
g.blockItemGroups.forEach((group, i) => {
|
|
396
|
+
let block = blocks[i];
|
|
397
|
+
group.forEach(ei => {
|
|
398
|
+
ei.payload.block = block;
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function includeBlocksForEcosystem(ecosystem) {
|
|
404
|
+
switch (ecosystem) {
|
|
405
|
+
case "fuel" :
|
|
406
|
+
return false;
|
|
407
|
+
case "evm" :
|
|
408
|
+
case "svm" :
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
async function materializeBatchItems(cs, items, ecosystem) {
|
|
414
|
+
let match = groupBatchItems(items, includeBlocksForEcosystem(ecosystem));
|
|
415
|
+
await Promise.all([
|
|
416
|
+
applyTransactionGroups(cs.transactionStore, match[0]),
|
|
417
|
+
applyBlockGroups(cs.blockStore, match[1])
|
|
418
|
+
]);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
async function materializePageItems(items, transactionStore, blockStore, ecosystem) {
|
|
422
|
+
let match = groupBatchItems(items, includeBlocksForEcosystem(ecosystem));
|
|
423
|
+
await Promise.all([
|
|
424
|
+
transactionStore !== undefined ? applyTransactionGroups(Primitive_option.valFromOption(transactionStore), match[0]) : Promise.resolve(),
|
|
425
|
+
blockStore !== undefined ? applyBlockGroups(Primitive_option.valFromOption(blockStore), match[1]) : Promise.resolve()
|
|
426
|
+
]);
|
|
343
427
|
}
|
|
344
428
|
|
|
345
|
-
function handleQueryResult(cs, query, newItems, newItemsWithDcs, latestFetchedBlock, knownHeight,
|
|
346
|
-
if (
|
|
347
|
-
cs.transactionStore.merge(Primitive_option.valFromOption(
|
|
429
|
+
function handleQueryResult(cs, query, newItems, newItemsWithDcs, latestFetchedBlock, knownHeight, txPage, blockPage) {
|
|
430
|
+
if (txPage !== undefined) {
|
|
431
|
+
cs.transactionStore.merge(Primitive_option.valFromOption(txPage));
|
|
432
|
+
}
|
|
433
|
+
if (blockPage !== undefined) {
|
|
434
|
+
cs.blockStore.merge(Primitive_option.valFromOption(blockPage));
|
|
348
435
|
}
|
|
349
436
|
let fs = newItemsWithDcs.length !== 0 ? FetchState.registerDynamicContracts(cs.fetchState, cs.indexingAddresses, newItemsWithDcs) : cs.fetchState;
|
|
350
437
|
cs.fetchState = FetchState.updateKnownHeight(FetchState.handleQueryResult(fs, cs.indexingAddresses, query, latestFetchedBlock, newItems), knownHeight);
|
|
351
|
-
cs.pendingBudget = Primitive_float.max(0, cs.pendingBudget - query.
|
|
438
|
+
cs.pendingBudget = Primitive_float.max(0, cs.pendingBudget - query.itemsTarget);
|
|
352
439
|
}
|
|
353
440
|
|
|
354
441
|
function registerReorgGuard(cs, blockHashes, knownHeight) {
|
|
@@ -387,7 +474,7 @@ function setEndBlockToFirstEvent(cs, blockNumber) {
|
|
|
387
474
|
blockLag: init.blockLag,
|
|
388
475
|
buffer: init.buffer,
|
|
389
476
|
maxOnBlockBufferSize: init.maxOnBlockBufferSize,
|
|
390
|
-
|
|
477
|
+
onBlockRegistrations: init.onBlockRegistrations,
|
|
391
478
|
knownHeight: init.knownHeight,
|
|
392
479
|
firstEventBlock: init.firstEventBlock
|
|
393
480
|
};
|
|
@@ -405,7 +492,7 @@ function setEndBlockToFirstEvent(cs, blockNumber) {
|
|
|
405
492
|
blockLag: init$1.blockLag,
|
|
406
493
|
buffer: init$1.buffer,
|
|
407
494
|
maxOnBlockBufferSize: init$1.maxOnBlockBufferSize,
|
|
408
|
-
|
|
495
|
+
onBlockRegistrations: init$1.onBlockRegistrations,
|
|
409
496
|
knownHeight: init$1.knownHeight,
|
|
410
497
|
firstEventBlock: init$1.firstEventBlock
|
|
411
498
|
};
|
|
@@ -465,7 +552,7 @@ function advanceAfterBatch(cs, batch, enteringReorgThreshold) {
|
|
|
465
552
|
}
|
|
466
553
|
}
|
|
467
554
|
|
|
468
|
-
function applyBatchProgress(cs, batch) {
|
|
555
|
+
function applyBatchProgress(cs, batch, blockTimestampName) {
|
|
469
556
|
let chainId = cs.chainConfig.id;
|
|
470
557
|
let chainAfterBatch = batch.progressedChainsById[chainId];
|
|
471
558
|
if (chainAfterBatch === undefined) {
|
|
@@ -477,9 +564,9 @@ function applyBatchProgress(cs, batch) {
|
|
|
477
564
|
if (cs.numEventsProcessed !== chainAfterBatch.totalEventsProcessed) {
|
|
478
565
|
Prometheus.ProgressEventsCount.set(chainAfterBatch.totalEventsProcessed, chainId);
|
|
479
566
|
}
|
|
480
|
-
let
|
|
481
|
-
if (
|
|
482
|
-
let blockTimestampMs =
|
|
567
|
+
let blockTimestamp = Stdlib_Option.flatMap(Stdlib_Option.flatMap(Batch.findLastEventItem(batch, chainId), eventItem => Primitive_option.fromNullable(eventItem.payload.block)), block => block[blockTimestampName]);
|
|
568
|
+
if (blockTimestamp !== undefined) {
|
|
569
|
+
let blockTimestampMs = Primitive_option.valFromOption(blockTimestamp) * 1000 | 0;
|
|
483
570
|
Prometheus.ProgressLatency.set((Date.now() | 0) - blockTimestampMs | 0, chainId);
|
|
484
571
|
}
|
|
485
572
|
let match = cs.fetchState.firstEventBlock;
|
|
@@ -498,15 +585,31 @@ function applyBatchProgress(cs, batch) {
|
|
|
498
585
|
blockLag: init.blockLag,
|
|
499
586
|
buffer: init.buffer,
|
|
500
587
|
maxOnBlockBufferSize: init.maxOnBlockBufferSize,
|
|
501
|
-
|
|
588
|
+
onBlockRegistrations: init.onBlockRegistrations,
|
|
502
589
|
knownHeight: init.knownHeight,
|
|
503
590
|
firstEventBlock: firstEventBlock
|
|
504
591
|
};
|
|
505
592
|
}
|
|
506
593
|
}
|
|
594
|
+
let deltaBlocks = chainAfterBatch.progressBlockNumber - cs.committedProgressBlockNumber | 0;
|
|
595
|
+
if (deltaBlocks > 0) {
|
|
596
|
+
let deltaEvents = chainAfterBatch.totalEventsProcessed - cs.numEventsProcessed;
|
|
597
|
+
let match$1 = cs.chainDensity;
|
|
598
|
+
let match$2 = deltaEvents > 0;
|
|
599
|
+
let exit = 0;
|
|
600
|
+
if (match$1 !== undefined || match$2) {
|
|
601
|
+
exit = 1;
|
|
602
|
+
}
|
|
603
|
+
if (exit === 1) {
|
|
604
|
+
let batchDensity = deltaEvents / deltaBlocks;
|
|
605
|
+
let oldDensity = cs.chainDensity;
|
|
606
|
+
cs.chainDensity = oldDensity !== undefined ? (oldDensity + batchDensity) / 2 : batchDensity;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
507
609
|
cs.committedProgressBlockNumber = chainAfterBatch.progressBlockNumber;
|
|
508
610
|
cs.numEventsProcessed = chainAfterBatch.totalEventsProcessed;
|
|
509
611
|
cs.transactionStore.prune(chainAfterBatch.progressBlockNumber);
|
|
612
|
+
cs.blockStore.prune(chainAfterBatch.progressBlockNumber);
|
|
510
613
|
cs.isProgressAtHead = cs.isProgressAtHead || chainAfterBatch.isProgressAtHeadWhenBatchCreated;
|
|
511
614
|
let safeCheckpointTracking = cs.safeCheckpointTracking;
|
|
512
615
|
if (safeCheckpointTracking !== undefined) {
|
|
@@ -529,6 +632,7 @@ function rollback(cs, newProgressBlockNumber, eventsProcessedDiff, rollbackTarge
|
|
|
529
632
|
cs.reorgDetection = ReorgDetection.rollbackToValidBlockNumber(cs.reorgDetection, rollbackTargetBlockNumber);
|
|
530
633
|
cs.fetchState = FetchState.rollback(cs.fetchState, cs.indexingAddresses, rollbackTargetBlockNumber);
|
|
531
634
|
cs.transactionStore.rollback(rollbackTargetBlockNumber);
|
|
635
|
+
cs.blockStore.rollback(rollbackTargetBlockNumber);
|
|
532
636
|
cs.committedProgressBlockNumber = Primitive_int.min(cs.committedProgressBlockNumber, rollbackTargetBlockNumber);
|
|
533
637
|
return;
|
|
534
638
|
} else {
|
|
@@ -551,6 +655,7 @@ function rollback(cs, newProgressBlockNumber, eventsProcessedDiff, rollbackTarge
|
|
|
551
655
|
}
|
|
552
656
|
cs.fetchState = FetchState.rollback(cs.fetchState, cs.indexingAddresses, newProgressBlockNumber);
|
|
553
657
|
cs.transactionStore.rollback(newProgressBlockNumber);
|
|
658
|
+
cs.blockStore.rollback(newProgressBlockNumber);
|
|
554
659
|
cs.committedProgressBlockNumber = newProgressBlockNumber;
|
|
555
660
|
cs.numEventsProcessed = newTotalEventsProcessed;
|
|
556
661
|
}
|
|
@@ -576,7 +681,7 @@ export {
|
|
|
576
681
|
bufferSize,
|
|
577
682
|
bufferReadyCount,
|
|
578
683
|
getProgressPercentage,
|
|
579
|
-
|
|
684
|
+
chainDensity,
|
|
580
685
|
hasReadyItem,
|
|
581
686
|
isReadyToEnterReorgThreshold,
|
|
582
687
|
getNextQuery,
|
package/src/ChainState.resi
CHANGED
|
@@ -17,13 +17,15 @@ let make: (
|
|
|
17
17
|
~timestampCaughtUpToHeadOrEndblock: option<Date.t>=?,
|
|
18
18
|
~isProgressAtHead: bool=?,
|
|
19
19
|
~transactionStore: TransactionStore.t=?,
|
|
20
|
+
~chainDensity: option<float>=?,
|
|
21
|
+
~blockStore: BlockStore.t=?,
|
|
20
22
|
~logger: Pino.t,
|
|
21
23
|
) => t
|
|
22
24
|
|
|
23
25
|
let makeFromConfig: (
|
|
24
26
|
Config.chain,
|
|
25
27
|
~config: Config.t,
|
|
26
|
-
~
|
|
28
|
+
~registrationsByChainId: HandlerRegister.registrationsByChainId,
|
|
27
29
|
~knownHeight: int,
|
|
28
30
|
) => t
|
|
29
31
|
|
|
@@ -34,7 +36,7 @@ let makeFromDbState: (
|
|
|
34
36
|
~isInReorgThreshold: bool,
|
|
35
37
|
~isRealtime: bool,
|
|
36
38
|
~config: Config.t,
|
|
37
|
-
~
|
|
39
|
+
~registrationsByChainId: HandlerRegister.registrationsByChainId,
|
|
38
40
|
~reducedPollingInterval: int=?,
|
|
39
41
|
) => t
|
|
40
42
|
|
|
@@ -57,12 +59,12 @@ let contractAddresses: (t, ~contractName: string) => array<Address.t>
|
|
|
57
59
|
let bufferSize: t => int
|
|
58
60
|
let bufferReadyCount: t => int
|
|
59
61
|
let getProgressPercentage: t => float
|
|
60
|
-
let
|
|
62
|
+
let chainDensity: t => option<float>
|
|
61
63
|
let hasReadyItem: t => bool
|
|
62
64
|
let isReadyToEnterReorgThreshold: t => bool
|
|
63
65
|
|
|
64
66
|
// Fetch control.
|
|
65
|
-
let getNextQuery: (t, ~
|
|
67
|
+
let getNextQuery: (t, ~chainTargetItems: float) => FetchState.nextQuery
|
|
66
68
|
let dispatch: (
|
|
67
69
|
t,
|
|
68
70
|
~executeQuery: FetchState.query => promise<unit>,
|
|
@@ -110,11 +112,18 @@ let handleQueryResult: (
|
|
|
110
112
|
~latestFetchedBlock: FetchState.blockNumberAndTimestamp,
|
|
111
113
|
~knownHeight: int,
|
|
112
114
|
~transactionStore: option<TransactionStore.t>,
|
|
115
|
+
~blockStore: option<BlockStore.t>,
|
|
113
116
|
) => unit
|
|
114
|
-
let materializeBatchItems: (
|
|
117
|
+
let materializeBatchItems: (
|
|
118
|
+
t,
|
|
119
|
+
~items: array<Internal.item>,
|
|
120
|
+
~ecosystem: Ecosystem.name,
|
|
121
|
+
) => promise<unit>
|
|
115
122
|
let materializePageItems: (
|
|
116
123
|
~items: array<Internal.item>,
|
|
117
|
-
~
|
|
124
|
+
~transactionStore: option<TransactionStore.t>,
|
|
125
|
+
~blockStore: option<BlockStore.t>,
|
|
126
|
+
~ecosystem: Ecosystem.name,
|
|
118
127
|
) => promise<unit>
|
|
119
128
|
let registerReorgGuard: (
|
|
120
129
|
t,
|
|
@@ -126,7 +135,7 @@ let updateKnownHeight: (t, ~knownHeight: int) => unit
|
|
|
126
135
|
let setEndBlockToFirstEvent: (t, ~blockNumber: int) => unit
|
|
127
136
|
let enterReorgThreshold: t => unit
|
|
128
137
|
let advanceAfterBatch: (t, ~batch: Batch.t, ~enteringReorgThreshold: bool) => unit
|
|
129
|
-
let applyBatchProgress: (t, ~batch: Batch.t) => unit
|
|
138
|
+
let applyBatchProgress: (t, ~batch: Batch.t, ~blockTimestampName: string) => unit
|
|
130
139
|
let markReady: t => unit
|
|
131
140
|
let rollback: (
|
|
132
141
|
t,
|