envio 3.3.0-alpha.0 → 3.3.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.
- package/evm.schema.json +10 -0
- package/index.d.ts +45 -25
- package/package.json +7 -7
- 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/Batch.res +0 -6
- package/src/Batch.res.mjs +1 -12
- package/src/BatchProcessing.res +7 -12
- package/src/BatchProcessing.res.mjs +8 -7
- package/src/Bin.res +3 -0
- package/src/Bin.res.mjs +4 -0
- package/src/ChainFetching.res +48 -16
- package/src/ChainFetching.res.mjs +36 -17
- package/src/ChainMetadata.res +1 -11
- package/src/ChainMetadata.res.mjs +1 -10
- package/src/ChainState.res +628 -149
- package/src/ChainState.res.mjs +440 -102
- package/src/ChainState.resi +74 -4
- package/src/Config.res +61 -33
- package/src/Config.res.mjs +50 -10
- package/src/ContractRegisterContext.res +2 -12
- package/src/ContractRegisterContext.res.mjs +3 -5
- package/src/Core.res +14 -3
- package/src/CrossChainState.res +142 -93
- package/src/CrossChainState.res.mjs +88 -60
- package/src/CrossChainState.resi +2 -10
- package/src/Ecosystem.res +5 -6
- package/src/Ecosystem.res.mjs +3 -3
- package/src/Env.res +0 -7
- package/src/Env.res.mjs +0 -6
- package/src/Envio.res +17 -11
- package/src/EnvioGlobal.res +53 -0
- package/src/EnvioGlobal.res.mjs +31 -0
- package/src/EventConfigBuilder.res +177 -88
- package/src/EventConfigBuilder.res.mjs +99 -42
- package/src/EventProcessing.res +74 -28
- package/src/EventProcessing.res.mjs +55 -29
- package/src/ExitOnCaughtUp.res +10 -2
- package/src/ExitOnCaughtUp.res.mjs +10 -1
- package/src/FetchState.res +558 -300
- package/src/FetchState.res.mjs +437 -423
- package/src/HandlerLoader.res +8 -104
- package/src/HandlerLoader.res.mjs +2 -81
- package/src/HandlerRegister.res +518 -144
- package/src/HandlerRegister.res.mjs +285 -133
- package/src/HandlerRegister.resi +24 -8
- package/src/IndexerLoop.res +2 -3
- package/src/IndexerLoop.res.mjs +1 -1
- package/src/IndexerState.res +10 -11
- package/src/IndexerState.res.mjs +14 -11
- package/src/IndexerState.resi +2 -5
- package/src/IndexingAddresses.res +108 -0
- package/src/IndexingAddresses.res.mjs +101 -0
- package/src/IndexingAddresses.resi +34 -0
- package/src/Internal.res +155 -46
- package/src/Internal.res.mjs +30 -2
- package/src/LoadLayer.res +5 -5
- package/src/LoadLayer.res.mjs +6 -6
- package/src/LogSelection.res +102 -165
- package/src/LogSelection.res.mjs +101 -116
- package/src/Main.res +71 -236
- package/src/Main.res.mjs +60 -145
- package/src/Metrics.res +74 -0
- package/src/Metrics.res.mjs +75 -0
- package/src/PgStorage.res +4 -4
- package/src/PgStorage.res.mjs +5 -5
- package/src/Prometheus.res +10 -74
- package/src/Prometheus.res.mjs +124 -186
- package/src/PruneStaleHistory.res +2 -2
- package/src/PruneStaleHistory.res.mjs +3 -3
- package/src/RawEvent.res +7 -2
- package/src/RawEvent.res.mjs +4 -4
- package/src/Rollback.res +3 -3
- package/src/Rollback.res.mjs +4 -4
- package/src/RollbackCommit.res +4 -1
- package/src/RollbackCommit.res.mjs +3 -2
- package/src/SimulateDeadInputTracker.res +85 -0
- package/src/SimulateDeadInputTracker.res.mjs +73 -0
- package/src/SimulateDeadInputTracker.resi +12 -0
- package/src/SimulateItems.res +91 -23
- package/src/SimulateItems.res.mjs +55 -32
- package/src/TestIndexer.res +54 -40
- package/src/TestIndexer.res.mjs +37 -30
- package/src/bindings/Performance.res +7 -0
- package/src/bindings/Performance.res.mjs +21 -0
- package/src/bindings/Performance.resi +7 -0
- package/src/bindings/Viem.res +0 -41
- package/src/bindings/Viem.res.mjs +1 -43
- package/src/sources/BlockStore.res +46 -0
- package/src/sources/BlockStore.res.mjs +24 -0
- package/src/sources/EventRouter.res +36 -33
- package/src/sources/EventRouter.res.mjs +13 -14
- package/src/sources/Evm.res +83 -72
- package/src/sources/Evm.res.mjs +53 -69
- package/src/sources/EvmChain.res +18 -20
- package/src/sources/EvmChain.res.mjs +15 -15
- package/src/sources/EvmRpcClient.res +74 -5
- package/src/sources/EvmRpcClient.res.mjs +13 -4
- package/src/sources/FieldMask.res +39 -0
- package/src/sources/FieldMask.res.mjs +42 -0
- package/src/sources/Fuel.res +9 -6
- package/src/sources/Fuel.res.mjs +5 -10
- package/src/sources/HyperFuelSource.res +46 -50
- package/src/sources/HyperFuelSource.res.mjs +64 -54
- package/src/sources/HyperSync.res +39 -7
- package/src/sources/HyperSync.res.mjs +57 -37
- package/src/sources/HyperSync.resi +12 -2
- package/src/sources/HyperSyncClient.res +22 -111
- package/src/sources/HyperSyncClient.res.mjs +2 -30
- package/src/sources/HyperSyncHeightStream.res +1 -8
- package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
- package/src/sources/HyperSyncSource.res +94 -107
- package/src/sources/HyperSyncSource.res.mjs +82 -86
- package/src/sources/Rpc.res +15 -47
- package/src/sources/Rpc.res.mjs +25 -56
- package/src/sources/RpcSource.res +320 -467
- package/src/sources/RpcSource.res.mjs +268 -385
- package/src/sources/RpcWebSocketHeightStream.res +0 -5
- package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
- package/src/sources/SimulateSource.res +10 -4
- package/src/sources/SimulateSource.res.mjs +16 -6
- package/src/sources/Source.res +34 -6
- package/src/sources/SourceManager.res +86 -27
- package/src/sources/SourceManager.res.mjs +84 -47
- package/src/sources/SourceManager.resi +12 -3
- package/src/sources/Svm.res +31 -16
- package/src/sources/Svm.res.mjs +36 -13
- package/src/sources/SvmHyperSyncClient.res +5 -32
- package/src/sources/SvmHyperSyncSource.res +159 -134
- package/src/sources/SvmHyperSyncSource.res.mjs +164 -129
- package/src/sources/TransactionStore.res +49 -0
- package/src/sources/TransactionStore.res.mjs +30 -0
- package/src/tui/Tui.res +13 -16
- package/src/tui/Tui.res.mjs +12 -14
- package/svm.schema.json +49 -37
- package/src/bindings/Hrtime.res +0 -58
- package/src/bindings/Hrtime.res.mjs +0 -90
- package/src/bindings/Hrtime.resi +0 -30
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Evm from "./sources/Evm.res.mjs";
|
|
4
|
+
import * as Svm from "./sources/Svm.res.mjs";
|
|
3
5
|
import * as Utils from "./Utils.res.mjs";
|
|
4
6
|
import * as Address from "./Address.res.mjs";
|
|
5
7
|
import * as FuelSDK from "./sources/FuelSDK.res.mjs";
|
|
@@ -211,7 +213,7 @@ function getTopicEncoder(abiType) {
|
|
|
211
213
|
}
|
|
212
214
|
switch (abiType) {
|
|
213
215
|
case "address" :
|
|
214
|
-
return TopicFilter.fromAddress;
|
|
216
|
+
return value => TopicFilter.fromAddress(value.toLowerCase());
|
|
215
217
|
case "bool" :
|
|
216
218
|
return TopicFilter.fromBool;
|
|
217
219
|
case "bytes" :
|
|
@@ -255,20 +257,30 @@ let compileAddressFilter = (function (body) {
|
|
|
255
257
|
return new Function("event", "blockNumber", "indexingAddresses", body);
|
|
256
258
|
});
|
|
257
259
|
|
|
258
|
-
function buildAddressFilterBody(groups) {
|
|
259
|
-
|
|
260
|
-
|
|
260
|
+
function buildAddressFilterBody(groups, isWildcard, srcAddressExprOpt) {
|
|
261
|
+
let srcAddressExpr = srcAddressExprOpt !== undefined ? srcAddressExprOpt : "event.srcAddress";
|
|
262
|
+
let paramLeaf = name => `(ic = indexingAddresses[p[` + JSON.stringify(name) + `]]) !== undefined && ic.effectiveStartBlock <= blockNumber`;
|
|
263
|
+
let paramDnf = groups.length !== 0 ? groups.map(group => "(" + group.map(paramLeaf).join(" && ") + ")").join(" || ") : undefined;
|
|
264
|
+
let srcLeaf = `(ic = indexingAddresses[` + srcAddressExpr + `]) !== undefined && ic.effectiveStartBlock <= blockNumber`;
|
|
265
|
+
if (isWildcard) {
|
|
266
|
+
if (paramDnf !== undefined) {
|
|
267
|
+
return "var p = event.params, ic; return " + paramDnf + ";";
|
|
268
|
+
} else {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
} else if (paramDnf !== undefined) {
|
|
272
|
+
return "var p = event.params, ic; return " + srcLeaf + " && (" + paramDnf + ");";
|
|
273
|
+
} else {
|
|
274
|
+
return "var ic; return " + srcLeaf + ";";
|
|
261
275
|
}
|
|
262
|
-
let leaf = name => `(ic = indexingAddresses[p[` + JSON.stringify(name) + `]]) !== undefined && ic.effectiveStartBlock <= blockNumber`;
|
|
263
|
-
let groupExprs = groups.map(group => "(" + group.map(leaf).join(" && ") + ")");
|
|
264
|
-
return "var p = event.params, ic; return " + groupExprs.join(" || ") + ";";
|
|
265
276
|
}
|
|
266
277
|
|
|
267
|
-
function buildAddressFilter(groups) {
|
|
268
|
-
|
|
278
|
+
function buildAddressFilter(groups, isWildcard, srcAddressExprOpt) {
|
|
279
|
+
let srcAddressExpr = srcAddressExprOpt !== undefined ? srcAddressExprOpt : "event.srcAddress";
|
|
280
|
+
return Stdlib_Option.map(buildAddressFilterBody(groups, isWildcard, srcAddressExpr), compileAddressFilter);
|
|
269
281
|
}
|
|
270
282
|
|
|
271
|
-
function buildEvmEventConfig(contractName, eventName, sighash, params,
|
|
283
|
+
function buildEvmEventConfig(contractName, eventName, sighash, params, blockFields, transactionFields, globalBlockFieldsSetOpt, globalTransactionFieldsSetOpt) {
|
|
272
284
|
let globalBlockFieldsSet = globalBlockFieldsSetOpt !== undefined ? Primitive_option.valFromOption(globalBlockFieldsSetOpt) : new Set();
|
|
273
285
|
let globalTransactionFieldsSet = globalTransactionFieldsSetOpt !== undefined ? Primitive_option.valFromOption(globalTransactionFieldsSetOpt) : new Set();
|
|
274
286
|
let topicCount = Stdlib_Array.reduce(params, 1, (acc, p) => {
|
|
@@ -278,57 +290,75 @@ function buildEvmEventConfig(contractName, eventName, sighash, params, isWildcar
|
|
|
278
290
|
return acc;
|
|
279
291
|
}
|
|
280
292
|
});
|
|
281
|
-
let
|
|
282
|
-
let
|
|
283
|
-
let
|
|
284
|
-
let filterByAddresses = match.filterByAddresses;
|
|
285
|
-
let resolvedStartBlock = whereStartBlock !== undefined ? whereStartBlock : startBlock;
|
|
286
|
-
let match$1 = resolveFieldSelection(blockFields, transactionFields, globalBlockFieldsSet, globalTransactionFieldsSet);
|
|
293
|
+
let match = resolveFieldSelection(blockFields, transactionFields, globalBlockFieldsSet, globalTransactionFieldsSet);
|
|
294
|
+
let selectedTransactionFields = match[1];
|
|
295
|
+
let selectedBlockFields = match[0];
|
|
287
296
|
return {
|
|
288
297
|
id: sighash + "_" + topicCount.toString(),
|
|
289
298
|
name: eventName,
|
|
290
299
|
contractName: contractName,
|
|
291
|
-
isWildcard: isWildcard,
|
|
292
|
-
filterByAddresses: filterByAddresses,
|
|
293
|
-
dependsOnAddresses: !isWildcard || filterByAddresses,
|
|
294
|
-
clientAddressFilter: Stdlib_Option.map(buildAddressFilterBody(match.addressFilterParamGroups), compileAddressFilter),
|
|
295
|
-
handler: handler,
|
|
296
|
-
contractRegister: contractRegister,
|
|
297
300
|
paramsRawEventSchema: buildParamsSchema(params),
|
|
298
301
|
simulateParamsSchema: buildSimulateParamsSchema(params),
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
302
|
+
selectedTransactionFields: selectedTransactionFields,
|
|
303
|
+
transactionFieldMask: Evm.eventTransactionFieldMask(selectedTransactionFields),
|
|
304
|
+
blockFieldMask: Evm.eventBlockFieldMask(selectedBlockFields),
|
|
305
|
+
selectedBlockFields: selectedBlockFields,
|
|
303
306
|
sighash: sighash,
|
|
304
307
|
topicCount: topicCount,
|
|
305
308
|
paramsMetadata: params
|
|
306
309
|
};
|
|
307
310
|
}
|
|
308
311
|
|
|
309
|
-
function
|
|
312
|
+
function buildEvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, where, chainId, onEventBlockFilterSchema, startBlock) {
|
|
313
|
+
let indexedParams = eventConfig.paramsMetadata.filter(p => p.indexed);
|
|
314
|
+
let match = LogSelection.parseWhereOrThrow(where, eventConfig.sighash, indexedParams.map(p => p.name), eventConfig.contractName, chainId, onEventBlockFilterSchema, Stdlib_Option.map(indexedParams[0], buildTopicGetter), Stdlib_Option.map(indexedParams[1], buildTopicGetter), Stdlib_Option.map(indexedParams[2], buildTopicGetter));
|
|
315
|
+
let filterByAddresses = match.filterByAddresses;
|
|
316
|
+
let resolvedWhere = match.resolvedWhere;
|
|
317
|
+
let sb = resolvedWhere.startBlock;
|
|
318
|
+
let resolvedStartBlock = sb !== undefined ? sb : startBlock;
|
|
319
|
+
return {
|
|
320
|
+
eventConfig: eventConfig,
|
|
321
|
+
handler: handler,
|
|
322
|
+
contractRegister: contractRegister,
|
|
323
|
+
isWildcard: isWildcard,
|
|
324
|
+
filterByAddresses: filterByAddresses,
|
|
325
|
+
dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, filterByAddresses),
|
|
326
|
+
clientAddressFilter: buildAddressFilter(match.addressFilterParamGroups, isWildcard, undefined),
|
|
327
|
+
startBlock: resolvedStartBlock,
|
|
328
|
+
resolvedWhere: resolvedWhere
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
let alwaysIncludedSvmBlockFields = [
|
|
333
|
+
"slot",
|
|
334
|
+
"time",
|
|
335
|
+
"hash"
|
|
336
|
+
];
|
|
337
|
+
|
|
338
|
+
function buildSvmInstructionEventConfig(contractName, instructionName, programId, discriminator, discriminatorByteLen, includeLogs, transactionFieldsOpt, blockFieldsOpt, accountFilters, isInner, accountsOpt, argsOpt, definedTypesOpt) {
|
|
339
|
+
let transactionFields = transactionFieldsOpt !== undefined ? transactionFieldsOpt : [];
|
|
340
|
+
let blockFields = blockFieldsOpt !== undefined ? blockFieldsOpt : [];
|
|
310
341
|
let accounts = accountsOpt !== undefined ? accountsOpt : [];
|
|
311
342
|
let args = argsOpt !== undefined ? argsOpt : null;
|
|
312
343
|
let definedTypes = definedTypesOpt !== undefined ? definedTypesOpt : null;
|
|
313
344
|
let paramsSchema = Utils.Schema.coerceToJsonPgType(S$RescriptSchema.json(false));
|
|
345
|
+
let selectedTransactionFields = new Set(transactionFields);
|
|
346
|
+
let selectedBlockFields = new Set(alwaysIncludedSvmBlockFields.concat(blockFields));
|
|
347
|
+
let blockFieldMask = Svm.eventBlockFieldMask(selectedBlockFields);
|
|
314
348
|
return {
|
|
315
349
|
id: discriminator !== undefined ? discriminator : "none",
|
|
316
350
|
name: instructionName,
|
|
317
351
|
contractName: contractName,
|
|
318
|
-
isWildcard: isWildcard,
|
|
319
|
-
filterByAddresses: false,
|
|
320
|
-
dependsOnAddresses: !isWildcard,
|
|
321
|
-
handler: handler,
|
|
322
|
-
contractRegister: contractRegister,
|
|
323
352
|
paramsRawEventSchema: paramsSchema,
|
|
324
353
|
simulateParamsSchema: paramsSchema,
|
|
325
|
-
|
|
354
|
+
selectedTransactionFields: selectedTransactionFields,
|
|
355
|
+
transactionFieldMask: Svm.eventTransactionFieldMask(selectedTransactionFields),
|
|
356
|
+
blockFieldMask: blockFieldMask,
|
|
357
|
+
selectedBlockFields: selectedBlockFields,
|
|
326
358
|
programId: programId,
|
|
327
359
|
discriminator: discriminator,
|
|
328
360
|
discriminatorByteLen: discriminatorByteLen,
|
|
329
|
-
includeTransaction: includeTransaction,
|
|
330
361
|
includeLogs: includeLogs,
|
|
331
|
-
includeTokenBalances: includeTokenBalances,
|
|
332
362
|
accountFilters: accountFilters,
|
|
333
363
|
isInner: isInner,
|
|
334
364
|
accounts: accounts,
|
|
@@ -337,7 +367,20 @@ function buildSvmInstructionEventConfig(contractName, instructionName, programId
|
|
|
337
367
|
};
|
|
338
368
|
}
|
|
339
369
|
|
|
340
|
-
function
|
|
370
|
+
function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, startBlock) {
|
|
371
|
+
return {
|
|
372
|
+
eventConfig: eventConfig,
|
|
373
|
+
handler: handler,
|
|
374
|
+
contractRegister: contractRegister,
|
|
375
|
+
isWildcard: isWildcard,
|
|
376
|
+
filterByAddresses: false,
|
|
377
|
+
dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, false),
|
|
378
|
+
clientAddressFilter: buildAddressFilter([], isWildcard, "event.programId"),
|
|
379
|
+
startBlock: startBlock
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function buildFuelEventConfig(contractName, eventName, kind, sighash, rawAbi) {
|
|
341
384
|
let fuelKind;
|
|
342
385
|
switch (kind) {
|
|
343
386
|
case "burn" :
|
|
@@ -384,18 +427,28 @@ function buildFuelEventConfig(contractName, eventName, kind, sighash, rawAbi, is
|
|
|
384
427
|
id: tmp,
|
|
385
428
|
name: eventName,
|
|
386
429
|
contractName: contractName,
|
|
387
|
-
isWildcard: isWildcard,
|
|
388
|
-
filterByAddresses: false,
|
|
389
|
-
dependsOnAddresses: !isWildcard,
|
|
390
|
-
handler: handler,
|
|
391
|
-
contractRegister: contractRegister,
|
|
392
430
|
paramsRawEventSchema: paramsSchema,
|
|
393
431
|
simulateParamsSchema: paramsSchema,
|
|
394
|
-
|
|
432
|
+
selectedTransactionFields: new Set(),
|
|
433
|
+
transactionFieldMask: 0,
|
|
434
|
+
blockFieldMask: 0,
|
|
395
435
|
kind: fuelKind
|
|
396
436
|
};
|
|
397
437
|
}
|
|
398
438
|
|
|
439
|
+
function buildFuelOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, startBlock) {
|
|
440
|
+
return {
|
|
441
|
+
eventConfig: eventConfig,
|
|
442
|
+
handler: handler,
|
|
443
|
+
contractRegister: contractRegister,
|
|
444
|
+
isWildcard: isWildcard,
|
|
445
|
+
filterByAddresses: false,
|
|
446
|
+
dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, false),
|
|
447
|
+
clientAddressFilter: buildAddressFilter([], isWildcard, undefined),
|
|
448
|
+
startBlock: startBlock
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
|
|
399
452
|
export {
|
|
400
453
|
paramMetaSchema,
|
|
401
454
|
normalizeOrThrow,
|
|
@@ -415,7 +468,11 @@ export {
|
|
|
415
468
|
buildAddressFilterBody,
|
|
416
469
|
buildAddressFilter,
|
|
417
470
|
buildEvmEventConfig,
|
|
471
|
+
buildEvmOnEventRegistration,
|
|
472
|
+
alwaysIncludedSvmBlockFields,
|
|
418
473
|
buildSvmInstructionEventConfig,
|
|
474
|
+
buildSvmOnEventRegistration,
|
|
419
475
|
buildFuelEventConfig,
|
|
476
|
+
buildFuelOnEventRegistration,
|
|
420
477
|
}
|
|
421
478
|
/* paramMetaSchema Not a pure module */
|
package/src/EventProcessing.res
CHANGED
|
@@ -39,7 +39,7 @@ let runEventHandlerOrThrow = async (
|
|
|
39
39
|
let eventItem = item->Internal.castUnsafeEventItem
|
|
40
40
|
|
|
41
41
|
//Include the load in time before handler
|
|
42
|
-
let timeBeforeHandler =
|
|
42
|
+
let timeBeforeHandler = Performance.now()
|
|
43
43
|
|
|
44
44
|
try {
|
|
45
45
|
let contextParams: UserContext.contextParams = {
|
|
@@ -72,10 +72,10 @@ let runEventHandlerOrThrow = async (
|
|
|
72
72
|
}),
|
|
73
73
|
)
|
|
74
74
|
}
|
|
75
|
-
let handlerDuration = timeBeforeHandler->
|
|
75
|
+
let handlerDuration = timeBeforeHandler->Performance.secondsSince
|
|
76
76
|
Prometheus.ProcessingHandler.increment(
|
|
77
|
-
~contract=eventItem.eventConfig.contractName,
|
|
78
|
-
~event=eventItem.eventConfig.name,
|
|
77
|
+
~contract=eventItem.onEventRegistration.eventConfig.contractName,
|
|
78
|
+
~event=eventItem.onEventRegistration.eventConfig.name,
|
|
79
79
|
~duration=handlerDuration,
|
|
80
80
|
)
|
|
81
81
|
}
|
|
@@ -90,7 +90,7 @@ let runHandlerOrThrow = async (
|
|
|
90
90
|
~chains: Internal.chains,
|
|
91
91
|
) => {
|
|
92
92
|
switch item {
|
|
93
|
-
| Block({
|
|
93
|
+
| Block({onBlockRegistration: {handler}, blockNumber}) =>
|
|
94
94
|
try {
|
|
95
95
|
let contextParams: UserContext.contextParams = {
|
|
96
96
|
item,
|
|
@@ -121,8 +121,8 @@ let runHandlerOrThrow = async (
|
|
|
121
121
|
}),
|
|
122
122
|
)
|
|
123
123
|
}
|
|
124
|
-
| Event({
|
|
125
|
-
switch
|
|
124
|
+
| Event({onEventRegistration}) =>
|
|
125
|
+
switch onEventRegistration.handler {
|
|
126
126
|
| Some(handler) =>
|
|
127
127
|
await item->runEventHandlerOrThrow(
|
|
128
128
|
~handler,
|
|
@@ -161,7 +161,7 @@ let preloadBatchOrThrow = async (
|
|
|
161
161
|
for idx in 0 to checkpointEventsProcessed - 1 {
|
|
162
162
|
let item = batch.items->Array.getUnsafe(itemIdx.contents + idx)
|
|
163
163
|
switch item {
|
|
164
|
-
| Event({
|
|
164
|
+
| Event({onEventRegistration: {handler, eventConfig: {contractName, name: eventName}}}) =>
|
|
165
165
|
switch handler {
|
|
166
166
|
| None => ()
|
|
167
167
|
| Some(handler) =>
|
|
@@ -200,7 +200,7 @@ let preloadBatchOrThrow = async (
|
|
|
200
200
|
| _ => ()
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
|
-
| Block({
|
|
203
|
+
| Block({onBlockRegistration: {handler}, blockNumber}) =>
|
|
204
204
|
try {
|
|
205
205
|
promises->Array.push(
|
|
206
206
|
handler({
|
|
@@ -264,11 +264,19 @@ let runBatchHandlersOrThrow = async (
|
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
-
let registerProcessEventBatchMetrics = (
|
|
268
|
-
logger
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
267
|
+
let registerProcessEventBatchMetrics = (
|
|
268
|
+
~logger,
|
|
269
|
+
~batch: Batch.t,
|
|
270
|
+
~loadDuration,
|
|
271
|
+
~handlerDuration,
|
|
272
|
+
) => {
|
|
273
|
+
batch.progressedChainsById->Dict.forEachWithKey((chainAfterBatch, chainId) => {
|
|
274
|
+
logger->Logging.childTrace({
|
|
275
|
+
"msg": "Finished processing",
|
|
276
|
+
"chainId": chainId->Int.fromString->Option.getUnsafe,
|
|
277
|
+
"batchSize": chainAfterBatch.batchSize,
|
|
278
|
+
"progress": chainAfterBatch.progressBlockNumber,
|
|
279
|
+
})
|
|
272
280
|
})
|
|
273
281
|
|
|
274
282
|
Prometheus.ProcessingBatch.registerMetrics(~loadDuration, ~handlerDuration)
|
|
@@ -281,6 +289,39 @@ type logPartitionInfo = {
|
|
|
281
289
|
lastItemBlockNumber?: int,
|
|
282
290
|
}
|
|
283
291
|
|
|
292
|
+
// Off the hot path: bulk-materialise the selected transaction and block fields
|
|
293
|
+
// for the batch's store-backed (HyperSync) items and write them onto the
|
|
294
|
+
// payloads, so handlers read plain objects. A batch can span chains, each with
|
|
295
|
+
// its own stores and field masks, so group items by chain before materialising.
|
|
296
|
+
let materializeBatchEvents = async (
|
|
297
|
+
batch: Batch.t,
|
|
298
|
+
~chainStates: dict<ChainState.t>,
|
|
299
|
+
~ecosystem,
|
|
300
|
+
) => {
|
|
301
|
+
switch chainStates->Dict.valuesToArray {
|
|
302
|
+
// Single-chain indexers (the common case): every item belongs to the one
|
|
303
|
+
// chain, so skip the per-chain grouping and its allocations.
|
|
304
|
+
| [cs] => await cs->ChainState.materializeBatchItems(~items=batch.items, ~ecosystem)
|
|
305
|
+
| _ =>
|
|
306
|
+
let itemsByChain: dict<array<Internal.item>> = Dict.make()
|
|
307
|
+
batch.items->Array.forEach(item => {
|
|
308
|
+
let chainId = item->Internal.getItemChainId->Int.toString
|
|
309
|
+
switch itemsByChain->Utils.Dict.dangerouslyGetNonOption(chainId) {
|
|
310
|
+
| Some(items) => items->Array.push(item)
|
|
311
|
+
| None => itemsByChain->Dict.set(chainId, [item])
|
|
312
|
+
}
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
let _ = await itemsByChain
|
|
316
|
+
->Dict.toArray
|
|
317
|
+
->Array.map(async ((chainId, items)) => {
|
|
318
|
+
let cs = chainStates->Dict.getUnsafe(chainId)
|
|
319
|
+
await cs->ChainState.materializeBatchItems(~items, ~ecosystem)
|
|
320
|
+
})
|
|
321
|
+
->Promise.all
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
284
325
|
let processEventBatch = async (
|
|
285
326
|
~batch: Batch.t,
|
|
286
327
|
~indexerState: IndexerState.t,
|
|
@@ -289,33 +330,33 @@ let processEventBatch = async (
|
|
|
289
330
|
~config: Config.t,
|
|
290
331
|
~chainStates: dict<ChainState.t>,
|
|
291
332
|
) => {
|
|
292
|
-
let totalBatchSize = batch.totalBatchSize
|
|
293
333
|
// Compute chains state for this batch
|
|
294
334
|
let chains: Internal.chains = chainStates->computeChainsState
|
|
295
335
|
|
|
296
336
|
let logger = Logging.getLogger()
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
}),
|
|
337
|
+
|
|
338
|
+
batch.progressedChainsById->Dict.forEachWithKey((chainAfterBatch, chainId) => {
|
|
339
|
+
logger->Logging.childTrace({
|
|
340
|
+
"msg": "Started processing",
|
|
341
|
+
"chainId": chainId->Int.fromString->Option.getUnsafe,
|
|
342
|
+
"batchSize": chainAfterBatch.batchSize,
|
|
343
|
+
})
|
|
306
344
|
})
|
|
307
345
|
|
|
308
346
|
try {
|
|
309
347
|
// Backpressure: keep processing within keepLatestChangesLimit of the cycle.
|
|
310
348
|
await indexerState->Writing.awaitCapacity
|
|
311
349
|
|
|
312
|
-
let timeRef =
|
|
350
|
+
let timeRef = Performance.now()
|
|
313
351
|
|
|
314
352
|
if batch.items->Utils.Array.notEmpty {
|
|
353
|
+
// Materialise store-backed transactions onto payloads before any handler
|
|
354
|
+
// (preload or execute) reads them.
|
|
355
|
+
await materializeBatchEvents(batch, ~chainStates, ~ecosystem=config.ecosystem.name)
|
|
315
356
|
await batch->preloadBatchOrThrow(~loadManager, ~persistence, ~indexerState, ~chains, ~config)
|
|
316
357
|
}
|
|
317
358
|
|
|
318
|
-
let elapsedTimeAfterLoaders = timeRef->
|
|
359
|
+
let elapsedTimeAfterLoaders = timeRef->Performance.secondsSince
|
|
319
360
|
|
|
320
361
|
if batch.items->Utils.Array.notEmpty {
|
|
321
362
|
await batch->runBatchHandlersOrThrow(
|
|
@@ -327,13 +368,18 @@ let processEventBatch = async (
|
|
|
327
368
|
)
|
|
328
369
|
}
|
|
329
370
|
|
|
330
|
-
let elapsedTimeAfterProcessing = timeRef->
|
|
371
|
+
let elapsedTimeAfterProcessing = timeRef->Performance.secondsSince
|
|
331
372
|
|
|
332
373
|
indexerState->Writing.commitBatch(~batch)
|
|
333
374
|
|
|
334
375
|
let loaderDuration = elapsedTimeAfterLoaders
|
|
335
376
|
let handlerDuration = elapsedTimeAfterProcessing -. loaderDuration
|
|
336
|
-
registerProcessEventBatchMetrics(
|
|
377
|
+
registerProcessEventBatchMetrics(
|
|
378
|
+
~logger,
|
|
379
|
+
~batch,
|
|
380
|
+
~loadDuration=loaderDuration,
|
|
381
|
+
~handlerDuration,
|
|
382
|
+
)
|
|
337
383
|
Ok()
|
|
338
384
|
} catch {
|
|
339
385
|
| Persistence.StorageError({message, reason}) =>
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Utils from "./Utils.res.mjs";
|
|
4
|
-
import * as Hrtime from "./bindings/Hrtime.res.mjs";
|
|
5
4
|
import * as Logging from "./Logging.res.mjs";
|
|
6
5
|
import * as Writing from "./Writing.res.mjs";
|
|
6
|
+
import * as Internal from "./Internal.res.mjs";
|
|
7
7
|
import * as Ecosystem from "./Ecosystem.res.mjs";
|
|
8
8
|
import * as ChainState from "./ChainState.res.mjs";
|
|
9
9
|
import * as Prometheus from "./Prometheus.res.mjs";
|
|
10
|
+
import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
|
|
11
|
+
import * as Performance from "./bindings/Performance.res.mjs";
|
|
10
12
|
import * as Persistence from "./Persistence.res.mjs";
|
|
13
|
+
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
11
14
|
import * as UserContext from "./UserContext.res.mjs";
|
|
12
15
|
import * as ErrorHandling from "./ErrorHandling.res.mjs";
|
|
13
16
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
@@ -33,7 +36,7 @@ function computeChainsState(chainStates) {
|
|
|
33
36
|
let ProcessingError = /* @__PURE__ */Primitive_exceptions.create("EventProcessing.ProcessingError");
|
|
34
37
|
|
|
35
38
|
async function runEventHandlerOrThrow(item, checkpointId, handler, indexerState, loadManager, persistence, chains, config) {
|
|
36
|
-
let timeBeforeHandler =
|
|
39
|
+
let timeBeforeHandler = Performance.now();
|
|
37
40
|
try {
|
|
38
41
|
let contextParams = {
|
|
39
42
|
item: item,
|
|
@@ -61,13 +64,13 @@ async function runEventHandlerOrThrow(item, checkpointId, handler, indexerState,
|
|
|
61
64
|
Error: new Error()
|
|
62
65
|
};
|
|
63
66
|
}
|
|
64
|
-
let handlerDuration =
|
|
65
|
-
return Prometheus.ProcessingHandler.increment(item.eventConfig.contractName, item.eventConfig.name, handlerDuration);
|
|
67
|
+
let handlerDuration = Performance.secondsSince(timeBeforeHandler);
|
|
68
|
+
return Prometheus.ProcessingHandler.increment(item.onEventRegistration.eventConfig.contractName, item.onEventRegistration.eventConfig.name, handlerDuration);
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
async function runHandlerOrThrow(item, checkpointId, indexerState, loadManager, persistence, config, chains) {
|
|
69
72
|
if (item.kind === 0) {
|
|
70
|
-
let handler = item.
|
|
73
|
+
let handler = item.onEventRegistration.handler;
|
|
71
74
|
if (handler !== undefined) {
|
|
72
75
|
return await runEventHandlerOrThrow(item, checkpointId, handler, indexerState, loadManager, persistence, chains, config);
|
|
73
76
|
} else {
|
|
@@ -86,7 +89,7 @@ async function runHandlerOrThrow(item, checkpointId, indexerState, loadManager,
|
|
|
86
89
|
config: config,
|
|
87
90
|
isResolved: false
|
|
88
91
|
};
|
|
89
|
-
await item.
|
|
92
|
+
await item.onBlockRegistration.handler(Ecosystem.makeOnBlockArgs(item.blockNumber, config.ecosystem, UserContext.getHandlerContext(contextParams)));
|
|
90
93
|
contextParams.isResolved = true;
|
|
91
94
|
return;
|
|
92
95
|
} catch (raw_exn) {
|
|
@@ -110,11 +113,12 @@ async function preloadBatchOrThrow(batch, loadManager, persistence, config, inde
|
|
|
110
113
|
for (let idx = 0; idx < checkpointEventsProcessed; ++idx) {
|
|
111
114
|
let item = batch.items[itemIdx + idx | 0];
|
|
112
115
|
if (item.kind === 0) {
|
|
113
|
-
let match = item.
|
|
116
|
+
let match = item.onEventRegistration;
|
|
114
117
|
let handler = match.handler;
|
|
115
118
|
if (handler !== undefined) {
|
|
116
|
-
let
|
|
117
|
-
let
|
|
119
|
+
let match$1 = match.eventConfig;
|
|
120
|
+
let contractName = match$1.contractName;
|
|
121
|
+
let eventName = match$1.name;
|
|
118
122
|
try {
|
|
119
123
|
let timerRef = Prometheus.PreloadHandler.startOperation(contractName, eventName);
|
|
120
124
|
promises.push(Utils.$$Promise.silentCatch(handler({
|
|
@@ -137,7 +141,7 @@ async function preloadBatchOrThrow(batch, loadManager, persistence, config, inde
|
|
|
137
141
|
}
|
|
138
142
|
} else {
|
|
139
143
|
try {
|
|
140
|
-
promises.push(Utils.$$Promise.silentCatch(item.
|
|
144
|
+
promises.push(Utils.$$Promise.silentCatch(item.onBlockRegistration.handler(Ecosystem.makeOnBlockArgs(item.blockNumber, config.ecosystem, UserContext.getHandlerContext({
|
|
141
145
|
item: item,
|
|
142
146
|
checkpointId: checkpointId,
|
|
143
147
|
indexerState: indexerState,
|
|
@@ -171,41 +175,62 @@ async function runBatchHandlersOrThrow(batch, indexerState, loadManager, persist
|
|
|
171
175
|
}
|
|
172
176
|
}
|
|
173
177
|
|
|
174
|
-
function registerProcessEventBatchMetrics(logger, loadDuration, handlerDuration) {
|
|
175
|
-
Logging.childTrace(logger, {
|
|
176
|
-
msg: "Finished processing
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
178
|
+
function registerProcessEventBatchMetrics(logger, batch, loadDuration, handlerDuration) {
|
|
179
|
+
Stdlib_Dict.forEachWithKey(batch.progressedChainsById, (chainAfterBatch, chainId) => Logging.childTrace(logger, {
|
|
180
|
+
msg: "Finished processing",
|
|
181
|
+
chainId: Stdlib_Int.fromString(chainId, undefined),
|
|
182
|
+
batchSize: chainAfterBatch.batchSize,
|
|
183
|
+
progress: chainAfterBatch.progressBlockNumber
|
|
184
|
+
}));
|
|
180
185
|
Prometheus.ProcessingBatch.registerMetrics(loadDuration, handlerDuration);
|
|
181
186
|
}
|
|
182
187
|
|
|
188
|
+
async function materializeBatchEvents(batch, chainStates, ecosystem) {
|
|
189
|
+
let match = Object.values(chainStates);
|
|
190
|
+
if (match.length !== 1) {
|
|
191
|
+
let itemsByChain = {};
|
|
192
|
+
batch.items.forEach(item => {
|
|
193
|
+
let chainId = Internal.getItemChainId(item).toString();
|
|
194
|
+
let items = itemsByChain[chainId];
|
|
195
|
+
if (items !== undefined) {
|
|
196
|
+
items.push(item);
|
|
197
|
+
} else {
|
|
198
|
+
itemsByChain[chainId] = [item];
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
await Promise.all(Object.entries(itemsByChain).map(async param => {
|
|
202
|
+
let cs = chainStates[param[0]];
|
|
203
|
+
return await ChainState.materializeBatchItems(cs, param[1], ecosystem);
|
|
204
|
+
}));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
let cs = match[0];
|
|
208
|
+
return await ChainState.materializeBatchItems(cs, batch.items, ecosystem);
|
|
209
|
+
}
|
|
210
|
+
|
|
183
211
|
async function processEventBatch(batch, indexerState, loadManager, persistence, config, chainStates) {
|
|
184
|
-
let totalBatchSize = batch.totalBatchSize;
|
|
185
212
|
let chains = computeChainsState(chainStates);
|
|
186
213
|
let logger = Logging.getLogger();
|
|
187
|
-
Logging.childTrace(logger, {
|
|
188
|
-
msg: "Started processing
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
progress: chainAfterBatch.progressBlockNumber
|
|
193
|
-
}))
|
|
194
|
-
});
|
|
214
|
+
Stdlib_Dict.forEachWithKey(batch.progressedChainsById, (chainAfterBatch, chainId) => Logging.childTrace(logger, {
|
|
215
|
+
msg: "Started processing",
|
|
216
|
+
chainId: Stdlib_Int.fromString(chainId, undefined),
|
|
217
|
+
batchSize: chainAfterBatch.batchSize
|
|
218
|
+
}));
|
|
195
219
|
try {
|
|
196
220
|
await Writing.awaitCapacity(indexerState);
|
|
197
|
-
let timeRef =
|
|
221
|
+
let timeRef = Performance.now();
|
|
198
222
|
if (Utils.$$Array.notEmpty(batch.items)) {
|
|
223
|
+
await materializeBatchEvents(batch, chainStates, config.ecosystem.name);
|
|
199
224
|
await preloadBatchOrThrow(batch, loadManager, persistence, config, indexerState, chains);
|
|
200
225
|
}
|
|
201
|
-
let elapsedTimeAfterLoaders =
|
|
226
|
+
let elapsedTimeAfterLoaders = Performance.secondsSince(timeRef);
|
|
202
227
|
if (Utils.$$Array.notEmpty(batch.items)) {
|
|
203
228
|
await runBatchHandlersOrThrow(batch, indexerState, loadManager, persistence, config, chains);
|
|
204
229
|
}
|
|
205
|
-
let elapsedTimeAfterProcessing =
|
|
230
|
+
let elapsedTimeAfterProcessing = Performance.secondsSince(timeRef);
|
|
206
231
|
Writing.commitBatch(indexerState, batch);
|
|
207
232
|
let handlerDuration = elapsedTimeAfterProcessing - elapsedTimeAfterLoaders;
|
|
208
|
-
registerProcessEventBatchMetrics(logger, elapsedTimeAfterLoaders, handlerDuration);
|
|
233
|
+
registerProcessEventBatchMetrics(logger, batch, elapsedTimeAfterLoaders, handlerDuration);
|
|
209
234
|
return {
|
|
210
235
|
TAG: "Ok",
|
|
211
236
|
_0: undefined
|
|
@@ -240,6 +265,7 @@ export {
|
|
|
240
265
|
preloadBatchOrThrow,
|
|
241
266
|
runBatchHandlersOrThrow,
|
|
242
267
|
registerProcessEventBatchMetrics,
|
|
268
|
+
materializeBatchEvents,
|
|
243
269
|
processEventBatch,
|
|
244
270
|
}
|
|
245
271
|
/* Utils Not a pure module */
|
package/src/ExitOnCaughtUp.res
CHANGED
|
@@ -4,7 +4,15 @@ let run = async (state: IndexerState.t) => {
|
|
|
4
4
|
ChainMetadata.stage(state)
|
|
5
5
|
await state->Writing.flush
|
|
6
6
|
if !(state->IndexerState.isStopped) && !(state->IndexerState.isResolvingReorg) {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
// A simulate run fails here when a provided item never reached a handler —
|
|
8
|
+
// dead test code. The tracker is None (a no-op) off the simulate path.
|
|
9
|
+
switch state
|
|
10
|
+
->IndexerState.simulateDeadInputTracker
|
|
11
|
+
->Option.flatMap(SimulateDeadInputTracker.failureMessage) {
|
|
12
|
+
| None =>
|
|
13
|
+
Logging.info("Exiting with success")
|
|
14
|
+
NodeJs.process->NodeJs.exitWithCode(Success)
|
|
15
|
+
| Some(message) => state->IndexerState.errorExit(ErrorHandling.make(Utils.Error.make(message)))
|
|
16
|
+
}
|
|
9
17
|
}
|
|
10
18
|
}
|
|
@@ -5,11 +5,20 @@ import * as Writing from "./Writing.res.mjs";
|
|
|
5
5
|
import * as Process from "process";
|
|
6
6
|
import * as IndexerState from "./IndexerState.res.mjs";
|
|
7
7
|
import * as ChainMetadata from "./ChainMetadata.res.mjs";
|
|
8
|
+
import * as ErrorHandling from "./ErrorHandling.res.mjs";
|
|
9
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
10
|
+
import * as SimulateDeadInputTracker from "./SimulateDeadInputTracker.res.mjs";
|
|
8
11
|
|
|
9
12
|
async function run(state) {
|
|
10
13
|
ChainMetadata.stage(state);
|
|
11
14
|
await Writing.flush(state);
|
|
12
|
-
if (
|
|
15
|
+
if (IndexerState.isStopped(state) || IndexerState.isResolvingReorg(state)) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
let message = Stdlib_Option.flatMap(IndexerState.simulateDeadInputTracker(state), SimulateDeadInputTracker.failureMessage);
|
|
19
|
+
if (message !== undefined) {
|
|
20
|
+
return IndexerState.errorExit(state, ErrorHandling.make(new Error(message), undefined, undefined));
|
|
21
|
+
} else {
|
|
13
22
|
Logging.info("Exiting with success");
|
|
14
23
|
Process.exit(0);
|
|
15
24
|
return;
|