envio 3.7.0 → 3.9.0-resolvers.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/evm.schema.json +7 -0
- package/fuel.schema.json +7 -0
- package/index.d.ts +674 -161
- package/index.js +10 -0
- package/package.json +6 -7
- package/src/AddressRows.res +121 -0
- package/src/AddressRows.res.mjs +143 -0
- package/src/Batch.res +11 -0
- package/src/Batch.res.mjs +2 -1
- package/src/Bin.res +47 -0
- package/src/Bin.res.mjs +34 -1
- package/src/ChainState.res +108 -98
- package/src/ChainState.res.mjs +86 -67
- package/src/ChainState.resi +28 -15
- package/src/Config.res +61 -131
- package/src/Config.res.mjs +47 -79
- package/src/ContractMapping.res +66 -0
- package/src/ContractMapping.res.mjs +73 -0
- package/src/Core.res +24 -0
- package/src/Core.res.mjs +4 -0
- package/src/Ecosystem.res +7 -2
- package/src/Env.res +128 -1
- package/src/Env.res.mjs +123 -1
- package/src/Envio.res +54 -76
- package/src/EventConfigBuilder.res +316 -46
- package/src/EventConfigBuilder.res.mjs +231 -28
- package/src/FetchState.res +59 -67
- package/src/FetchState.res.mjs +34 -44
- package/src/HandlerRegister.res +26 -15
- package/src/HandlerRegister.res.mjs +27 -7
- package/src/Hasura.res +30 -22
- package/src/Hasura.res.mjs +11 -5
- package/src/InMemoryStore.res +23 -38
- package/src/InMemoryStore.res.mjs +13 -27
- package/src/IndexerState.res +40 -3
- package/src/IndexerState.res.mjs +30 -4
- package/src/IndexerState.resi +4 -1
- package/src/Internal.res +49 -30
- package/src/Internal.res.mjs +12 -16
- package/src/Main.res +27 -20
- package/src/Main.res.mjs +19 -14
- package/src/Metrics.res +15 -1
- package/src/Metrics.res.mjs +5 -1
- package/src/Persistence.res +46 -21
- package/src/Persistence.res.mjs +8 -5
- package/src/PgStorage.res +238 -79
- package/src/PgStorage.res.mjs +115 -73
- package/src/PruneStaleHistory.res +1 -1
- package/src/PruneStaleHistory.res.mjs +1 -1
- package/src/Rollback.res +62 -41
- package/src/Rollback.res.mjs +61 -19
- package/src/RollbackCommit.res +7 -9
- package/src/RollbackCommit.res.mjs +5 -6
- package/src/SimulateItems.res +254 -9
- package/src/SimulateItems.res.mjs +214 -47
- package/src/Sink.res +35 -26
- package/src/Sink.res.mjs +20 -16
- package/src/TestIndexer.res +121 -123
- package/src/TestIndexer.res.mjs +97 -102
- package/src/Utils.res +38 -0
- package/src/Utils.res.mjs +39 -2
- package/src/Writing.res +4 -2
- package/src/Writing.res.mjs +3 -2
- package/src/bindings/ClickHouse.res +311 -656
- package/src/bindings/ClickHouse.res.mjs +294 -395
- package/src/bindings/ClickHouseSink.res +303 -0
- package/src/bindings/ClickHouseSink.res.mjs +216 -0
- package/src/bindings/NodeJs.res +9 -0
- package/src/bindings/NodeJs.res.mjs +8 -1
- package/src/bindings/Postgres.res +9 -0
- package/src/bindings/Postgres.res.mjs +3 -0
- package/src/db/EntityHistory.res +29 -24
- package/src/db/EntityHistory.res.mjs +11 -19
- package/src/db/InternalTable.res +258 -83
- package/src/db/InternalTable.res.mjs +223 -85
- package/src/db/RollbackScope.res +29 -0
- package/src/db/RollbackScope.res.mjs +31 -0
- package/src/db/Table.res +28 -1
- package/src/db/Table.res.mjs +26 -2
- package/src/resolvers/ResolverProcess.res +809 -0
- package/src/resolvers/ResolverProcess.res.mjs +667 -0
- package/src/resolvers/ResolverQuery.res +317 -0
- package/src/resolvers/ResolverQuery.res.mjs +220 -0
- package/src/resolvers/collisions.js +108 -0
- package/src/resolvers/db.js +363 -0
- package/src/resolvers/dispatch.js +165 -0
- package/src/resolvers/errors.js +30 -0
- package/src/resolvers/graphqlSelection.js +292 -0
- package/src/resolvers/hasuraAction.js +84 -0
- package/src/resolvers/hasuraApply.js +323 -0
- package/src/resolvers/hasuraMetadata.js +119 -0
- package/src/resolvers/index.js +95 -0
- package/src/resolvers/manifest.js +370 -0
- package/src/resolvers/server.js +270 -0
- package/src/sources/AddressSet.res +0 -22
- package/src/sources/AddressStore.res +48 -88
- package/src/sources/AddressStore.res.mjs +11 -22
- package/src/sources/Evm.res +2 -0
- package/src/sources/Evm.res.mjs +2 -0
- package/src/sources/EvmHyperSyncSource.res +3 -2
- package/src/sources/Fuel.res +2 -0
- package/src/sources/Fuel.res.mjs +2 -0
- package/src/sources/SimulateSource.res +8 -4
- package/src/sources/SimulateSource.res.mjs +7 -3
- package/src/sources/Svm.res +36 -7
- package/src/sources/Svm.res.mjs +34 -4
- package/src/sources/SvmHyperSyncClient.res +20 -116
- package/src/sources/SvmHyperSyncClient.res.mjs +5 -7
- package/src/sources/SvmHyperSyncSource.res +89 -37
- package/src/sources/SvmHyperSyncSource.res.mjs +71 -39
- package/src/sources/TransactionStore.res +38 -0
- package/src/sources/TransactionStore.res.mjs +5 -0
- package/src/tui/Tui.res +1 -1
- package/src/tui/Tui.res.mjs +1 -1
- package/svm.schema.json +44 -156
- package/src/MemoryStorage.res +0 -724
- package/src/MemoryStorage.res.mjs +0 -601
|
@@ -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),
|
|
@@ -238,7 +239,7 @@ let alwaysIncludedBlockFields = [
|
|
|
238
239
|
function resolveFieldSelection(blockFields, transactionFields, globalBlockFieldsSet, globalTransactionFieldsSet) {
|
|
239
240
|
let selectedBlockFields = blockFields !== undefined ? new Set(alwaysIncludedBlockFields.concat(blockFields)) : globalBlockFieldsSet;
|
|
240
241
|
let selectedTransactionFields = transactionFields !== undefined ? new Set(transactionFields) : globalTransactionFieldsSet;
|
|
241
|
-
return Internal.makeFieldSelection(selectedBlockFields, selectedTransactionFields, Evm.eventBlockFieldMask, Evm.eventTransactionFieldMask);
|
|
242
|
+
return Internal.makeFieldSelection(selectedBlockFields, selectedTransactionFields, undefined, undefined, undefined, Evm.eventBlockFieldMask, Evm.eventTransactionFieldMask);
|
|
242
243
|
}
|
|
243
244
|
|
|
244
245
|
let internalBlockFields = ["number"];
|
|
@@ -248,53 +249,72 @@ let rawEventBlockFields = [
|
|
|
248
249
|
"timestamp"
|
|
249
250
|
];
|
|
250
251
|
|
|
251
|
-
let
|
|
252
|
+
let evmSelectionKinds = [
|
|
252
253
|
"block",
|
|
253
254
|
"transaction"
|
|
254
255
|
];
|
|
255
256
|
|
|
256
|
-
|
|
257
|
+
let svmSelectionKinds = [
|
|
258
|
+
"instruction",
|
|
259
|
+
"transaction",
|
|
260
|
+
"accountActivity",
|
|
261
|
+
"block",
|
|
262
|
+
"log"
|
|
263
|
+
];
|
|
264
|
+
|
|
265
|
+
function validateFieldsShapeOrThrow(fields, registration, validKeys, shapeNoun) {
|
|
257
266
|
if (typeof fields !== "object" || fields === null || Array.isArray(fields)) {
|
|
258
|
-
Stdlib_JsError.throwWithMessage(`The fields option of ` + registration + ` must be an object of
|
|
267
|
+
Stdlib_JsError.throwWithMessage(`The fields option of ` + registration + ` must be an object of ` + shapeNoun + ` field names.`);
|
|
259
268
|
}
|
|
260
269
|
Object.keys(fields).forEach(key => {
|
|
261
|
-
if (!
|
|
262
|
-
return Stdlib_JsError.throwWithMessage(`Invalid "` + key + `" key in the fields option of ` + registration + `. Valid keys: ` +
|
|
270
|
+
if (!validKeys.includes(key)) {
|
|
271
|
+
return Stdlib_JsError.throwWithMessage(`Invalid "` + key + `" key in the fields option of ` + registration + `. Valid keys: ` + Utils.$$Array.quotedJoin(validKeys) + `.`);
|
|
263
272
|
}
|
|
264
273
|
});
|
|
265
274
|
}
|
|
266
275
|
|
|
276
|
+
function selectionList(fields, key) {
|
|
277
|
+
let value = fields[key];
|
|
278
|
+
if (value !== undefined) {
|
|
279
|
+
return Primitive_option.valFromOption(value);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
267
283
|
let validBlockFields = new Set(Evm.blockFields);
|
|
268
284
|
|
|
269
285
|
let validTransactionFields = new Set(Evm.transactionFields);
|
|
270
286
|
|
|
271
|
-
function parseFieldsOrThrow(fields, valid, kind, registration) {
|
|
287
|
+
function parseFieldsOrThrow(fields, valid, kind, registration, rejectEmptyOpt) {
|
|
288
|
+
let rejectEmpty = rejectEmptyOpt !== undefined ? rejectEmptyOpt : false;
|
|
272
289
|
let seen = new Set();
|
|
273
290
|
let fields$1 = fields !== undefined ? (
|
|
274
291
|
Array.isArray(fields) ? fields : Stdlib_JsError.throwWithMessage(`The fields.` + kind + ` option of ` + registration + ` must be an array of field names.`)
|
|
275
292
|
) : [];
|
|
276
293
|
fields$1.forEach(name => {
|
|
277
294
|
if (!valid.has(name)) {
|
|
278
|
-
Stdlib_JsError.throwWithMessage(`Invalid "` + name + `" field in the fields.` + kind + ` option of ` + registration + `. Valid ` + kind + ` fields: ` + 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)) + `.`);
|
|
279
296
|
}
|
|
280
297
|
if (seen.has(name)) {
|
|
281
298
|
Stdlib_JsError.throwWithMessage(`Duplicate "` + name + `" field in the fields.` + kind + ` option of ` + registration + `.`);
|
|
282
299
|
}
|
|
283
300
|
seen.add(name);
|
|
284
301
|
});
|
|
302
|
+
if (rejectEmpty && fields$1.length === 0) {
|
|
303
|
+
Stdlib_JsError.throwWithMessage(`The fields.` + kind + ` option of ` + registration + ` must list at least one field.`);
|
|
304
|
+
}
|
|
285
305
|
return seen;
|
|
286
306
|
}
|
|
287
307
|
|
|
288
308
|
function resolveInlineFieldSelection(fields, contractName, eventName, enableRawEvents) {
|
|
289
309
|
let registration = `the "` + eventName + `" event registration on contract "` + contractName + `"`;
|
|
290
|
-
validateFieldsShapeOrThrow(fields, registration);
|
|
291
|
-
let blockFields = parseFieldsOrThrow(fields
|
|
292
|
-
let transactionFields = parseFieldsOrThrow(fields
|
|
310
|
+
validateFieldsShapeOrThrow(fields, registration, evmSelectionKinds, "block and transaction");
|
|
311
|
+
let blockFields = parseFieldsOrThrow(selectionList(fields, "block"), validBlockFields, "block", registration, undefined);
|
|
312
|
+
let transactionFields = parseFieldsOrThrow(selectionList(fields, "transaction"), validTransactionFields, "transaction", registration, undefined);
|
|
293
313
|
Utils.$$Set.addMany(blockFields, internalBlockFields);
|
|
294
314
|
if (enableRawEvents) {
|
|
295
315
|
Utils.$$Set.addMany(blockFields, rawEventBlockFields);
|
|
296
316
|
}
|
|
297
|
-
return Internal.makeFieldSelection(blockFields, transactionFields, Evm.eventBlockFieldMask, Evm.eventTransactionFieldMask);
|
|
317
|
+
return Internal.makeFieldSelection(blockFields, transactionFields, undefined, undefined, undefined, Evm.eventBlockFieldMask, Evm.eventTransactionFieldMask);
|
|
298
318
|
}
|
|
299
319
|
|
|
300
320
|
function buildEvmEventConfig(contractName, eventName, sighash, params, blockFields, transactionFields, globalBlockFieldsSetOpt, globalTransactionFieldsSetOpt) {
|
|
@@ -342,20 +362,83 @@ function buildEvmOnEventRegistration(eventConfig, isWildcard, handler, contractR
|
|
|
342
362
|
};
|
|
343
363
|
}
|
|
344
364
|
|
|
345
|
-
let alwaysIncludedSvmBlockFields = [
|
|
365
|
+
let alwaysIncludedSvmBlockFields = ["slot"];
|
|
366
|
+
|
|
367
|
+
let validSvmInstructionFields = new Set([
|
|
368
|
+
"args",
|
|
369
|
+
"accounts",
|
|
370
|
+
"accountArguments",
|
|
371
|
+
"programId",
|
|
372
|
+
"data",
|
|
373
|
+
"path",
|
|
374
|
+
"isInner"
|
|
375
|
+
]);
|
|
376
|
+
|
|
377
|
+
let validSvmTransactionFields = new Set([
|
|
378
|
+
"transactionIndex",
|
|
379
|
+
"signature",
|
|
380
|
+
"feePayer",
|
|
381
|
+
"success",
|
|
382
|
+
"err",
|
|
383
|
+
"fee",
|
|
384
|
+
"computeUnitsConsumed",
|
|
385
|
+
"accountKeys",
|
|
386
|
+
"recentBlockhash",
|
|
387
|
+
"version",
|
|
388
|
+
"allSignatures"
|
|
389
|
+
]);
|
|
390
|
+
|
|
391
|
+
let validSvmAccountActivityFields = new Set([
|
|
392
|
+
"address",
|
|
393
|
+
"transactionAccountIndex",
|
|
394
|
+
"isSigner",
|
|
395
|
+
"isWritable",
|
|
396
|
+
"lamports.pre",
|
|
397
|
+
"lamports.post",
|
|
398
|
+
"token.mint",
|
|
399
|
+
"token.owner",
|
|
400
|
+
"token.decimals",
|
|
401
|
+
"token.preAmount",
|
|
402
|
+
"token.postAmount"
|
|
403
|
+
]);
|
|
404
|
+
|
|
405
|
+
let validSvmBlockFields = new Set([
|
|
346
406
|
"slot",
|
|
347
407
|
"time",
|
|
348
|
-
"hash"
|
|
349
|
-
|
|
408
|
+
"hash",
|
|
409
|
+
"height",
|
|
410
|
+
"parentSlot",
|
|
411
|
+
"parentHash"
|
|
412
|
+
]);
|
|
413
|
+
|
|
414
|
+
let validSvmLogFields = new Set([
|
|
415
|
+
"kind",
|
|
416
|
+
"message"
|
|
417
|
+
]);
|
|
350
418
|
|
|
351
|
-
function
|
|
352
|
-
let
|
|
353
|
-
|
|
419
|
+
function resolveSvmInlineFieldSelection(fields, contractName, eventName) {
|
|
420
|
+
let registration = `the "` + eventName + `" instruction on program "` + contractName + `"`;
|
|
421
|
+
validateFieldsShapeOrThrow(fields, registration, svmSelectionKinds, "instruction, transaction, accountActivity, block and log");
|
|
422
|
+
let accountActivity = selectionList(fields, "accountActivity");
|
|
423
|
+
let log = selectionList(fields, "log");
|
|
424
|
+
let instructionFields = parseFieldsOrThrow(selectionList(fields, "instruction"), validSvmInstructionFields, "instruction", registration, undefined);
|
|
425
|
+
let transactionFields = parseFieldsOrThrow(selectionList(fields, "transaction"), validSvmTransactionFields, "transaction", registration, undefined);
|
|
426
|
+
let accountActivityFields = parseFieldsOrThrow(accountActivity, validSvmAccountActivityFields, "accountActivity", registration, Stdlib_Option.isSome(accountActivity));
|
|
427
|
+
let blockFields = parseFieldsOrThrow(selectionList(fields, "block"), validSvmBlockFields, "block", registration, undefined);
|
|
428
|
+
let logFields = parseFieldsOrThrow(log, validSvmLogFields, "log", registration, Stdlib_Option.isSome(log));
|
|
429
|
+
Utils.$$Set.addMany(blockFields, alwaysIncludedSvmBlockFields);
|
|
430
|
+
if (accountActivityFields.size > 0) {
|
|
431
|
+
transactionFields.add("accountActivities");
|
|
432
|
+
}
|
|
433
|
+
return Internal.makeFieldSelection(blockFields, transactionFields, Primitive_option.some(instructionFields), Primitive_option.some(accountActivityFields), Primitive_option.some(logFields), Svm.eventBlockFieldMask, Svm.eventTransactionFieldMask);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function buildSvmInstructionEventConfig(contractName, instructionName, programId, discriminator, accountsOpt, argsOpt, definedTypesOpt) {
|
|
354
437
|
let accounts = accountsOpt !== undefined ? accountsOpt : [];
|
|
355
438
|
let args = argsOpt !== undefined ? argsOpt : null;
|
|
356
439
|
let definedTypes = definedTypesOpt !== undefined ? definedTypesOpt : null;
|
|
357
440
|
let paramsSchema = Utils.Schema.coerceToJsonPgType(S$RescriptSchema.json(false));
|
|
358
|
-
let fieldSelection = Internal.makeFieldSelection(new Set(alwaysIncludedSvmBlockFields
|
|
441
|
+
let fieldSelection = Internal.makeFieldSelection(new Set(alwaysIncludedSvmBlockFields), new Set(), undefined, undefined, undefined, Svm.eventBlockFieldMask, Svm.eventTransactionFieldMask);
|
|
359
442
|
return {
|
|
360
443
|
id: discriminator !== undefined ? discriminator : "none",
|
|
361
444
|
name: instructionName,
|
|
@@ -365,17 +448,121 @@ function buildSvmInstructionEventConfig(contractName, instructionName, programId
|
|
|
365
448
|
fieldSelection: fieldSelection,
|
|
366
449
|
programId: programId,
|
|
367
450
|
discriminator: discriminator,
|
|
368
|
-
discriminatorByteLen: discriminatorByteLen,
|
|
369
|
-
includeLogs: includeLogs,
|
|
370
|
-
accountFilters: accountFilters,
|
|
371
|
-
isInner: isInner,
|
|
372
451
|
accounts: accounts,
|
|
373
452
|
args: args,
|
|
374
453
|
definedTypes: definedTypes
|
|
375
454
|
};
|
|
376
455
|
}
|
|
377
456
|
|
|
378
|
-
|
|
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;
|
|
379
566
|
return {
|
|
380
567
|
index: -1,
|
|
381
568
|
eventConfig: eventConfig,
|
|
@@ -384,8 +571,10 @@ function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractR
|
|
|
384
571
|
isWildcard: isWildcard,
|
|
385
572
|
filterByAddresses: false,
|
|
386
573
|
dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, false),
|
|
387
|
-
startBlock: startBlock,
|
|
388
|
-
fieldSelection: eventConfig.fieldSelection
|
|
574
|
+
startBlock: sb !== undefined ? sb : startBlock,
|
|
575
|
+
fieldSelection: fieldSelection !== undefined ? fieldSelection : eventConfig.fieldSelection,
|
|
576
|
+
accountFilters: resolvedWhere.accountFilters,
|
|
577
|
+
isInner: resolvedWhere.isInner
|
|
389
578
|
};
|
|
390
579
|
}
|
|
391
580
|
|
|
@@ -438,7 +627,7 @@ function buildFuelEventConfig(contractName, eventName, kind, sighash, rawAbi) {
|
|
|
438
627
|
contractName: contractName,
|
|
439
628
|
paramsRawEventSchema: paramsSchema,
|
|
440
629
|
simulateParamsSchema: paramsSchema,
|
|
441
|
-
fieldSelection: Internal.makeFieldSelection(new Set(Fuel.blockFields), new Set(Fuel.transactionFields), Fuel.eventBlockFieldMask, Fuel.eventTransactionFieldMask),
|
|
630
|
+
fieldSelection: Internal.makeFieldSelection(new Set(Fuel.blockFields), new Set(Fuel.transactionFields), undefined, undefined, undefined, Fuel.eventBlockFieldMask, Fuel.eventTransactionFieldMask),
|
|
442
631
|
kind: fuelKind
|
|
443
632
|
};
|
|
444
633
|
}
|
|
@@ -457,6 +646,8 @@ function buildFuelOnEventRegistration(eventConfig, isWildcard, handler, contract
|
|
|
457
646
|
};
|
|
458
647
|
}
|
|
459
648
|
|
|
649
|
+
let filterableAccountCount = 10;
|
|
650
|
+
|
|
460
651
|
export {
|
|
461
652
|
paramMetaSchema,
|
|
462
653
|
normalizeOrThrow,
|
|
@@ -474,8 +665,10 @@ export {
|
|
|
474
665
|
resolveFieldSelection,
|
|
475
666
|
internalBlockFields,
|
|
476
667
|
rawEventBlockFields,
|
|
477
|
-
|
|
668
|
+
evmSelectionKinds,
|
|
669
|
+
svmSelectionKinds,
|
|
478
670
|
validateFieldsShapeOrThrow,
|
|
671
|
+
selectionList,
|
|
479
672
|
validBlockFields,
|
|
480
673
|
validTransactionFields,
|
|
481
674
|
parseFieldsOrThrow,
|
|
@@ -483,7 +676,17 @@ export {
|
|
|
483
676
|
buildEvmEventConfig,
|
|
484
677
|
buildEvmOnEventRegistration,
|
|
485
678
|
alwaysIncludedSvmBlockFields,
|
|
679
|
+
validSvmInstructionFields,
|
|
680
|
+
validSvmTransactionFields,
|
|
681
|
+
validSvmAccountActivityFields,
|
|
682
|
+
validSvmBlockFields,
|
|
683
|
+
validSvmLogFields,
|
|
684
|
+
resolveSvmInlineFieldSelection,
|
|
486
685
|
buildSvmInstructionEventConfig,
|
|
686
|
+
validSvmWhereKeys,
|
|
687
|
+
svmBlockFilterSchema,
|
|
688
|
+
filterableAccountCount,
|
|
689
|
+
resolveSvmWhereOrThrow,
|
|
487
690
|
buildSvmOnEventRegistration,
|
|
488
691
|
buildFuelEventConfig,
|
|
489
692
|
buildFuelOnEventRegistration,
|
package/src/FetchState.res
CHANGED
|
@@ -1469,7 +1469,6 @@ let warnAddressRegistration = (
|
|
|
1469
1469
|
|
|
1470
1470
|
// A rejected registration is simply absent from every partition, so without a
|
|
1471
1471
|
// warning the user sees a contract that never indexes and nothing saying why.
|
|
1472
|
-
// Shared by config-time registration in `make` and by dynamic registration.
|
|
1473
1472
|
let warnRejectedRegistration = (
|
|
1474
1473
|
verdict: AddressStore.verdict,
|
|
1475
1474
|
~chainId: ChainId.t,
|
|
@@ -1477,20 +1476,7 @@ let warnRejectedRegistration = (
|
|
|
1477
1476
|
~contractName: string,
|
|
1478
1477
|
) =>
|
|
1479
1478
|
switch verdict {
|
|
1480
|
-
| Conflict({existingContractName}) =>
|
|
1481
|
-
warnAddressRegistration(
|
|
1482
|
-
~chainId,
|
|
1483
|
-
~contractAddress,
|
|
1484
|
-
~params={
|
|
1485
|
-
"existingContractType": existingContractName,
|
|
1486
|
-
"newContractType": contractName,
|
|
1487
|
-
},
|
|
1488
|
-
`Skipping contract registration: Contract address is already registered for one contract and cannot be registered for another contract.`,
|
|
1489
|
-
)
|
|
1490
1479
|
| Duplicate({effectiveStartBlock, existingEffectiveStartBlock}) =>
|
|
1491
|
-
// FIXME: Instead of filtering out duplicates, we should check the block
|
|
1492
|
-
// number first. If a new registration has an earlier block number we
|
|
1493
|
-
// should register it for the missing block range.
|
|
1494
1480
|
if existingEffectiveStartBlock > effectiveStartBlock {
|
|
1495
1481
|
warnAddressRegistration(
|
|
1496
1482
|
~chainId,
|
|
@@ -1499,7 +1485,7 @@ let warnRejectedRegistration = (
|
|
|
1499
1485
|
"existingBlockNumber": existingEffectiveStartBlock,
|
|
1500
1486
|
"newBlockNumber": effectiveStartBlock,
|
|
1501
1487
|
},
|
|
1502
|
-
`Skipping contract registration:
|
|
1488
|
+
`Skipping same-contract re-registration: the address is already registered for this contract. The start block does not move earlier.`,
|
|
1503
1489
|
)
|
|
1504
1490
|
}
|
|
1505
1491
|
| Invalid =>
|
|
@@ -1723,9 +1709,10 @@ let registerDynamicContracts = (
|
|
|
1723
1709
|
// exactly what this batch adds.
|
|
1724
1710
|
let idCursor = addressStore->AddressStore.nextId
|
|
1725
1711
|
// The store resolves each address against both what it already holds and the
|
|
1726
|
-
// batch's own earlier entries, so
|
|
1727
|
-
// single batch
|
|
1728
|
-
// additions this chain fetches for, since it's what
|
|
1712
|
+
// batch's own earlier entries, so the same address registered twice for one
|
|
1713
|
+
// contract inside a single batch is a duplicate just as it is across batches.
|
|
1714
|
+
// It also decides which additions this chain fetches for, since it's what
|
|
1715
|
+
// holds the contract list.
|
|
1729
1716
|
let verdicts = addressStore->AddressStore.registerBatch(registrations)
|
|
1730
1717
|
|
|
1731
1718
|
let registeringContractNames = []
|
|
@@ -1741,7 +1728,7 @@ let registerDynamicContracts = (
|
|
|
1741
1728
|
// no partition to build. The address is still stored and persisted, so a
|
|
1742
1729
|
// config that later adds address-dependent events picks it up on restart.
|
|
1743
1730
|
| Added({fetchable: false}) => ()
|
|
1744
|
-
|
|
|
1731
|
+
| Duplicate(_) | Invalid =>
|
|
1745
1732
|
verdict->warnRejectedRegistration(
|
|
1746
1733
|
~chainId=fetchState.chainId,
|
|
1747
1734
|
~contractAddress=registration.address,
|
|
@@ -2627,7 +2614,7 @@ let make = (
|
|
|
2627
2614
|
~endBlock,
|
|
2628
2615
|
~onEventRegistrations: array<Internal.onEventRegistration>,
|
|
2629
2616
|
~addressStore: AddressStore.t,
|
|
2630
|
-
~
|
|
2617
|
+
~addressRows: AddressRows.seedRows,
|
|
2631
2618
|
~maxAddrInPartition,
|
|
2632
2619
|
~chainId: ChainId.t,
|
|
2633
2620
|
~maxOnBlockBufferSize,
|
|
@@ -2681,27 +2668,24 @@ let make = (
|
|
|
2681
2668
|
)
|
|
2682
2669
|
|
|
2683
2670
|
// Every address the chain indexes goes into the store — including ones whose
|
|
2684
|
-
// contract has no address-dependent events, so
|
|
2685
|
-
//
|
|
2671
|
+
// contract has no address-dependent events, so the address is still persisted
|
|
2672
|
+
// and a config that later adds events picks it up.
|
|
2673
|
+
//
|
|
2674
|
+
// These rows come from the config or from a resume, so they're already stored
|
|
2675
|
+
// and must never be drained back into a write. Only the rows the store
|
|
2676
|
+
// refuses come back: a resume seeds millions of them.
|
|
2686
2677
|
addressStore
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
addresses->Array.map((contract): AddressStore.registration => {
|
|
2691
|
-
address: contract.address,
|
|
2692
|
-
contractName: contract.contractName,
|
|
2693
|
-
registrationBlock: contract.registrationBlock,
|
|
2694
|
-
}),
|
|
2695
|
-
)
|
|
2696
|
-
// Verdicts are in the batch's order, so they line up with `addresses`. A
|
|
2697
|
-
// config address the store rejects is dropped exactly like a dynamic one, and
|
|
2698
|
-
// needs the same warning — restored dynamic addresses come through here too.
|
|
2699
|
-
->Array.forEachWithIndex((verdict, idx) => {
|
|
2700
|
-
let contract = addresses->Array.getUnsafe(idx)
|
|
2701
|
-
verdict->warnRejectedRegistration(
|
|
2678
|
+
->AddressStore.seedRows(addressRows)
|
|
2679
|
+
->Array.forEach(rejected => {
|
|
2680
|
+
warnAddressRegistration(
|
|
2702
2681
|
~chainId,
|
|
2703
|
-
~contractAddress=
|
|
2704
|
-
~
|
|
2682
|
+
~contractAddress=rejected.address,
|
|
2683
|
+
~params={
|
|
2684
|
+
"contractName": rejected.contractName,
|
|
2685
|
+
"existingBlockNumber": rejected.existingEffectiveStartBlock,
|
|
2686
|
+
"newBlockNumber": rejected.effectiveStartBlock,
|
|
2687
|
+
},
|
|
2688
|
+
`Skipping a stored address: it is already registered for this contract.`,
|
|
2705
2689
|
)
|
|
2706
2690
|
})
|
|
2707
2691
|
|
|
@@ -2709,23 +2693,24 @@ let make = (
|
|
|
2709
2693
|
let clientFilteredContracts = Utils.Set.make()
|
|
2710
2694
|
let registeringSetsByContract = Dict.make()
|
|
2711
2695
|
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2696
|
+
// What each contract needs a partition for is read back off the store rather
|
|
2697
|
+
// than re-derived from the seeded columns: the store is what resolved the
|
|
2698
|
+
// rows, including the ones it refused.
|
|
2699
|
+
contractNamesWithNormalEvents
|
|
2700
|
+
->Utils.Set.toArray
|
|
2701
|
+
->Array.forEach(contractName => {
|
|
2702
|
+
if addressStore->AddressStore.contractCount(contractName) > 0 {
|
|
2703
|
+
registeringSetsByContract->Dict.set(
|
|
2704
|
+
contractName,
|
|
2705
|
+
addressStore->AddressStore.makeSet(~contractName),
|
|
2706
|
+
)
|
|
2707
|
+
}
|
|
2708
|
+
})
|
|
2709
|
+
addressStore
|
|
2710
|
+
->AddressStore.dynamicContractNames
|
|
2711
|
+
->Array.forEach(contractName => {
|
|
2717
2712
|
if contractNamesWithNormalEvents->Utils.Set.has(contractName) {
|
|
2718
|
-
|
|
2719
|
-
registeringSetsByContract->Dict.set(
|
|
2720
|
-
contractName,
|
|
2721
|
-
addressStore->AddressStore.makeSet(~contractName),
|
|
2722
|
-
)
|
|
2723
|
-
}
|
|
2724
|
-
|
|
2725
|
-
// Detect dynamic contracts by registrationBlock
|
|
2726
|
-
if contract.registrationBlock !== -1 {
|
|
2727
|
-
dynamicContracts->Utils.Set.add(contractName)->ignore
|
|
2728
|
-
}
|
|
2713
|
+
dynamicContracts->Utils.Set.add(contractName)->ignore
|
|
2729
2714
|
}
|
|
2730
2715
|
})
|
|
2731
2716
|
|
|
@@ -2768,7 +2753,7 @@ let make = (
|
|
|
2768
2753
|
) {
|
|
2769
2754
|
JsError.throwWithMessage(
|
|
2770
2755
|
`Invalid configuration: Nothing to fetch on chain ${chainId->ChainId.toString}. ` ++
|
|
2771
|
-
`addresses=${addresses->Array.length->Int.toString}, ` ++
|
|
2756
|
+
`addresses=${addressRows.addresses->Array.length->Int.toString}, ` ++
|
|
2772
2757
|
`onEventRegistrations=${onEventRegistrations->Array.length->Int.toString}, ` ++
|
|
2773
2758
|
`normalRegistrations=${normalRegistrations
|
|
2774
2759
|
->Array.length
|
|
@@ -2845,20 +2830,28 @@ let rollbackPendingQueries = (mutPendingQueries: array<pendingQuery>, ~targetBlo
|
|
|
2845
2830
|
adjusted
|
|
2846
2831
|
}
|
|
2847
2832
|
|
|
2833
|
+
type rollbackResult = {
|
|
2834
|
+
fetchState: t,
|
|
2835
|
+
// The registrations the prune dropped, for the storage that deletes their rows.
|
|
2836
|
+
rolledBackAddresses: array<AddressStore.rolledBackAddress>,
|
|
2837
|
+
}
|
|
2838
|
+
|
|
2848
2839
|
/**
|
|
2849
2840
|
Rolls back fetch state to the given valid block.
|
|
2841
|
+
Prunes the store first, then rebuilds partitions from it: an address survives iff
|
|
2842
|
+
`filterByRegistrationBlock` keeps it, so the partitions and the rows the caller
|
|
2843
|
+
goes on to delete can't disagree about which registrations died.
|
|
2850
2844
|
Always recreates optimized partitions to avoid duplicate addresses:
|
|
2851
2845
|
- Wildcard: only rollback latestFetchedBlock
|
|
2852
2846
|
- Non-wildcard with lfb <= target: keep, adjust pending queries and mergeBlock
|
|
2853
2847
|
- Non-wildcard with lfb > target: delete, track addresses for recreation
|
|
2854
2848
|
*/
|
|
2855
|
-
let rollback = (
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
// Step 2: Categorize partitions
|
|
2849
|
+
let rollback = (
|
|
2850
|
+
fetchState: t,
|
|
2851
|
+
~rolledBackAddressStore: AddressStore.t,
|
|
2852
|
+
~targetBlockNumber,
|
|
2853
|
+
): rollbackResult => {
|
|
2854
|
+
let rolledBackAddresses = rolledBackAddressStore->AddressStore.rollback(targetBlockNumber)
|
|
2862
2855
|
let keptPartitions = []
|
|
2863
2856
|
let nextKeptIdRef = ref(0)
|
|
2864
2857
|
let registeringSetsByContract: dict<AddressSet.t> = Dict.make()
|
|
@@ -2935,10 +2928,9 @@ let rollback = (fetchState: t, ~addressStore: AddressStore.t, ~targetBlockNumber
|
|
|
2935
2928
|
}
|
|
2936
2929
|
}
|
|
2937
2930
|
|
|
2938
|
-
// Step 3: Recreate partitions from deleted partition addresses
|
|
2939
2931
|
let optimizedPartitions = createPartitions(
|
|
2940
2932
|
~registeringSetsByContract,
|
|
2941
|
-
~addressStore,
|
|
2933
|
+
~addressStore=rolledBackAddressStore,
|
|
2942
2934
|
~dynamicContracts=fetchState.optimizedPartitions.dynamicContracts,
|
|
2943
2935
|
~clientFilteredContracts=fetchState.optimizedPartitions.clientFilteredContracts,
|
|
2944
2936
|
~normalSelection=fetchState.normalSelection,
|
|
@@ -2949,8 +2941,7 @@ let rollback = (fetchState: t, ~addressStore: AddressStore.t, ~targetBlockNumber
|
|
|
2949
2941
|
~knownHeight=fetchState.knownHeight,
|
|
2950
2942
|
)
|
|
2951
2943
|
|
|
2952
|
-
|
|
2953
|
-
{
|
|
2944
|
+
let rolledBack = {
|
|
2954
2945
|
...fetchState,
|
|
2955
2946
|
// TODO: Test this. Currently it's not tested.
|
|
2956
2947
|
latestOnBlockBlockNumber: Pervasives.min(
|
|
@@ -2969,6 +2960,7 @@ let rollback = (fetchState: t, ~addressStore: AddressStore.t, ~targetBlockNumber
|
|
|
2969
2960
|
targetBlockNumber
|
|
2970
2961
|
),
|
|
2971
2962
|
)
|
|
2963
|
+
{fetchState: rolledBack, rolledBackAddresses}
|
|
2972
2964
|
}
|
|
2973
2965
|
|
|
2974
2966
|
// Reset pending queries by removing in-flight queries (ones without fetchedBlock).
|