envio 3.6.1 → 3.7.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.
Files changed (80) hide show
  1. package/index.d.ts +197 -9
  2. package/package.json +6 -6
  3. package/src/Batch.res +64 -25
  4. package/src/Batch.res.mjs +69 -46
  5. package/src/ChainFetching.res +13 -17
  6. package/src/ChainFetching.res.mjs +9 -14
  7. package/src/ChainState.res +160 -119
  8. package/src/ChainState.res.mjs +75 -46
  9. package/src/ChainState.resi +15 -12
  10. package/src/Config.res +9 -2
  11. package/src/Config.res.mjs +4 -4
  12. package/src/Core.res +5 -0
  13. package/src/Ecosystem.res +0 -1
  14. package/src/Envio.res +16 -3
  15. package/src/EventConfigBuilder.res +155 -40
  16. package/src/EventConfigBuilder.res.mjs +76 -24
  17. package/src/EventProcessing.res +4 -8
  18. package/src/EventProcessing.res.mjs +4 -4
  19. package/src/EventUtils.res +3 -47
  20. package/src/FetchState.res +124 -104
  21. package/src/FetchState.res.mjs +116 -100
  22. package/src/HandlerRegister.res +108 -2
  23. package/src/HandlerRegister.res.mjs +59 -10
  24. package/src/HandlerRegister.resi +4 -0
  25. package/src/Internal.res +84 -24
  26. package/src/Internal.res.mjs +33 -2
  27. package/src/LazyLoader.res +12 -11
  28. package/src/LazyLoader.res.mjs +13 -7
  29. package/src/Main.res +22 -9
  30. package/src/Main.res.mjs +18 -5
  31. package/src/MemoryStorage.res +724 -0
  32. package/src/MemoryStorage.res.mjs +601 -0
  33. package/src/PgStorage.res +18 -7
  34. package/src/PgStorage.res.mjs +14 -11
  35. package/src/ReorgDetection.res +0 -222
  36. package/src/ReorgDetection.res.mjs +0 -163
  37. package/src/Rollback.res +14 -15
  38. package/src/Rollback.res.mjs +4 -5
  39. package/src/SimulateItems.res +2 -2
  40. package/src/Utils.res +3 -0
  41. package/src/bindings/ClickHouse.res +16 -11
  42. package/src/bindings/ClickHouse.res.mjs +10 -10
  43. package/src/bindings/Vitest.res +1 -1
  44. package/src/sources/BlockStore.res +115 -5
  45. package/src/sources/BlockStore.res.mjs +25 -0
  46. package/src/sources/Evm.res +0 -1
  47. package/src/sources/Evm.res.mjs +0 -1
  48. package/src/sources/EvmHyperSyncSource.res +19 -84
  49. package/src/sources/EvmHyperSyncSource.res.mjs +24 -60
  50. package/src/sources/Fuel.res +24 -4
  51. package/src/sources/Fuel.res.mjs +23 -3
  52. package/src/sources/FuelHyperSync.res +8 -3
  53. package/src/sources/FuelHyperSync.res.mjs +5 -4
  54. package/src/sources/FuelHyperSync.resi +3 -1
  55. package/src/sources/FuelHyperSyncClient.res +7 -10
  56. package/src/sources/FuelHyperSyncSource.res +18 -45
  57. package/src/sources/FuelHyperSyncSource.res.mjs +18 -35
  58. package/src/sources/HyperSync.res +49 -229
  59. package/src/sources/HyperSync.res.mjs +74 -191
  60. package/src/sources/HyperSync.resi +11 -35
  61. package/src/sources/HyperSyncClient.res +9 -79
  62. package/src/sources/HyperSyncClient.res.mjs +2 -6
  63. package/src/sources/RequestStat.res +5 -0
  64. package/src/sources/RequestStat.res.mjs +2 -0
  65. package/src/sources/RpcSource.res +149 -43
  66. package/src/sources/RpcSource.res.mjs +104 -41
  67. package/src/sources/SimulateSource.res +8 -5
  68. package/src/sources/SimulateSource.res.mjs +6 -6
  69. package/src/sources/Source.res +89 -16
  70. package/src/sources/Source.res.mjs +50 -1
  71. package/src/sources/SourceManager.res +255 -50
  72. package/src/sources/SourceManager.res.mjs +149 -55
  73. package/src/sources/SourceManager.resi +2 -6
  74. package/src/sources/Svm.res +0 -7
  75. package/src/sources/Svm.res.mjs +0 -8
  76. package/src/sources/SvmHyperSyncClient.res +21 -16
  77. package/src/sources/SvmHyperSyncClient.res.mjs +3 -4
  78. package/src/sources/SvmHyperSyncSource.res +25 -117
  79. package/src/sources/SvmHyperSyncSource.res.mjs +8 -121
  80. package/svm.schema.json +3 -2
@@ -236,8 +236,8 @@ let buildSimulateParamsSchema = (params: array<paramMeta>): S.t<Internal.eventPa
236
236
 
237
237
  // ============== Build topic filter getters ==============
238
238
 
239
- let getTopicEncoder = (abiType: string): (unknown => EvmTypes.Hex.t) => value =>
240
- Core.getAddon().encodeIndexedTopic(~abiType, ~value)
239
+ let getTopicEncoder = (abiType: string): (unknown => EvmTypes.Hex.t) =>
240
+ value => Core.getAddon().encodeIndexedTopic(~abiType, ~value)
241
241
 
242
242
  let buildTopicGetter = (p: paramMeta) => {
243
243
  let encoder = getTopicEncoder(p.abiType)
@@ -247,6 +247,7 @@ let buildTopicGetter = (p: paramMeta) => {
247
247
  ->Utils.Dict.dangerouslyGetNonOption(p.name)
248
248
  ->Option.mapOr([], topicFilters => {
249
249
  let raw = topicFilters->(Utils.magic: JSON.t => unknown)
250
+
250
251
  // A tuple filter value is itself an array, so a directly-passed tuple is
251
252
  // indistinguishable from an OR-list by shape alone. A single tuple is
252
253
  // the common case, so try it first; when the value doesn't ABI-encode as
@@ -282,13 +283,128 @@ let resolveFieldSelection = (
282
283
  | Some(fields) => Utils.Set.fromArray(fields)
283
284
  | None => globalTransactionFieldsSet
284
285
  }
285
- // The base eventConfig stores these as a string set (field names match the
286
- // typed variants at runtime).
287
- (
288
- selectedBlockFields,
289
- selectedTransactionFields->(
286
+ Internal.makeFieldSelection(
287
+ ~blockFields=selectedBlockFields->(
288
+ Utils.magic: Utils.Set.t<Internal.evmBlockField> => Utils.Set.t<string>
289
+ ),
290
+ ~transactionFields=selectedTransactionFields->(
290
291
  Utils.magic: Utils.Set.t<Internal.evmTransactionField> => Utils.Set.t<string>
291
292
  ),
293
+ ~blockMaskFn=Evm.eventBlockFieldMask,
294
+ ~transactionMaskFn=Evm.eventTransactionFieldMask,
295
+ )
296
+ }
297
+
298
+ // `block.number` is the item's own key, so an inline selection carries it
299
+ // whether or not the handler listed it. Nothing else is added: dropping
300
+ // `timestamp`/`hash` is the point of naming fields inline, and the two things
301
+ // that read them off the payload cope — the progress-latency metric
302
+ // (`ChainState.applyBatchProgress`) skips a batch whose last block has no
303
+ // timestamp, and `raw_events` selects them back below.
304
+ let internalBlockFields = ["number"]
305
+
306
+ // `toRawEvent` reads `block.hash`/`block.timestamp` for the `raw_events` row's
307
+ // own columns, which are not nullable. They stay out of the row's stored
308
+ // `block_fields` (`Evm.cleanUpRawEventFieldsInPlace` strips number/timestamp/
309
+ // hash from it), so the column still holds exactly what the registration
310
+ // selected.
311
+ let rawEventBlockFields = ["hash", "timestamp"]
312
+
313
+ let selectionKinds = ["block", "transaction"]
314
+
315
+ // A handler written in plain JS gets no type error for a `blocks`/`transactions`
316
+ // typo, and an unrecognised key would read as an empty selection — silently
317
+ // dropping every field `config.yaml` selected. Rejected here so the option is
318
+ // held to the same shape whether or not the project type-checks it.
319
+ let validateFieldsShapeOrThrow = (fields: Internal.evmFieldsSelection, ~registration: string) => {
320
+ let raw = fields->(Utils.magic: Internal.evmFieldsSelection => unknown)
321
+ if typeof(raw) !== #object || raw === %raw(`null`) || Array.isArray(raw) {
322
+ JsError.throwWithMessage(
323
+ `The fields option of ${registration} must be an object of block and transaction field names.`,
324
+ )
325
+ }
326
+ raw
327
+ ->(Utils.magic: unknown => dict<unknown>)
328
+ ->Dict.keysToArray
329
+ ->Array.forEach(key =>
330
+ if !(selectionKinds->Array.includes(key)) {
331
+ JsError.throwWithMessage(
332
+ `Invalid "${key}" key in the fields option of ${registration}. Valid keys: ${selectionKinds->Array.joinUnsafe(
333
+ ", ",
334
+ )}.`,
335
+ )
336
+ }
337
+ )
338
+ }
339
+
340
+ let validBlockFields = Utils.Set.fromArray(Evm.blockFields)
341
+ let validTransactionFields = Utils.Set.fromArray(Evm.transactionFields)
342
+
343
+ let parseFieldsOrThrow = (
344
+ fields: option<array<string>>,
345
+ ~valid: Utils.Set.t<string>,
346
+ ~kind: string,
347
+ ~registration: string,
348
+ ) => {
349
+ let seen = Utils.Set.make()
350
+ let fields = switch fields {
351
+ | None => []
352
+ | Some(fields) if !Array.isArray(fields) =>
353
+ JsError.throwWithMessage(
354
+ `The fields.${kind} option of ${registration} must be an array of field names.`,
355
+ )
356
+ | Some(fields) => fields
357
+ }
358
+ fields->Array.forEach(name => {
359
+ if !(valid->Utils.Set.has(name)) {
360
+ JsError.throwWithMessage(
361
+ `Invalid "${name}" field in the fields.${kind} option of ${registration}. Valid ${kind} fields: ${valid
362
+ ->Utils.Set.toArray
363
+ ->Array.joinUnsafe(", ")}.`,
364
+ )
365
+ }
366
+ if seen->Utils.Set.has(name) {
367
+ JsError.throwWithMessage(
368
+ `Duplicate "${name}" field in the fields.${kind} option of ${registration}.`,
369
+ )
370
+ }
371
+ seen->Utils.Set.add(name)->ignore
372
+ })
373
+ seen
374
+ }
375
+
376
+ // Resolve an inline `fields` option into a selection. Depends only on the
377
+ // option itself (the names are for error messages), never on the chain, so one
378
+ // `onEvent` call resolves once and shares the result across every chain.
379
+ let resolveInlineFieldSelection = (
380
+ fields: Internal.evmFieldsSelection,
381
+ ~contractName: string,
382
+ ~eventName: string,
383
+ ~enableRawEvents: bool,
384
+ ): Internal.fieldSelection => {
385
+ let registration = `the "${eventName}" event registration on contract "${contractName}"`
386
+ validateFieldsShapeOrThrow(fields, ~registration)
387
+ let blockFields = parseFieldsOrThrow(
388
+ fields.block,
389
+ ~valid=validBlockFields,
390
+ ~kind="block",
391
+ ~registration,
392
+ )
393
+ let transactionFields = parseFieldsOrThrow(
394
+ fields.transaction,
395
+ ~valid=validTransactionFields,
396
+ ~kind="transaction",
397
+ ~registration,
398
+ )
399
+ blockFields->Utils.Set.addMany(internalBlockFields)
400
+ if enableRawEvents {
401
+ blockFields->Utils.Set.addMany(rawEventBlockFields)
402
+ }
403
+ Internal.makeFieldSelection(
404
+ ~blockFields,
405
+ ~transactionFields,
406
+ ~blockMaskFn=Evm.eventBlockFieldMask,
407
+ ~transactionMaskFn=Evm.eventTransactionFieldMask,
292
408
  )
293
409
  }
294
410
 
@@ -306,26 +422,17 @@ let buildEvmEventConfig = (
306
422
  ): Internal.evmEventConfig => {
307
423
  let topicCount = params->Array.reduce(1, (acc, p) => p.indexed ? acc + 1 : acc)
308
424
 
309
- let (selectedBlockFields, selectedTransactionFields) = resolveFieldSelection(
310
- ~blockFields,
311
- ~transactionFields,
312
- ~globalBlockFieldsSet,
313
- ~globalTransactionFieldsSet,
314
- )
315
-
316
425
  {
317
426
  id: sighash ++ "_" ++ topicCount->Int.toString,
318
427
  name: eventName,
319
428
  contractName,
320
429
  paramsRawEventSchema: buildParamsSchema(params),
321
430
  simulateParamsSchema: buildSimulateParamsSchema(params),
322
- selectedBlockFields,
323
- selectedTransactionFields,
324
- transactionFieldMask: Evm.eventTransactionFieldMask(selectedTransactionFields),
325
- blockFieldMask: Evm.eventBlockFieldMask(
326
- selectedBlockFields->(
327
- Utils.magic: Utils.Set.t<Internal.evmBlockField> => Utils.Set.t<string>
328
- ),
431
+ fieldSelection: resolveFieldSelection(
432
+ ~blockFields,
433
+ ~transactionFields,
434
+ ~globalBlockFieldsSet,
435
+ ~globalTransactionFieldsSet,
329
436
  ),
330
437
  sighash,
331
438
  topicCount,
@@ -344,6 +451,9 @@ let buildEvmOnEventRegistration = (
344
451
  ~where: option<JSON.t>,
345
452
  ~chainId: ChainId.t,
346
453
  ~onEventBlockFilterSchema: S.t<option<unknown>>,
454
+ // The registration's inline selection, already resolved; absent when it named
455
+ // no fields and takes the event config's.
456
+ ~fieldSelection: option<Internal.fieldSelection>=?,
347
457
  ~startBlock: option<int>=?,
348
458
  ): Internal.evmOnEventRegistration => {
349
459
  let indexedParams = eventConfig.paramsMetadata->Array.filter(p => p.indexed)
@@ -379,6 +489,10 @@ let buildEvmOnEventRegistration = (
379
489
  addressFilterParamGroups,
380
490
  dependsOnAddresses: Internal.dependsOnAddresses(~isWildcard, ~filterByAddresses),
381
491
  startBlock: resolvedStartBlock,
492
+ fieldSelection: switch fieldSelection {
493
+ | Some(fieldSelection) => fieldSelection
494
+ | None => eventConfig.fieldSelection
495
+ },
382
496
  }
383
497
  }
384
498
 
@@ -408,17 +522,15 @@ let buildSvmInstructionEventConfig = (
408
522
  ->Utils.Schema.coerceToJsonPgType
409
523
  ->(Utils.magic: S.t<JSON.t> => S.t<Internal.eventParams>)
410
524
 
411
- // The base eventConfig stores these as a string set (field names match the
412
- // typed variants at runtime).
413
- let selectedTransactionFields =
414
- Utils.Set.fromArray(transactionFields)->(
525
+ let fieldSelection = Internal.makeFieldSelection(
526
+ ~blockFields=Utils.Set.fromArray(Array.concat(alwaysIncludedSvmBlockFields, blockFields))->(
527
+ Utils.magic: Utils.Set.t<Internal.svmBlockField> => Utils.Set.t<string>
528
+ ),
529
+ ~transactionFields=Utils.Set.fromArray(transactionFields)->(
415
530
  Utils.magic: Utils.Set.t<Internal.svmTransactionField> => Utils.Set.t<string>
416
- )
417
- let selectedBlockFields = Utils.Set.fromArray(
418
- Array.concat(alwaysIncludedSvmBlockFields, blockFields),
419
- )
420
- let blockFieldMask = Svm.eventBlockFieldMask(
421
- selectedBlockFields->(Utils.magic: Utils.Set.t<Internal.svmBlockField> => Utils.Set.t<string>),
531
+ ),
532
+ ~blockMaskFn=Svm.eventBlockFieldMask,
533
+ ~transactionMaskFn=Svm.eventTransactionFieldMask,
422
534
  )
423
535
  {
424
536
  id: switch discriminator {
@@ -433,10 +545,7 @@ let buildSvmInstructionEventConfig = (
433
545
  discriminator,
434
546
  discriminatorByteLen,
435
547
  includeLogs,
436
- selectedTransactionFields,
437
- transactionFieldMask: Svm.eventTransactionFieldMask(selectedTransactionFields),
438
- selectedBlockFields,
439
- blockFieldMask,
548
+ fieldSelection,
440
549
  accountFilters,
441
550
  isInner,
442
551
  accounts,
@@ -462,6 +571,7 @@ let buildSvmOnEventRegistration = (
462
571
  filterByAddresses: false,
463
572
  dependsOnAddresses: Internal.dependsOnAddresses(~isWildcard, ~filterByAddresses=false),
464
573
  startBlock,
574
+ fieldSelection: eventConfig.fieldSelection,
465
575
  }
466
576
 
467
577
  // ============== Build Fuel event config ==============
@@ -513,11 +623,15 @@ let buildFuelEventConfig = (
513
623
  contractName,
514
624
  paramsRawEventSchema: paramsSchema,
515
625
  simulateParamsSchema: paramsSchema,
516
- // Fuel keeps the transaction and block inline on the payload; nothing to
517
- // materialise.
518
- selectedTransactionFields: Utils.Set.make(),
519
- transactionFieldMask: 0.,
520
- blockFieldMask: 0.,
626
+ // Fuel keeps the transaction inline on the payload, so nothing is selected
627
+ // for it; the block is materialised from the store with the full
628
+ // always-queried trio.
629
+ fieldSelection: Internal.makeFieldSelection(
630
+ ~blockFields=Utils.Set.fromArray(Fuel.blockFields),
631
+ ~transactionFields=Utils.Set.fromArray(Fuel.transactionFields),
632
+ ~blockMaskFn=Fuel.eventBlockFieldMask,
633
+ ~transactionMaskFn=Fuel.eventTransactionFieldMask,
634
+ ),
521
635
  kind: fuelKind,
522
636
  }
523
637
  }
@@ -539,4 +653,5 @@ let buildFuelOnEventRegistration = (
539
653
  filterByAddresses: false,
540
654
  dependsOnAddresses: Internal.dependsOnAddresses(~isWildcard, ~filterByAddresses=false),
541
655
  startBlock,
656
+ fieldSelection: eventConfig.fieldSelection,
542
657
  }
@@ -3,6 +3,7 @@
3
3
  import * as Evm from "./sources/Evm.res.mjs";
4
4
  import * as Svm from "./sources/Svm.res.mjs";
5
5
  import * as Core from "./Core.res.mjs";
6
+ import * as Fuel from "./sources/Fuel.res.mjs";
6
7
  import * as Utils from "./Utils.res.mjs";
7
8
  import * as Address from "./Address.res.mjs";
8
9
  import * as FuelSDK from "./sources/FuelSDK.res.mjs";
@@ -237,10 +238,63 @@ let alwaysIncludedBlockFields = [
237
238
  function resolveFieldSelection(blockFields, transactionFields, globalBlockFieldsSet, globalTransactionFieldsSet) {
238
239
  let selectedBlockFields = blockFields !== undefined ? new Set(alwaysIncludedBlockFields.concat(blockFields)) : globalBlockFieldsSet;
239
240
  let selectedTransactionFields = transactionFields !== undefined ? new Set(transactionFields) : globalTransactionFieldsSet;
240
- return [
241
- selectedBlockFields,
242
- selectedTransactionFields
243
- ];
241
+ return Internal.makeFieldSelection(selectedBlockFields, selectedTransactionFields, Evm.eventBlockFieldMask, Evm.eventTransactionFieldMask);
242
+ }
243
+
244
+ let internalBlockFields = ["number"];
245
+
246
+ let rawEventBlockFields = [
247
+ "hash",
248
+ "timestamp"
249
+ ];
250
+
251
+ let selectionKinds = [
252
+ "block",
253
+ "transaction"
254
+ ];
255
+
256
+ function validateFieldsShapeOrThrow(fields, registration) {
257
+ if (typeof fields !== "object" || fields === null || Array.isArray(fields)) {
258
+ Stdlib_JsError.throwWithMessage(`The fields option of ` + registration + ` must be an object of block and transaction field names.`);
259
+ }
260
+ Object.keys(fields).forEach(key => {
261
+ if (!selectionKinds.includes(key)) {
262
+ return Stdlib_JsError.throwWithMessage(`Invalid "` + key + `" key in the fields option of ` + registration + `. Valid keys: ` + selectionKinds.join(", ") + `.`);
263
+ }
264
+ });
265
+ }
266
+
267
+ let validBlockFields = new Set(Evm.blockFields);
268
+
269
+ let validTransactionFields = new Set(Evm.transactionFields);
270
+
271
+ function parseFieldsOrThrow(fields, valid, kind, registration) {
272
+ let seen = new Set();
273
+ let fields$1 = fields !== undefined ? (
274
+ Array.isArray(fields) ? fields : Stdlib_JsError.throwWithMessage(`The fields.` + kind + ` option of ` + registration + ` must be an array of field names.`)
275
+ ) : [];
276
+ fields$1.forEach(name => {
277
+ if (!valid.has(name)) {
278
+ Stdlib_JsError.throwWithMessage(`Invalid "` + name + `" field in the fields.` + kind + ` option of ` + registration + `. Valid ` + kind + ` fields: ` + Array.from(valid).join(", ") + `.`);
279
+ }
280
+ if (seen.has(name)) {
281
+ Stdlib_JsError.throwWithMessage(`Duplicate "` + name + `" field in the fields.` + kind + ` option of ` + registration + `.`);
282
+ }
283
+ seen.add(name);
284
+ });
285
+ return seen;
286
+ }
287
+
288
+ function resolveInlineFieldSelection(fields, contractName, eventName, enableRawEvents) {
289
+ let registration = `the "` + eventName + `" event registration on contract "` + contractName + `"`;
290
+ validateFieldsShapeOrThrow(fields, registration);
291
+ let blockFields = parseFieldsOrThrow(fields.block, validBlockFields, "block", registration);
292
+ let transactionFields = parseFieldsOrThrow(fields.transaction, validTransactionFields, "transaction", registration);
293
+ Utils.$$Set.addMany(blockFields, internalBlockFields);
294
+ if (enableRawEvents) {
295
+ Utils.$$Set.addMany(blockFields, rawEventBlockFields);
296
+ }
297
+ return Internal.makeFieldSelection(blockFields, transactionFields, Evm.eventBlockFieldMask, Evm.eventTransactionFieldMask);
244
298
  }
245
299
 
246
300
  function buildEvmEventConfig(contractName, eventName, sighash, params, blockFields, transactionFields, globalBlockFieldsSetOpt, globalTransactionFieldsSetOpt) {
@@ -253,26 +307,20 @@ function buildEvmEventConfig(contractName, eventName, sighash, params, blockFiel
253
307
  return acc;
254
308
  }
255
309
  });
256
- let match = resolveFieldSelection(blockFields, transactionFields, globalBlockFieldsSet, globalTransactionFieldsSet);
257
- let selectedTransactionFields = match[1];
258
- let selectedBlockFields = match[0];
259
310
  return {
260
311
  id: sighash + "_" + topicCount.toString(),
261
312
  name: eventName,
262
313
  contractName: contractName,
263
314
  paramsRawEventSchema: buildParamsSchema(params),
264
315
  simulateParamsSchema: buildSimulateParamsSchema(params),
265
- selectedTransactionFields: selectedTransactionFields,
266
- transactionFieldMask: Evm.eventTransactionFieldMask(selectedTransactionFields),
267
- blockFieldMask: Evm.eventBlockFieldMask(selectedBlockFields),
268
- selectedBlockFields: selectedBlockFields,
316
+ fieldSelection: resolveFieldSelection(blockFields, transactionFields, globalBlockFieldsSet, globalTransactionFieldsSet),
269
317
  sighash: sighash,
270
318
  topicCount: topicCount,
271
319
  paramsMetadata: params
272
320
  };
273
321
  }
274
322
 
275
- function buildEvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, where, chainId, onEventBlockFilterSchema, startBlock) {
323
+ function buildEvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, where, chainId, onEventBlockFilterSchema, fieldSelection, startBlock) {
276
324
  let indexedParams = eventConfig.paramsMetadata.filter(p => p.indexed);
277
325
  let match = LogSelection.parseWhereOrThrow(where, eventConfig.sighash, indexedParams.map(p => p.name), eventConfig.contractName, chainId, onEventBlockFilterSchema, Stdlib_Option.map(indexedParams[0], buildTopicGetter), Stdlib_Option.map(indexedParams[1], buildTopicGetter), Stdlib_Option.map(indexedParams[2], buildTopicGetter));
278
326
  let filterByAddresses = match.filterByAddresses;
@@ -289,6 +337,7 @@ function buildEvmOnEventRegistration(eventConfig, isWildcard, handler, contractR
289
337
  dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, filterByAddresses),
290
338
  addressFilterParamGroups: match.addressFilterParamGroups,
291
339
  startBlock: resolvedStartBlock,
340
+ fieldSelection: fieldSelection !== undefined ? fieldSelection : eventConfig.fieldSelection,
292
341
  resolvedWhere: resolvedWhere
293
342
  };
294
343
  }
@@ -306,19 +355,14 @@ function buildSvmInstructionEventConfig(contractName, instructionName, programId
306
355
  let args = argsOpt !== undefined ? argsOpt : null;
307
356
  let definedTypes = definedTypesOpt !== undefined ? definedTypesOpt : null;
308
357
  let paramsSchema = Utils.Schema.coerceToJsonPgType(S$RescriptSchema.json(false));
309
- let selectedTransactionFields = new Set(transactionFields);
310
- let selectedBlockFields = new Set(alwaysIncludedSvmBlockFields.concat(blockFields));
311
- let blockFieldMask = Svm.eventBlockFieldMask(selectedBlockFields);
358
+ let fieldSelection = Internal.makeFieldSelection(new Set(alwaysIncludedSvmBlockFields.concat(blockFields)), new Set(transactionFields), Svm.eventBlockFieldMask, Svm.eventTransactionFieldMask);
312
359
  return {
313
360
  id: discriminator !== undefined ? discriminator : "none",
314
361
  name: instructionName,
315
362
  contractName: contractName,
316
363
  paramsRawEventSchema: paramsSchema,
317
364
  simulateParamsSchema: paramsSchema,
318
- selectedTransactionFields: selectedTransactionFields,
319
- transactionFieldMask: Svm.eventTransactionFieldMask(selectedTransactionFields),
320
- blockFieldMask: blockFieldMask,
321
- selectedBlockFields: selectedBlockFields,
365
+ fieldSelection: fieldSelection,
322
366
  programId: programId,
323
367
  discriminator: discriminator,
324
368
  discriminatorByteLen: discriminatorByteLen,
@@ -340,7 +384,8 @@ function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractR
340
384
  isWildcard: isWildcard,
341
385
  filterByAddresses: false,
342
386
  dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, false),
343
- startBlock: startBlock
387
+ startBlock: startBlock,
388
+ fieldSelection: eventConfig.fieldSelection
344
389
  };
345
390
  }
346
391
 
@@ -393,9 +438,7 @@ function buildFuelEventConfig(contractName, eventName, kind, sighash, rawAbi) {
393
438
  contractName: contractName,
394
439
  paramsRawEventSchema: paramsSchema,
395
440
  simulateParamsSchema: paramsSchema,
396
- selectedTransactionFields: new Set(),
397
- transactionFieldMask: 0,
398
- blockFieldMask: 0,
441
+ fieldSelection: Internal.makeFieldSelection(new Set(Fuel.blockFields), new Set(Fuel.transactionFields), Fuel.eventBlockFieldMask, Fuel.eventTransactionFieldMask),
399
442
  kind: fuelKind
400
443
  };
401
444
  }
@@ -409,7 +452,8 @@ function buildFuelOnEventRegistration(eventConfig, isWildcard, handler, contract
409
452
  isWildcard: isWildcard,
410
453
  filterByAddresses: false,
411
454
  dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, false),
412
- startBlock: startBlock
455
+ startBlock: startBlock,
456
+ fieldSelection: eventConfig.fieldSelection
413
457
  };
414
458
  }
415
459
 
@@ -428,6 +472,14 @@ export {
428
472
  buildTopicGetter,
429
473
  alwaysIncludedBlockFields,
430
474
  resolveFieldSelection,
475
+ internalBlockFields,
476
+ rawEventBlockFields,
477
+ selectionKinds,
478
+ validateFieldsShapeOrThrow,
479
+ validBlockFields,
480
+ validTransactionFields,
481
+ parseFieldsOrThrow,
482
+ resolveInlineFieldSelection,
431
483
  buildEvmEventConfig,
432
484
  buildEvmOnEventRegistration,
433
485
  alwaysIncludedSvmBlockFields,
@@ -300,15 +300,11 @@ type logPartitionInfo = {
300
300
  // for the batch's store-backed (HyperSync) items and write them onto the
301
301
  // payloads, so handlers read plain objects. A batch can span chains, each with
302
302
  // its own stores and field masks, so group items by chain before materialising.
303
- let materializeBatchEvents = async (
304
- batch: Batch.t,
305
- ~chainStates: dict<ChainState.t>,
306
- ~ecosystem,
307
- ) => {
303
+ let materializeBatchEvents = async (batch: Batch.t, ~chainStates: dict<ChainState.t>) => {
308
304
  switch chainStates->Dict.valuesToArray {
309
305
  // Single-chain indexers (the common case): every item belongs to the one
310
306
  // chain, so skip the per-chain grouping and its allocations.
311
- | [cs] => await cs->ChainState.materializeBatchItems(~items=batch.items, ~ecosystem)
307
+ | [cs] => await cs->ChainState.materializeBatchItems(~items=batch.items)
312
308
  | _ =>
313
309
  let itemsByChain: dict<array<Internal.item>> = Dict.make()
314
310
  batch.items->Array.forEach(item => {
@@ -323,7 +319,7 @@ let materializeBatchEvents = async (
323
319
  ->Dict.toArray
324
320
  ->Array.map(async ((chainId, items)) => {
325
321
  let cs = chainStates->Dict.getUnsafe(chainId)
326
- await cs->ChainState.materializeBatchItems(~items, ~ecosystem)
322
+ await cs->ChainState.materializeBatchItems(~items)
327
323
  })
328
324
  ->Promise.all
329
325
  }
@@ -359,7 +355,7 @@ let processEventBatch = async (
359
355
  if batch.items->Utils.Array.notEmpty {
360
356
  // Materialise store-backed transactions onto payloads before any handler
361
357
  // (preload or execute) reads them.
362
- await materializeBatchEvents(batch, ~chainStates, ~ecosystem=config.ecosystem.name)
358
+ await materializeBatchEvents(batch, ~chainStates)
363
359
  await batch->preloadBatchOrThrow(~loadManager, ~persistence, ~indexerState, ~chains, ~config)
364
360
  }
365
361
 
@@ -186,7 +186,7 @@ function registerProcessEventBatchMetrics(logger, batch, indexerState, loadDurat
186
186
  IndexerState.recordBatchDurations(indexerState, loadDuration, handlerDuration);
187
187
  }
188
188
 
189
- async function materializeBatchEvents(batch, chainStates, ecosystem) {
189
+ async function materializeBatchEvents(batch, chainStates) {
190
190
  let match = Object.values(chainStates);
191
191
  if (match.length !== 1) {
192
192
  let itemsByChain = {};
@@ -201,12 +201,12 @@ async function materializeBatchEvents(batch, chainStates, ecosystem) {
201
201
  });
202
202
  await Promise.all(Object.entries(itemsByChain).map(async param => {
203
203
  let cs = chainStates[param[0]];
204
- return await ChainState.materializeBatchItems(cs, param[1], ecosystem);
204
+ return await ChainState.materializeBatchItems(cs, param[1]);
205
205
  }));
206
206
  return;
207
207
  }
208
208
  let cs = match[0];
209
- return await ChainState.materializeBatchItems(cs, batch.items, ecosystem);
209
+ return await ChainState.materializeBatchItems(cs, batch.items);
210
210
  }
211
211
 
212
212
  async function processEventBatch(batch, indexerState, loadManager, persistence, config, chainStates) {
@@ -221,7 +221,7 @@ async function processEventBatch(batch, indexerState, loadManager, persistence,
221
221
  await Writing.awaitCapacity(indexerState);
222
222
  let timeRef = Performance.now();
223
223
  if (Utils.$$Array.notEmpty(batch.items)) {
224
- await materializeBatchEvents(batch, chainStates, config.ecosystem.name);
224
+ await materializeBatchEvents(batch, chainStates);
225
225
  await preloadBatchOrThrow(batch, loadManager, persistence, config, indexerState, chains);
226
226
  }
227
227
  let elapsedTimeAfterLoaders = Performance.secondsSince(timeRef);
@@ -1,11 +1,6 @@
1
- // type eventIndex = {
2
- // blockNumber: int,
3
- // logIndex: int,
4
- // }
5
- //
6
-
7
- // takes blockNumber, logIndex and packs them into a number with
8
- //32 bits, 16 bits and 16 bits respectively
1
+ // Packs blockNumber and logIndex into one number: 32 bits and 16 bits
2
+ // respectively. EVM only — it is the `raw_events.event_id` primary value, and
3
+ // no other ecosystem writes that table.
9
4
  let packEventIndex = (~blockNumber, ~logIndex) => {
10
5
  let blockNumber = blockNumber->BigInt.fromInt
11
6
  let logIndex = logIndex->BigInt.fromInt
@@ -13,42 +8,3 @@ let packEventIndex = (~blockNumber, ~logIndex) => {
13
8
 
14
9
  blockNumber->BigInt.bitwiseOr(logIndex)
15
10
  }
16
-
17
- // //Currently not used but keeping in utils
18
- // //using @live flag for dead code analyser
19
- // @live
20
- // let packMultiChainEventIndex = (~timestamp, ~chainId, ~blockNumber, ~logIndex) => {
21
- // let timestamp = timestamp->BigInt.fromInt
22
- // let chainId = chainId->BigInt.fromInt
23
- // let blockNumber = blockNumber->BigInt.fromInt
24
- // let logIndex = logIndex->BigInt.fromInt
25
-
26
- // let timestamp = BigInt.shiftLeft(timestamp, 48->BigInt.fromInt)
27
- // let chainId = BigInt.shiftLeft(chainId, 16->BigInt.fromInt)
28
- // let blockNumber = BigInt.shiftLeft(blockNumber, 16->BigInt.fromInt)
29
-
30
- // timestamp
31
- // ->BigInt.bitwiseOr(chainId)
32
- // ->BigInt.bitwiseOr(blockNumber)
33
- // ->BigInt.bitwiseOr(logIndex)
34
- // }
35
-
36
- // //Currently not used but keeping in utils
37
- // //using @live flag for dead code analyser
38
- // @live
39
- // let unpackEventIndex = (packedEventIndex: bigint) => {
40
- // let blockNumber = packedEventIndex->BigInt.shiftRight(16->BigInt.fromInt)
41
- // let logIndexMask = 65535->BigInt.fromInt
42
- // let logIndex = packedEventIndex->BigInt.bitwiseAnd(logIndexMask)
43
- // {
44
- // blockNumber: blockNumber->BigInt.toString->Int.fromString->Option.getUnsafe,
45
- // logIndex: logIndex->BigInt.toString->Int.fromString->Option.getUnsafe,
46
- // }
47
- // }
48
-
49
- // //takes an eventIndex record and returnts a packed event index
50
- // //used in TS tests
51
- // @live
52
- // let packEventIndexFromRecord = (eventIndex: eventIndex) => {
53
- // packEventIndex(~blockNumber=eventIndex.blockNumber, ~logIndex=eventIndex.logIndex)
54
- // }