envio 3.3.0-alpha.1 → 3.3.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/evm.schema.json +10 -0
  2. package/index.d.ts +45 -25
  3. package/package.json +7 -7
  4. package/src/Address.res +5 -2
  5. package/src/Address.res.mjs +3 -1
  6. package/src/Api.res +1 -1
  7. package/src/Api.res.mjs +1 -1
  8. package/src/Batch.res +0 -6
  9. package/src/Batch.res.mjs +1 -12
  10. package/src/BatchProcessing.res +7 -12
  11. package/src/BatchProcessing.res.mjs +8 -7
  12. package/src/Bin.res +3 -0
  13. package/src/Bin.res.mjs +4 -0
  14. package/src/ChainFetching.res +43 -9
  15. package/src/ChainFetching.res.mjs +34 -15
  16. package/src/ChainMetadata.res +1 -11
  17. package/src/ChainMetadata.res.mjs +1 -10
  18. package/src/ChainState.res +605 -151
  19. package/src/ChainState.res.mjs +427 -104
  20. package/src/ChainState.resi +72 -4
  21. package/src/Config.res +61 -33
  22. package/src/Config.res.mjs +50 -10
  23. package/src/ContractRegisterContext.res +2 -12
  24. package/src/ContractRegisterContext.res.mjs +3 -5
  25. package/src/Core.res +14 -3
  26. package/src/CrossChainState.res +113 -89
  27. package/src/CrossChainState.res.mjs +64 -60
  28. package/src/CrossChainState.resi +1 -1
  29. package/src/Ecosystem.res +5 -6
  30. package/src/Ecosystem.res.mjs +3 -3
  31. package/src/Envio.res +17 -11
  32. package/src/EnvioGlobal.res +53 -0
  33. package/src/EnvioGlobal.res.mjs +31 -0
  34. package/src/EventConfigBuilder.res +177 -88
  35. package/src/EventConfigBuilder.res.mjs +99 -42
  36. package/src/EventProcessing.res +74 -28
  37. package/src/EventProcessing.res.mjs +55 -29
  38. package/src/ExitOnCaughtUp.res +10 -2
  39. package/src/ExitOnCaughtUp.res.mjs +10 -1
  40. package/src/FetchState.res +544 -356
  41. package/src/FetchState.res.mjs +412 -471
  42. package/src/HandlerLoader.res +8 -104
  43. package/src/HandlerLoader.res.mjs +2 -81
  44. package/src/HandlerRegister.res +518 -144
  45. package/src/HandlerRegister.res.mjs +285 -133
  46. package/src/HandlerRegister.resi +24 -8
  47. package/src/IndexerState.res +10 -3
  48. package/src/IndexerState.res.mjs +11 -4
  49. package/src/IndexerState.resi +2 -1
  50. package/src/IndexingAddresses.res +108 -0
  51. package/src/IndexingAddresses.res.mjs +101 -0
  52. package/src/IndexingAddresses.resi +34 -0
  53. package/src/Internal.res +155 -46
  54. package/src/Internal.res.mjs +30 -2
  55. package/src/LoadLayer.res +5 -5
  56. package/src/LoadLayer.res.mjs +6 -6
  57. package/src/LogSelection.res +102 -165
  58. package/src/LogSelection.res.mjs +101 -116
  59. package/src/Main.res +71 -236
  60. package/src/Main.res.mjs +60 -145
  61. package/src/Metrics.res +74 -0
  62. package/src/Metrics.res.mjs +75 -0
  63. package/src/PgStorage.res +4 -4
  64. package/src/PgStorage.res.mjs +5 -5
  65. package/src/Prometheus.res +10 -63
  66. package/src/Prometheus.res.mjs +124 -171
  67. package/src/PruneStaleHistory.res +2 -2
  68. package/src/PruneStaleHistory.res.mjs +3 -3
  69. package/src/RawEvent.res +7 -2
  70. package/src/RawEvent.res.mjs +4 -4
  71. package/src/Rollback.res +3 -3
  72. package/src/Rollback.res.mjs +4 -4
  73. package/src/RollbackCommit.res +4 -1
  74. package/src/RollbackCommit.res.mjs +3 -2
  75. package/src/SimulateDeadInputTracker.res +85 -0
  76. package/src/SimulateDeadInputTracker.res.mjs +73 -0
  77. package/src/SimulateDeadInputTracker.resi +12 -0
  78. package/src/SimulateItems.res +91 -23
  79. package/src/SimulateItems.res.mjs +55 -32
  80. package/src/TestIndexer.res +54 -40
  81. package/src/TestIndexer.res.mjs +37 -30
  82. package/src/bindings/Performance.res +7 -0
  83. package/src/bindings/Performance.res.mjs +21 -0
  84. package/src/bindings/Performance.resi +7 -0
  85. package/src/bindings/Viem.res +0 -41
  86. package/src/bindings/Viem.res.mjs +1 -43
  87. package/src/sources/BlockStore.res +46 -0
  88. package/src/sources/BlockStore.res.mjs +24 -0
  89. package/src/sources/EventRouter.res +36 -33
  90. package/src/sources/EventRouter.res.mjs +13 -14
  91. package/src/sources/Evm.res +83 -72
  92. package/src/sources/Evm.res.mjs +53 -69
  93. package/src/sources/EvmChain.res +18 -20
  94. package/src/sources/EvmChain.res.mjs +15 -15
  95. package/src/sources/EvmRpcClient.res +74 -5
  96. package/src/sources/EvmRpcClient.res.mjs +13 -4
  97. package/src/sources/FieldMask.res +39 -0
  98. package/src/sources/FieldMask.res.mjs +42 -0
  99. package/src/sources/Fuel.res +9 -6
  100. package/src/sources/Fuel.res.mjs +5 -10
  101. package/src/sources/HyperFuelSource.res +46 -50
  102. package/src/sources/HyperFuelSource.res.mjs +64 -54
  103. package/src/sources/HyperSync.res +39 -7
  104. package/src/sources/HyperSync.res.mjs +57 -37
  105. package/src/sources/HyperSync.resi +12 -2
  106. package/src/sources/HyperSyncClient.res +22 -111
  107. package/src/sources/HyperSyncClient.res.mjs +2 -30
  108. package/src/sources/HyperSyncHeightStream.res +1 -8
  109. package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
  110. package/src/sources/HyperSyncSource.res +94 -107
  111. package/src/sources/HyperSyncSource.res.mjs +82 -86
  112. package/src/sources/Rpc.res +15 -47
  113. package/src/sources/Rpc.res.mjs +25 -56
  114. package/src/sources/RpcSource.res +320 -467
  115. package/src/sources/RpcSource.res.mjs +268 -385
  116. package/src/sources/RpcWebSocketHeightStream.res +0 -5
  117. package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
  118. package/src/sources/SimulateSource.res +10 -4
  119. package/src/sources/SimulateSource.res.mjs +16 -6
  120. package/src/sources/Source.res +34 -6
  121. package/src/sources/SourceManager.res +77 -19
  122. package/src/sources/SourceManager.res.mjs +63 -21
  123. package/src/sources/SourceManager.resi +10 -0
  124. package/src/sources/Svm.res +31 -16
  125. package/src/sources/Svm.res.mjs +36 -13
  126. package/src/sources/SvmHyperSyncClient.res +5 -32
  127. package/src/sources/SvmHyperSyncSource.res +159 -134
  128. package/src/sources/SvmHyperSyncSource.res.mjs +164 -129
  129. package/src/sources/TransactionStore.res +49 -0
  130. package/src/sources/TransactionStore.res.mjs +30 -0
  131. package/src/tui/Tui.res +13 -16
  132. package/src/tui/Tui.res.mjs +12 -14
  133. package/svm.schema.json +49 -37
  134. package/src/bindings/Hrtime.res +0 -58
  135. package/src/bindings/Hrtime.res.mjs +0 -90
  136. package/src/bindings/Hrtime.resi +0 -30
@@ -0,0 +1,31 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Utils from "./Utils.res.mjs";
4
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
5
+
6
+ let version = Utils.EnvioPackage.value.version;
7
+
8
+ let existing = globalThis.__envioGlobal;
9
+
10
+ let value;
11
+
12
+ if (existing == null) {
13
+ let fresh = {
14
+ version: version,
15
+ eventRegistrations: {},
16
+ activeRegistration: undefined,
17
+ preRegistered: [],
18
+ rollbackCommitCallbacks: [],
19
+ indexerState: undefined,
20
+ persistence: undefined
21
+ };
22
+ globalThis.__envioGlobal = fresh;
23
+ value = fresh;
24
+ } else {
25
+ value = existing.version === version ? existing : Stdlib_JsError.throwWithMessage(`Multiple incompatible envio versions loaded in the same process: ` + existing.version + ` and ` + version + `. Deduplicate the 'envio' dependency in your project.`);
26
+ }
27
+
28
+ export {
29
+ value,
30
+ }
31
+ /* existing Not a pure module */
@@ -243,9 +243,13 @@ let getTopicEncoder = (abiType: string): (unknown => EvmTypes.Hex.t) => {
243
243
  } else {
244
244
  switch abiType {
245
245
  | "address" =>
246
- TopicFilter.fromAddress->(
247
- Utils.magic: (Address.t => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t
248
- )
246
+ // Lowercase before encoding so mixed-case (checksummed) user input
247
+ // still matches the lowercase hex topics returned by sources.
248
+
249
+ (
250
+ (value: string) =>
251
+ value->String.toLowerCase->Address.unsafeFromString->TopicFilter.fromAddress
252
+ )->(Utils.magic: (string => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t)
249
253
 
250
254
  | "bool" =>
251
255
  TopicFilter.fromBool->(Utils.magic: (bool => EvmTypes.Hex.t) => unknown => EvmTypes.Hex.t)
@@ -306,7 +310,14 @@ let resolveFieldSelection = (
306
310
  | Some(fields) => Utils.Set.fromArray(fields)
307
311
  | None => globalTransactionFieldsSet
308
312
  }
309
- (selectedBlockFields, selectedTransactionFields)
313
+ // The base eventConfig stores these as a string set (field names match the
314
+ // typed variants at runtime).
315
+ (
316
+ selectedBlockFields,
317
+ selectedTransactionFields->(
318
+ Utils.magic: Utils.Set.t<Internal.evmTransactionField> => Utils.Set.t<string>
319
+ ),
320
+ )
310
321
  }
311
322
 
312
323
  // ============== Client-side address filter ==============
@@ -319,28 +330,50 @@ let compileAddressFilter: string => (
319
330
  return new Function("event", "blockNumber", "indexingAddresses", body);
320
331
  }`)
321
332
 
322
- // Body of the client-side address filter for a DNF of address-filtered param
323
- // names (OR of AND-groups): keep the event only if some group's params are all
324
- // registered at or before the log's block. The DNF is fixed here, so it's
325
- // unrolled into one boolean expression no per-event closure, loop, or array.
326
- // `None` when there's no address-param filter. Exposed for snapshotting.
327
- let buildAddressFilterBody = (groups: array<array<string>>): option<string> => {
328
- switch groups {
333
+ // Body of the client-side address filter. Two analogous registered-at-or-before
334
+ // checks, ANDed: (1) for non-wildcard events, the log's srcAddress must itself be
335
+ // registered (ownership is resolved structurally by partition, but the temporal
336
+ // `effectiveStartBlock` gate lives here now); (2) a DNF of address-filtered param
337
+ // names (OR of AND-groups) for events that filter an indexed address param. The
338
+ // DNF is fixed here, so it's unrolled into one boolean expression — no per-event
339
+ // closure, loop, or array. `None` only for wildcard events without a param
340
+ // filter. Exposed for snapshotting.
341
+ // `srcAddressExpr` is the JS expression for the event's owning address: EVM and
342
+ // Fuel events expose `event.srcAddress`; SVM instructions expose `event.programId`.
343
+ let buildAddressFilterBody = (
344
+ groups: array<array<string>>,
345
+ ~isWildcard: bool,
346
+ ~srcAddressExpr: string="event.srcAddress",
347
+ ): option<string> => {
348
+ let paramLeaf = name =>
349
+ `(ic = indexingAddresses[p[${JSON.stringify(
350
+ JSON.String(name),
351
+ )}]]) !== undefined && ic.effectiveStartBlock <= blockNumber`
352
+ let paramDnf = switch groups {
329
353
  | [] => None
330
354
  | _ =>
331
- let leaf = name =>
332
- `(ic = indexingAddresses[p[${JSON.stringify(
333
- JSON.String(name),
334
- )}]]) !== undefined && ic.effectiveStartBlock <= blockNumber`
335
- let groupExprs =
336
- groups->Array.map(group => "(" ++ group->Array.map(leaf)->Array.join(" && ") ++ ")")
337
- Some("var p = event.params, ic; return " ++ groupExprs->Array.join(" || ") ++ ";")
355
+ Some(
356
+ groups
357
+ ->Array.map(group => "(" ++ group->Array.map(paramLeaf)->Array.join(" && ") ++ ")")
358
+ ->Array.join(" || "),
359
+ )
360
+ }
361
+ let srcLeaf = `(ic = indexingAddresses[${srcAddressExpr}]) !== undefined && ic.effectiveStartBlock <= blockNumber`
362
+ switch (isWildcard, paramDnf) {
363
+ | (true, None) => None
364
+ | (true, Some(dnf)) => Some("var p = event.params, ic; return " ++ dnf ++ ";")
365
+ | (false, None) => Some("var ic; return " ++ srcLeaf ++ ";")
366
+ | (false, Some(dnf)) =>
367
+ Some("var p = event.params, ic; return " ++ srcLeaf ++ " && (" ++ dnf ++ ");")
338
368
  }
339
369
  }
340
370
 
341
- let buildAddressFilter = (groups: array<array<string>>): option<
342
- (Internal.eventPayload, int, dict<Internal.indexingContract>) => bool,
343
- > => buildAddressFilterBody(groups)->Option.map(compileAddressFilter)
371
+ let buildAddressFilter = (
372
+ groups: array<array<string>>,
373
+ ~isWildcard: bool,
374
+ ~srcAddressExpr: string="event.srcAddress",
375
+ ): option<(Internal.eventPayload, int, dict<Internal.indexingContract>) => bool> =>
376
+ buildAddressFilterBody(groups, ~isWildcard, ~srcAddressExpr)->Option.map(compileAddressFilter)
344
377
 
345
378
  // ============== Build complete EVM event config ==============
346
379
 
@@ -349,46 +382,12 @@ let buildEvmEventConfig = (
349
382
  ~eventName: string,
350
383
  ~sighash: string,
351
384
  ~params: array<paramMeta>,
352
- ~isWildcard: bool,
353
- ~handler: option<Internal.handler>,
354
- ~contractRegister: option<Internal.contractRegister>,
355
- ~eventFilters: option<JSON.t>,
356
- ~probeChainId: int,
357
- ~onEventBlockFilterSchema: S.t<option<unknown>>,
358
385
  ~blockFields: option<array<Internal.evmBlockField>>=?,
359
386
  ~transactionFields: option<array<Internal.evmTransactionField>>=?,
360
- ~startBlock: option<int>=?,
361
387
  ~globalBlockFieldsSet: Utils.Set.t<Internal.evmBlockField>=Utils.Set.make(),
362
388
  ~globalTransactionFieldsSet: Utils.Set.t<Internal.evmTransactionField>=Utils.Set.make(),
363
389
  ): Internal.evmEventConfig => {
364
390
  let topicCount = params->Array.reduce(1, (acc, p) => p.indexed ? acc + 1 : acc)
365
- let indexedParams = params->Array.filter(p => p.indexed)
366
-
367
- let {
368
- getEventFiltersOrThrow,
369
- filterByAddresses,
370
- addressFilterParamGroups,
371
- startBlock: whereStartBlock,
372
- } = LogSelection.parseEventFiltersOrThrow(
373
- ~eventFilters,
374
- ~sighash,
375
- ~params=indexedParams->Array.map(p => p.name),
376
- ~contractName,
377
- ~probeChainId,
378
- ~onEventBlockFilterSchema,
379
- ~topic1=?indexedParams->Array.get(0)->Option.map(buildTopicGetter),
380
- ~topic2=?indexedParams->Array.get(1)->Option.map(buildTopicGetter),
381
- ~topic3=?indexedParams->Array.get(2)->Option.map(buildTopicGetter),
382
- )
383
-
384
- // `where.block.number._gte` overrides the contract-level startBlock
385
- // when present. The user opts into this explicitly in handler code so
386
- // it should win over the `config.yaml` contract `start_block`; absent
387
- // `where.block`, the caller's contract-level value passes through.
388
- let resolvedStartBlock = switch whereStartBlock {
389
- | Some(_) as sb => sb
390
- | None => startBlock
391
- }
392
391
 
393
392
  let (selectedBlockFields, selectedTransactionFields) = resolveFieldSelection(
394
393
  ~blockFields,
@@ -401,25 +400,75 @@ let buildEvmEventConfig = (
401
400
  id: sighash ++ "_" ++ topicCount->Int.toString,
402
401
  name: eventName,
403
402
  contractName,
404
- isWildcard,
405
- handler,
406
- contractRegister,
407
403
  paramsRawEventSchema: buildParamsSchema(params),
408
404
  simulateParamsSchema: buildSimulateParamsSchema(params),
409
- getEventFiltersOrThrow,
410
- filterByAddresses,
411
- clientAddressFilter: ?buildAddressFilter(addressFilterParamGroups),
412
- dependsOnAddresses: !isWildcard || filterByAddresses,
413
- startBlock: resolvedStartBlock,
414
405
  selectedBlockFields,
415
406
  selectedTransactionFields,
407
+ transactionFieldMask: Evm.eventTransactionFieldMask(selectedTransactionFields),
408
+ blockFieldMask: Evm.eventBlockFieldMask(
409
+ selectedBlockFields->(
410
+ Utils.magic: Utils.Set.t<Internal.evmBlockField> => Utils.Set.t<string>
411
+ ),
412
+ ),
416
413
  sighash,
417
414
  topicCount,
418
415
  paramsMetadata: params,
419
416
  }
420
417
  }
421
418
 
422
- // ============== Build Fuel event config ==============
419
+ // Enrich an EVM definition into a per-(event,chain) registration: resolve the
420
+ // registered `where` for this chain into `resolvedWhere` + address filters,
421
+ // and override `startBlock` with `where.block._gte`.
422
+ let buildEvmOnEventRegistration = (
423
+ ~eventConfig: Internal.evmEventConfig,
424
+ ~isWildcard: bool,
425
+ ~handler: option<Internal.handler>,
426
+ ~contractRegister: option<Internal.contractRegister>,
427
+ ~where: option<JSON.t>,
428
+ ~chainId: int,
429
+ ~onEventBlockFilterSchema: S.t<option<unknown>>,
430
+ ~startBlock: option<int>=?,
431
+ ): Internal.evmOnEventRegistration => {
432
+ let indexedParams = eventConfig.paramsMetadata->Array.filter(p => p.indexed)
433
+
434
+ let {resolvedWhere, filterByAddresses, addressFilterParamGroups} = LogSelection.parseWhereOrThrow(
435
+ ~where,
436
+ ~sighash=eventConfig.sighash,
437
+ ~params=indexedParams->Array.map(p => p.name),
438
+ ~contractName=eventConfig.contractName,
439
+ ~chainId,
440
+ ~onEventBlockFilterSchema,
441
+ ~topic1=?indexedParams->Array.get(0)->Option.map(buildTopicGetter),
442
+ ~topic2=?indexedParams->Array.get(1)->Option.map(buildTopicGetter),
443
+ ~topic3=?indexedParams->Array.get(2)->Option.map(buildTopicGetter),
444
+ )
445
+
446
+ // `where.block.number._gte` overrides the contract-level startBlock when
447
+ // present (an explicit per-event opt-in that wins over `config.yaml`);
448
+ // otherwise the contract/chain value passes through.
449
+ let resolvedStartBlock = switch resolvedWhere.startBlock {
450
+ | Some(_) as sb => sb
451
+ | None => startBlock
452
+ }
453
+
454
+ {
455
+ eventConfig: (eventConfig :> Internal.eventConfig),
456
+ isWildcard,
457
+ handler,
458
+ contractRegister,
459
+ resolvedWhere,
460
+ filterByAddresses,
461
+ clientAddressFilter: ?buildAddressFilter(addressFilterParamGroups, ~isWildcard),
462
+ dependsOnAddresses: Internal.dependsOnAddresses(~isWildcard, ~filterByAddresses),
463
+ startBlock: resolvedStartBlock,
464
+ }
465
+ }
466
+
467
+ // ============== Build SVM instruction event config ==============
468
+
469
+ // Always-included block fields (slot, time, hash) are prepended at runtime so
470
+ // they're always present regardless of config.
471
+ let alwaysIncludedSvmBlockFields: array<Internal.svmBlockField> = [Slot, Time, Hash]
423
472
 
424
473
  let buildSvmInstructionEventConfig = (
425
474
  ~contractName: string,
@@ -427,23 +476,32 @@ let buildSvmInstructionEventConfig = (
427
476
  ~programId: SvmTypes.Pubkey.t,
428
477
  ~discriminator: option<string>,
429
478
  ~discriminatorByteLen: int,
430
- ~includeTransaction: bool,
431
479
  ~includeLogs: bool,
432
- ~includeTokenBalances: bool,
480
+ ~transactionFields: array<Internal.svmTransactionField>=[],
481
+ ~blockFields: array<Internal.svmBlockField>=[],
433
482
  ~accountFilters: array<Internal.svmAccountFilterGroup>,
434
483
  ~isInner: option<bool>,
435
- ~isWildcard: bool,
436
- ~handler: option<Internal.handler>,
437
- ~contractRegister: option<Internal.contractRegister>,
438
484
  ~accounts: array<string>=[],
439
485
  ~args: JSON.t=JSON.Null,
440
486
  ~definedTypes: JSON.t=JSON.Null,
441
- ~startBlock: option<int>=?,
442
487
  ): Internal.svmInstructionEventConfig => {
443
488
  let paramsSchema =
444
489
  S.json(~validate=false)
445
490
  ->Utils.Schema.coerceToJsonPgType
446
491
  ->(Utils.magic: S.t<JSON.t> => S.t<Internal.eventParams>)
492
+
493
+ // The base eventConfig stores these as a string set (field names match the
494
+ // typed variants at runtime).
495
+ let selectedTransactionFields =
496
+ Utils.Set.fromArray(transactionFields)->(
497
+ Utils.magic: Utils.Set.t<Internal.svmTransactionField> => Utils.Set.t<string>
498
+ )
499
+ let selectedBlockFields = Utils.Set.fromArray(
500
+ Array.concat(alwaysIncludedSvmBlockFields, blockFields),
501
+ )
502
+ let blockFieldMask = Svm.eventBlockFieldMask(
503
+ selectedBlockFields->(Utils.magic: Utils.Set.t<Internal.svmBlockField> => Utils.Set.t<string>),
504
+ )
447
505
  {
448
506
  id: switch discriminator {
449
507
  | Some(d) => d
@@ -451,20 +509,16 @@ let buildSvmInstructionEventConfig = (
451
509
  },
452
510
  name: instructionName,
453
511
  contractName,
454
- isWildcard,
455
- handler,
456
- contractRegister,
457
512
  paramsRawEventSchema: paramsSchema,
458
513
  simulateParamsSchema: paramsSchema,
459
- filterByAddresses: false,
460
- dependsOnAddresses: !isWildcard,
461
- startBlock,
462
514
  programId,
463
515
  discriminator,
464
516
  discriminatorByteLen,
465
- includeTransaction,
466
517
  includeLogs,
467
- includeTokenBalances,
518
+ selectedTransactionFields,
519
+ transactionFieldMask: Svm.eventTransactionFieldMask(selectedTransactionFields),
520
+ selectedBlockFields,
521
+ blockFieldMask,
468
522
  accountFilters,
469
523
  isInner,
470
524
  accounts,
@@ -473,16 +527,33 @@ let buildSvmInstructionEventConfig = (
473
527
  }
474
528
  }
475
529
 
530
+ // Enrich an SVM definition into a registration. SVM has no `where`; only the
531
+ // handler binding + wildcard-derived address gate are registration state.
532
+ let buildSvmOnEventRegistration = (
533
+ ~eventConfig: Internal.svmInstructionEventConfig,
534
+ ~isWildcard: bool,
535
+ ~handler: option<Internal.handler>,
536
+ ~contractRegister: option<Internal.contractRegister>,
537
+ ~startBlock: option<int>=?,
538
+ ): Internal.svmOnEventRegistration => {
539
+ eventConfig: (eventConfig :> Internal.eventConfig),
540
+ handler,
541
+ contractRegister,
542
+ isWildcard,
543
+ filterByAddresses: false,
544
+ dependsOnAddresses: Internal.dependsOnAddresses(~isWildcard, ~filterByAddresses=false),
545
+ clientAddressFilter: ?buildAddressFilter([], ~isWildcard, ~srcAddressExpr="event.programId"),
546
+ startBlock,
547
+ }
548
+
549
+ // ============== Build Fuel event config ==============
550
+
476
551
  let buildFuelEventConfig = (
477
552
  ~contractName: string,
478
553
  ~eventName: string,
479
554
  ~kind: string,
480
555
  ~sighash: string,
481
556
  ~rawAbi: JSON.t,
482
- ~isWildcard: bool,
483
- ~handler: option<Internal.handler>,
484
- ~contractRegister: option<Internal.contractRegister>,
485
- ~startBlock: option<int>=?,
486
557
  ): Internal.fuelEventConfig => {
487
558
  let fuelKind = switch kind {
488
559
  | "logData" =>
@@ -522,14 +593,32 @@ let buildFuelEventConfig = (
522
593
  },
523
594
  name: eventName,
524
595
  contractName,
525
- isWildcard,
526
- handler,
527
- contractRegister,
528
596
  paramsRawEventSchema: paramsSchema,
529
597
  simulateParamsSchema: paramsSchema,
530
- filterByAddresses: false,
531
- dependsOnAddresses: !isWildcard,
532
- startBlock,
598
+ // Fuel keeps the transaction and block inline on the payload; nothing to
599
+ // materialise.
600
+ selectedTransactionFields: Utils.Set.make(),
601
+ transactionFieldMask: 0.,
602
+ blockFieldMask: 0.,
533
603
  kind: fuelKind,
534
604
  }
535
605
  }
606
+
607
+ // Enrich a Fuel definition into a registration (handler binding +
608
+ // wildcard-derived address gate; Fuel never filters by addresses).
609
+ let buildFuelOnEventRegistration = (
610
+ ~eventConfig: Internal.fuelEventConfig,
611
+ ~isWildcard: bool,
612
+ ~handler: option<Internal.handler>,
613
+ ~contractRegister: option<Internal.contractRegister>,
614
+ ~startBlock: option<int>=?,
615
+ ): Internal.fuelOnEventRegistration => {
616
+ eventConfig: (eventConfig :> Internal.eventConfig),
617
+ handler,
618
+ contractRegister,
619
+ isWildcard,
620
+ filterByAddresses: false,
621
+ dependsOnAddresses: Internal.dependsOnAddresses(~isWildcard, ~filterByAddresses=false),
622
+ clientAddressFilter: ?buildAddressFilter([], ~isWildcard),
623
+ startBlock,
624
+ }
@@ -1,5 +1,7 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Evm from "./sources/Evm.res.mjs";
4
+ import * as Svm from "./sources/Svm.res.mjs";
3
5
  import * as Utils from "./Utils.res.mjs";
4
6
  import * as Address from "./Address.res.mjs";
5
7
  import * as FuelSDK from "./sources/FuelSDK.res.mjs";
@@ -211,7 +213,7 @@ function getTopicEncoder(abiType) {
211
213
  }
212
214
  switch (abiType) {
213
215
  case "address" :
214
- return TopicFilter.fromAddress;
216
+ return value => TopicFilter.fromAddress(value.toLowerCase());
215
217
  case "bool" :
216
218
  return TopicFilter.fromBool;
217
219
  case "bytes" :
@@ -255,20 +257,30 @@ let compileAddressFilter = (function (body) {
255
257
  return new Function("event", "blockNumber", "indexingAddresses", body);
256
258
  });
257
259
 
258
- function buildAddressFilterBody(groups) {
259
- if (groups.length === 0) {
260
- return;
260
+ function buildAddressFilterBody(groups, isWildcard, srcAddressExprOpt) {
261
+ let srcAddressExpr = srcAddressExprOpt !== undefined ? srcAddressExprOpt : "event.srcAddress";
262
+ let paramLeaf = name => `(ic = indexingAddresses[p[` + JSON.stringify(name) + `]]) !== undefined && ic.effectiveStartBlock <= blockNumber`;
263
+ let paramDnf = groups.length !== 0 ? groups.map(group => "(" + group.map(paramLeaf).join(" && ") + ")").join(" || ") : undefined;
264
+ let srcLeaf = `(ic = indexingAddresses[` + srcAddressExpr + `]) !== undefined && ic.effectiveStartBlock <= blockNumber`;
265
+ if (isWildcard) {
266
+ if (paramDnf !== undefined) {
267
+ return "var p = event.params, ic; return " + paramDnf + ";";
268
+ } else {
269
+ return;
270
+ }
271
+ } else if (paramDnf !== undefined) {
272
+ return "var p = event.params, ic; return " + srcLeaf + " && (" + paramDnf + ");";
273
+ } else {
274
+ return "var ic; return " + srcLeaf + ";";
261
275
  }
262
- let leaf = name => `(ic = indexingAddresses[p[` + JSON.stringify(name) + `]]) !== undefined && ic.effectiveStartBlock <= blockNumber`;
263
- let groupExprs = groups.map(group => "(" + group.map(leaf).join(" && ") + ")");
264
- return "var p = event.params, ic; return " + groupExprs.join(" || ") + ";";
265
276
  }
266
277
 
267
- function buildAddressFilter(groups) {
268
- return Stdlib_Option.map(buildAddressFilterBody(groups), compileAddressFilter);
278
+ function buildAddressFilter(groups, isWildcard, srcAddressExprOpt) {
279
+ let srcAddressExpr = srcAddressExprOpt !== undefined ? srcAddressExprOpt : "event.srcAddress";
280
+ return Stdlib_Option.map(buildAddressFilterBody(groups, isWildcard, srcAddressExpr), compileAddressFilter);
269
281
  }
270
282
 
271
- function buildEvmEventConfig(contractName, eventName, sighash, params, isWildcard, handler, contractRegister, eventFilters, probeChainId, onEventBlockFilterSchema, blockFields, transactionFields, startBlock, globalBlockFieldsSetOpt, globalTransactionFieldsSetOpt) {
283
+ function buildEvmEventConfig(contractName, eventName, sighash, params, blockFields, transactionFields, globalBlockFieldsSetOpt, globalTransactionFieldsSetOpt) {
272
284
  let globalBlockFieldsSet = globalBlockFieldsSetOpt !== undefined ? Primitive_option.valFromOption(globalBlockFieldsSetOpt) : new Set();
273
285
  let globalTransactionFieldsSet = globalTransactionFieldsSetOpt !== undefined ? Primitive_option.valFromOption(globalTransactionFieldsSetOpt) : new Set();
274
286
  let topicCount = Stdlib_Array.reduce(params, 1, (acc, p) => {
@@ -278,57 +290,75 @@ function buildEvmEventConfig(contractName, eventName, sighash, params, isWildcar
278
290
  return acc;
279
291
  }
280
292
  });
281
- let indexedParams = params.filter(p => p.indexed);
282
- let match = LogSelection.parseEventFiltersOrThrow(eventFilters, sighash, indexedParams.map(p => p.name), contractName, probeChainId, onEventBlockFilterSchema, Stdlib_Option.map(indexedParams[0], buildTopicGetter), Stdlib_Option.map(indexedParams[1], buildTopicGetter), Stdlib_Option.map(indexedParams[2], buildTopicGetter));
283
- let whereStartBlock = match.startBlock;
284
- let filterByAddresses = match.filterByAddresses;
285
- let resolvedStartBlock = whereStartBlock !== undefined ? whereStartBlock : startBlock;
286
- let match$1 = resolveFieldSelection(blockFields, transactionFields, globalBlockFieldsSet, globalTransactionFieldsSet);
293
+ let match = resolveFieldSelection(blockFields, transactionFields, globalBlockFieldsSet, globalTransactionFieldsSet);
294
+ let selectedTransactionFields = match[1];
295
+ let selectedBlockFields = match[0];
287
296
  return {
288
297
  id: sighash + "_" + topicCount.toString(),
289
298
  name: eventName,
290
299
  contractName: contractName,
291
- isWildcard: isWildcard,
292
- filterByAddresses: filterByAddresses,
293
- dependsOnAddresses: !isWildcard || filterByAddresses,
294
- clientAddressFilter: Stdlib_Option.map(buildAddressFilterBody(match.addressFilterParamGroups), compileAddressFilter),
295
- handler: handler,
296
- contractRegister: contractRegister,
297
300
  paramsRawEventSchema: buildParamsSchema(params),
298
301
  simulateParamsSchema: buildSimulateParamsSchema(params),
299
- startBlock: resolvedStartBlock,
300
- getEventFiltersOrThrow: match.getEventFiltersOrThrow,
301
- selectedBlockFields: match$1[0],
302
- selectedTransactionFields: match$1[1],
302
+ selectedTransactionFields: selectedTransactionFields,
303
+ transactionFieldMask: Evm.eventTransactionFieldMask(selectedTransactionFields),
304
+ blockFieldMask: Evm.eventBlockFieldMask(selectedBlockFields),
305
+ selectedBlockFields: selectedBlockFields,
303
306
  sighash: sighash,
304
307
  topicCount: topicCount,
305
308
  paramsMetadata: params
306
309
  };
307
310
  }
308
311
 
309
- function buildSvmInstructionEventConfig(contractName, instructionName, programId, discriminator, discriminatorByteLen, includeTransaction, includeLogs, includeTokenBalances, accountFilters, isInner, isWildcard, handler, contractRegister, accountsOpt, argsOpt, definedTypesOpt, startBlock) {
312
+ function buildEvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, where, chainId, onEventBlockFilterSchema, startBlock) {
313
+ let indexedParams = eventConfig.paramsMetadata.filter(p => p.indexed);
314
+ let match = LogSelection.parseWhereOrThrow(where, eventConfig.sighash, indexedParams.map(p => p.name), eventConfig.contractName, chainId, onEventBlockFilterSchema, Stdlib_Option.map(indexedParams[0], buildTopicGetter), Stdlib_Option.map(indexedParams[1], buildTopicGetter), Stdlib_Option.map(indexedParams[2], buildTopicGetter));
315
+ let filterByAddresses = match.filterByAddresses;
316
+ let resolvedWhere = match.resolvedWhere;
317
+ let sb = resolvedWhere.startBlock;
318
+ let resolvedStartBlock = sb !== undefined ? sb : startBlock;
319
+ return {
320
+ eventConfig: eventConfig,
321
+ handler: handler,
322
+ contractRegister: contractRegister,
323
+ isWildcard: isWildcard,
324
+ filterByAddresses: filterByAddresses,
325
+ dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, filterByAddresses),
326
+ clientAddressFilter: buildAddressFilter(match.addressFilterParamGroups, isWildcard, undefined),
327
+ startBlock: resolvedStartBlock,
328
+ resolvedWhere: resolvedWhere
329
+ };
330
+ }
331
+
332
+ let alwaysIncludedSvmBlockFields = [
333
+ "slot",
334
+ "time",
335
+ "hash"
336
+ ];
337
+
338
+ function buildSvmInstructionEventConfig(contractName, instructionName, programId, discriminator, discriminatorByteLen, includeLogs, transactionFieldsOpt, blockFieldsOpt, accountFilters, isInner, accountsOpt, argsOpt, definedTypesOpt) {
339
+ let transactionFields = transactionFieldsOpt !== undefined ? transactionFieldsOpt : [];
340
+ let blockFields = blockFieldsOpt !== undefined ? blockFieldsOpt : [];
310
341
  let accounts = accountsOpt !== undefined ? accountsOpt : [];
311
342
  let args = argsOpt !== undefined ? argsOpt : null;
312
343
  let definedTypes = definedTypesOpt !== undefined ? definedTypesOpt : null;
313
344
  let paramsSchema = Utils.Schema.coerceToJsonPgType(S$RescriptSchema.json(false));
345
+ let selectedTransactionFields = new Set(transactionFields);
346
+ let selectedBlockFields = new Set(alwaysIncludedSvmBlockFields.concat(blockFields));
347
+ let blockFieldMask = Svm.eventBlockFieldMask(selectedBlockFields);
314
348
  return {
315
349
  id: discriminator !== undefined ? discriminator : "none",
316
350
  name: instructionName,
317
351
  contractName: contractName,
318
- isWildcard: isWildcard,
319
- filterByAddresses: false,
320
- dependsOnAddresses: !isWildcard,
321
- handler: handler,
322
- contractRegister: contractRegister,
323
352
  paramsRawEventSchema: paramsSchema,
324
353
  simulateParamsSchema: paramsSchema,
325
- startBlock: startBlock,
354
+ selectedTransactionFields: selectedTransactionFields,
355
+ transactionFieldMask: Svm.eventTransactionFieldMask(selectedTransactionFields),
356
+ blockFieldMask: blockFieldMask,
357
+ selectedBlockFields: selectedBlockFields,
326
358
  programId: programId,
327
359
  discriminator: discriminator,
328
360
  discriminatorByteLen: discriminatorByteLen,
329
- includeTransaction: includeTransaction,
330
361
  includeLogs: includeLogs,
331
- includeTokenBalances: includeTokenBalances,
332
362
  accountFilters: accountFilters,
333
363
  isInner: isInner,
334
364
  accounts: accounts,
@@ -337,7 +367,20 @@ function buildSvmInstructionEventConfig(contractName, instructionName, programId
337
367
  };
338
368
  }
339
369
 
340
- function buildFuelEventConfig(contractName, eventName, kind, sighash, rawAbi, isWildcard, handler, contractRegister, startBlock) {
370
+ function buildSvmOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, startBlock) {
371
+ return {
372
+ eventConfig: eventConfig,
373
+ handler: handler,
374
+ contractRegister: contractRegister,
375
+ isWildcard: isWildcard,
376
+ filterByAddresses: false,
377
+ dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, false),
378
+ clientAddressFilter: buildAddressFilter([], isWildcard, "event.programId"),
379
+ startBlock: startBlock
380
+ };
381
+ }
382
+
383
+ function buildFuelEventConfig(contractName, eventName, kind, sighash, rawAbi) {
341
384
  let fuelKind;
342
385
  switch (kind) {
343
386
  case "burn" :
@@ -384,18 +427,28 @@ function buildFuelEventConfig(contractName, eventName, kind, sighash, rawAbi, is
384
427
  id: tmp,
385
428
  name: eventName,
386
429
  contractName: contractName,
387
- isWildcard: isWildcard,
388
- filterByAddresses: false,
389
- dependsOnAddresses: !isWildcard,
390
- handler: handler,
391
- contractRegister: contractRegister,
392
430
  paramsRawEventSchema: paramsSchema,
393
431
  simulateParamsSchema: paramsSchema,
394
- startBlock: startBlock,
432
+ selectedTransactionFields: new Set(),
433
+ transactionFieldMask: 0,
434
+ blockFieldMask: 0,
395
435
  kind: fuelKind
396
436
  };
397
437
  }
398
438
 
439
+ function buildFuelOnEventRegistration(eventConfig, isWildcard, handler, contractRegister, startBlock) {
440
+ return {
441
+ eventConfig: eventConfig,
442
+ handler: handler,
443
+ contractRegister: contractRegister,
444
+ isWildcard: isWildcard,
445
+ filterByAddresses: false,
446
+ dependsOnAddresses: Internal.dependsOnAddresses(isWildcard, false),
447
+ clientAddressFilter: buildAddressFilter([], isWildcard, undefined),
448
+ startBlock: startBlock
449
+ };
450
+ }
451
+
399
452
  export {
400
453
  paramMetaSchema,
401
454
  normalizeOrThrow,
@@ -415,7 +468,11 @@ export {
415
468
  buildAddressFilterBody,
416
469
  buildAddressFilter,
417
470
  buildEvmEventConfig,
471
+ buildEvmOnEventRegistration,
472
+ alwaysIncludedSvmBlockFields,
418
473
  buildSvmInstructionEventConfig,
474
+ buildSvmOnEventRegistration,
419
475
  buildFuelEventConfig,
476
+ buildFuelOnEventRegistration,
420
477
  }
421
478
  /* paramMetaSchema Not a pure module */