envio 3.9.0 → 3.10.0-subgraph
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/evm.schema.json +26 -0
- package/fuel.schema.json +26 -0
- package/index.d.ts +41 -8
- package/package.json +6 -7
- package/src/Batch.res +9 -0
- package/src/ChainState.res +35 -39
- package/src/ChainState.res.mjs +14 -11
- package/src/ChainState.resi +15 -7
- package/src/Config.res +61 -44
- package/src/Config.res.mjs +56 -19
- package/src/Core.res +19 -0
- package/src/Core.res.mjs +11 -0
- package/src/CrossChainState.res +15 -23
- package/src/CrossChainState.res.mjs +10 -18
- package/src/CrossChainState.resi +4 -1
- package/src/Ecosystem.res +7 -2
- package/src/Envio.res +6 -4
- package/src/EventConfigBuilder.res +169 -26
- package/src/EventConfigBuilder.res.mjs +124 -15
- package/src/EventProcessing.res +6 -6
- package/src/EventProcessing.res.mjs +8 -6
- package/src/HandlerLoader.res +20 -8
- package/src/HandlerLoader.res.mjs +11 -2
- package/src/HandlerRegister.res +21 -4
- package/src/HandlerRegister.res.mjs +24 -5
- package/src/InMemoryStore.res +9 -7
- package/src/InMemoryStore.res.mjs +3 -3
- package/src/IndexerState.res +43 -6
- package/src/IndexerState.res.mjs +36 -7
- package/src/IndexerState.resi +4 -4
- package/src/Internal.res +16 -17
- package/src/Metrics.res +72 -6
- package/src/Metrics.res.mjs +30 -2
- package/src/Persistence.res +36 -30
- package/src/Persistence.res.mjs +1 -20
- package/src/PgStorage.res +104 -56
- package/src/PgStorage.res.mjs +57 -35
- package/src/PruneStaleHistory.res +85 -52
- package/src/PruneStaleHistory.res.mjs +63 -37
- package/src/Rollback.res +68 -45
- package/src/Rollback.res.mjs +38 -19
- package/src/RollbackCommit.res +7 -9
- package/src/RollbackCommit.res.mjs +5 -6
- package/src/SafeCheckpointTracking.res +11 -11
- package/src/SafeCheckpointTracking.res.mjs +7 -6
- package/src/SimulateItems.res +33 -18
- package/src/SimulateItems.res.mjs +26 -22
- package/src/Sink.res +38 -26
- package/src/Sink.res.mjs +21 -16
- package/src/TestIndexer.res +5 -5
- package/src/TestIndexer.res.mjs +1 -1
- package/src/UserContext.res +358 -51
- package/src/UserContext.res.mjs +271 -35
- package/src/Utils.res +170 -0
- package/src/Utils.res.mjs +153 -0
- package/src/Writing.res +2 -2
- package/src/Writing.res.mjs +1 -1
- package/src/bindings/ClickHouse.res +366 -698
- package/src/bindings/ClickHouse.res.mjs +371 -421
- package/src/bindings/ClickHouseSink.res +337 -0
- package/src/bindings/ClickHouseSink.res.mjs +246 -0
- package/src/bindings/EventSource.res +8 -2
- package/src/bindings/NodeJs.res +6 -0
- package/src/bindings/Vitest.res +23 -0
- package/src/bindings/Vitest.res.mjs +3 -0
- package/src/bindings/WebSocket.res +9 -10
- package/src/db/CheckpointBounds.res +53 -0
- package/src/db/CheckpointBounds.res.mjs +44 -0
- package/src/db/EntityFilter.res +36 -17
- package/src/db/EntityFilter.res.mjs +25 -14
- package/src/db/EntityHistory.res +47 -22
- package/src/db/EntityHistory.res.mjs +19 -12
- package/src/db/InternalTable.res +84 -35
- package/src/db/InternalTable.res.mjs +56 -23
- package/src/db/RollbackFloors.res +55 -0
- package/src/db/RollbackFloors.res.mjs +92 -0
- package/src/db/Table.res +22 -4
- package/src/db/Table.res.mjs +30 -9
- package/src/sources/Evm.res +2 -0
- package/src/sources/Evm.res.mjs +2 -0
- package/src/sources/EvmHyperSyncSource.res +3 -3
- package/src/sources/EvmHyperSyncSource.res.mjs +3 -3
- package/src/sources/EvmRpcWs.res +124 -0
- package/src/sources/EvmRpcWs.res.mjs +117 -0
- package/src/sources/Fuel.res +2 -0
- package/src/sources/Fuel.res.mjs +2 -0
- package/src/sources/FuelHyperSyncSource.res +1 -1
- package/src/sources/FuelHyperSyncSource.res.mjs +2 -1
- package/src/sources/HeightFeed.res +568 -0
- package/src/sources/HeightFeed.res.mjs +452 -0
- package/src/sources/HeightStream.res +257 -0
- package/src/sources/HeightStream.res.mjs +194 -0
- package/src/sources/HyperSync.res +5 -0
- package/src/sources/HyperSync.res.mjs +3 -0
- package/src/sources/HyperSync.resi +4 -0
- package/src/sources/HyperSyncSSE.res +49 -0
- package/src/sources/HyperSyncSSE.res.mjs +79 -0
- package/src/sources/RpcSource.res +1 -1
- package/src/sources/RpcSource.res.mjs +2 -2
- package/src/sources/Source.res +54 -1
- package/src/sources/Source.res.mjs +25 -0
- package/src/sources/SourceManager.res +220 -227
- package/src/sources/SourceManager.res.mjs +139 -164
- package/src/sources/SourceManager.resi +8 -0
- package/src/sources/Svm.res +2 -0
- package/src/sources/Svm.res.mjs +2 -0
- package/src/sources/SvmHyperSyncClient.res +70 -127
- package/src/sources/SvmHyperSyncClient.res.mjs +51 -25
- package/src/sources/SvmHyperSyncSource.res +18 -15
- package/src/sources/SvmHyperSyncSource.res.mjs +5 -4
- package/src/subgraph/blocks.ts +176 -0
- package/src/subgraph/calls.ts +217 -0
- package/src/subgraph/conformance.ts +102 -0
- package/src/subgraph/division.ts +133 -0
- package/src/subgraph/errors.ts +90 -0
- package/src/subgraph/graph-ts-types/VERSION +2 -0
- package/src/subgraph/graph-ts-types/chain/arweave.d.ts +70 -0
- package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +327 -0
- package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +233 -0
- package/src/subgraph/graph-ts-types/chain/near.d.ts +253 -0
- package/src/subgraph/graph-ts-types/chain/starknet.d.ts +32 -0
- package/src/subgraph/graph-ts-types/common/collections.d.ts +136 -0
- package/src/subgraph/graph-ts-types/common/conversion.d.ts +11 -0
- package/src/subgraph/graph-ts-types/common/datasource.d.ts +30 -0
- package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
- package/src/subgraph/graph-ts-types/common/json.d.ts +17 -0
- package/src/subgraph/graph-ts-types/common/numbers.d.ts +120 -0
- package/src/subgraph/graph-ts-types/common/value.d.ts +120 -0
- package/src/subgraph/graph-ts-types/common/yaml.d.ts +90 -0
- package/src/subgraph/graph-ts-types/global/global.d.ts +194 -0
- package/src/subgraph/graph-ts-types/helper-functions.d.ts +22 -0
- package/src/subgraph/graph-ts-types/index.d.ts +102 -0
- package/src/subgraph/graph-ts.ts +1948 -0
- package/src/subgraph/hosts.ts +148 -0
- package/src/subgraph/runtime.ts +863 -0
- package/src/subgraph/scope.ts +66 -0
- package/svm.schema.json +6 -81
- package/src/MemoryStorage.res +0 -729
- package/src/MemoryStorage.res.mjs +0 -586
- package/src/sources/HyperSyncHeightStream.res +0 -129
- package/src/sources/HyperSyncHeightStream.res.mjs +0 -110
- package/src/sources/RpcWebSocketHeightStream.res +0 -175
- package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -180
|
@@ -14,6 +14,7 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
|
14
14
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
15
15
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
16
16
|
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
17
|
+
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
17
18
|
|
|
18
19
|
let paramMetaSchema = S$RescriptSchema.recursive(self => S$RescriptSchema.object(s => ({
|
|
19
20
|
name: s.f("name", S$RescriptSchema.string),
|
|
@@ -261,17 +262,13 @@ let svmSelectionKinds = [
|
|
|
261
262
|
"log"
|
|
262
263
|
];
|
|
263
264
|
|
|
264
|
-
function quotedJoin(names) {
|
|
265
|
-
return names.map(name => `"` + name + `"`).join(", ");
|
|
266
|
-
}
|
|
267
|
-
|
|
268
265
|
function validateFieldsShapeOrThrow(fields, registration, validKeys, shapeNoun) {
|
|
269
266
|
if (typeof fields !== "object" || fields === null || Array.isArray(fields)) {
|
|
270
267
|
Stdlib_JsError.throwWithMessage(`The fields option of ` + registration + ` must be an object of ` + shapeNoun + ` field names.`);
|
|
271
268
|
}
|
|
272
269
|
Object.keys(fields).forEach(key => {
|
|
273
270
|
if (!validKeys.includes(key)) {
|
|
274
|
-
return Stdlib_JsError.throwWithMessage(`Invalid "` + key + `" key in the fields option of ` + registration + `. Valid keys: ` + quotedJoin(validKeys) + `.`);
|
|
271
|
+
return Stdlib_JsError.throwWithMessage(`Invalid "` + key + `" key in the fields option of ` + registration + `. Valid keys: ` + Utils.$$Array.quotedJoin(validKeys) + `.`);
|
|
275
272
|
}
|
|
276
273
|
});
|
|
277
274
|
}
|
|
@@ -295,7 +292,7 @@ function parseFieldsOrThrow(fields, valid, kind, registration, rejectEmptyOpt) {
|
|
|
295
292
|
) : [];
|
|
296
293
|
fields$1.forEach(name => {
|
|
297
294
|
if (!valid.has(name)) {
|
|
298
|
-
Stdlib_JsError.throwWithMessage(`Invalid "` + name + `" field in the fields.` + kind + ` option of ` + registration + `. Valid ` + kind + ` fields: ` + quotedJoin(Array.from(valid)) + `.`);
|
|
295
|
+
Stdlib_JsError.throwWithMessage(`Invalid "` + name + `" field in the fields.` + kind + ` option of ` + registration + `. Valid ` + kind + ` fields: ` + Utils.$$Array.quotedJoin(Array.from(valid)) + `.`);
|
|
299
296
|
}
|
|
300
297
|
if (seen.has(name)) {
|
|
301
298
|
Stdlib_JsError.throwWithMessage(`Duplicate "` + name + `" field in the fields.` + kind + ` option of ` + registration + `.`);
|
|
@@ -420,7 +417,7 @@ let validSvmLogFields = new Set([
|
|
|
420
417
|
]);
|
|
421
418
|
|
|
422
419
|
function resolveSvmInlineFieldSelection(fields, contractName, eventName) {
|
|
423
|
-
let registration = `the "` + eventName + `"
|
|
420
|
+
let registration = `the "` + eventName + `" instruction on program "` + contractName + `"`;
|
|
424
421
|
validateFieldsShapeOrThrow(fields, registration, svmSelectionKinds, "instruction, transaction, accountActivity, block and log");
|
|
425
422
|
let accountActivity = selectionList(fields, "accountActivity");
|
|
426
423
|
let log = selectionList(fields, "log");
|
|
@@ -436,7 +433,7 @@ function resolveSvmInlineFieldSelection(fields, contractName, eventName) {
|
|
|
436
433
|
return Internal.makeFieldSelection(blockFields, transactionFields, Primitive_option.some(instructionFields), Primitive_option.some(accountActivityFields), Primitive_option.some(logFields), Svm.eventBlockFieldMask, Svm.eventTransactionFieldMask);
|
|
437
434
|
}
|
|
438
435
|
|
|
439
|
-
function buildSvmInstructionEventConfig(contractName, instructionName, programId, discriminator,
|
|
436
|
+
function buildSvmInstructionEventConfig(contractName, instructionName, programId, discriminator, accountsOpt, argsOpt, definedTypesOpt) {
|
|
440
437
|
let accounts = accountsOpt !== undefined ? accountsOpt : [];
|
|
441
438
|
let args = argsOpt !== undefined ? argsOpt : null;
|
|
442
439
|
let definedTypes = definedTypesOpt !== undefined ? definedTypesOpt : null;
|
|
@@ -451,16 +448,121 @@ function buildSvmInstructionEventConfig(contractName, instructionName, programId
|
|
|
451
448
|
fieldSelection: fieldSelection,
|
|
452
449
|
programId: programId,
|
|
453
450
|
discriminator: discriminator,
|
|
454
|
-
discriminatorByteLen: discriminatorByteLen,
|
|
455
|
-
accountFilters: accountFilters,
|
|
456
|
-
isInner: isInner,
|
|
457
451
|
accounts: accounts,
|
|
458
452
|
args: args,
|
|
459
453
|
definedTypes: definedTypes
|
|
460
454
|
};
|
|
461
455
|
}
|
|
462
456
|
|
|
463
|
-
|
|
457
|
+
let validSvmWhereKeys = [
|
|
458
|
+
"accounts",
|
|
459
|
+
"isInner",
|
|
460
|
+
"block"
|
|
461
|
+
];
|
|
462
|
+
|
|
463
|
+
let svmBlockFilterSchema = S$RescriptSchema.strict(S$RescriptSchema.object(s => ({
|
|
464
|
+
slot: s.f("slot", S$RescriptSchema.option(LogSelection.eventBlockRangeSchema))
|
|
465
|
+
})));
|
|
466
|
+
|
|
467
|
+
function resolveSvmWhereOrThrow(where, contractName, eventName, accountNames) {
|
|
468
|
+
let invalid = message => Stdlib_JsError.throwWithMessage(`Invalid where configuration for the "` + eventName + `" instruction on program "` + contractName + `". ` + message);
|
|
469
|
+
let obj;
|
|
470
|
+
obj = typeof where === "object" && where !== null && !Array.isArray(where) ? where : invalid("Expected an object.");
|
|
471
|
+
Utils.Dict.forEachWithKey(obj, (param, key) => {
|
|
472
|
+
if (!validSvmWhereKeys.includes(key)) {
|
|
473
|
+
return invalid(`Unknown field "` + key + `". Valid fields: ` + Utils.$$Array.quotedJoin(validSvmWhereKeys) + `.`);
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
let match = obj["isInner"];
|
|
477
|
+
let isInner = match !== undefined ? (
|
|
478
|
+
typeof match === "boolean" ? match : invalid(`The "isInner" filter must be a boolean.`)
|
|
479
|
+
) : undefined;
|
|
480
|
+
let parseGroup = group => Object.entries(group).map(param => {
|
|
481
|
+
let name = param[0];
|
|
482
|
+
let position = accountNames.indexOf(name);
|
|
483
|
+
let position$1 = position !== -1 ? (
|
|
484
|
+
position >= 10 ? invalid(`Account "` + name + `" is at position ` + position.toString() + `, and only the first ` + (10).toString() + ` accounts of an instruction can be filtered.`) : position
|
|
485
|
+
) : (
|
|
486
|
+
Utils.$$Array.isEmpty(accountNames) ? invalid("The instruction has no named accounts to filter on. Add `accounts` and `args` to it in config.yaml, or attach an IDL.") : invalid(`The instruction has no account named "` + name + `" to filter on. Named accounts: ` + Utils.$$Array.quotedJoin(accountNames) + `.`)
|
|
487
|
+
);
|
|
488
|
+
let values = normalizeOrThrow(param[1]);
|
|
489
|
+
if (Utils.$$Array.isEmpty(values)) {
|
|
490
|
+
invalid(`The "` + name + `" filter must list at least one pubkey.`);
|
|
491
|
+
}
|
|
492
|
+
return {
|
|
493
|
+
position: position$1,
|
|
494
|
+
values: values.map(value => {
|
|
495
|
+
if (typeof value === "string") {
|
|
496
|
+
if (Core.getAddon().isSvmPubkey(value)) {
|
|
497
|
+
return value;
|
|
498
|
+
} else {
|
|
499
|
+
return invalid(`The "` + name + `" filter value "` + value + `" is not a base58 SVM pubkey.`);
|
|
500
|
+
}
|
|
501
|
+
} else {
|
|
502
|
+
return invalid(`The "` + name + `" filter must list base58 pubkeys as strings.`);
|
|
503
|
+
}
|
|
504
|
+
})
|
|
505
|
+
};
|
|
506
|
+
});
|
|
507
|
+
let match$1 = obj["accounts"];
|
|
508
|
+
let groups;
|
|
509
|
+
if (match$1 !== undefined) {
|
|
510
|
+
if (Array.isArray(match$1)) {
|
|
511
|
+
groups = match$1.map(entry => {
|
|
512
|
+
if (typeof entry === "object" && entry !== null && !Array.isArray(entry)) {
|
|
513
|
+
return parseGroup(entry);
|
|
514
|
+
} else {
|
|
515
|
+
return invalid(`Each entry in "accounts" must be an object.`);
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
} else if (match$1 === null) {
|
|
519
|
+
groups = invalid(`Expected "accounts" to be an object or an array of objects.`);
|
|
520
|
+
} else {
|
|
521
|
+
switch (typeof match$1) {
|
|
522
|
+
case "object" :
|
|
523
|
+
groups = [parseGroup(match$1)];
|
|
524
|
+
break;
|
|
525
|
+
default:
|
|
526
|
+
groups = invalid(`Expected "accounts" to be an object or an array of objects.`);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
} else {
|
|
530
|
+
groups = [];
|
|
531
|
+
}
|
|
532
|
+
let accountFilters = groups.some(Utils.$$Array.isEmpty) ? [] : groups;
|
|
533
|
+
let block = obj["block"];
|
|
534
|
+
let startBlock;
|
|
535
|
+
if (block !== undefined) {
|
|
536
|
+
let filter;
|
|
537
|
+
try {
|
|
538
|
+
filter = S$RescriptSchema.parseOrThrow(block, svmBlockFilterSchema);
|
|
539
|
+
} catch (raw_exn) {
|
|
540
|
+
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
541
|
+
if (exn.RE_EXN_ID === S$RescriptSchema.Raised) {
|
|
542
|
+
filter = invalid(`The "block" filter is invalid: ` + Utils.prettifyExn(exn._1) + `. Only \`_gte\` is supported on instruction filters — use \`indexer.onSlot\` for \`_lte\` or \`_every\`.`);
|
|
543
|
+
} else {
|
|
544
|
+
throw exn;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
let match$2 = filter.slot;
|
|
548
|
+
startBlock = match$2 !== undefined ? match$2._gte : undefined;
|
|
549
|
+
} else {
|
|
550
|
+
startBlock = undefined;
|
|
551
|
+
}
|
|
552
|
+
return {
|
|
553
|
+
accountFilters: accountFilters,
|
|
554
|
+
isInner: isInner,
|
|
555
|
+
startBlock: startBlock
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, where, fieldSelection, startBlock) {
|
|
560
|
+
let resolvedWhere = where !== undefined ? resolveSvmWhereOrThrow(where, eventConfig.contractName, eventConfig.name, eventConfig.accounts) : ({
|
|
561
|
+
accountFilters: [],
|
|
562
|
+
isInner: undefined,
|
|
563
|
+
startBlock: undefined
|
|
564
|
+
});
|
|
565
|
+
let sb = resolvedWhere.startBlock;
|
|
464
566
|
return {
|
|
465
567
|
index: -1,
|
|
466
568
|
eventConfig: eventConfig,
|
|
@@ -469,8 +571,10 @@ function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractR
|
|
|
469
571
|
isWildcard: isWildcard,
|
|
470
572
|
filterByAddresses: false,
|
|
471
573
|
dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, false),
|
|
472
|
-
startBlock: startBlock,
|
|
473
|
-
fieldSelection: fieldSelection !== undefined ? fieldSelection : eventConfig.fieldSelection
|
|
574
|
+
startBlock: sb !== undefined ? sb : startBlock,
|
|
575
|
+
fieldSelection: fieldSelection !== undefined ? fieldSelection : eventConfig.fieldSelection,
|
|
576
|
+
accountFilters: resolvedWhere.accountFilters,
|
|
577
|
+
isInner: resolvedWhere.isInner
|
|
474
578
|
};
|
|
475
579
|
}
|
|
476
580
|
|
|
@@ -542,6 +646,8 @@ function buildFuelOnEventRegistration(eventConfig, isWildcard, handler, contract
|
|
|
542
646
|
};
|
|
543
647
|
}
|
|
544
648
|
|
|
649
|
+
let filterableAccountCount = 10;
|
|
650
|
+
|
|
545
651
|
export {
|
|
546
652
|
paramMetaSchema,
|
|
547
653
|
normalizeOrThrow,
|
|
@@ -561,7 +667,6 @@ export {
|
|
|
561
667
|
rawEventBlockFields,
|
|
562
668
|
evmSelectionKinds,
|
|
563
669
|
svmSelectionKinds,
|
|
564
|
-
quotedJoin,
|
|
565
670
|
validateFieldsShapeOrThrow,
|
|
566
671
|
selectionList,
|
|
567
672
|
validBlockFields,
|
|
@@ -578,6 +683,10 @@ export {
|
|
|
578
683
|
validSvmLogFields,
|
|
579
684
|
resolveSvmInlineFieldSelection,
|
|
580
685
|
buildSvmInstructionEventConfig,
|
|
686
|
+
validSvmWhereKeys,
|
|
687
|
+
svmBlockFilterSchema,
|
|
688
|
+
filterableAccountCount,
|
|
689
|
+
resolveSvmWhereOrThrow,
|
|
581
690
|
buildSvmOnEventRegistration,
|
|
582
691
|
buildFuelEventConfig,
|
|
583
692
|
buildFuelOnEventRegistration,
|
package/src/EventProcessing.res
CHANGED
|
@@ -51,7 +51,7 @@ let runEventHandlerOrThrow = async (
|
|
|
51
51
|
isPreload: false,
|
|
52
52
|
chains,
|
|
53
53
|
config,
|
|
54
|
-
|
|
54
|
+
sync: UserContext.makeSyncState(),
|
|
55
55
|
}
|
|
56
56
|
await handler(
|
|
57
57
|
(
|
|
@@ -61,7 +61,7 @@ let runEventHandlerOrThrow = async (
|
|
|
61
61
|
}: Internal.handlerArgs
|
|
62
62
|
),
|
|
63
63
|
)
|
|
64
|
-
contextParams.
|
|
64
|
+
contextParams.sync.status = Resolved
|
|
65
65
|
} catch {
|
|
66
66
|
| exn =>
|
|
67
67
|
throw(
|
|
@@ -102,7 +102,7 @@ let runHandlerOrThrow = async (
|
|
|
102
102
|
isPreload: false,
|
|
103
103
|
chains,
|
|
104
104
|
config,
|
|
105
|
-
|
|
105
|
+
sync: UserContext.makeSyncState(),
|
|
106
106
|
}
|
|
107
107
|
await handler(
|
|
108
108
|
Ecosystem.makeOnBlockArgs(
|
|
@@ -111,7 +111,7 @@ let runHandlerOrThrow = async (
|
|
|
111
111
|
~context=UserContext.getHandlerContext(contextParams),
|
|
112
112
|
),
|
|
113
113
|
)
|
|
114
|
-
contextParams.
|
|
114
|
+
contextParams.sync.status = Resolved
|
|
115
115
|
} catch {
|
|
116
116
|
| exn =>
|
|
117
117
|
throw(
|
|
@@ -186,7 +186,7 @@ let preloadBatchOrThrow = async (
|
|
|
186
186
|
checkpointId,
|
|
187
187
|
isPreload: true,
|
|
188
188
|
chains,
|
|
189
|
-
|
|
189
|
+
sync: UserContext.makeSyncState(),
|
|
190
190
|
config,
|
|
191
191
|
}),
|
|
192
192
|
})
|
|
@@ -221,7 +221,7 @@ let preloadBatchOrThrow = async (
|
|
|
221
221
|
checkpointId,
|
|
222
222
|
isPreload: true,
|
|
223
223
|
chains,
|
|
224
|
-
|
|
224
|
+
sync: UserContext.makeSyncState(),
|
|
225
225
|
config,
|
|
226
226
|
}),
|
|
227
227
|
)
|
|
@@ -38,6 +38,7 @@ let ProcessingError = /* @__PURE__ */Primitive_exceptions.create("EventProcessin
|
|
|
38
38
|
async function runEventHandlerOrThrow(item, checkpointId, handler, indexerState, loadManager, persistence, chains, config) {
|
|
39
39
|
let timeBeforeHandler = Performance.now();
|
|
40
40
|
try {
|
|
41
|
+
let contextParams_sync = UserContext.makeSyncState();
|
|
41
42
|
let contextParams = {
|
|
42
43
|
item: item,
|
|
43
44
|
checkpointId: checkpointId,
|
|
@@ -47,13 +48,13 @@ async function runEventHandlerOrThrow(item, checkpointId, handler, indexerState,
|
|
|
47
48
|
isPreload: false,
|
|
48
49
|
chains: chains,
|
|
49
50
|
config: config,
|
|
50
|
-
|
|
51
|
+
sync: contextParams_sync
|
|
51
52
|
};
|
|
52
53
|
await handler({
|
|
53
54
|
event: Ecosystem.getItemEvent(item, config.ecosystem),
|
|
54
55
|
context: UserContext.getHandlerContext(contextParams)
|
|
55
56
|
});
|
|
56
|
-
|
|
57
|
+
contextParams_sync.status = "Resolved";
|
|
57
58
|
} catch (raw_exn) {
|
|
58
59
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
59
60
|
throw {
|
|
@@ -79,6 +80,7 @@ async function runHandlerOrThrow(item, checkpointId, indexerState, loadManager,
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
try {
|
|
83
|
+
let contextParams_sync = UserContext.makeSyncState();
|
|
82
84
|
let contextParams = {
|
|
83
85
|
item: item,
|
|
84
86
|
checkpointId: checkpointId,
|
|
@@ -88,10 +90,10 @@ async function runHandlerOrThrow(item, checkpointId, indexerState, loadManager,
|
|
|
88
90
|
isPreload: false,
|
|
89
91
|
chains: chains,
|
|
90
92
|
config: config,
|
|
91
|
-
|
|
93
|
+
sync: contextParams_sync
|
|
92
94
|
};
|
|
93
95
|
await item.onBlockRegistration.handler(Ecosystem.makeOnBlockArgs(item.blockNumber, config.ecosystem, UserContext.getHandlerContext(contextParams)));
|
|
94
|
-
|
|
96
|
+
contextParams_sync.status = "Resolved";
|
|
95
97
|
return;
|
|
96
98
|
} catch (raw_exn) {
|
|
97
99
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
@@ -133,7 +135,7 @@ async function preloadBatchOrThrow(batch, loadManager, persistence, config, inde
|
|
|
133
135
|
isPreload: true,
|
|
134
136
|
chains: chains,
|
|
135
137
|
config: config,
|
|
136
|
-
|
|
138
|
+
sync: UserContext.makeSyncState()
|
|
137
139
|
})
|
|
138
140
|
}).then(() => IndexerState.endPreloadHandler(indexerState, timerRef, contractName, eventName))));
|
|
139
141
|
} catch (exn) {
|
|
@@ -151,7 +153,7 @@ async function preloadBatchOrThrow(batch, loadManager, persistence, config, inde
|
|
|
151
153
|
isPreload: true,
|
|
152
154
|
chains: chains,
|
|
153
155
|
config: config,
|
|
154
|
-
|
|
156
|
+
sync: UserContext.makeSyncState()
|
|
155
157
|
})))));
|
|
156
158
|
} catch (exn$1) {
|
|
157
159
|
|
package/src/HandlerLoader.res
CHANGED
|
@@ -77,18 +77,30 @@ let autoLoadFromSrcHandlers = async (~handlers: string) => {
|
|
|
77
77
|
// `HandlerRegister.finishRegistration`. This loads the user handler files
|
|
78
78
|
// (populating the global `HandlerRegister` registry as a side effect) and
|
|
79
79
|
// returns the resulting per-chain registrations.
|
|
80
|
+
// The subgraph runtime lives in this package but is never exported: it's
|
|
81
|
+
// reached only from here, when the resolved config carries a translated
|
|
82
|
+
// manifest.
|
|
83
|
+
let registerSubgraph: (JSON.t, ~isDev: bool) => promise<unit> = %raw(`(subgraph, isDev) =>
|
|
84
|
+
import("./subgraph/runtime.ts").then((m) => m.registerSubgraph({ ...subgraph, isDev }))`)
|
|
85
|
+
|
|
80
86
|
let registerAllHandlers = async (~config: Config.t): HandlerRegister.registrationsByChainId => {
|
|
81
87
|
HandlerRegister.startRegistration(~config)
|
|
82
88
|
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
switch config.subgraph {
|
|
90
|
+
// A subgraph project's `src/` holds AssemblyScript mappings, not envio
|
|
91
|
+
// handlers, so the usual auto-load would import them without a scope.
|
|
92
|
+
| Some(subgraph) => await registerSubgraph(subgraph, ~isDev=config.isDev)
|
|
93
|
+
| None =>
|
|
94
|
+
// Auto-load all .js files from src/handlers directory
|
|
95
|
+
await autoLoadFromSrcHandlers(~handlers=config.handlers)
|
|
85
96
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
// Load contract-specific handlers
|
|
98
|
+
let _ = await config.contractHandlers
|
|
99
|
+
->Array.map(({name, handler}) => {
|
|
100
|
+
registerContractHandlers(~contractName=name, ~handler)
|
|
101
|
+
})
|
|
102
|
+
->Promise.all
|
|
103
|
+
}
|
|
92
104
|
|
|
93
105
|
HandlerRegister.finishRegistration(~config)
|
|
94
106
|
}
|
|
@@ -56,10 +56,18 @@ async function autoLoadFromSrcHandlers(handlers) {
|
|
|
56
56
|
})));
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
let registerSubgraph = ((subgraph, isDev) =>
|
|
60
|
+
import("./subgraph/runtime.ts").then((m) => m.registerSubgraph({ ...subgraph, isDev })));
|
|
61
|
+
|
|
59
62
|
async function registerAllHandlers(config) {
|
|
60
63
|
HandlerRegister.startRegistration(config);
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
let subgraph = config.subgraph;
|
|
65
|
+
if (subgraph !== undefined) {
|
|
66
|
+
await registerSubgraph(subgraph, config.isDev);
|
|
67
|
+
} else {
|
|
68
|
+
await autoLoadFromSrcHandlers(config.handlers);
|
|
69
|
+
await Promise.all(config.contractHandlers.map(param => registerContractHandlers(param.name, param.handler)));
|
|
70
|
+
}
|
|
63
71
|
return HandlerRegister.finishRegistration(config);
|
|
64
72
|
}
|
|
65
73
|
|
|
@@ -67,6 +75,7 @@ export {
|
|
|
67
75
|
toImportUrl,
|
|
68
76
|
registerContractHandlers,
|
|
69
77
|
autoLoadFromSrcHandlers,
|
|
78
|
+
registerSubgraph,
|
|
70
79
|
registerAllHandlers,
|
|
71
80
|
}
|
|
72
81
|
/* Not a pure module */
|
package/src/HandlerRegister.res
CHANGED
|
@@ -154,6 +154,7 @@ let buildOnEventRegistrationWith = (
|
|
|
154
154
|
~isWildcard,
|
|
155
155
|
~handler,
|
|
156
156
|
~contractRegister,
|
|
157
|
+
~where,
|
|
157
158
|
~fieldSelection?,
|
|
158
159
|
~startBlock?,
|
|
159
160
|
) :> Internal.onEventRegistration)
|
|
@@ -320,7 +321,7 @@ let addOnEventRegistration = (
|
|
|
320
321
|
)
|
|
321
322
|
| Fuel =>
|
|
322
323
|
JsError.throwWithMessage(
|
|
323
|
-
`The fields option of the "${eventName}" event registration on contract "${contractName}" is
|
|
324
|
+
`The fields option of the "${eventName}" event registration on contract "${contractName}" is not supported on Fuel. Select the fields in your config instead.`,
|
|
324
325
|
)
|
|
325
326
|
}
|
|
326
327
|
}
|
|
@@ -335,6 +336,21 @@ let addOnEventRegistration = (
|
|
|
335
336
|
| None => ()
|
|
336
337
|
| Some(eventConfig) =>
|
|
337
338
|
matched := true
|
|
339
|
+
switch (registration.config.ecosystem.name, fieldSelection) {
|
|
340
|
+
| (Svm, Some(fieldSelection)) if fieldSelection.instructionFields->Utils.Set.has("args") =>
|
|
341
|
+
let svmEventConfig =
|
|
342
|
+
eventConfig->(Utils.magic: Internal.eventConfig => Internal.svmInstructionEventConfig)
|
|
343
|
+
let declaresArgs = switch svmEventConfig.args {
|
|
344
|
+
| JSON.Array(args) => args->Array.length > 0
|
|
345
|
+
| _ => false
|
|
346
|
+
}
|
|
347
|
+
if !declaresArgs {
|
|
348
|
+
JsError.throwWithMessage(
|
|
349
|
+
`Invalid "args" field in the fields.instruction option of the "${eventName}" instruction on program "${contractName}". The instruction declares no args in config.yaml, so there is nothing to decode. Remove "args" from the selection, or declare the instruction's args.`,
|
|
350
|
+
)
|
|
351
|
+
}
|
|
352
|
+
| _ => ()
|
|
353
|
+
}
|
|
338
354
|
let reg = buildOnEventRegistrationWith(
|
|
339
355
|
~config=registration.config,
|
|
340
356
|
~chainId=chainConfig.id,
|
|
@@ -359,17 +375,18 @@ let addOnEventRegistration = (
|
|
|
359
375
|
if !matched.contents {
|
|
360
376
|
let (contractNames, eventNames) = registration->describeConfigured(~contractName)
|
|
361
377
|
let listOr = (names, empty) =>
|
|
362
|
-
names->Utils.Array.isEmpty ? empty : names->Array.
|
|
378
|
+
names->Utils.Array.isEmpty ? empty : names->Utils.Array.quotedJoin
|
|
379
|
+
let {contractNoun, eventNoun} = registration.config.ecosystem
|
|
363
380
|
if eventNames->Utils.Array.isEmpty {
|
|
364
381
|
JsError.throwWithMessage(
|
|
365
|
-
|
|
382
|
+
`${contractNoun->Utils.String.capitalize} "${contractName}" is not configured on any chain, so its handler for "${eventName}" would never run. Add it to your config, or remove the registration. Configured ${contractNoun}s: ${listOr(
|
|
366
383
|
contractNames,
|
|
367
384
|
"none",
|
|
368
385
|
)}.`,
|
|
369
386
|
)
|
|
370
387
|
} else {
|
|
371
388
|
JsError.throwWithMessage(
|
|
372
|
-
|
|
389
|
+
`${eventNoun->Utils.String.capitalize} "${eventName}" is not configured on ${contractNoun} "${contractName}", so its handler would never run. Add it to your config, or remove the registration. Configured ${eventNoun}s on "${contractName}": ${listOr(
|
|
373
390
|
eventNames,
|
|
374
391
|
"none",
|
|
375
392
|
)}.`,
|
|
@@ -102,7 +102,7 @@ function buildOnEventRegistrationWith(config, chainId, eventConfig, isWildcard,
|
|
|
102
102
|
case "fuel" :
|
|
103
103
|
return EventConfigBuilder.buildFuelOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, startBlock);
|
|
104
104
|
case "svm" :
|
|
105
|
-
return EventConfigBuilder.buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, fieldSelection, startBlock);
|
|
105
|
+
return EventConfigBuilder.buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, where, fieldSelection, startBlock);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -209,7 +209,7 @@ function addOnEventRegistration(registration, contractName, eventName, handler,
|
|
|
209
209
|
fieldSelection = EventConfigBuilder.resolveInlineFieldSelection(fields$1, contractName, eventName, registration.config.enableRawEvents);
|
|
210
210
|
break;
|
|
211
211
|
case "fuel" :
|
|
212
|
-
fieldSelection = Stdlib_JsError.throwWithMessage(`The fields option of the "` + eventName + `" event registration on contract "` + contractName + `" is
|
|
212
|
+
fieldSelection = Stdlib_JsError.throwWithMessage(`The fields option of the "` + eventName + `" event registration on contract "` + contractName + `" is not supported on Fuel. Select the fields in your config instead.`);
|
|
213
213
|
break;
|
|
214
214
|
case "svm" :
|
|
215
215
|
fieldSelection = EventConfigBuilder.resolveSvmInlineFieldSelection(fields$1, contractName, eventName);
|
|
@@ -231,6 +231,22 @@ function addOnEventRegistration(registration, contractName, eventName, handler,
|
|
|
231
231
|
return;
|
|
232
232
|
}
|
|
233
233
|
matched.contents = true;
|
|
234
|
+
let match = registration.config.ecosystem.name;
|
|
235
|
+
switch (match) {
|
|
236
|
+
case "evm" :
|
|
237
|
+
case "fuel" :
|
|
238
|
+
break;
|
|
239
|
+
case "svm" :
|
|
240
|
+
if (fieldSelection !== undefined && fieldSelection.instructionFields.has("args")) {
|
|
241
|
+
let args = eventConfig.args;
|
|
242
|
+
let declaresArgs;
|
|
243
|
+
declaresArgs = Array.isArray(args) ? args.length !== 0 : false;
|
|
244
|
+
if (!declaresArgs) {
|
|
245
|
+
Stdlib_JsError.throwWithMessage(`Invalid "args" field in the fields.instruction option of the "` + eventName + `" instruction on program "` + contractName + `". The instruction declares no args in config.yaml, so there is nothing to decode. Remove "args" from the selection, or declare the instruction's args.`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
234
250
|
let reg = buildOnEventRegistrationWith(registration.config, chainConfig.id, eventConfig, isWildcard, handler, contractRegister, where, fieldSelection, contract.startBlock);
|
|
235
251
|
getChainRegistrations(registration, chainConfig.id).onEventRegistrations.push(reg);
|
|
236
252
|
});
|
|
@@ -243,13 +259,16 @@ function addOnEventRegistration(registration, contractName, eventName, handler,
|
|
|
243
259
|
if (Utils.$$Array.isEmpty(names)) {
|
|
244
260
|
return empty;
|
|
245
261
|
} else {
|
|
246
|
-
return
|
|
262
|
+
return Utils.$$Array.quotedJoin(names);
|
|
247
263
|
}
|
|
248
264
|
};
|
|
265
|
+
let match$2 = registration.config.ecosystem;
|
|
266
|
+
let eventNoun = match$2.eventNoun;
|
|
267
|
+
let contractNoun = match$2.contractNoun;
|
|
249
268
|
if (Utils.$$Array.isEmpty(eventNames)) {
|
|
250
|
-
return Stdlib_JsError.throwWithMessage(`
|
|
269
|
+
return Stdlib_JsError.throwWithMessage(Utils.$$String.capitalize(contractNoun) + ` "` + contractName + `" is not configured on any chain, so its handler for "` + eventName + `" would never run. Add it to your config, or remove the registration. Configured ` + contractNoun + `s: ` + listOr(match$1[0], "none") + `.`);
|
|
251
270
|
} else {
|
|
252
|
-
return Stdlib_JsError.throwWithMessage(`
|
|
271
|
+
return Stdlib_JsError.throwWithMessage(Utils.$$String.capitalize(eventNoun) + ` "` + eventName + `" is not configured on ` + contractNoun + ` "` + contractName + `", so its handler would never run. Add it to your config, or remove the registration. Configured ` + eventNoun + `s on "` + contractName + `": ` + listOr(eventNames, "none") + `.`);
|
|
253
272
|
}
|
|
254
273
|
}
|
|
255
274
|
|
package/src/InMemoryStore.res
CHANGED
|
@@ -127,15 +127,15 @@ let dropCommittedEffects = (
|
|
|
127
127
|
|
|
128
128
|
let prepareRollbackDiff = async (
|
|
129
129
|
state: IndexerState.t,
|
|
130
|
-
~
|
|
130
|
+
~floors: RollbackFloors.t,
|
|
131
131
|
~rollbackDiffCheckpointId,
|
|
132
|
-
~
|
|
132
|
+
~progressedChains,
|
|
133
133
|
~rolledBackAddresses,
|
|
134
134
|
) => {
|
|
135
135
|
state->IndexerState.beginRollbackDiff(
|
|
136
|
-
~targetCheckpointId=rollbackTargetCheckpointId,
|
|
137
136
|
~diffCheckpointId=rollbackDiffCheckpointId,
|
|
138
|
-
~
|
|
137
|
+
~floors,
|
|
138
|
+
~progressedChains,
|
|
139
139
|
~rolledBackAddresses,
|
|
140
140
|
)
|
|
141
141
|
let persistence = state->IndexerState.persistence
|
|
@@ -152,7 +152,7 @@ let prepareRollbackDiff = async (
|
|
|
152
152
|
->Array.map(async entityConfig => {
|
|
153
153
|
let (removals, restoredEntities) = await persistence.storage.getRollbackData(
|
|
154
154
|
~entityConfig,
|
|
155
|
-
~
|
|
155
|
+
~floors,
|
|
156
156
|
)
|
|
157
157
|
|
|
158
158
|
removals->Array.forEach(({entityId, scope}: Persistence.rollbackRemoval) => {
|
|
@@ -215,7 +215,8 @@ let setBatchDcs = (state: IndexerState.t, ~batch: Batch.t) => {
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
batch.registeredAddresses
|
|
218
|
+
batch.registeredAddresses
|
|
219
|
+
->Array.pushMany(
|
|
219
220
|
chainState
|
|
220
221
|
->ChainState.drainAddressesForWrite(
|
|
221
222
|
~toBlockInclusive=progressedChain.progressBlockNumber,
|
|
@@ -230,7 +231,8 @@ let setBatchDcs = (state: IndexerState.t, ~batch: Batch.t) => {
|
|
|
230
231
|
},
|
|
231
232
|
checkpointId: checkpointIds->Array.getUnsafe(dc.checkpointIdx),
|
|
232
233
|
}),
|
|
233
|
-
)
|
|
234
|
+
)
|
|
235
|
+
->ignore
|
|
234
236
|
}
|
|
235
237
|
})
|
|
236
238
|
}
|
|
@@ -106,14 +106,14 @@ function dropCommittedEffects(inMemTable, committedCheckpointId, keepLoadedFromD
|
|
|
106
106
|
inMemTable.changesCount = inMemTable.changesCount - keysToDelete.length;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
async function prepareRollbackDiff(state,
|
|
110
|
-
IndexerState.beginRollbackDiff(state,
|
|
109
|
+
async function prepareRollbackDiff(state, floors, rollbackDiffCheckpointId, progressedChains, rolledBackAddresses) {
|
|
110
|
+
IndexerState.beginRollbackDiff(state, rollbackDiffCheckpointId, floors, progressedChains, rolledBackAddresses);
|
|
111
111
|
let persistence = IndexerState.persistence(state);
|
|
112
112
|
let committedCheckpointId = IndexerState.committedCheckpointId(state);
|
|
113
113
|
let deletedEntities = {};
|
|
114
114
|
let setEntities = {};
|
|
115
115
|
await Promise.all(persistence.allEntities.filter(entityConfig => entityConfig.storage.postgres).map(async entityConfig => {
|
|
116
|
-
let match = await persistence.storage.getRollbackData(entityConfig,
|
|
116
|
+
let match = await persistence.storage.getRollbackData(entityConfig, floors);
|
|
117
117
|
match[0].forEach(param => {
|
|
118
118
|
let entityId = param.entityId;
|
|
119
119
|
Utils.Dict.push(deletedEntities, entityConfig.name, entityId);
|