envio 3.7.0 → 3.8.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/index.d.ts +331 -142
- package/package.json +6 -6
- package/src/ChainState.res +9 -1
- package/src/ChainState.res.mjs +6 -1
- package/src/Config.res +19 -10
- package/src/Config.res.mjs +17 -7
- package/src/Envio.res +54 -76
- package/src/EventConfigBuilder.res +159 -30
- package/src/EventConfigBuilder.res.mjs +120 -24
- package/src/HandlerRegister.res +20 -11
- package/src/HandlerRegister.res.mjs +22 -5
- package/src/Hasura.res +30 -22
- package/src/Hasura.res.mjs +11 -5
- package/src/InMemoryStore.res +1 -6
- package/src/InMemoryStore.res.mjs +1 -3
- package/src/Internal.res +33 -13
- package/src/Internal.res.mjs +12 -16
- package/src/Main.res +2 -5
- package/src/MemoryStorage.res +40 -8
- package/src/MemoryStorage.res.mjs +38 -16
- package/src/Persistence.res +4 -2
- package/src/PgStorage.res +6 -1
- package/src/PgStorage.res.mjs +1 -1
- package/src/SimulateItems.res +261 -9
- package/src/SimulateItems.res.mjs +218 -47
- package/src/TestIndexer.res +26 -10
- package/src/TestIndexer.res.mjs +34 -12
- package/src/bindings/ClickHouse.res +33 -6
- package/src/bindings/ClickHouse.res.mjs +25 -4
- package/src/db/InternalTable.res +11 -0
- package/src/db/InternalTable.res.mjs +7 -0
- package/src/sources/EvmHyperSyncSource.res +3 -2
- package/src/sources/SimulateSource.res +8 -4
- package/src/sources/SimulateSource.res.mjs +7 -3
- package/src/sources/Svm.res +34 -7
- package/src/sources/Svm.res.mjs +32 -4
- package/src/sources/SvmHyperSyncClient.res +10 -12
- package/src/sources/SvmHyperSyncClient.res.mjs +3 -2
- package/src/sources/SvmHyperSyncSource.res +91 -34
- package/src/sources/SvmHyperSyncSource.res.mjs +77 -37
- package/src/sources/TransactionStore.res +38 -0
- package/src/sources/TransactionStore.res.mjs +5 -0
- package/svm.schema.json +27 -78
|
@@ -238,7 +238,7 @@ let alwaysIncludedBlockFields = [
|
|
|
238
238
|
function resolveFieldSelection(blockFields, transactionFields, globalBlockFieldsSet, globalTransactionFieldsSet) {
|
|
239
239
|
let selectedBlockFields = blockFields !== undefined ? new Set(alwaysIncludedBlockFields.concat(blockFields)) : globalBlockFieldsSet;
|
|
240
240
|
let selectedTransactionFields = transactionFields !== undefined ? new Set(transactionFields) : globalTransactionFieldsSet;
|
|
241
|
-
return Internal.makeFieldSelection(selectedBlockFields, selectedTransactionFields, Evm.eventBlockFieldMask, Evm.eventTransactionFieldMask);
|
|
241
|
+
return Internal.makeFieldSelection(selectedBlockFields, selectedTransactionFields, undefined, undefined, undefined, Evm.eventBlockFieldMask, Evm.eventTransactionFieldMask);
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
let internalBlockFields = ["number"];
|
|
@@ -248,53 +248,76 @@ let rawEventBlockFields = [
|
|
|
248
248
|
"timestamp"
|
|
249
249
|
];
|
|
250
250
|
|
|
251
|
-
let
|
|
251
|
+
let evmSelectionKinds = [
|
|
252
252
|
"block",
|
|
253
253
|
"transaction"
|
|
254
254
|
];
|
|
255
255
|
|
|
256
|
-
|
|
256
|
+
let svmSelectionKinds = [
|
|
257
|
+
"instruction",
|
|
258
|
+
"transaction",
|
|
259
|
+
"accountActivity",
|
|
260
|
+
"block",
|
|
261
|
+
"log"
|
|
262
|
+
];
|
|
263
|
+
|
|
264
|
+
function quotedJoin(names) {
|
|
265
|
+
return names.map(name => `"` + name + `"`).join(", ");
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function validateFieldsShapeOrThrow(fields, registration, validKeys, shapeNoun) {
|
|
257
269
|
if (typeof fields !== "object" || fields === null || Array.isArray(fields)) {
|
|
258
|
-
Stdlib_JsError.throwWithMessage(`The fields option of ` + registration + ` must be an object of
|
|
270
|
+
Stdlib_JsError.throwWithMessage(`The fields option of ` + registration + ` must be an object of ` + shapeNoun + ` field names.`);
|
|
259
271
|
}
|
|
260
272
|
Object.keys(fields).forEach(key => {
|
|
261
|
-
if (!
|
|
262
|
-
return Stdlib_JsError.throwWithMessage(`Invalid "` + key + `" key in the fields option of ` + registration + `. Valid keys: ` +
|
|
273
|
+
if (!validKeys.includes(key)) {
|
|
274
|
+
return Stdlib_JsError.throwWithMessage(`Invalid "` + key + `" key in the fields option of ` + registration + `. Valid keys: ` + quotedJoin(validKeys) + `.`);
|
|
263
275
|
}
|
|
264
276
|
});
|
|
265
277
|
}
|
|
266
278
|
|
|
279
|
+
function selectionList(fields, key) {
|
|
280
|
+
let value = fields[key];
|
|
281
|
+
if (value !== undefined) {
|
|
282
|
+
return Primitive_option.valFromOption(value);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
267
286
|
let validBlockFields = new Set(Evm.blockFields);
|
|
268
287
|
|
|
269
288
|
let validTransactionFields = new Set(Evm.transactionFields);
|
|
270
289
|
|
|
271
|
-
function parseFieldsOrThrow(fields, valid, kind, registration) {
|
|
290
|
+
function parseFieldsOrThrow(fields, valid, kind, registration, rejectEmptyOpt) {
|
|
291
|
+
let rejectEmpty = rejectEmptyOpt !== undefined ? rejectEmptyOpt : false;
|
|
272
292
|
let seen = new Set();
|
|
273
293
|
let fields$1 = fields !== undefined ? (
|
|
274
294
|
Array.isArray(fields) ? fields : Stdlib_JsError.throwWithMessage(`The fields.` + kind + ` option of ` + registration + ` must be an array of field names.`)
|
|
275
295
|
) : [];
|
|
276
296
|
fields$1.forEach(name => {
|
|
277
297
|
if (!valid.has(name)) {
|
|
278
|
-
Stdlib_JsError.throwWithMessage(`Invalid "` + name + `" field in the fields.` + kind + ` option of ` + registration + `. Valid ` + kind + ` fields: ` + Array.from(valid)
|
|
298
|
+
Stdlib_JsError.throwWithMessage(`Invalid "` + name + `" field in the fields.` + kind + ` option of ` + registration + `. Valid ` + kind + ` fields: ` + quotedJoin(Array.from(valid)) + `.`);
|
|
279
299
|
}
|
|
280
300
|
if (seen.has(name)) {
|
|
281
301
|
Stdlib_JsError.throwWithMessage(`Duplicate "` + name + `" field in the fields.` + kind + ` option of ` + registration + `.`);
|
|
282
302
|
}
|
|
283
303
|
seen.add(name);
|
|
284
304
|
});
|
|
305
|
+
if (rejectEmpty && fields$1.length === 0) {
|
|
306
|
+
Stdlib_JsError.throwWithMessage(`The fields.` + kind + ` option of ` + registration + ` must list at least one field.`);
|
|
307
|
+
}
|
|
285
308
|
return seen;
|
|
286
309
|
}
|
|
287
310
|
|
|
288
311
|
function resolveInlineFieldSelection(fields, contractName, eventName, enableRawEvents) {
|
|
289
312
|
let registration = `the "` + eventName + `" event registration on contract "` + contractName + `"`;
|
|
290
|
-
validateFieldsShapeOrThrow(fields, registration);
|
|
291
|
-
let blockFields = parseFieldsOrThrow(fields
|
|
292
|
-
let transactionFields = parseFieldsOrThrow(fields
|
|
313
|
+
validateFieldsShapeOrThrow(fields, registration, evmSelectionKinds, "block and transaction");
|
|
314
|
+
let blockFields = parseFieldsOrThrow(selectionList(fields, "block"), validBlockFields, "block", registration, undefined);
|
|
315
|
+
let transactionFields = parseFieldsOrThrow(selectionList(fields, "transaction"), validTransactionFields, "transaction", registration, undefined);
|
|
293
316
|
Utils.$$Set.addMany(blockFields, internalBlockFields);
|
|
294
317
|
if (enableRawEvents) {
|
|
295
318
|
Utils.$$Set.addMany(blockFields, rawEventBlockFields);
|
|
296
319
|
}
|
|
297
|
-
return Internal.makeFieldSelection(blockFields, transactionFields, Evm.eventBlockFieldMask, Evm.eventTransactionFieldMask);
|
|
320
|
+
return Internal.makeFieldSelection(blockFields, transactionFields, undefined, undefined, undefined, Evm.eventBlockFieldMask, Evm.eventTransactionFieldMask);
|
|
298
321
|
}
|
|
299
322
|
|
|
300
323
|
function buildEvmEventConfig(contractName, eventName, sighash, params, blockFields, transactionFields, globalBlockFieldsSetOpt, globalTransactionFieldsSetOpt) {
|
|
@@ -342,20 +365,85 @@ function buildEvmOnEventRegistration(eventConfig, isWildcard, handler, contractR
|
|
|
342
365
|
};
|
|
343
366
|
}
|
|
344
367
|
|
|
345
|
-
let alwaysIncludedSvmBlockFields = [
|
|
368
|
+
let alwaysIncludedSvmBlockFields = ["slot"];
|
|
369
|
+
|
|
370
|
+
let validSvmInstructionFields = new Set([
|
|
371
|
+
"args",
|
|
372
|
+
"accounts",
|
|
373
|
+
"accountArguments",
|
|
374
|
+
"programId",
|
|
375
|
+
"data",
|
|
376
|
+
"path",
|
|
377
|
+
"isInner"
|
|
378
|
+
]);
|
|
379
|
+
|
|
380
|
+
let validSvmTransactionFields = new Set([
|
|
381
|
+
"transactionIndex",
|
|
382
|
+
"signature",
|
|
383
|
+
"feePayer",
|
|
384
|
+
"success",
|
|
385
|
+
"err",
|
|
386
|
+
"fee",
|
|
387
|
+
"computeUnitsConsumed",
|
|
388
|
+
"accountKeys",
|
|
389
|
+
"recentBlockhash",
|
|
390
|
+
"version",
|
|
391
|
+
"allSignatures"
|
|
392
|
+
]);
|
|
393
|
+
|
|
394
|
+
let validSvmAccountActivityFields = new Set([
|
|
395
|
+
"address",
|
|
396
|
+
"transactionAccountIndex",
|
|
397
|
+
"isSigner",
|
|
398
|
+
"isWritable",
|
|
399
|
+
"lamports",
|
|
400
|
+
"lamports.pre",
|
|
401
|
+
"lamports.post",
|
|
402
|
+
"token",
|
|
403
|
+
"token.mint",
|
|
404
|
+
"token.owner",
|
|
405
|
+
"token.decimals",
|
|
406
|
+
"token.preAmount",
|
|
407
|
+
"token.postAmount"
|
|
408
|
+
]);
|
|
409
|
+
|
|
410
|
+
let validSvmBlockFields = new Set([
|
|
346
411
|
"slot",
|
|
347
412
|
"time",
|
|
348
|
-
"hash"
|
|
349
|
-
|
|
413
|
+
"hash",
|
|
414
|
+
"height",
|
|
415
|
+
"parentSlot",
|
|
416
|
+
"parentHash"
|
|
417
|
+
]);
|
|
418
|
+
|
|
419
|
+
let validSvmLogFields = new Set([
|
|
420
|
+
"kind",
|
|
421
|
+
"message"
|
|
422
|
+
]);
|
|
350
423
|
|
|
351
|
-
function
|
|
352
|
-
let
|
|
353
|
-
|
|
424
|
+
function resolveSvmInlineFieldSelection(fields, contractName, eventName) {
|
|
425
|
+
let registration = `the "` + eventName + `" event registration on contract "` + contractName + `"`;
|
|
426
|
+
validateFieldsShapeOrThrow(fields, registration, svmSelectionKinds, "instruction, transaction, accountActivity, block and log");
|
|
427
|
+
let accountActivity = selectionList(fields, "accountActivity");
|
|
428
|
+
let log = selectionList(fields, "log");
|
|
429
|
+
let instructionFields = parseFieldsOrThrow(selectionList(fields, "instruction"), validSvmInstructionFields, "instruction", registration, undefined);
|
|
430
|
+
let transactionFields = parseFieldsOrThrow(selectionList(fields, "transaction"), validSvmTransactionFields, "transaction", registration, undefined);
|
|
431
|
+
let accountActivityFields = parseFieldsOrThrow(accountActivity, validSvmAccountActivityFields, "accountActivity", registration, Stdlib_Option.isSome(accountActivity));
|
|
432
|
+
let blockFields = parseFieldsOrThrow(selectionList(fields, "block"), validSvmBlockFields, "block", registration, undefined);
|
|
433
|
+
let logFields = parseFieldsOrThrow(log, validSvmLogFields, "log", registration, Stdlib_Option.isSome(log));
|
|
434
|
+
Utils.$$Set.addMany(blockFields, alwaysIncludedSvmBlockFields);
|
|
435
|
+
if (accountActivityFields.size > 0) {
|
|
436
|
+
transactionFields.add("accountActivities");
|
|
437
|
+
}
|
|
438
|
+
return Internal.makeFieldSelection(blockFields, transactionFields, Primitive_option.some(instructionFields), Primitive_option.some(accountActivityFields), Primitive_option.some(logFields), Svm.eventBlockFieldMask, Svm.eventTransactionFieldMask);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function buildSvmInstructionEventConfig(contractName, instructionName, programId, discriminator, discriminatorByteLen, accountFilters, isInner, accountsOpt, argsOpt, definedTypesOpt) {
|
|
354
442
|
let accounts = accountsOpt !== undefined ? accountsOpt : [];
|
|
355
443
|
let args = argsOpt !== undefined ? argsOpt : null;
|
|
356
444
|
let definedTypes = definedTypesOpt !== undefined ? definedTypesOpt : null;
|
|
357
445
|
let paramsSchema = Utils.Schema.coerceToJsonPgType(S$RescriptSchema.json(false));
|
|
358
|
-
let fieldSelection = Internal.makeFieldSelection(new Set(alwaysIncludedSvmBlockFields
|
|
446
|
+
let fieldSelection = Internal.makeFieldSelection(new Set(alwaysIncludedSvmBlockFields), new Set(), undefined, undefined, undefined, Svm.eventBlockFieldMask, Svm.eventTransactionFieldMask);
|
|
359
447
|
return {
|
|
360
448
|
id: discriminator !== undefined ? discriminator : "none",
|
|
361
449
|
name: instructionName,
|
|
@@ -366,7 +454,6 @@ function buildSvmInstructionEventConfig(contractName, instructionName, programId
|
|
|
366
454
|
programId: programId,
|
|
367
455
|
discriminator: discriminator,
|
|
368
456
|
discriminatorByteLen: discriminatorByteLen,
|
|
369
|
-
includeLogs: includeLogs,
|
|
370
457
|
accountFilters: accountFilters,
|
|
371
458
|
isInner: isInner,
|
|
372
459
|
accounts: accounts,
|
|
@@ -375,7 +462,7 @@ function buildSvmInstructionEventConfig(contractName, instructionName, programId
|
|
|
375
462
|
};
|
|
376
463
|
}
|
|
377
464
|
|
|
378
|
-
function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, startBlock) {
|
|
465
|
+
function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, fieldSelection, startBlock) {
|
|
379
466
|
return {
|
|
380
467
|
index: -1,
|
|
381
468
|
eventConfig: eventConfig,
|
|
@@ -385,7 +472,7 @@ function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractR
|
|
|
385
472
|
filterByAddresses: false,
|
|
386
473
|
dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, false),
|
|
387
474
|
startBlock: startBlock,
|
|
388
|
-
fieldSelection: eventConfig.fieldSelection
|
|
475
|
+
fieldSelection: fieldSelection !== undefined ? fieldSelection : eventConfig.fieldSelection
|
|
389
476
|
};
|
|
390
477
|
}
|
|
391
478
|
|
|
@@ -438,7 +525,7 @@ function buildFuelEventConfig(contractName, eventName, kind, sighash, rawAbi) {
|
|
|
438
525
|
contractName: contractName,
|
|
439
526
|
paramsRawEventSchema: paramsSchema,
|
|
440
527
|
simulateParamsSchema: paramsSchema,
|
|
441
|
-
fieldSelection: Internal.makeFieldSelection(new Set(Fuel.blockFields), new Set(Fuel.transactionFields), Fuel.eventBlockFieldMask, Fuel.eventTransactionFieldMask),
|
|
528
|
+
fieldSelection: Internal.makeFieldSelection(new Set(Fuel.blockFields), new Set(Fuel.transactionFields), undefined, undefined, undefined, Fuel.eventBlockFieldMask, Fuel.eventTransactionFieldMask),
|
|
442
529
|
kind: fuelKind
|
|
443
530
|
};
|
|
444
531
|
}
|
|
@@ -474,8 +561,11 @@ export {
|
|
|
474
561
|
resolveFieldSelection,
|
|
475
562
|
internalBlockFields,
|
|
476
563
|
rawEventBlockFields,
|
|
477
|
-
|
|
564
|
+
evmSelectionKinds,
|
|
565
|
+
svmSelectionKinds,
|
|
566
|
+
quotedJoin,
|
|
478
567
|
validateFieldsShapeOrThrow,
|
|
568
|
+
selectionList,
|
|
479
569
|
validBlockFields,
|
|
480
570
|
validTransactionFields,
|
|
481
571
|
parseFieldsOrThrow,
|
|
@@ -483,6 +573,12 @@ export {
|
|
|
483
573
|
buildEvmEventConfig,
|
|
484
574
|
buildEvmOnEventRegistration,
|
|
485
575
|
alwaysIncludedSvmBlockFields,
|
|
576
|
+
validSvmInstructionFields,
|
|
577
|
+
validSvmTransactionFields,
|
|
578
|
+
validSvmAccountActivityFields,
|
|
579
|
+
validSvmBlockFields,
|
|
580
|
+
validSvmLogFields,
|
|
581
|
+
resolveSvmInlineFieldSelection,
|
|
486
582
|
buildSvmInstructionEventConfig,
|
|
487
583
|
buildSvmOnEventRegistration,
|
|
488
584
|
buildFuelEventConfig,
|
package/src/HandlerRegister.res
CHANGED
|
@@ -154,6 +154,7 @@ let buildOnEventRegistrationWith = (
|
|
|
154
154
|
~isWildcard,
|
|
155
155
|
~handler,
|
|
156
156
|
~contractRegister,
|
|
157
|
+
~fieldSelection?,
|
|
157
158
|
~startBlock?,
|
|
158
159
|
) :> Internal.onEventRegistration)
|
|
159
160
|
| Evm =>
|
|
@@ -299,21 +300,29 @@ let addOnEventRegistration = (
|
|
|
299
300
|
let fieldSelection = switch eventOptions->Option.flatMap(v => v.fields) {
|
|
300
301
|
| None => None
|
|
301
302
|
| Some(fields) =>
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
switch registration.config.ecosystem.name {
|
|
304
|
+
| Evm =>
|
|
305
|
+
Some(
|
|
306
|
+
EventConfigBuilder.resolveInlineFieldSelection(
|
|
307
|
+
fields,
|
|
308
|
+
~contractName,
|
|
309
|
+
~eventName,
|
|
310
|
+
~enableRawEvents=registration.config.enableRawEvents,
|
|
311
|
+
),
|
|
312
|
+
)
|
|
313
|
+
| Svm =>
|
|
314
|
+
Some(
|
|
315
|
+
EventConfigBuilder.resolveSvmInlineFieldSelection(
|
|
316
|
+
fields,
|
|
317
|
+
~contractName,
|
|
318
|
+
~eventName,
|
|
319
|
+
),
|
|
320
|
+
)
|
|
321
|
+
| Fuel =>
|
|
305
322
|
JsError.throwWithMessage(
|
|
306
323
|
`The fields option of the "${eventName}" event registration on contract "${contractName}" is only supported on EVM. Select the fields in your config instead.`,
|
|
307
324
|
)
|
|
308
325
|
}
|
|
309
|
-
Some(
|
|
310
|
-
EventConfigBuilder.resolveInlineFieldSelection(
|
|
311
|
-
fields,
|
|
312
|
-
~contractName,
|
|
313
|
-
~eventName,
|
|
314
|
-
~enableRawEvents=registration.config.enableRawEvents,
|
|
315
|
-
),
|
|
316
|
-
)
|
|
317
326
|
}
|
|
318
327
|
let matched = ref(false)
|
|
319
328
|
registration.config.chainMap
|
|
@@ -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, startBlock);
|
|
105
|
+
return EventConfigBuilder.buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, fieldSelection, startBlock);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -200,7 +200,24 @@ function addOnEventRegistration(registration, contractName, eventName, handler,
|
|
|
200
200
|
let isWildcard = Stdlib_Option.getOr(Stdlib_Option.flatMap(eventOptions, v => v.wildcard), false);
|
|
201
201
|
let where = Stdlib_Option.flatMap(eventOptions, v => v.where);
|
|
202
202
|
let fields = Stdlib_Option.flatMap(eventOptions, v => v.fields);
|
|
203
|
-
let fieldSelection
|
|
203
|
+
let fieldSelection;
|
|
204
|
+
if (fields !== undefined) {
|
|
205
|
+
let fields$1 = Primitive_option.valFromOption(fields);
|
|
206
|
+
let match = registration.config.ecosystem.name;
|
|
207
|
+
switch (match) {
|
|
208
|
+
case "evm" :
|
|
209
|
+
fieldSelection = EventConfigBuilder.resolveInlineFieldSelection(fields$1, contractName, eventName, registration.config.enableRawEvents);
|
|
210
|
+
break;
|
|
211
|
+
case "fuel" :
|
|
212
|
+
fieldSelection = Stdlib_JsError.throwWithMessage(`The fields option of the "` + eventName + `" event registration on contract "` + contractName + `" is only supported on EVM. Select the fields in your config instead.`);
|
|
213
|
+
break;
|
|
214
|
+
case "svm" :
|
|
215
|
+
fieldSelection = EventConfigBuilder.resolveSvmInlineFieldSelection(fields$1, contractName, eventName);
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
fieldSelection = undefined;
|
|
220
|
+
}
|
|
204
221
|
let matched = {
|
|
205
222
|
contents: false
|
|
206
223
|
};
|
|
@@ -220,8 +237,8 @@ function addOnEventRegistration(registration, contractName, eventName, handler,
|
|
|
220
237
|
if (matched.contents) {
|
|
221
238
|
return;
|
|
222
239
|
}
|
|
223
|
-
let match = describeConfigured(registration, contractName);
|
|
224
|
-
let eventNames = match[1];
|
|
240
|
+
let match$1 = describeConfigured(registration, contractName);
|
|
241
|
+
let eventNames = match$1[1];
|
|
225
242
|
let listOr = (names, empty) => {
|
|
226
243
|
if (Utils.$$Array.isEmpty(names)) {
|
|
227
244
|
return empty;
|
|
@@ -230,7 +247,7 @@ function addOnEventRegistration(registration, contractName, eventName, handler,
|
|
|
230
247
|
}
|
|
231
248
|
};
|
|
232
249
|
if (Utils.$$Array.isEmpty(eventNames)) {
|
|
233
|
-
return Stdlib_JsError.throwWithMessage(`Contract "` + 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 contracts: ` + listOr(match[0], "none") + `.`);
|
|
250
|
+
return Stdlib_JsError.throwWithMessage(`Contract "` + 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 contracts: ` + listOr(match$1[0], "none") + `.`);
|
|
234
251
|
} else {
|
|
235
252
|
return Stdlib_JsError.throwWithMessage(`Event "` + eventName + `" is not configured on contract "` + contractName + `", so its handler would never run. Add it to your config, or remove the registration. Configured events on "` + contractName + `": ` + listOr(eventNames, "none") + `.`);
|
|
236
253
|
}
|
package/src/Hasura.res
CHANGED
|
@@ -286,9 +286,7 @@ let createSelectPermission = async (
|
|
|
286
286
|
// column joins alongside the id — without it the relationship would resolve to
|
|
287
287
|
// another chain's row with the same id.
|
|
288
288
|
let makeColumnMapping = (~relationalKey, ~isDerivedFrom, ~chainIdColumn) => {
|
|
289
|
-
let pairs = [
|
|
290
|
-
isDerivedFrom ? `"id": "${relationalKey}"` : `"${relationalKey}": "id"`,
|
|
291
|
-
]
|
|
289
|
+
let pairs = [isDerivedFrom ? `"id": "${relationalKey}"` : `"${relationalKey}": "id"`]
|
|
292
290
|
switch chainIdColumn {
|
|
293
291
|
| Some(column) => pairs->Array.push(`"${column}": "${column}"`)->ignore
|
|
294
292
|
| None => ()
|
|
@@ -309,7 +307,6 @@ let createEntityRelationship = async (
|
|
|
309
307
|
~chainIdColumn: option<string>,
|
|
310
308
|
~comment: option<string>=?,
|
|
311
309
|
) => {
|
|
312
|
-
|
|
313
310
|
let tableJson = {
|
|
314
311
|
"schema": pgSchema,
|
|
315
312
|
"name": tableName,
|
|
@@ -347,15 +344,7 @@ let createEntityRelationship = async (
|
|
|
347
344
|
)
|
|
348
345
|
}
|
|
349
346
|
|
|
350
|
-
let
|
|
351
|
-
~endpoint,
|
|
352
|
-
~auth,
|
|
353
|
-
~pgSchema,
|
|
354
|
-
~userEntities: array<Internal.entityConfig>,
|
|
355
|
-
~aggregateEntities,
|
|
356
|
-
~responseLimit,
|
|
357
|
-
~schema,
|
|
358
|
-
) => {
|
|
347
|
+
let makeTableConfigs = (~userEntities: array<Internal.entityConfig>) => {
|
|
359
348
|
let exposedInternalTableConfigs = [
|
|
360
349
|
{
|
|
361
350
|
tableName: InternalTable.RawEvents.table.tableName,
|
|
@@ -373,12 +362,27 @@ let trackDatabase = async (
|
|
|
373
362
|
columnConfigs: dict{},
|
|
374
363
|
},
|
|
375
364
|
]
|
|
376
|
-
let userTableConfigs =
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
365
|
+
let userTableConfigs =
|
|
366
|
+
userEntities
|
|
367
|
+
->Array.filter(entity => !entity.internal)
|
|
368
|
+
->Array.map(entity => {
|
|
369
|
+
tableName: entity.table.tableName,
|
|
370
|
+
description: entity.table.description,
|
|
371
|
+
columnConfigs: entity.table->makeColumnConfigs,
|
|
372
|
+
})
|
|
373
|
+
[exposedInternalTableConfigs, userTableConfigs]->Array.flat
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
let trackDatabase = async (
|
|
377
|
+
~endpoint,
|
|
378
|
+
~auth,
|
|
379
|
+
~pgSchema,
|
|
380
|
+
~userEntities: array<Internal.entityConfig>,
|
|
381
|
+
~aggregateEntities,
|
|
382
|
+
~responseLimit,
|
|
383
|
+
~schema,
|
|
384
|
+
) => {
|
|
385
|
+
let tableConfigs = makeTableConfigs(~userEntities)
|
|
382
386
|
let tableNames = tableConfigs->Array.map(c => c.tableName)
|
|
383
387
|
|
|
384
388
|
Logging.info("Tracking tables in Hasura")
|
|
@@ -414,10 +418,14 @@ let trackDatabase = async (
|
|
|
414
418
|
->Option.flatMap(e => e.table->Table.getChainIdField)
|
|
415
419
|
->Option.map(Table.getPgDbFieldName)
|
|
416
420
|
|
|
417
|
-
|
|
418
|
-
|
|
421
|
+
// Relationships to an @internal entity can't exist here: codegen rejects a
|
|
422
|
+
// reference from an exposed entity to an @internal one.
|
|
423
|
+
let exposedEntities = userEntities->Array.filter(e => !e.internal)
|
|
424
|
+
for i in 0 to exposedEntities->Array.length - 1 {
|
|
425
|
+
let entityConfig = exposedEntities->Array.getUnsafe(i)
|
|
419
426
|
let {tableName} = entityConfig.table
|
|
420
|
-
let ownChainIdColumn =
|
|
427
|
+
let ownChainIdColumn =
|
|
428
|
+
entityConfig.table->Table.getChainIdField->Option.map(Table.getPgDbFieldName)
|
|
421
429
|
let sharedChainIdColumn = mappedEntity =>
|
|
422
430
|
switch (ownChainIdColumn, chainIdColumnOf(mappedEntity)) {
|
|
423
431
|
| (Some(column), Some(_)) => Some(column)
|
package/src/Hasura.res.mjs
CHANGED
|
@@ -285,7 +285,7 @@ async function createEntityRelationship(endpoint, auth, pgSchema, tableName, rel
|
|
|
285
285
|
});
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
-
|
|
288
|
+
function makeTableConfigs(userEntities) {
|
|
289
289
|
let exposedInternalTableConfigs = [
|
|
290
290
|
{
|
|
291
291
|
tableName: InternalTable.RawEvents.table.tableName,
|
|
@@ -303,15 +303,19 @@ async function trackDatabase(endpoint, auth, pgSchema, userEntities, aggregateEn
|
|
|
303
303
|
columnConfigs: {}
|
|
304
304
|
}
|
|
305
305
|
];
|
|
306
|
-
let userTableConfigs = userEntities.map(entity => ({
|
|
306
|
+
let userTableConfigs = userEntities.filter(entity => !entity.internal).map(entity => ({
|
|
307
307
|
tableName: entity.table.tableName,
|
|
308
308
|
description: entity.table.description,
|
|
309
309
|
columnConfigs: makeColumnConfigs(entity.table)
|
|
310
310
|
}));
|
|
311
|
-
|
|
311
|
+
return [
|
|
312
312
|
exposedInternalTableConfigs,
|
|
313
313
|
userTableConfigs
|
|
314
314
|
].flat();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async function trackDatabase(endpoint, auth, pgSchema, userEntities, aggregateEntities, responseLimit, schema) {
|
|
318
|
+
let tableConfigs = makeTableConfigs(userEntities);
|
|
315
319
|
let tableNames = tableConfigs.map(c => c.tableName);
|
|
316
320
|
Logging.info("Tracking tables in Hasura");
|
|
317
321
|
await clearHasuraMetadata(endpoint, auth);
|
|
@@ -322,8 +326,9 @@ async function trackDatabase(endpoint, auth, pgSchema, userEntities, aggregateEn
|
|
|
322
326
|
await createSelectPermission(endpoint, auth, tableName, pgSchema, responseLimit, aggregateEntities);
|
|
323
327
|
}
|
|
324
328
|
let chainIdColumnOf = entityName => Stdlib_Option.map(Stdlib_Option.flatMap(userEntities.find(e => e.name === entityName), e => Table.getChainIdField(e.table)), Table.getPgDbFieldName);
|
|
325
|
-
|
|
326
|
-
|
|
329
|
+
let exposedEntities = userEntities.filter(e => !e.internal);
|
|
330
|
+
for (let i$1 = 0, i_finish$1 = exposedEntities.length; i$1 < i_finish$1; ++i$1) {
|
|
331
|
+
let entityConfig = exposedEntities[i$1];
|
|
327
332
|
let match = entityConfig.table;
|
|
328
333
|
let tableName$1 = match.tableName;
|
|
329
334
|
let ownChainIdColumn = Stdlib_Option.map(Table.getChainIdField(entityConfig.table), Table.getPgDbFieldName);
|
|
@@ -365,6 +370,7 @@ export {
|
|
|
365
370
|
createSelectPermission,
|
|
366
371
|
makeColumnMapping,
|
|
367
372
|
createEntityRelationship,
|
|
373
|
+
makeTableConfigs,
|
|
368
374
|
trackDatabase,
|
|
369
375
|
}
|
|
370
376
|
/* Rest Not a pure module */
|
package/src/InMemoryStore.res
CHANGED
|
@@ -148,7 +148,7 @@ let prepareRollbackDiff = async (
|
|
|
148
148
|
let _ = await persistence.allEntities
|
|
149
149
|
->Array.filter(entityConfig => entityConfig.storage.postgres)
|
|
150
150
|
->Array.map(async entityConfig => {
|
|
151
|
-
let (removals,
|
|
151
|
+
let (removals, restoredEntities) = await persistence.storage.getRollbackData(
|
|
152
152
|
~entityConfig,
|
|
153
153
|
~rollbackTargetCheckpointId,
|
|
154
154
|
)
|
|
@@ -166,11 +166,6 @@ let prepareRollbackDiff = async (
|
|
|
166
166
|
)
|
|
167
167
|
})
|
|
168
168
|
|
|
169
|
-
let restoredEntities =
|
|
170
|
-
restoredEntitiesResult
|
|
171
|
-
->S.parseOrThrow(entityConfig.table->Table.pgRowsSchema)
|
|
172
|
-
->(Utils.magic: array<unknown> => array<Internal.entity>)
|
|
173
|
-
|
|
174
169
|
restoredEntities->Array.forEach((entity: Internal.entity) => {
|
|
175
170
|
let scope = entity->takeRowScope(~entityConfig)
|
|
176
171
|
setEntities->Utils.Dict.push(entityConfig.name, entity.id)
|
|
@@ -12,7 +12,6 @@ import * as InMemoryTable from "./InMemoryTable.res.mjs";
|
|
|
12
12
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
13
13
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
14
14
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
15
|
-
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
16
15
|
|
|
17
16
|
function getInMemTable(state, entityConfig, scope) {
|
|
18
17
|
let tmp;
|
|
@@ -125,8 +124,7 @@ async function prepareRollbackDiff(state, rollbackTargetCheckpointId, rollbackDi
|
|
|
125
124
|
checkpointId: rollbackDiffCheckpointId
|
|
126
125
|
});
|
|
127
126
|
});
|
|
128
|
-
|
|
129
|
-
restoredEntities.forEach(entity => {
|
|
127
|
+
match[1].forEach(entity => {
|
|
130
128
|
let scope = takeRowScope(entity, entityConfig);
|
|
131
129
|
Utils.Dict.push(setEntities, entityConfig.name, entity.id);
|
|
132
130
|
InMemoryTable.Entity.set(getInMemTable(state, entityConfig, scope), committedCheckpointId, {
|
package/src/Internal.res
CHANGED
|
@@ -149,8 +149,8 @@ type svmTransactionField =
|
|
|
149
149
|
| @as("accountKeys") AccountKeys
|
|
150
150
|
| @as("recentBlockhash") RecentBlockhash
|
|
151
151
|
| @as("version") Version
|
|
152
|
-
| @as("tokenBalances") TokenBalances
|
|
153
152
|
| @as("allSignatures") AllSignatures
|
|
153
|
+
| @as("accountActivities") AccountActivities
|
|
154
154
|
|
|
155
155
|
let allSvmTransactionFields: array<svmTransactionField> = [
|
|
156
156
|
TransactionIndex,
|
|
@@ -163,13 +163,12 @@ let allSvmTransactionFields: array<svmTransactionField> = [
|
|
|
163
163
|
AccountKeys,
|
|
164
164
|
RecentBlockhash,
|
|
165
165
|
Version,
|
|
166
|
-
TokenBalances,
|
|
167
166
|
AllSignatures,
|
|
167
|
+
AccountActivities,
|
|
168
168
|
]
|
|
169
|
-
let svmTransactionFieldSchema = S.enum(allSvmTransactionFields)
|
|
170
169
|
|
|
171
|
-
// All SVM block fields. `slot
|
|
172
|
-
// selectable via
|
|
170
|
+
// All SVM block fields. `slot` is always included (the item's key); the rest
|
|
171
|
+
// are selectable via handler `fields.block`.
|
|
173
172
|
type svmBlockField =
|
|
174
173
|
| @as("slot") Slot
|
|
175
174
|
| @as("time") Time
|
|
@@ -178,9 +177,6 @@ type svmBlockField =
|
|
|
178
177
|
| @as("parentSlot") ParentSlot
|
|
179
178
|
| @as("parentHash") ParentHash
|
|
180
179
|
|
|
181
|
-
let allSvmBlockFields: array<svmBlockField> = [Height, ParentSlot, ParentHash]
|
|
182
|
-
let svmBlockFieldSchema = S.enum(allSvmBlockFields)
|
|
183
|
-
|
|
184
180
|
// Static sets of field names whose source schemas must be wrapped with S.nullable.
|
|
185
181
|
let evmNullableBlockFields = Utils.Set.fromArray(
|
|
186
182
|
(
|
|
@@ -427,6 +423,9 @@ type indexingContract = {
|
|
|
427
423
|
type fieldSelection = {
|
|
428
424
|
blockFields: Utils.Set.t<string>,
|
|
429
425
|
transactionFields: Utils.Set.t<string>,
|
|
426
|
+
instructionFields: Utils.Set.t<string>,
|
|
427
|
+
accountActivityFields: Utils.Set.t<string>,
|
|
428
|
+
logFields: Utils.Set.t<string>,
|
|
430
429
|
// The sets precompiled to the store selections `ChainState` materialises with.
|
|
431
430
|
blockMask: float,
|
|
432
431
|
transactionMask: float,
|
|
@@ -438,11 +437,17 @@ type fieldSelection = {
|
|
|
438
437
|
let makeFieldSelection = (
|
|
439
438
|
~blockFields: Utils.Set.t<string>,
|
|
440
439
|
~transactionFields: Utils.Set.t<string>,
|
|
440
|
+
~instructionFields: Utils.Set.t<string>=Utils.Set.make(),
|
|
441
|
+
~accountActivityFields: Utils.Set.t<string>=Utils.Set.make(),
|
|
442
|
+
~logFields: Utils.Set.t<string>=Utils.Set.make(),
|
|
441
443
|
~blockMaskFn: Utils.Set.t<string> => float,
|
|
442
444
|
~transactionMaskFn: Utils.Set.t<string> => float,
|
|
443
445
|
): fieldSelection => {
|
|
444
446
|
blockFields,
|
|
445
447
|
transactionFields,
|
|
448
|
+
instructionFields,
|
|
449
|
+
accountActivityFields,
|
|
450
|
+
logFields,
|
|
446
451
|
blockMask: blockMaskFn(blockFields),
|
|
447
452
|
transactionMask: transactionMaskFn(transactionFields),
|
|
448
453
|
}
|
|
@@ -459,6 +464,9 @@ let unionFields = (a, b) => a === b ? a : a->Utils.Set.union(b)
|
|
|
459
464
|
let unionFieldSelection = (a: fieldSelection, b: fieldSelection): fieldSelection => {
|
|
460
465
|
blockFields: unionFields(a.blockFields, b.blockFields),
|
|
461
466
|
transactionFields: unionFields(a.transactionFields, b.transactionFields),
|
|
467
|
+
instructionFields: unionFields(a.instructionFields, b.instructionFields),
|
|
468
|
+
accountActivityFields: unionFields(a.accountActivityFields, b.accountActivityFields),
|
|
469
|
+
logFields: unionFields(a.logFields, b.logFields),
|
|
462
470
|
blockMask: FieldMask.orMask(a.blockMask, b.blockMask),
|
|
463
471
|
transactionMask: FieldMask.orMask(a.transactionMask, b.transactionMask),
|
|
464
472
|
}
|
|
@@ -569,7 +577,6 @@ type svmInstructionEventConfig = {
|
|
|
569
577
|
`dN` selector at query time and the dispatch-key precomputation in the
|
|
570
578
|
router. */
|
|
571
579
|
discriminatorByteLen: int,
|
|
572
|
-
includeLogs: bool,
|
|
573
580
|
/** Disjunctive normal form: outer array is OR of AND-groups, inner array is
|
|
574
581
|
AND across positions. Empty outer array means "no account filter". */
|
|
575
582
|
accountFilters: array<svmAccountFilterGroup>,
|
|
@@ -747,9 +754,8 @@ let getItemChainId = item =>
|
|
|
747
754
|
| Block({onBlockRegistration: {chainId}}) => chainId
|
|
748
755
|
}
|
|
749
756
|
|
|
750
|
-
//
|
|
751
|
-
//
|
|
752
|
-
// `field_selection` for this registration.
|
|
757
|
+
// EVM `fields` bag. Parsed from the JS object as `unknown` at registration;
|
|
758
|
+
// this record exists so ReScript tests can construct a typed EVM selection.
|
|
753
759
|
type evmFieldsSelection = {
|
|
754
760
|
block?: array<string>,
|
|
755
761
|
transaction?: array<string>,
|
|
@@ -758,7 +764,7 @@ type evmFieldsSelection = {
|
|
|
758
764
|
type eventOptions<'where> = {
|
|
759
765
|
wildcard?: bool,
|
|
760
766
|
where?: 'where,
|
|
761
|
-
fields?:
|
|
767
|
+
fields?: unknown,
|
|
762
768
|
}
|
|
763
769
|
|
|
764
770
|
type fuelSupplyParams = {
|
|
@@ -782,12 +788,23 @@ let fuelTransferParamsSchema = S.schema(s => {
|
|
|
782
788
|
|
|
783
789
|
type entity = private {id: string}
|
|
784
790
|
|
|
791
|
+
// A data skipping index emitted into the history table DDL as
|
|
792
|
+
// `INDEX <name> <expr> TYPE <type> GRANULARITY <granularity>`.
|
|
793
|
+
type clickhouseSkippingIndex = {
|
|
794
|
+
name: string,
|
|
795
|
+
expr: string,
|
|
796
|
+
@as("type")
|
|
797
|
+
type_: string,
|
|
798
|
+
granularity?: int,
|
|
799
|
+
}
|
|
800
|
+
|
|
785
801
|
// Raw ClickHouse expressions/field names from the entity's
|
|
786
802
|
// @storage(clickhouse: {...}) directive, applied to the history table DDL.
|
|
787
803
|
type clickhouseTableOptions = {
|
|
788
804
|
partitionBy?: string,
|
|
789
805
|
orderBy?: array<string>,
|
|
790
806
|
ttl?: string,
|
|
807
|
+
skippingIndexes?: array<clickhouseSkippingIndex>,
|
|
791
808
|
}
|
|
792
809
|
|
|
793
810
|
// Per-entity storage resolved at parse time against the global storage
|
|
@@ -808,6 +825,9 @@ type genericEntityConfig<'entity> = {
|
|
|
808
825
|
// entity's `@crossChain`. When false the table carries a chain-id column in
|
|
809
826
|
// its primary key and every row belongs to exactly one chain.
|
|
810
827
|
crossChain: bool,
|
|
828
|
+
// `@internal` on the entity: stored and usable in handlers as normal, but
|
|
829
|
+
// never exposed through the GraphQL API (no Hasura tracking).
|
|
830
|
+
internal: bool,
|
|
811
831
|
}
|
|
812
832
|
type entityConfig = genericEntityConfig<entity>
|
|
813
833
|
external fromGenericEntityConfig: genericEntityConfig<'entity> => entityConfig = "%identity"
|