envio 3.0.0-alpha.0 → 3.0.0-alpha.10

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 (136) hide show
  1. package/README.md +2 -2
  2. package/evm.schema.json +53 -57
  3. package/fuel.schema.json +35 -31
  4. package/index.d.ts +446 -1
  5. package/index.js +4 -0
  6. package/package.json +23 -11
  7. package/rescript.json +4 -1
  8. package/src/Batch.res.mjs +1 -1
  9. package/src/Benchmark.res +394 -0
  10. package/src/Benchmark.res.mjs +398 -0
  11. package/src/ChainFetcher.res +526 -0
  12. package/src/ChainFetcher.res.mjs +343 -0
  13. package/src/ChainManager.res +182 -0
  14. package/src/ChainManager.res.mjs +150 -0
  15. package/src/Config.res +367 -27
  16. package/src/Config.res.mjs +338 -28
  17. package/src/{Indexer.res → Ctx.res} +1 -1
  18. package/src/Ecosystem.res +25 -0
  19. package/src/Ecosystem.res.mjs +29 -0
  20. package/src/Env.res +252 -0
  21. package/src/Env.res.mjs +271 -0
  22. package/src/Envio.gen.ts +9 -1
  23. package/src/Envio.res +12 -9
  24. package/src/EventProcessing.res +476 -0
  25. package/src/EventProcessing.res.mjs +341 -0
  26. package/src/EventRegister.res +4 -15
  27. package/src/EventRegister.res.mjs +3 -9
  28. package/src/EventRegister.resi +2 -8
  29. package/src/FetchState.res +54 -29
  30. package/src/FetchState.res.mjs +62 -35
  31. package/src/GlobalState.res +1163 -0
  32. package/src/GlobalState.res.mjs +1196 -0
  33. package/src/GlobalStateManager.res +68 -0
  34. package/src/GlobalStateManager.res.mjs +75 -0
  35. package/src/GlobalStateManager.resi +7 -0
  36. package/src/HandlerLoader.res +89 -0
  37. package/src/HandlerLoader.res.mjs +79 -0
  38. package/src/Internal.gen.ts +3 -14
  39. package/src/Internal.res +45 -13
  40. package/src/LoadLayer.res +444 -0
  41. package/src/LoadLayer.res.mjs +296 -0
  42. package/src/LoadLayer.resi +32 -0
  43. package/src/LogSelection.res +33 -27
  44. package/src/LogSelection.res.mjs +6 -0
  45. package/src/Logging.res +11 -4
  46. package/src/Logging.res.mjs +14 -6
  47. package/src/Main.res +351 -0
  48. package/src/Main.res.mjs +312 -0
  49. package/src/Persistence.res +1 -2
  50. package/src/PgStorage.gen.ts +10 -0
  51. package/src/PgStorage.res +28 -34
  52. package/src/PgStorage.res.d.mts +5 -0
  53. package/src/PgStorage.res.mjs +27 -27
  54. package/src/Prometheus.res +8 -8
  55. package/src/Prometheus.res.mjs +10 -10
  56. package/src/ReorgDetection.res +6 -10
  57. package/src/ReorgDetection.res.mjs +6 -6
  58. package/src/TestIndexer.res +536 -0
  59. package/src/TestIndexer.res.mjs +412 -0
  60. package/src/TestIndexerProxyStorage.res +210 -0
  61. package/src/TestIndexerProxyStorage.res.mjs +157 -0
  62. package/src/Types.ts +1 -1
  63. package/src/UserContext.res +355 -0
  64. package/src/UserContext.res.mjs +236 -0
  65. package/src/Utils.res +28 -0
  66. package/src/Utils.res.mjs +18 -0
  67. package/src/bindings/ClickHouse.res +31 -1
  68. package/src/bindings/ClickHouse.res.mjs +27 -1
  69. package/src/bindings/DateFns.res +71 -0
  70. package/src/bindings/DateFns.res.mjs +22 -0
  71. package/src/bindings/Ethers.res +27 -67
  72. package/src/bindings/Ethers.res.mjs +18 -70
  73. package/src/bindings/EventSource.res +13 -0
  74. package/src/bindings/EventSource.res.mjs +2 -0
  75. package/src/bindings/NodeJs.res +44 -3
  76. package/src/bindings/NodeJs.res.mjs +11 -3
  77. package/src/bindings/Pino.res +21 -7
  78. package/src/bindings/Pino.res.mjs +11 -5
  79. package/src/bindings/Postgres.gen.ts +8 -0
  80. package/src/bindings/Postgres.res +3 -0
  81. package/src/bindings/Postgres.res.d.mts +5 -0
  82. package/src/bindings/RescriptMocha.res +123 -0
  83. package/src/bindings/RescriptMocha.res.mjs +18 -0
  84. package/src/bindings/Vitest.res +134 -0
  85. package/src/bindings/Vitest.res.mjs +9 -0
  86. package/src/bindings/Yargs.res +8 -0
  87. package/src/bindings/Yargs.res.mjs +2 -0
  88. package/src/db/InternalTable.res +2 -0
  89. package/src/db/InternalTable.res.mjs +1 -1
  90. package/src/sources/Evm.res +87 -0
  91. package/src/sources/Evm.res.mjs +105 -0
  92. package/src/sources/EvmChain.res +90 -0
  93. package/src/sources/EvmChain.res.mjs +57 -0
  94. package/src/sources/Fuel.res +19 -34
  95. package/src/sources/Fuel.res.mjs +34 -16
  96. package/src/sources/FuelSDK.res +38 -0
  97. package/src/sources/FuelSDK.res.mjs +29 -0
  98. package/src/sources/HyperFuel.res +2 -2
  99. package/src/sources/HyperFuel.resi +1 -1
  100. package/src/sources/HyperFuelClient.res +2 -2
  101. package/src/sources/HyperFuelSource.res +8 -8
  102. package/src/sources/HyperFuelSource.res.mjs +5 -5
  103. package/src/sources/HyperSyncHeightStream.res +97 -0
  104. package/src/sources/HyperSyncHeightStream.res.mjs +94 -0
  105. package/src/sources/HyperSyncSource.res +64 -172
  106. package/src/sources/HyperSyncSource.res.mjs +73 -155
  107. package/src/sources/Rpc.res +43 -0
  108. package/src/sources/Rpc.res.mjs +31 -0
  109. package/src/sources/RpcSource.res +32 -130
  110. package/src/sources/RpcSource.res.mjs +47 -121
  111. package/src/sources/Source.res +3 -2
  112. package/src/sources/SourceManager.res +183 -108
  113. package/src/sources/SourceManager.res.mjs +162 -99
  114. package/src/sources/SourceManager.resi +4 -5
  115. package/src/sources/Svm.res +59 -0
  116. package/src/sources/Svm.res.mjs +79 -0
  117. package/src/tui/Tui.res +266 -0
  118. package/src/tui/Tui.res.mjs +342 -0
  119. package/src/tui/bindings/Ink.res +376 -0
  120. package/src/tui/bindings/Ink.res.mjs +75 -0
  121. package/src/tui/bindings/Style.res +123 -0
  122. package/src/tui/bindings/Style.res.mjs +2 -0
  123. package/src/tui/components/BufferedProgressBar.res +40 -0
  124. package/src/tui/components/BufferedProgressBar.res.mjs +57 -0
  125. package/src/tui/components/CustomHooks.res +122 -0
  126. package/src/tui/components/CustomHooks.res.mjs +179 -0
  127. package/src/tui/components/Messages.res +41 -0
  128. package/src/tui/components/Messages.res.mjs +75 -0
  129. package/src/tui/components/SyncETA.res +193 -0
  130. package/src/tui/components/SyncETA.res.mjs +269 -0
  131. package/src/tui/components/TuiData.res +46 -0
  132. package/src/tui/components/TuiData.res.mjs +29 -0
  133. package/src/Platform.res +0 -140
  134. package/src/Platform.res.mjs +0 -170
  135. package/src/bindings/Ethers.gen.ts +0 -14
  136. /package/src/{Indexer.res.mjs → Ctx.res.mjs} +0 -0
@@ -0,0 +1,343 @@
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 Caml from "rescript/lib/es6/caml.js";
6
+ import * as Utils from "./Utils.res.mjs";
7
+ import * as Js_exn from "rescript/lib/es6/js_exn.js";
8
+ import * as Logging from "./Logging.res.mjs";
9
+ import * as $$Promise from "./bindings/Promise.res.mjs";
10
+ import * as ChainMap from "./ChainMap.res.mjs";
11
+ import * as EvmChain from "./sources/EvmChain.res.mjs";
12
+ import * as Belt_Array from "rescript/lib/es6/belt_Array.js";
13
+ import * as FetchState from "./FetchState.res.mjs";
14
+ import * as Prometheus from "./Prometheus.res.mjs";
15
+ import * as Belt_Option from "rescript/lib/es6/belt_Option.js";
16
+ import * as Belt_Result from "rescript/lib/es6/belt_Result.js";
17
+ import * as Caml_option from "rescript/lib/es6/caml_option.js";
18
+ import * as EventRouter from "./sources/EventRouter.res.mjs";
19
+ import * as UserContext from "./UserContext.res.mjs";
20
+ import * as ErrorHandling from "./ErrorHandling.res.mjs";
21
+ import * as SourceManager from "./sources/SourceManager.res.mjs";
22
+ import * as ReorgDetection from "./ReorgDetection.res.mjs";
23
+ import * as HyperFuelSource from "./sources/HyperFuelSource.res.mjs";
24
+ import * as Caml_js_exceptions from "rescript/lib/es6/caml_js_exceptions.js";
25
+ import * as SafeCheckpointTracking from "./SafeCheckpointTracking.res.mjs";
26
+
27
+ function make(chainConfig, dynamicContracts, startBlock, endBlock, firstEventBlockNumber, progressBlockNumber, config, registrations, targetBufferSize, logger, timestampCaughtUpToHeadOrEndblock, numEventsProcessed, numBatchesFetched, isInReorgThreshold, reorgCheckpoints, maxReorgDepth, knownHeightOpt) {
28
+ var knownHeight = knownHeightOpt !== undefined ? knownHeightOpt : 0;
29
+ var eventRouter = EventRouter.empty();
30
+ var contracts = [];
31
+ var eventConfigs = [];
32
+ var notRegisteredEvents = [];
33
+ Belt_Array.forEach(chainConfig.contracts, (function (contract) {
34
+ var contractName = contract.name;
35
+ Belt_Array.forEach(contract.events, (function (eventConfig) {
36
+ var hasContractRegister = Belt_Option.isSome(eventConfig.contractRegister);
37
+ EventRouter.addOrThrow(eventRouter, eventConfig.id, undefined, contractName, eventConfig.isWildcard, eventConfig.name, ChainMap.Chain.makeUnsafe(chainConfig.id));
38
+ var shouldBeIncluded;
39
+ if (config.enableRawEvents) {
40
+ shouldBeIncluded = true;
41
+ } else {
42
+ var isRegistered = hasContractRegister || Belt_Option.isSome(eventConfig.handler);
43
+ if (!isRegistered) {
44
+ notRegisteredEvents.push(eventConfig);
45
+ }
46
+ shouldBeIncluded = isRegistered;
47
+ }
48
+ var shouldSkip;
49
+ try {
50
+ var getEventFiltersOrThrow = eventConfig.getEventFiltersOrThrow;
51
+ if (getEventFiltersOrThrow) {
52
+ var match = getEventFiltersOrThrow(ChainMap.Chain.makeUnsafe(chainConfig.id));
53
+ shouldSkip = match.TAG === "Static" ? match._0.length === 0 : false;
54
+ } else {
55
+ shouldSkip = false;
56
+ }
57
+ }
58
+ catch (exn){
59
+ shouldSkip = false;
60
+ }
61
+ if (shouldBeIncluded && !shouldSkip) {
62
+ eventConfigs.push(eventConfig);
63
+ return ;
64
+ }
65
+
66
+ }));
67
+ var startBlock = contract.startBlock;
68
+ if (startBlock !== undefined && startBlock < chainConfig.startBlock) {
69
+ Js_exn.raiseError("The start block for contract \"" + contractName + "\" is less than the chain start block. This is not supported yet.");
70
+ }
71
+ Belt_Array.forEach(contract.addresses, (function (address) {
72
+ var startBlock = contract.startBlock;
73
+ contracts.push({
74
+ address: address,
75
+ contractName: contract.name,
76
+ startBlock: startBlock !== undefined ? startBlock : chainConfig.startBlock,
77
+ registrationBlock: undefined
78
+ });
79
+ }));
80
+ }));
81
+ Belt_Array.forEach(dynamicContracts, (function (dc) {
82
+ contracts.push(dc);
83
+ }));
84
+ if (Utils.$$Array.notEmpty(notRegisteredEvents)) {
85
+ Logging.childInfo(logger, "The event" + (
86
+ notRegisteredEvents.length > 1 ? "s" : ""
87
+ ) + " " + Belt_Array.map(notRegisteredEvents, (function (eventConfig) {
88
+ return eventConfig.contractName + "." + eventConfig.name;
89
+ })).join(", ") + " don't have an event handler and skipped for indexing.");
90
+ }
91
+ var onBlockConfigs = registrations.onBlockByChainId[String(chainConfig.id)];
92
+ if (onBlockConfigs !== undefined) {
93
+ Belt_Array.forEach(onBlockConfigs, (function (onBlockConfig) {
94
+ if (Belt_Option.getWithDefault(onBlockConfig.startBlock, startBlock) < startBlock) {
95
+ Js_exn.raiseError("The start block for onBlock handler \"" + onBlockConfig.name + "\" is less than the chain start block (" + String(startBlock) + "). This is not supported yet.");
96
+ }
97
+ if (endBlock !== undefined && Belt_Option.getWithDefault(onBlockConfig.endBlock, endBlock) > endBlock) {
98
+ return Js_exn.raiseError("The end block for onBlock handler \"" + onBlockConfig.name + "\" is greater than the chain end block (" + String(endBlock) + "). This is not supported yet.");
99
+ }
100
+
101
+ }));
102
+ }
103
+ var fetchState = FetchState.make(startBlock, endBlock, eventConfigs, contracts, config.maxAddrInPartition, chainConfig.id, targetBufferSize, knownHeight, progressBlockNumber, onBlockConfigs, Caml.int_max(!config.shouldRollbackOnReorg || isInReorgThreshold ? 0 : chainConfig.maxReorgDepth, Belt_Option.getWithDefault(Env.indexingBlockLag, 0)));
104
+ var chainReorgCheckpoints = Belt_Array.keepMapU(reorgCheckpoints, (function (reorgCheckpoint) {
105
+ if (reorgCheckpoint.chain_id === chainConfig.id) {
106
+ return reorgCheckpoint;
107
+ }
108
+
109
+ }));
110
+ var chain = ChainMap.Chain.makeUnsafe(chainConfig.id);
111
+ var lowercaseAddresses = config.lowercaseAddresses;
112
+ var sources = chainConfig.sourceConfig;
113
+ var sources$1;
114
+ switch (sources.TAG) {
115
+ case "EvmSourceConfig" :
116
+ var evmContracts = Belt_Array.map(chainConfig.contracts, (function (contract) {
117
+ return {
118
+ name: contract.name,
119
+ abi: contract.abi,
120
+ events: contract.events
121
+ };
122
+ }));
123
+ var allEventSignatures = Belt_Array.flatMap(chainConfig.contracts, (function (contract) {
124
+ return contract.eventSignatures;
125
+ }));
126
+ var evmRpcs = Belt_Array.map(sources.rpcs, (function (rpc) {
127
+ var syncConfig = rpc.syncConfig;
128
+ return {
129
+ url: rpc.url,
130
+ sourceFor: rpc.sourceFor,
131
+ syncConfig: syncConfig
132
+ };
133
+ }));
134
+ sources$1 = EvmChain.makeSources(chain, evmContracts, sources.hypersync, allEventSignatures, evmRpcs, lowercaseAddresses);
135
+ break;
136
+ case "FuelSourceConfig" :
137
+ sources$1 = [HyperFuelSource.make({
138
+ chain: chain,
139
+ endpointUrl: sources.hypersync
140
+ })];
141
+ break;
142
+ case "SvmSourceConfig" :
143
+ sources$1 = [Svm.makeRPCSource(chain, sources.rpc)];
144
+ break;
145
+ case "CustomSources" :
146
+ sources$1 = sources._0;
147
+ break;
148
+
149
+ }
150
+ return {
151
+ logger: logger,
152
+ fetchState: fetchState,
153
+ sourceManager: SourceManager.make(sources$1, Env.maxPartitionConcurrency, undefined, undefined, undefined),
154
+ chainConfig: chainConfig,
155
+ isProgressAtHead: false,
156
+ timestampCaughtUpToHeadOrEndblock: timestampCaughtUpToHeadOrEndblock,
157
+ committedProgressBlockNumber: progressBlockNumber,
158
+ firstEventBlockNumber: firstEventBlockNumber,
159
+ numEventsProcessed: numEventsProcessed,
160
+ numBatchesFetched: numBatchesFetched,
161
+ reorgDetection: ReorgDetection.make(chainReorgCheckpoints, maxReorgDepth, config.shouldRollbackOnReorg),
162
+ safeCheckpointTracking: SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)
163
+ };
164
+ }
165
+
166
+ function makeFromConfig(chainConfig, config, registrations, targetBufferSize) {
167
+ var logger = Logging.createChild({
168
+ chainId: chainConfig.id
169
+ });
170
+ return make(chainConfig, [], chainConfig.startBlock, chainConfig.endBlock, undefined, -1, config, registrations, targetBufferSize, logger, undefined, 0, 0, false, [], chainConfig.maxReorgDepth, undefined);
171
+ }
172
+
173
+ async function makeFromDbState(chainConfig, resumedChainState, reorgCheckpoints, isInReorgThreshold, config, registrations, targetBufferSize) {
174
+ var chainId = chainConfig.id;
175
+ var logger = Logging.createChild({
176
+ chainId: chainId
177
+ });
178
+ Prometheus.ProgressEventsCount.set(resumedChainState.numEventsProcessed, chainId);
179
+ var progressBlockNumber = resumedChainState.progressBlockNumber >= 0 ? resumedChainState.progressBlockNumber : resumedChainState.startBlock - 1 | 0;
180
+ return make(chainConfig, resumedChainState.dynamicContracts, resumedChainState.startBlock, resumedChainState.endBlock, resumedChainState.firstEventBlockNumber, progressBlockNumber, config, registrations, targetBufferSize, logger, Env.updateSyncTimeOnRestart ? undefined : resumedChainState.timestampCaughtUpToHeadOrEndblock, resumedChainState.numEventsProcessed, 0, isInReorgThreshold, reorgCheckpoints, resumedChainState.maxReorgDepth, resumedChainState.sourceBlockNumber);
181
+ }
182
+
183
+ function getContractStartBlock(config, chain, contractName) {
184
+ var chainConfig = ChainMap.get(config.chainMap, chain);
185
+ return Belt_Option.flatMap(Caml_option.undefined_to_opt(chainConfig.contracts.find(function (contract) {
186
+ return contract.name === contractName;
187
+ })), (function (contract) {
188
+ return contract.startBlock;
189
+ }));
190
+ }
191
+
192
+ async function runContractRegistersOrThrow(itemsWithContractRegister, chain, config) {
193
+ var itemsWithDcs = [];
194
+ var onRegister = function (item, contractAddress, contractName) {
195
+ var blockNumber = item.blockNumber;
196
+ var configuredStartBlock = getContractStartBlock(config, chain, contractName);
197
+ var contractStartBlock = configuredStartBlock !== undefined ? configuredStartBlock : blockNumber;
198
+ var dc_registrationBlock = blockNumber;
199
+ var dc = {
200
+ address: contractAddress,
201
+ contractName: contractName,
202
+ startBlock: contractStartBlock,
203
+ registrationBlock: dc_registrationBlock
204
+ };
205
+ var dcs = item.dcs;
206
+ if (dcs !== undefined) {
207
+ dcs.push(dc);
208
+ } else {
209
+ item.dcs = [dc];
210
+ itemsWithDcs.push(item);
211
+ }
212
+ };
213
+ var promises = [];
214
+ for(var idx = 0 ,idx_finish = itemsWithContractRegister.length; idx < idx_finish; ++idx){
215
+ var item = itemsWithContractRegister[idx];
216
+ var match = item.eventConfig;
217
+ var contractRegister = match.contractRegister;
218
+ var contractRegister$1 = contractRegister !== undefined ? contractRegister : Js_exn.raiseError("Contract register is not set for event " + match.name);
219
+ var errorMessage = "Event contractRegister failed, please fix the error to keep the indexer running smoothly";
220
+ try {
221
+ var params = {
222
+ item: item,
223
+ onRegister: onRegister,
224
+ config: config,
225
+ isResolved: false
226
+ };
227
+ var result = contractRegister$1(UserContext.getContractRegisterArgs(params));
228
+ if ($$Promise.isCatchable(result)) {
229
+ promises.push($$Promise.$$catch(result.then((function(params){
230
+ return function (r) {
231
+ params.isResolved = true;
232
+
233
+ }
234
+ }(params))), (function(item,params){
235
+ return function (exn) {
236
+ params.isResolved = true;
237
+ return ErrorHandling.mkLogAndRaise(Logging.getItemLogger(item), errorMessage, exn);
238
+ }
239
+ }(item,params))));
240
+ } else {
241
+ params.isResolved = true;
242
+ }
243
+ }
244
+ catch (raw_exn){
245
+ var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
246
+ ErrorHandling.mkLogAndRaise(Logging.getItemLogger(item), errorMessage, exn);
247
+ }
248
+ }
249
+ if (Utils.$$Array.notEmpty(promises)) {
250
+ await Promise.all(promises);
251
+ }
252
+ return itemsWithDcs;
253
+ }
254
+
255
+ function handleQueryResult(chainFetcher, query, newItems, newItemsWithDcs, latestFetchedBlock, knownHeight) {
256
+ var fs = newItemsWithDcs.length !== 0 ? FetchState.registerDynamicContracts(chainFetcher.fetchState, newItemsWithDcs) : chainFetcher.fetchState;
257
+ return Belt_Result.map(FetchState.handleQueryResult(fs, query, latestFetchedBlock, newItems), (function (fs) {
258
+ return {
259
+ logger: chainFetcher.logger,
260
+ fetchState: FetchState.updateKnownHeight(fs, knownHeight),
261
+ sourceManager: chainFetcher.sourceManager,
262
+ chainConfig: chainFetcher.chainConfig,
263
+ isProgressAtHead: chainFetcher.isProgressAtHead,
264
+ timestampCaughtUpToHeadOrEndblock: chainFetcher.timestampCaughtUpToHeadOrEndblock,
265
+ committedProgressBlockNumber: chainFetcher.committedProgressBlockNumber,
266
+ firstEventBlockNumber: chainFetcher.firstEventBlockNumber,
267
+ numEventsProcessed: chainFetcher.numEventsProcessed,
268
+ numBatchesFetched: chainFetcher.numBatchesFetched,
269
+ reorgDetection: chainFetcher.reorgDetection,
270
+ safeCheckpointTracking: chainFetcher.safeCheckpointTracking
271
+ };
272
+ }));
273
+ }
274
+
275
+ function hasProcessedToEndblock(self) {
276
+ var endBlock = self.fetchState.endBlock;
277
+ if (endBlock !== undefined) {
278
+ return self.committedProgressBlockNumber >= endBlock;
279
+ } else {
280
+ return false;
281
+ }
282
+ }
283
+
284
+ function hasNoMoreEventsToProcess(self) {
285
+ return FetchState.bufferSize(self.fetchState) === 0;
286
+ }
287
+
288
+ function getHighestBlockBelowThreshold(cf) {
289
+ var highestBlockBelowThreshold = cf.fetchState.knownHeight - cf.chainConfig.maxReorgDepth | 0;
290
+ if (highestBlockBelowThreshold < 0) {
291
+ return 0;
292
+ } else {
293
+ return highestBlockBelowThreshold;
294
+ }
295
+ }
296
+
297
+ async function getLastKnownValidBlock(chainFetcher, reorgBlockNumber, getBlockHashesOpt) {
298
+ var getBlockHashes = getBlockHashesOpt !== undefined ? getBlockHashesOpt : SourceManager.getActiveSource(chainFetcher.sourceManager).getBlockHashes;
299
+ var scannedBlockNumbers = ReorgDetection.getThresholdBlockNumbersBelowBlock(chainFetcher.reorgDetection, reorgBlockNumber, chainFetcher.fetchState.knownHeight);
300
+ var getBlockHashes$1 = function (blockNumbers) {
301
+ return getBlockHashes(blockNumbers, chainFetcher.logger).then(function (res) {
302
+ if (res.TAG === "Ok") {
303
+ return res._0;
304
+ } else {
305
+ return ErrorHandling.mkLogAndRaise(undefined, "Failed to fetch blockHashes for given blockNumbers during rollback", res._0);
306
+ }
307
+ });
308
+ };
309
+ if (scannedBlockNumbers.length === 0) {
310
+ return getHighestBlockBelowThreshold(chainFetcher);
311
+ }
312
+ var blockNumbersAndHashes = await getBlockHashes$1(scannedBlockNumbers);
313
+ var blockNumber = ReorgDetection.getLatestValidScannedBlock(chainFetcher.reorgDetection, blockNumbersAndHashes);
314
+ if (blockNumber !== undefined) {
315
+ return blockNumber;
316
+ } else {
317
+ return getHighestBlockBelowThreshold(chainFetcher);
318
+ }
319
+ }
320
+
321
+ function isActivelyIndexing(chainFetcher) {
322
+ return FetchState.isActivelyIndexing(chainFetcher.fetchState);
323
+ }
324
+
325
+ function isLive(chainFetcher) {
326
+ return chainFetcher.timestampCaughtUpToHeadOrEndblock !== undefined;
327
+ }
328
+
329
+ export {
330
+ make ,
331
+ makeFromConfig ,
332
+ makeFromDbState ,
333
+ getContractStartBlock ,
334
+ runContractRegistersOrThrow ,
335
+ handleQueryResult ,
336
+ hasProcessedToEndblock ,
337
+ hasNoMoreEventsToProcess ,
338
+ getHighestBlockBelowThreshold ,
339
+ getLastKnownValidBlock ,
340
+ isActivelyIndexing ,
341
+ isLive ,
342
+ }
343
+ /* Env Not a pure module */
@@ -0,0 +1,182 @@
1
+ open Belt
2
+
3
+ type t = {
4
+ committedCheckpointId: float,
5
+ chainFetchers: ChainMap.t<ChainFetcher.t>,
6
+ multichain: Config.multichain,
7
+ isInReorgThreshold: bool,
8
+ }
9
+
10
+ // Check if progress is past the reorg threshold (safe block).
11
+ // A chain is in reorg threshold when progressBlockNumber > sourceBlockNumber - maxReorgDepth.
12
+ // This matches the logic in InternalTable.Checkpoints.makeGetReorgCheckpointsQuery.
13
+ let isProgressInReorgThreshold = (~progressBlockNumber, ~sourceBlockNumber, ~maxReorgDepth) => {
14
+ maxReorgDepth > 0 && progressBlockNumber > sourceBlockNumber - maxReorgDepth
15
+ }
16
+
17
+ let calculateTargetBufferSize = (~activeChainsCount, ~config: Config.t) => {
18
+ let targetBatchesInBuffer = 3
19
+ switch Env.targetBufferSize {
20
+ | Some(size) => size
21
+ | None =>
22
+ config.batchSize * (activeChainsCount > targetBatchesInBuffer ? 1 : targetBatchesInBuffer)
23
+ }
24
+ }
25
+
26
+ let makeFromConfig = (~config: Config.t, ~registrations): t => {
27
+ let targetBufferSize = calculateTargetBufferSize(
28
+ ~activeChainsCount=config.chainMap->ChainMap.size,
29
+ ~config,
30
+ )
31
+ let chainFetchers =
32
+ config.chainMap->ChainMap.map(
33
+ ChainFetcher.makeFromConfig(_, ~config, ~registrations, ~targetBufferSize),
34
+ )
35
+ {
36
+ committedCheckpointId: 0.,
37
+ chainFetchers,
38
+ multichain: config.multichain,
39
+ isInReorgThreshold: false,
40
+ }
41
+ }
42
+
43
+ let makeFromDbState = async (
44
+ ~initialState: Persistence.initialState,
45
+ ~config: Config.t,
46
+ ~registrations,
47
+ ): t => {
48
+ let isInReorgThreshold = if initialState.cleanRun {
49
+ false
50
+ } else {
51
+ // Check if any chain is in reorg threshold by comparing progress with sourceBlock - maxReorgDepth.
52
+ initialState.chains->Array.some(chain =>
53
+ isProgressInReorgThreshold(
54
+ ~progressBlockNumber=chain.progressBlockNumber,
55
+ ~sourceBlockNumber=chain.sourceBlockNumber,
56
+ ~maxReorgDepth=chain.maxReorgDepth,
57
+ )
58
+ )
59
+ }
60
+
61
+ let targetBufferSize = calculateTargetBufferSize(
62
+ ~activeChainsCount=initialState.chains->Array.length,
63
+ ~config,
64
+ )
65
+ Prometheus.ProcessingMaxBatchSize.set(~maxBatchSize=config.batchSize)
66
+ Prometheus.IndexingTargetBufferSize.set(~targetBufferSize)
67
+ Prometheus.ReorgThreshold.set(~isInReorgThreshold)
68
+ initialState.cache->Utils.Dict.forEach(({effectName, count}) => {
69
+ Prometheus.EffectCacheCount.set(~count, ~effectName)
70
+ })
71
+
72
+ let chainFetchersArr =
73
+ await initialState.chains
74
+ ->Array.map(async (resumedChainState: Persistence.initialChainState) => {
75
+ let chain = Config.getChain(config, ~chainId=resumedChainState.id)
76
+ let chainConfig = config.chainMap->ChainMap.get(chain)
77
+
78
+ (
79
+ chain,
80
+ await chainConfig->ChainFetcher.makeFromDbState(
81
+ ~resumedChainState,
82
+ ~reorgCheckpoints=initialState.reorgCheckpoints,
83
+ ~isInReorgThreshold,
84
+ ~targetBufferSize,
85
+ ~config,
86
+ ~registrations,
87
+ ),
88
+ )
89
+ })
90
+ ->Promise.all
91
+
92
+ let chainFetchers = ChainMap.fromArrayUnsafe(chainFetchersArr)
93
+
94
+ {
95
+ committedCheckpointId: initialState.checkpointId,
96
+ multichain: config.multichain,
97
+ chainFetchers,
98
+ isInReorgThreshold,
99
+ }
100
+ }
101
+
102
+ let getChainFetcher = (chainManager: t, ~chain: ChainMap.Chain.t): ChainFetcher.t => {
103
+ chainManager.chainFetchers->ChainMap.get(chain)
104
+ }
105
+
106
+ let setChainFetcher = (chainManager: t, chainFetcher: ChainFetcher.t) => {
107
+ {
108
+ ...chainManager,
109
+ chainFetchers: chainManager.chainFetchers->ChainMap.set(
110
+ ChainMap.Chain.makeUnsafe(~chainId=chainFetcher.chainConfig.id),
111
+ chainFetcher,
112
+ ),
113
+ }
114
+ }
115
+
116
+ let nextItemIsNone = (chainManager: t): bool => {
117
+ !Batch.hasMultichainReadyItem(
118
+ chainManager.chainFetchers->ChainMap.map(cf => {
119
+ cf.fetchState
120
+ }),
121
+ ~multichain=chainManager.multichain,
122
+ )
123
+ }
124
+
125
+ let createBatch = (chainManager: t, ~batchSizeTarget: int, ~isRollback: bool): Batch.t => {
126
+ Batch.make(
127
+ ~checkpointIdBeforeBatch=chainManager.committedCheckpointId +. (
128
+ // Since for rollback we have a diff checkpoint id.
129
+ // This is needed to currectly overwrite old state
130
+ // in an append-only ClickHouse insert.
131
+ isRollback ? 1. : 0.
132
+ ),
133
+ ~chainsBeforeBatch=chainManager.chainFetchers->ChainMap.map((cf): Batch.chainBeforeBatch => {
134
+ fetchState: cf.fetchState,
135
+ progressBlockNumber: cf.committedProgressBlockNumber,
136
+ totalEventsProcessed: cf.numEventsProcessed,
137
+ sourceBlockNumber: cf.fetchState.knownHeight,
138
+ reorgDetection: cf.reorgDetection,
139
+ }),
140
+ ~multichain=chainManager.multichain,
141
+ ~batchSizeTarget,
142
+ )
143
+ }
144
+
145
+ let isProgressAtHead = chainManager =>
146
+ chainManager.chainFetchers
147
+ ->ChainMap.values
148
+ ->Js.Array2.every(cf => cf.isProgressAtHead)
149
+
150
+ let isActivelyIndexing = chainManager =>
151
+ chainManager.chainFetchers
152
+ ->ChainMap.values
153
+ ->Js.Array2.every(ChainFetcher.isActivelyIndexing)
154
+
155
+ let getSafeCheckpointId = (chainManager: t) => {
156
+ let chainFetchers = chainManager.chainFetchers->ChainMap.values
157
+
158
+ let infinity = (%raw(`Infinity`): float)
159
+ let result = ref(infinity)
160
+
161
+ for idx in 0 to chainFetchers->Array.length - 1 {
162
+ let chainFetcher = chainFetchers->Array.getUnsafe(idx)
163
+ switch chainFetcher.safeCheckpointTracking {
164
+ | None => () // Skip chains with maxReorgDepth = 0
165
+ | Some(safeCheckpointTracking) => {
166
+ let safeCheckpointId =
167
+ safeCheckpointTracking->SafeCheckpointTracking.getSafeCheckpointId(
168
+ ~sourceBlockNumber=chainFetcher.fetchState.knownHeight,
169
+ )
170
+ if safeCheckpointId < result.contents {
171
+ result := safeCheckpointId
172
+ }
173
+ }
174
+ }
175
+ }
176
+
177
+ if result.contents === infinity || result.contents === 0. {
178
+ None // No safe checkpoint found
179
+ } else {
180
+ Some(result.contents)
181
+ }
182
+ }
@@ -0,0 +1,150 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Env from "./Env.res.mjs";
4
+ import * as Batch from "./Batch.res.mjs";
5
+ import * as Utils from "./Utils.res.mjs";
6
+ import * as Config from "./Config.res.mjs";
7
+ import * as ChainMap from "./ChainMap.res.mjs";
8
+ import * as Belt_Array from "rescript/lib/es6/belt_Array.js";
9
+ import * as Prometheus from "./Prometheus.res.mjs";
10
+ import * as ChainFetcher from "./ChainFetcher.res.mjs";
11
+ import * as SafeCheckpointTracking from "./SafeCheckpointTracking.res.mjs";
12
+
13
+ function isProgressInReorgThreshold(progressBlockNumber, sourceBlockNumber, maxReorgDepth) {
14
+ if (maxReorgDepth > 0) {
15
+ return progressBlockNumber > (sourceBlockNumber - maxReorgDepth | 0);
16
+ } else {
17
+ return false;
18
+ }
19
+ }
20
+
21
+ function calculateTargetBufferSize(activeChainsCount, config) {
22
+ if (Env.targetBufferSize !== undefined) {
23
+ return Env.targetBufferSize;
24
+ } else {
25
+ return Math.imul(config.batchSize, activeChainsCount > 3 ? 1 : 3);
26
+ }
27
+ }
28
+
29
+ function makeFromConfig(config, registrations) {
30
+ var targetBufferSize = calculateTargetBufferSize(ChainMap.size(config.chainMap), config);
31
+ var chainFetchers = ChainMap.map(config.chainMap, (function (__x) {
32
+ return ChainFetcher.makeFromConfig(__x, config, registrations, targetBufferSize);
33
+ }));
34
+ return {
35
+ committedCheckpointId: 0,
36
+ chainFetchers: chainFetchers,
37
+ multichain: config.multichain,
38
+ isInReorgThreshold: false
39
+ };
40
+ }
41
+
42
+ async function makeFromDbState(initialState, config, registrations) {
43
+ var isInReorgThreshold = initialState.cleanRun ? false : Belt_Array.some(initialState.chains, (function (chain) {
44
+ return isProgressInReorgThreshold(chain.progressBlockNumber, chain.sourceBlockNumber, chain.maxReorgDepth);
45
+ }));
46
+ var targetBufferSize = calculateTargetBufferSize(initialState.chains.length, config);
47
+ Prometheus.ProcessingMaxBatchSize.set(config.batchSize);
48
+ Prometheus.IndexingTargetBufferSize.set(targetBufferSize);
49
+ Prometheus.ReorgThreshold.set(isInReorgThreshold);
50
+ Utils.Dict.forEach(initialState.cache, (function (param) {
51
+ var count = param.count;
52
+ Prometheus.EffectCacheCount.set(count, param.effectName);
53
+ }));
54
+ var chainFetchersArr = await Promise.all(Belt_Array.map(initialState.chains, (async function (resumedChainState) {
55
+ var chain = Config.getChain(config, resumedChainState.id);
56
+ var chainConfig = ChainMap.get(config.chainMap, chain);
57
+ return [
58
+ chain,
59
+ await ChainFetcher.makeFromDbState(chainConfig, resumedChainState, initialState.reorgCheckpoints, isInReorgThreshold, config, registrations, targetBufferSize)
60
+ ];
61
+ })));
62
+ var chainFetchers = ChainMap.fromArrayUnsafe(chainFetchersArr);
63
+ return {
64
+ committedCheckpointId: initialState.checkpointId,
65
+ chainFetchers: chainFetchers,
66
+ multichain: config.multichain,
67
+ isInReorgThreshold: isInReorgThreshold
68
+ };
69
+ }
70
+
71
+ function getChainFetcher(chainManager, chain) {
72
+ return ChainMap.get(chainManager.chainFetchers, chain);
73
+ }
74
+
75
+ function setChainFetcher(chainManager, chainFetcher) {
76
+ return {
77
+ committedCheckpointId: chainManager.committedCheckpointId,
78
+ chainFetchers: ChainMap.set(chainManager.chainFetchers, ChainMap.Chain.makeUnsafe(chainFetcher.chainConfig.id), chainFetcher),
79
+ multichain: chainManager.multichain,
80
+ isInReorgThreshold: chainManager.isInReorgThreshold
81
+ };
82
+ }
83
+
84
+ function nextItemIsNone(chainManager) {
85
+ return !Batch.hasMultichainReadyItem(ChainMap.map(chainManager.chainFetchers, (function (cf) {
86
+ return cf.fetchState;
87
+ })), chainManager.multichain);
88
+ }
89
+
90
+ function createBatch(chainManager, batchSizeTarget, isRollback) {
91
+ return Batch.make(chainManager.committedCheckpointId + (
92
+ isRollback ? 1 : 0
93
+ ), ChainMap.map(chainManager.chainFetchers, (function (cf) {
94
+ return {
95
+ fetchState: cf.fetchState,
96
+ reorgDetection: cf.reorgDetection,
97
+ progressBlockNumber: cf.committedProgressBlockNumber,
98
+ sourceBlockNumber: cf.fetchState.knownHeight,
99
+ totalEventsProcessed: cf.numEventsProcessed
100
+ };
101
+ })), chainManager.multichain, batchSizeTarget);
102
+ }
103
+
104
+ function isProgressAtHead(chainManager) {
105
+ return ChainMap.values(chainManager.chainFetchers).every(function (cf) {
106
+ return cf.isProgressAtHead;
107
+ });
108
+ }
109
+
110
+ function isActivelyIndexing(chainManager) {
111
+ return ChainMap.values(chainManager.chainFetchers).every(ChainFetcher.isActivelyIndexing);
112
+ }
113
+
114
+ function getSafeCheckpointId(chainManager) {
115
+ var chainFetchers = ChainMap.values(chainManager.chainFetchers);
116
+ var infinity = Infinity;
117
+ var result = infinity;
118
+ for(var idx = 0 ,idx_finish = chainFetchers.length; idx < idx_finish; ++idx){
119
+ var chainFetcher = chainFetchers[idx];
120
+ var safeCheckpointTracking = chainFetcher.safeCheckpointTracking;
121
+ if (safeCheckpointTracking !== undefined) {
122
+ var safeCheckpointId = SafeCheckpointTracking.getSafeCheckpointId(safeCheckpointTracking, chainFetcher.fetchState.knownHeight);
123
+ if (safeCheckpointId < result) {
124
+ result = safeCheckpointId;
125
+ }
126
+
127
+ }
128
+
129
+ }
130
+ if (result === infinity || result === 0) {
131
+ return ;
132
+ } else {
133
+ return result;
134
+ }
135
+ }
136
+
137
+ export {
138
+ isProgressInReorgThreshold ,
139
+ calculateTargetBufferSize ,
140
+ makeFromConfig ,
141
+ makeFromDbState ,
142
+ getChainFetcher ,
143
+ setChainFetcher ,
144
+ nextItemIsNone ,
145
+ createBatch ,
146
+ isProgressAtHead ,
147
+ isActivelyIndexing ,
148
+ getSafeCheckpointId ,
149
+ }
150
+ /* Env Not a pure module */