envio 3.2.0 → 3.3.0-alpha.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.
Files changed (113) hide show
  1. package/package.json +6 -7
  2. package/src/Batch.res +12 -15
  3. package/src/Batch.res.mjs +4 -5
  4. package/src/BatchProcessing.res +199 -0
  5. package/src/BatchProcessing.res.mjs +125 -0
  6. package/src/ChainFetching.res +375 -0
  7. package/src/ChainFetching.res.mjs +206 -0
  8. package/src/ChainMetadata.res +27 -0
  9. package/src/ChainMetadata.res.mjs +27 -0
  10. package/src/ChainState.res +618 -0
  11. package/src/ChainState.res.mjs +461 -0
  12. package/src/ChainState.resi +85 -0
  13. package/src/Config.res +13 -4
  14. package/src/Config.res.mjs +8 -3
  15. package/src/ContractRegisterContext.res +106 -0
  16. package/src/ContractRegisterContext.res.mjs +76 -0
  17. package/src/Core.res +3 -0
  18. package/src/CrossChainState.res +269 -0
  19. package/src/CrossChainState.res.mjs +197 -0
  20. package/src/CrossChainState.resi +47 -0
  21. package/src/Ecosystem.res +58 -0
  22. package/src/Ecosystem.res.mjs +43 -1
  23. package/src/Env.res +7 -2
  24. package/src/Env.res.mjs +5 -2
  25. package/src/EventConfigBuilder.res +35 -0
  26. package/src/EventConfigBuilder.res.mjs +21 -0
  27. package/src/EventProcessing.res +60 -46
  28. package/src/EventProcessing.res.mjs +33 -32
  29. package/src/EventUtils.res +0 -4
  30. package/src/EventUtils.res.mjs +0 -4
  31. package/src/ExitOnCaughtUp.res +10 -0
  32. package/src/ExitOnCaughtUp.res.mjs +22 -0
  33. package/src/FetchState.res +162 -113
  34. package/src/FetchState.res.mjs +181 -119
  35. package/src/HandlerLoader.res +6 -1
  36. package/src/HandlerLoader.res.mjs +13 -36
  37. package/src/InMemoryStore.res +36 -451
  38. package/src/InMemoryStore.res.mjs +20 -369
  39. package/src/IndexerLoop.res +44 -0
  40. package/src/IndexerLoop.res.mjs +46 -0
  41. package/src/IndexerState.res +544 -0
  42. package/src/IndexerState.res.mjs +547 -0
  43. package/src/IndexerState.resi +132 -0
  44. package/src/Internal.res +44 -7
  45. package/src/LoadLayer.res +20 -18
  46. package/src/LoadLayer.res.mjs +14 -12
  47. package/src/LoadLayer.resi +6 -3
  48. package/src/LogSelection.res +86 -17
  49. package/src/LogSelection.res.mjs +67 -14
  50. package/src/Logging.res +11 -44
  51. package/src/Logging.res.mjs +10 -42
  52. package/src/Main.res +54 -79
  53. package/src/Main.res.mjs +44 -56
  54. package/src/PgStorage.res +8 -71
  55. package/src/PgStorage.res.mjs +3 -47
  56. package/src/Prometheus.res +7 -8
  57. package/src/Prometheus.res.mjs +7 -4
  58. package/src/PruneStaleHistory.res +45 -0
  59. package/src/PruneStaleHistory.res.mjs +46 -0
  60. package/src/RawEvent.res +73 -0
  61. package/src/RawEvent.res.mjs +51 -0
  62. package/src/Rollback.res +204 -0
  63. package/src/Rollback.res.mjs +118 -0
  64. package/src/SimulateItems.res +12 -10
  65. package/src/SimulateItems.res.mjs +1 -1
  66. package/src/TestIndexer.res +34 -27
  67. package/src/TestIndexer.res.mjs +4 -1
  68. package/src/UserContext.res +26 -114
  69. package/src/UserContext.res.mjs +15 -78
  70. package/src/Writing.res +242 -0
  71. package/src/Writing.res.mjs +215 -0
  72. package/src/db/InternalTable.res +14 -27
  73. package/src/sources/Evm.res +40 -1
  74. package/src/sources/Evm.res.mjs +94 -84
  75. package/src/sources/Fuel.res +40 -1
  76. package/src/sources/Fuel.res.mjs +36 -26
  77. package/src/sources/HyperFuel.res +41 -120
  78. package/src/sources/HyperFuel.res.mjs +42 -80
  79. package/src/sources/HyperFuel.resi +1 -24
  80. package/src/sources/HyperFuelClient.res +16 -297
  81. package/src/sources/HyperFuelClient.res.mjs +5 -4
  82. package/src/sources/HyperFuelSource.res +33 -8
  83. package/src/sources/HyperFuelSource.res.mjs +56 -10
  84. package/src/sources/HyperSyncSource.res +7 -5
  85. package/src/sources/HyperSyncSource.res.mjs +3 -3
  86. package/src/sources/RpcSource.res +2 -2
  87. package/src/sources/RpcSource.res.mjs +1 -1
  88. package/src/sources/SourceManager.res +8 -18
  89. package/src/sources/SourceManager.res.mjs +8 -5
  90. package/src/sources/SourceManager.resi +4 -1
  91. package/src/sources/Svm.res +18 -1
  92. package/src/sources/Svm.res.mjs +30 -22
  93. package/src/sources/SvmHyperSyncSource.res +1 -1
  94. package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
  95. package/src/tui/Tui.res +38 -36
  96. package/src/tui/Tui.res.mjs +51 -51
  97. package/src/ChainFetcher.res +0 -519
  98. package/src/ChainFetcher.res.mjs +0 -314
  99. package/src/ChainManager.res +0 -358
  100. package/src/ChainManager.res.mjs +0 -291
  101. package/src/Ctx.res +0 -6
  102. package/src/Ctx.res.mjs +0 -2
  103. package/src/GlobalState.res +0 -1056
  104. package/src/GlobalState.res.mjs +0 -1086
  105. package/src/GlobalStateManager.res +0 -57
  106. package/src/GlobalStateManager.res.mjs +0 -68
  107. package/src/GlobalStateManager.resi +0 -7
  108. package/src/Ports.res +0 -5
  109. package/src/Ports.res.mjs +0 -9
  110. package/src/adapters/MarkBatchProcessedAdapter.res +0 -5
  111. package/src/adapters/MarkBatchProcessedAdapter.res.mjs +0 -14
  112. package/src/sources/EnvioApiClient.res +0 -15
  113. package/src/sources/EnvioApiClient.res.mjs +0 -24
@@ -0,0 +1,461 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Env from "./Env.res.mjs";
4
+ import * as Svm from "./sources/Svm.res.mjs";
5
+ import * as Batch from "./Batch.res.mjs";
6
+ import * as Utils from "./Utils.res.mjs";
7
+ import * as Logging from "./Logging.res.mjs";
8
+ import * as ChainMap from "./ChainMap.res.mjs";
9
+ import * as EvmChain from "./sources/EvmChain.res.mjs";
10
+ import * as FetchState from "./FetchState.res.mjs";
11
+ import * as Prometheus from "./Prometheus.res.mjs";
12
+ import * as EventRouter from "./sources/EventRouter.res.mjs";
13
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
14
+ import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
15
+ import * as SourceManager from "./sources/SourceManager.res.mjs";
16
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
17
+ import * as ReorgDetection from "./ReorgDetection.res.mjs";
18
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
19
+ import * as HyperFuelSource from "./sources/HyperFuelSource.res.mjs";
20
+ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
21
+ import * as SvmHyperSyncSource from "./sources/SvmHyperSyncSource.res.mjs";
22
+ import * as SafeCheckpointTracking from "./SafeCheckpointTracking.res.mjs";
23
+
24
+ function configAddresses(chainConfig) {
25
+ let addresses = [];
26
+ chainConfig.contracts.forEach(contract => {
27
+ contract.addresses.forEach(address => {
28
+ addresses.push({
29
+ address: address,
30
+ contractName: contract.name,
31
+ registrationBlock: -1
32
+ });
33
+ });
34
+ });
35
+ return addresses;
36
+ }
37
+
38
+ function make(chainConfig, fetchState, sourceManager, reorgDetection, committedProgressBlockNumber, safeCheckpointTrackingOpt, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt, logger) {
39
+ let safeCheckpointTracking = safeCheckpointTrackingOpt !== undefined ? Primitive_option.valFromOption(safeCheckpointTrackingOpt) : undefined;
40
+ let numEventsProcessed = numEventsProcessedOpt !== undefined ? numEventsProcessedOpt : 0;
41
+ let timestampCaughtUpToHeadOrEndblock = timestampCaughtUpToHeadOrEndblockOpt !== undefined ? Primitive_option.valFromOption(timestampCaughtUpToHeadOrEndblockOpt) : undefined;
42
+ let isProgressAtHead = isProgressAtHeadOpt !== undefined ? isProgressAtHeadOpt : false;
43
+ return {
44
+ logger: logger,
45
+ fetchState: fetchState,
46
+ sourceManager: sourceManager,
47
+ chainConfig: chainConfig,
48
+ isProgressAtHead: isProgressAtHead,
49
+ timestampCaughtUpToHeadOrEndblock: timestampCaughtUpToHeadOrEndblock,
50
+ committedProgressBlockNumber: committedProgressBlockNumber,
51
+ numEventsProcessed: numEventsProcessed,
52
+ reorgDetection: reorgDetection,
53
+ safeCheckpointTracking: safeCheckpointTracking
54
+ };
55
+ }
56
+
57
+ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firstEventBlockOpt, progressBlockNumber, config, registrations, logger, timestampCaughtUpToHeadOrEndblock, numEventsProcessed, isInReorgThreshold, isRealtime, reorgCheckpoints, maxReorgDepth, knownHeightOpt, reducedPollingInterval) {
58
+ let firstEventBlock = firstEventBlockOpt !== undefined ? Primitive_option.valFromOption(firstEventBlockOpt) : undefined;
59
+ let knownHeight = knownHeightOpt !== undefined ? knownHeightOpt : 0;
60
+ let eventRouter = EventRouter.empty();
61
+ let eventConfigs = [];
62
+ let notRegisteredEvents = [];
63
+ chainConfig.contracts.forEach(contract => {
64
+ let contractName = contract.name;
65
+ contract.events.forEach(eventConfig => {
66
+ let hasContractRegister = Stdlib_Option.isSome(eventConfig.contractRegister);
67
+ EventRouter.addOrThrow(eventRouter, eventConfig.id, undefined, contractName, eventConfig.isWildcard, eventConfig.name, ChainMap.Chain.makeUnsafe(chainConfig.id));
68
+ let shouldBeIncluded;
69
+ if (config.enableRawEvents) {
70
+ shouldBeIncluded = true;
71
+ } else {
72
+ let isRegistered = hasContractRegister || Stdlib_Option.isSome(eventConfig.handler);
73
+ if (!isRegistered) {
74
+ notRegisteredEvents.push(eventConfig);
75
+ }
76
+ shouldBeIncluded = isRegistered;
77
+ }
78
+ let shouldSkip;
79
+ try {
80
+ let getEventFiltersOrThrow = eventConfig.getEventFiltersOrThrow;
81
+ if (getEventFiltersOrThrow) {
82
+ let match = getEventFiltersOrThrow(ChainMap.Chain.makeUnsafe(chainConfig.id));
83
+ shouldSkip = match.TAG === "Static" ? match._0.length === 0 : false;
84
+ } else {
85
+ shouldSkip = false;
86
+ }
87
+ } catch (exn) {
88
+ shouldSkip = false;
89
+ }
90
+ if (shouldBeIncluded && !shouldSkip) {
91
+ eventConfigs.push(eventConfig);
92
+ return;
93
+ }
94
+ });
95
+ let startBlock = contract.startBlock;
96
+ if (startBlock !== undefined && startBlock < chainConfig.startBlock) {
97
+ return Stdlib_JsError.throwWithMessage(`The start block for contract "` + contractName + `" is less than the chain start block. This is not supported yet.`);
98
+ }
99
+ });
100
+ if (Utils.$$Array.notEmpty(notRegisteredEvents)) {
101
+ Logging.childInfo(logger, `The event` + (
102
+ notRegisteredEvents.length > 1 ? "s" : ""
103
+ ) + ` ` + notRegisteredEvents.map(eventConfig => eventConfig.contractName + `.` + eventConfig.name).join(", ") + ` don't have an event handler and skipped for indexing.`);
104
+ }
105
+ let onBlockConfigs = registrations.onBlockByChainId[chainConfig.id.toString()];
106
+ if (onBlockConfigs !== undefined) {
107
+ onBlockConfigs.forEach(onBlockConfig => {
108
+ if (Stdlib_Option.getOr(onBlockConfig.startBlock, startBlock) < startBlock) {
109
+ 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.`);
110
+ }
111
+ if (endBlock !== undefined && Stdlib_Option.getOr(onBlockConfig.endBlock, endBlock) > endBlock) {
112
+ 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.`);
113
+ }
114
+ });
115
+ }
116
+ let fetchState = FetchState.make(startBlock, endBlock, eventConfigs, indexingAddresses, config.maxAddrInPartition, chainConfig.id, (config.batchSize << 1), knownHeight, progressBlockNumber, onBlockConfigs, Primitive_int.max(!config.shouldRollbackOnReorg || isInReorgThreshold ? 0 : chainConfig.maxReorgDepth, chainConfig.blockLag), Primitive_option.some(firstEventBlock));
117
+ let chainReorgCheckpoints = Stdlib_Array.filterMap(reorgCheckpoints, reorgCheckpoint => {
118
+ if (reorgCheckpoint.chain_id === chainConfig.id) {
119
+ return reorgCheckpoint;
120
+ }
121
+ });
122
+ let chain = ChainMap.Chain.makeUnsafe(chainConfig.id);
123
+ let lowercaseAddresses = config.lowercaseAddresses;
124
+ let sources = chainConfig.sourceConfig;
125
+ let sources$1;
126
+ switch (sources.TAG) {
127
+ case "EvmSourceConfig" :
128
+ let evmContracts = chainConfig.contracts.map(contract => ({
129
+ name: contract.name,
130
+ abi: contract.abi,
131
+ events: contract.events
132
+ }));
133
+ let evmRpcs = sources.rpcs.map(rpc => {
134
+ let syncConfig = rpc.syncConfig;
135
+ let ws = rpc.ws;
136
+ return {
137
+ url: rpc.url,
138
+ sourceFor: rpc.sourceFor,
139
+ syncConfig: syncConfig,
140
+ ws: ws
141
+ };
142
+ });
143
+ sources$1 = EvmChain.makeSources(chain, evmContracts, sources.hypersync, evmRpcs, lowercaseAddresses);
144
+ break;
145
+ case "FuelSourceConfig" :
146
+ sources$1 = [HyperFuelSource.make({
147
+ chain: chain,
148
+ endpointUrl: sources.hypersync,
149
+ apiToken: Env.envioApiToken
150
+ })];
151
+ break;
152
+ case "SvmSourceConfig" :
153
+ let rpc = sources.rpc;
154
+ let hypersync = sources.hypersync;
155
+ if (hypersync !== undefined) {
156
+ let svmEventConfigs = chainConfig.contracts.flatMap(contract => contract.events);
157
+ sources$1 = [SvmHyperSyncSource.make({
158
+ chain: chain,
159
+ endpointUrl: hypersync,
160
+ apiToken: Env.envioApiToken,
161
+ eventConfigs: svmEventConfigs,
162
+ clientTimeoutMillis: Env.hyperSyncClientTimeoutMillis
163
+ })];
164
+ } else {
165
+ sources$1 = rpc !== undefined ? [Svm.makeRPCSource(chain, rpc, undefined)] : Stdlib_JsError.throwWithMessage(`Chain ` + chain.toString() + ` has no SVM data source`);
166
+ }
167
+ break;
168
+ case "CustomSources" :
169
+ sources$1 = sources._0;
170
+ break;
171
+ }
172
+ return make(chainConfig, fetchState, 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, logger);
173
+ }
174
+
175
+ function makeFromConfig(chainConfig, config, registrations, knownHeight) {
176
+ let logger = Logging.createChild({
177
+ chainId: chainConfig.id
178
+ });
179
+ return makeInternal(chainConfig, configAddresses(chainConfig), chainConfig.startBlock, chainConfig.endBlock, undefined, -1, config, registrations, logger, undefined, 0, false, false, [], chainConfig.maxReorgDepth, knownHeight, undefined);
180
+ }
181
+
182
+ function makeFromDbState(chainConfig, resumedChainState, reorgCheckpoints, isInReorgThreshold, isRealtime, config, registrations, reducedPollingInterval) {
183
+ let chainId = chainConfig.id;
184
+ let logger = Logging.createChild({
185
+ chainId: chainId
186
+ });
187
+ Prometheus.ProgressEventsCount.set(resumedChainState.numEventsProcessed, chainId);
188
+ let progressBlockNumber = resumedChainState.progressBlockNumber >= 0 ? resumedChainState.progressBlockNumber : resumedChainState.startBlock - 1 | 0;
189
+ return makeInternal(chainConfig, resumedChainState.indexingAddresses, resumedChainState.startBlock, resumedChainState.endBlock, Primitive_option.some(resumedChainState.firstEventBlockNumber), progressBlockNumber, config, registrations, logger, Env.updateSyncTimeOnRestart ? undefined : resumedChainState.timestampCaughtUpToHeadOrEndblock, resumedChainState.numEventsProcessed, isInReorgThreshold, isRealtime, reorgCheckpoints, resumedChainState.maxReorgDepth, resumedChainState.sourceBlockNumber, reducedPollingInterval);
190
+ }
191
+
192
+ function logger(cs) {
193
+ return cs.logger;
194
+ }
195
+
196
+ function fetchState(cs) {
197
+ return cs.fetchState;
198
+ }
199
+
200
+ function sourceManager(cs) {
201
+ return cs.sourceManager;
202
+ }
203
+
204
+ function chainConfig(cs) {
205
+ return cs.chainConfig;
206
+ }
207
+
208
+ function reorgDetection(cs) {
209
+ return cs.reorgDetection;
210
+ }
211
+
212
+ function safeCheckpointTracking(cs) {
213
+ return cs.safeCheckpointTracking;
214
+ }
215
+
216
+ function isProgressAtHead(cs) {
217
+ return cs.isProgressAtHead;
218
+ }
219
+
220
+ function committedProgressBlockNumber(cs) {
221
+ return cs.committedProgressBlockNumber;
222
+ }
223
+
224
+ function numEventsProcessed(cs) {
225
+ return cs.numEventsProcessed;
226
+ }
227
+
228
+ function timestampCaughtUpToHeadOrEndblock(cs) {
229
+ return cs.timestampCaughtUpToHeadOrEndblock;
230
+ }
231
+
232
+ function hasProcessedToEndblock(cs) {
233
+ let fetchState = cs.fetchState;
234
+ let committedProgressBlockNumber = cs.committedProgressBlockNumber;
235
+ let endBlock = fetchState.endBlock;
236
+ if (endBlock !== undefined) {
237
+ return committedProgressBlockNumber >= endBlock;
238
+ } else {
239
+ return false;
240
+ }
241
+ }
242
+
243
+ function getHighestBlockBelowThreshold(cs) {
244
+ let highestBlockBelowThreshold = cs.fetchState.knownHeight - cs.chainConfig.maxReorgDepth | 0;
245
+ if (highestBlockBelowThreshold < 0) {
246
+ return 0;
247
+ } else {
248
+ return highestBlockBelowThreshold;
249
+ }
250
+ }
251
+
252
+ function isActivelyIndexing(cs) {
253
+ return FetchState.isActivelyIndexing(cs.fetchState);
254
+ }
255
+
256
+ function isReady(cs) {
257
+ return cs.timestampCaughtUpToHeadOrEndblock !== undefined;
258
+ }
259
+
260
+ function isFetchingAtHead(cs) {
261
+ return FetchState.isFetchingAtHead(cs.fetchState);
262
+ }
263
+
264
+ function handleQueryResult(cs, query, newItems, newItemsWithDcs, latestFetchedBlock, knownHeight) {
265
+ let fs = newItemsWithDcs.length !== 0 ? FetchState.registerDynamicContracts(cs.fetchState, newItemsWithDcs) : cs.fetchState;
266
+ cs.fetchState = FetchState.updateKnownHeight(FetchState.handleQueryResult(fs, query, latestFetchedBlock, newItems), knownHeight);
267
+ }
268
+
269
+ function registerReorgGuard(cs, blockHashes, knownHeight) {
270
+ let match = ReorgDetection.registerReorgGuard(cs.reorgDetection, blockHashes, knownHeight);
271
+ cs.reorgDetection = match[0];
272
+ return match[1];
273
+ }
274
+
275
+ function prepareReorg(cs, eventsProcessedDiff) {
276
+ if (eventsProcessedDiff !== undefined) {
277
+ cs.numEventsProcessed = cs.numEventsProcessed + eventsProcessedDiff;
278
+ }
279
+ cs.fetchState = FetchState.resetPendingQueries(cs.fetchState);
280
+ }
281
+
282
+ function updateKnownHeight(cs, knownHeight) {
283
+ cs.fetchState = FetchState.updateKnownHeight(cs.fetchState, knownHeight);
284
+ }
285
+
286
+ function setEndBlockToFirstEvent(cs, blockNumber) {
287
+ let currentEndBlock = cs.fetchState.endBlock;
288
+ if (currentEndBlock !== undefined) {
289
+ if (blockNumber >= currentEndBlock) {
290
+ return;
291
+ }
292
+ let init = cs.fetchState;
293
+ cs.fetchState = {
294
+ optimizedPartitions: init.optimizedPartitions,
295
+ startBlock: init.startBlock,
296
+ endBlock: blockNumber,
297
+ normalSelection: init.normalSelection,
298
+ indexingAddresses: init.indexingAddresses,
299
+ contractConfigs: init.contractConfigs,
300
+ chainId: init.chainId,
301
+ latestOnBlockBlockNumber: init.latestOnBlockBlockNumber,
302
+ blockLag: init.blockLag,
303
+ buffer: init.buffer,
304
+ maxOnBlockBufferSize: init.maxOnBlockBufferSize,
305
+ onBlockConfigs: init.onBlockConfigs,
306
+ knownHeight: init.knownHeight,
307
+ firstEventBlock: init.firstEventBlock
308
+ };
309
+ return;
310
+ }
311
+ let init$1 = cs.fetchState;
312
+ cs.fetchState = {
313
+ optimizedPartitions: init$1.optimizedPartitions,
314
+ startBlock: init$1.startBlock,
315
+ endBlock: blockNumber,
316
+ normalSelection: init$1.normalSelection,
317
+ indexingAddresses: init$1.indexingAddresses,
318
+ contractConfigs: init$1.contractConfigs,
319
+ chainId: init$1.chainId,
320
+ latestOnBlockBlockNumber: init$1.latestOnBlockBlockNumber,
321
+ blockLag: init$1.blockLag,
322
+ buffer: init$1.buffer,
323
+ maxOnBlockBufferSize: init$1.maxOnBlockBufferSize,
324
+ onBlockConfigs: init$1.onBlockConfigs,
325
+ knownHeight: init$1.knownHeight,
326
+ firstEventBlock: init$1.firstEventBlock
327
+ };
328
+ }
329
+
330
+ function enterReorgThreshold(cs) {
331
+ cs.fetchState = FetchState.updateInternal(cs.fetchState, undefined, undefined, undefined, cs.chainConfig.blockLag, undefined);
332
+ }
333
+
334
+ function advanceAfterBatch(cs, batch, enteringReorgThreshold) {
335
+ let chainAfterBatch = batch.progressedChainsById[cs.fetchState.chainId];
336
+ if (chainAfterBatch !== undefined) {
337
+ cs.fetchState = enteringReorgThreshold ? FetchState.updateInternal(chainAfterBatch.fetchState, undefined, undefined, undefined, cs.chainConfig.blockLag, undefined) : chainAfterBatch.fetchState;
338
+ return;
339
+ }
340
+ }
341
+
342
+ function applyBatchProgress(cs, batch) {
343
+ let chainId = cs.chainConfig.id;
344
+ let chainAfterBatch = batch.progressedChainsById[chainId];
345
+ if (chainAfterBatch === undefined) {
346
+ return;
347
+ }
348
+ if (cs.committedProgressBlockNumber !== chainAfterBatch.progressBlockNumber) {
349
+ Prometheus.ProgressBlockNumber.set(chainAfterBatch.progressBlockNumber, chainId);
350
+ }
351
+ if (cs.numEventsProcessed !== chainAfterBatch.totalEventsProcessed) {
352
+ Prometheus.ProgressEventsCount.set(chainAfterBatch.totalEventsProcessed, chainId);
353
+ }
354
+ let eventItem = Batch.findLastEventItem(batch, chainId);
355
+ if (eventItem !== undefined) {
356
+ let blockTimestampMs = eventItem.timestamp * 1000 | 0;
357
+ Prometheus.ProgressLatency.set((Date.now() | 0) - blockTimestampMs | 0, chainId);
358
+ }
359
+ let match = cs.fetchState.firstEventBlock;
360
+ if (match === undefined) {
361
+ let firstEventBlock = Batch.findFirstEventBlockNumber(batch, chainId);
362
+ if (firstEventBlock !== undefined) {
363
+ let init = cs.fetchState;
364
+ cs.fetchState = {
365
+ optimizedPartitions: init.optimizedPartitions,
366
+ startBlock: init.startBlock,
367
+ endBlock: init.endBlock,
368
+ normalSelection: init.normalSelection,
369
+ indexingAddresses: init.indexingAddresses,
370
+ contractConfigs: init.contractConfigs,
371
+ chainId: init.chainId,
372
+ latestOnBlockBlockNumber: init.latestOnBlockBlockNumber,
373
+ blockLag: init.blockLag,
374
+ buffer: init.buffer,
375
+ maxOnBlockBufferSize: init.maxOnBlockBufferSize,
376
+ onBlockConfigs: init.onBlockConfigs,
377
+ knownHeight: init.knownHeight,
378
+ firstEventBlock: firstEventBlock
379
+ };
380
+ }
381
+ }
382
+ cs.committedProgressBlockNumber = chainAfterBatch.progressBlockNumber;
383
+ cs.numEventsProcessed = chainAfterBatch.totalEventsProcessed;
384
+ cs.isProgressAtHead = cs.isProgressAtHead || chainAfterBatch.isProgressAtHeadWhenBatchCreated;
385
+ let safeCheckpointTracking = cs.safeCheckpointTracking;
386
+ if (safeCheckpointTracking !== undefined) {
387
+ cs.safeCheckpointTracking = SafeCheckpointTracking.updateOnNewBatch(safeCheckpointTracking, cs.fetchState.knownHeight, chainId, batch.checkpointIds, batch.checkpointBlockNumbers, batch.checkpointChainIds);
388
+ return;
389
+ }
390
+ }
391
+
392
+ function markReady(cs) {
393
+ if (cs.timestampCaughtUpToHeadOrEndblock === undefined) {
394
+ cs.timestampCaughtUpToHeadOrEndblock = new Date();
395
+ return Prometheus.ProgressReady.set(cs.chainConfig.id);
396
+ }
397
+ }
398
+
399
+ function rollback(cs, newProgressBlockNumber, eventsProcessedDiff, rollbackTargetBlockNumber, isReorgChain) {
400
+ let chainId = cs.chainConfig.id;
401
+ if (newProgressBlockNumber === undefined) {
402
+ if (isReorgChain) {
403
+ cs.reorgDetection = ReorgDetection.rollbackToValidBlockNumber(cs.reorgDetection, rollbackTargetBlockNumber);
404
+ cs.fetchState = FetchState.rollback(cs.fetchState, rollbackTargetBlockNumber);
405
+ cs.committedProgressBlockNumber = Primitive_int.min(cs.committedProgressBlockNumber, rollbackTargetBlockNumber);
406
+ return;
407
+ } else {
408
+ return;
409
+ }
410
+ }
411
+ let newTotalEventsProcessed = cs.numEventsProcessed - Stdlib_Option.getOrThrow(eventsProcessedDiff, "Missing events-processed diff for rolled-back chain");
412
+ if (cs.committedProgressBlockNumber !== newProgressBlockNumber) {
413
+ Prometheus.ProgressBlockNumber.set(newProgressBlockNumber, chainId);
414
+ }
415
+ if (cs.numEventsProcessed !== newTotalEventsProcessed) {
416
+ Prometheus.ProgressEventsCount.set(newTotalEventsProcessed, chainId);
417
+ }
418
+ if (isReorgChain) {
419
+ cs.reorgDetection = ReorgDetection.rollbackToValidBlockNumber(cs.reorgDetection, rollbackTargetBlockNumber);
420
+ }
421
+ let safeCheckpointTracking = cs.safeCheckpointTracking;
422
+ if (safeCheckpointTracking !== undefined) {
423
+ cs.safeCheckpointTracking = SafeCheckpointTracking.rollback(safeCheckpointTracking, newProgressBlockNumber);
424
+ }
425
+ cs.fetchState = FetchState.rollback(cs.fetchState, newProgressBlockNumber);
426
+ cs.committedProgressBlockNumber = newProgressBlockNumber;
427
+ cs.numEventsProcessed = newTotalEventsProcessed;
428
+ }
429
+
430
+ export {
431
+ configAddresses,
432
+ make,
433
+ makeFromConfig,
434
+ makeFromDbState,
435
+ logger,
436
+ fetchState,
437
+ sourceManager,
438
+ chainConfig,
439
+ reorgDetection,
440
+ safeCheckpointTracking,
441
+ isProgressAtHead,
442
+ committedProgressBlockNumber,
443
+ numEventsProcessed,
444
+ timestampCaughtUpToHeadOrEndblock,
445
+ hasProcessedToEndblock,
446
+ getHighestBlockBelowThreshold,
447
+ isActivelyIndexing,
448
+ isReady,
449
+ isFetchingAtHead,
450
+ handleQueryResult,
451
+ registerReorgGuard,
452
+ prepareReorg,
453
+ updateKnownHeight,
454
+ setEndBlockToFirstEvent,
455
+ enterReorgThreshold,
456
+ advanceAfterBatch,
457
+ applyBatchProgress,
458
+ markReady,
459
+ rollback,
460
+ }
461
+ /* Env Not a pure module */
@@ -0,0 +1,85 @@
1
+ // Per-chain runtime state. `t` is opaque: other modules read it through the
2
+ // accessors and change it only through the mutators exposed here.
3
+
4
+ type t
5
+
6
+ let configAddresses: Config.chain => array<Internal.indexingAddress>
7
+
8
+ let make: (
9
+ ~chainConfig: Config.chain,
10
+ ~fetchState: FetchState.t,
11
+ ~sourceManager: SourceManager.t,
12
+ ~reorgDetection: ReorgDetection.t,
13
+ ~committedProgressBlockNumber: int,
14
+ ~safeCheckpointTracking: option<SafeCheckpointTracking.t>=?,
15
+ ~numEventsProcessed: float=?,
16
+ ~timestampCaughtUpToHeadOrEndblock: option<Date.t>=?,
17
+ ~isProgressAtHead: bool=?,
18
+ ~logger: Pino.t,
19
+ ) => t
20
+
21
+ let makeFromConfig: (
22
+ Config.chain,
23
+ ~config: Config.t,
24
+ ~registrations: HandlerRegister.registrations,
25
+ ~knownHeight: int,
26
+ ) => t
27
+
28
+ let makeFromDbState: (
29
+ Config.chain,
30
+ ~resumedChainState: Persistence.initialChainState,
31
+ ~reorgCheckpoints: array<Internal.reorgCheckpoint>,
32
+ ~isInReorgThreshold: bool,
33
+ ~isRealtime: bool,
34
+ ~config: Config.t,
35
+ ~registrations: HandlerRegister.registrations,
36
+ ~reducedPollingInterval: int=?,
37
+ ) => t
38
+
39
+ // Accessors.
40
+ let logger: t => Pino.t
41
+ let fetchState: t => FetchState.t
42
+ let sourceManager: t => SourceManager.t
43
+ let chainConfig: t => Config.chain
44
+ let reorgDetection: t => ReorgDetection.t
45
+ let safeCheckpointTracking: t => option<SafeCheckpointTracking.t>
46
+ let isProgressAtHead: t => bool
47
+ let committedProgressBlockNumber: t => int
48
+ let numEventsProcessed: t => float
49
+ let timestampCaughtUpToHeadOrEndblock: t => option<Date.t>
50
+
51
+ // Derived (pure).
52
+ let hasProcessedToEndblock: t => bool
53
+ let getHighestBlockBelowThreshold: t => int
54
+ let isActivelyIndexing: t => bool
55
+ let isReady: t => bool
56
+ let isFetchingAtHead: t => bool
57
+
58
+ // State transitions. The chain state is mutated only through these.
59
+ let handleQueryResult: (
60
+ t,
61
+ ~query: FetchState.query,
62
+ ~newItems: array<Internal.item>,
63
+ ~newItemsWithDcs: array<Internal.item>,
64
+ ~latestFetchedBlock: FetchState.blockNumberAndTimestamp,
65
+ ~knownHeight: int,
66
+ ) => unit
67
+ let registerReorgGuard: (
68
+ t,
69
+ ~blockHashes: array<ReorgDetection.blockData>,
70
+ ~knownHeight: int,
71
+ ) => ReorgDetection.reorgResult
72
+ let prepareReorg: (t, ~eventsProcessedDiff: option<float>) => unit
73
+ let updateKnownHeight: (t, ~knownHeight: int) => unit
74
+ let setEndBlockToFirstEvent: (t, ~blockNumber: int) => unit
75
+ let enterReorgThreshold: t => unit
76
+ let advanceAfterBatch: (t, ~batch: Batch.t, ~enteringReorgThreshold: bool) => unit
77
+ let applyBatchProgress: (t, ~batch: Batch.t) => unit
78
+ let markReady: t => unit
79
+ let rollback: (
80
+ t,
81
+ ~newProgressBlockNumber: option<int>,
82
+ ~eventsProcessedDiff: option<float>,
83
+ ~rollbackTargetBlockNumber: int,
84
+ ~isReorgChain: bool,
85
+ ) => unit
package/src/Config.res CHANGED
@@ -17,7 +17,7 @@ type contract = {
17
17
  startBlock: option<int>,
18
18
  }
19
19
 
20
- // Sources are instantiated lazily in ChainFetcher from this config.
20
+ // Sources are instantiated lazily in ChainState from this config.
21
21
  type evmRpcConfig = {
22
22
  url: string,
23
23
  sourceFor: Source.sourceFor,
@@ -546,10 +546,19 @@ let fromPublic = (publicConfigJson: JSON.t) => {
546
546
  )
547
547
  }
548
548
 
549
+ let logger = Logging.getLogger()
549
550
  let ecosystem = switch ecosystemName {
550
- | Ecosystem.Evm => Evm.ecosystem
551
- | Ecosystem.Fuel => Fuel.ecosystem
552
- | Ecosystem.Svm => Svm.ecosystem
551
+ | Ecosystem.Evm => Evm.make(~logger)
552
+ | Ecosystem.Fuel => Fuel.make(~logger)
553
+ | Ecosystem.Svm => Svm.make(~logger)
554
+ }
555
+
556
+ // SVM has no raw-events representation (`Svm.toRawEvent` throws), so reject
557
+ // it at config time instead of failing mid-indexing.
558
+ if ecosystemName === Ecosystem.Svm && publicConfig["rawEvents"]->Option.getOr(false) {
559
+ JsError.throwWithMessage(
560
+ "Invalid indexer config: rawEvents is not supported for the SVM ecosystem",
561
+ )
553
562
  }
554
563
 
555
564
  // Extract EVM-specific options with defaults
@@ -8,6 +8,7 @@ import * as Fuel from "./sources/Fuel.res.mjs";
8
8
  import * as Table from "./db/Table.res.mjs";
9
9
  import * as Utils from "./Utils.res.mjs";
10
10
  import * as Address from "./Address.res.mjs";
11
+ import * as Logging from "./Logging.res.mjs";
11
12
  import * as ChainMap from "./ChainMap.res.mjs";
12
13
  import * as Internal from "./Internal.res.mjs";
13
14
  import * as BigDecimal from "./bindings/BigDecimal.res.mjs";
@@ -424,18 +425,22 @@ function fromPublic(publicConfigJson) {
424
425
  );
425
426
  let ecosystemName = match$3[1];
426
427
  let publicChainsConfig = match$3[0];
428
+ let logger = Logging.getLogger();
427
429
  let ecosystem;
428
430
  switch (ecosystemName) {
429
431
  case "evm" :
430
- ecosystem = Evm.ecosystem;
432
+ ecosystem = Evm.make(logger);
431
433
  break;
432
434
  case "fuel" :
433
- ecosystem = Fuel.ecosystem;
435
+ ecosystem = Fuel.make(logger);
434
436
  break;
435
437
  case "svm" :
436
- ecosystem = Svm.ecosystem;
438
+ ecosystem = Svm.make(logger);
437
439
  break;
438
440
  }
441
+ if (ecosystemName === "svm" && Stdlib_Option.getOr(publicConfig.rawEvents, false)) {
442
+ Stdlib_JsError.throwWithMessage("Invalid indexer config: rawEvents is not supported for the SVM ecosystem");
443
+ }
439
444
  let evm = publicConfig.evm;
440
445
  let lowercaseAddresses = evm !== undefined ? Stdlib_Option.getOr(Primitive_option.valFromOption(evm).addressFormat, "checksum") === "lowercase" : false;
441
446
  let match$4 = publicConfig.evm;