envio 3.3.0-alpha.2 → 3.3.0-alpha.4

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 (71) hide show
  1. package/index.d.ts +23 -21
  2. package/package.json +6 -6
  3. package/src/Bin.res +3 -0
  4. package/src/Bin.res.mjs +4 -0
  5. package/src/ChainFetching.res +26 -3
  6. package/src/ChainFetching.res.mjs +22 -3
  7. package/src/ChainState.res +3 -12
  8. package/src/ChainState.res.mjs +6 -8
  9. package/src/ChainState.resi +0 -2
  10. package/src/CrossChainState.res +15 -0
  11. package/src/CrossChainState.res.mjs +12 -0
  12. package/src/Ecosystem.res +0 -6
  13. package/src/EventConfigBuilder.res +45 -18
  14. package/src/EventConfigBuilder.res.mjs +28 -10
  15. package/src/EventProcessing.res +53 -37
  16. package/src/EventProcessing.res.mjs +41 -36
  17. package/src/FetchState.res +35 -42
  18. package/src/FetchState.res.mjs +37 -63
  19. package/src/HandlerLoader.res +10 -1
  20. package/src/HandlerLoader.res.mjs +15 -8
  21. package/src/Internal.res +8 -3
  22. package/src/Internal.res.mjs +1 -1
  23. package/src/LoadLayer.res +5 -5
  24. package/src/LoadLayer.res.mjs +6 -6
  25. package/src/Main.res +17 -9
  26. package/src/Main.res.mjs +15 -6
  27. package/src/PgStorage.res +4 -4
  28. package/src/PgStorage.res.mjs +5 -5
  29. package/src/Prometheus.res +10 -10
  30. package/src/Prometheus.res.mjs +9 -9
  31. package/src/PruneStaleHistory.res +2 -2
  32. package/src/PruneStaleHistory.res.mjs +3 -3
  33. package/src/Rollback.res +2 -2
  34. package/src/Rollback.res.mjs +3 -3
  35. package/src/SimulateItems.res +81 -15
  36. package/src/SimulateItems.res.mjs +63 -20
  37. package/src/TestIndexer.res +77 -39
  38. package/src/TestIndexer.res.mjs +45 -31
  39. package/src/bindings/Performance.res +7 -0
  40. package/src/bindings/Performance.res.mjs +21 -0
  41. package/src/bindings/Performance.resi +7 -0
  42. package/src/sources/EventRouter.res +17 -21
  43. package/src/sources/EventRouter.res.mjs +6 -9
  44. package/src/sources/Evm.res +10 -37
  45. package/src/sources/Evm.res.mjs +5 -40
  46. package/src/sources/Fuel.res +0 -4
  47. package/src/sources/Fuel.res.mjs +0 -7
  48. package/src/sources/HyperFuelSource.res +10 -11
  49. package/src/sources/HyperFuelSource.res.mjs +11 -11
  50. package/src/sources/HyperSync.res +3 -0
  51. package/src/sources/HyperSync.res.mjs +1 -0
  52. package/src/sources/HyperSync.resi +1 -0
  53. package/src/sources/HyperSyncClient.res +5 -1
  54. package/src/sources/HyperSyncSource.res +42 -24
  55. package/src/sources/HyperSyncSource.res.mjs +30 -26
  56. package/src/sources/RpcSource.res +7 -8
  57. package/src/sources/RpcSource.res.mjs +8 -8
  58. package/src/sources/SimulateSource.res +1 -1
  59. package/src/sources/Source.res +1 -1
  60. package/src/sources/SourceManager.res +17 -16
  61. package/src/sources/SourceManager.res.mjs +10 -15
  62. package/src/sources/Svm.res +6 -11
  63. package/src/sources/Svm.res.mjs +6 -14
  64. package/src/sources/SvmHyperSyncSource.res +24 -18
  65. package/src/sources/SvmHyperSyncSource.res.mjs +22 -15
  66. package/src/sources/TransactionStore.res +62 -35
  67. package/src/sources/TransactionStore.res.mjs +44 -18
  68. package/svm.schema.json +30 -37
  69. package/src/bindings/Hrtime.res +0 -58
  70. package/src/bindings/Hrtime.res.mjs +0 -90
  71. package/src/bindings/Hrtime.resi +0 -30
@@ -12,6 +12,7 @@ import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
12
12
  import * as Persistence from "./Persistence.res.mjs";
13
13
  import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
14
14
  import * as EntityFilter from "./db/EntityFilter.res.mjs";
15
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
15
16
  import * as InternalTable from "./db/InternalTable.res.mjs";
16
17
  import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
17
18
  import * as SimulateItems from "./SimulateItems.res.mjs";
@@ -32,6 +33,27 @@ function toIndexingAddress(dc) {
32
33
  };
33
34
  }
34
35
 
36
+ function getIndexingAddressesByChain(state) {
37
+ let byChain = {};
38
+ let dcDict = state.entities[Config.EnvioAddresses.name];
39
+ if (dcDict !== undefined) {
40
+ Object.values(dcDict).forEach(entity => {
41
+ let chainIdStr = entity.chain_id.toString();
42
+ let arr = byChain[chainIdStr];
43
+ let contracts;
44
+ if (arr !== undefined) {
45
+ contracts = arr;
46
+ } else {
47
+ let arr$1 = [];
48
+ byChain[chainIdStr] = arr$1;
49
+ contracts = arr$1;
50
+ }
51
+ contracts.push(toIndexingAddress(entity));
52
+ });
53
+ }
54
+ return byChain;
55
+ }
56
+
35
57
  function handleLoad(state, tableName, filter) {
36
58
  let entityConfig = state.entityConfigs[tableName];
37
59
  if (entityConfig === undefined) {
@@ -403,17 +425,11 @@ function makeCreateTestIndexer(config, workerPath) {
403
425
  if (state.processInProgress) {
404
426
  Stdlib_JsError.throwWithMessage(`Cannot access ` + contract.name + `.addresses while indexer.process() is running. ` + "Wait for process() to complete before reading contract addresses.");
405
427
  }
406
- let addresses = [];
407
- let dcDict = state.entities[Config.EnvioAddresses.name];
408
- if (dcDict !== undefined) {
409
- Object.values(dcDict).forEach(entity => {
410
- if (entity.contract_name === contract.name && entity.chain_id === chainConfig.id) {
411
- addresses.push(Config.EnvioAddresses.getAddress(entity));
412
- return;
413
- }
414
- });
415
- }
416
- return addresses;
428
+ return Stdlib_Array.filterMap(Stdlib_Option.getOr(getIndexingAddressesByChain(state)[chainConfig.id.toString()], []), ia => {
429
+ if (ia.contractName === contract.name) {
430
+ return Primitive_option.some(ia.address);
431
+ }
432
+ });
417
433
  }
418
434
  });
419
435
  Object.defineProperty(chainObj, contract.name, {
@@ -484,23 +500,7 @@ function makeCreateTestIndexer(config, workerPath) {
484
500
  let chainId = param[1];
485
501
  let chains = {};
486
502
  chains[param[0]] = processChainConfig;
487
- let indexingAddressesByChain = {};
488
- let dcDict = state.entities[Config.EnvioAddresses.name];
489
- if (dcDict !== undefined) {
490
- Object.values(dcDict).forEach(entity => {
491
- let dcChainIdStr = entity.chain_id.toString();
492
- let arr = indexingAddressesByChain[dcChainIdStr];
493
- let contracts;
494
- if (arr !== undefined) {
495
- contracts = arr;
496
- } else {
497
- let arr$1 = [];
498
- indexingAddressesByChain[dcChainIdStr] = arr$1;
499
- contracts = arr$1;
500
- }
501
- contracts.push(toIndexingAddress(entity));
502
- });
503
- }
503
+ let indexingAddressesByChain = getIndexingAddressesByChain(state);
504
504
  let initialState = makeInitialState(config, chains, indexingAddressesByChain);
505
505
  return new Promise((resolve, reject) => {
506
506
  let workerData_startBlock = processChainConfig.startBlock;
@@ -586,9 +586,11 @@ function initTestWorker() {
586
586
  Process.exit(1);
587
587
  return;
588
588
  }
589
+ let initialState = workerData.initialState;
589
590
  let simulate = workerData.simulate;
590
591
  let endBlock = workerData.endBlock;
591
- let chainIdStr = workerData.chainId.toString();
592
+ let chainId = workerData.chainId;
593
+ let chainIdStr = chainId.toString();
592
594
  let exitAfterFirstEventBlock = Stdlib_Option.isNone(endBlock);
593
595
  let resolvedChainDict = {};
594
596
  resolvedChainDict["startBlock"] = workerData.startBlock;
@@ -603,7 +605,7 @@ function initTestWorker() {
603
605
  let processConfig = {
604
606
  chains: resolvedChainsDict
605
607
  };
606
- let proxy = TestIndexerProxyStorage.make(parentPort, workerData.initialState);
608
+ let proxy = TestIndexerProxyStorage.make(parentPort, initialState);
607
609
  let storage = TestIndexerProxyStorage.makeStorage(proxy);
608
610
  let config = Config.loadWithoutRegistrations();
609
611
  let persistence = Persistence.make(config.userEntities, config.allEnums, storage);
@@ -613,6 +615,11 @@ function initTestWorker() {
613
615
  Logging.setLogLevel("silent");
614
616
  }
615
617
  let patchConfig = (config, _registrations) => {
618
+ if (simulate !== undefined) {
619
+ let chainConfig = ChainMap.get(config.chainMap, ChainMap.Chain.makeUnsafe(chainId));
620
+ let indexingAddresses = Stdlib_Option.mapOr(initialState.chains.find(c => c.id === chainId), [], c => c.indexingAddresses);
621
+ SimulateItems.validateSrcAddresses(simulate, config, chainConfig, indexingAddresses);
622
+ }
616
623
  let config$1 = SimulateItems.patchConfig(config, processConfig);
617
624
  if (exitAfterFirstEventBlock) {
618
625
  return {
@@ -640,11 +647,18 @@ function initTestWorker() {
640
647
  return config$1;
641
648
  }
642
649
  };
643
- Main.start(persistence, undefined, true, exitAfterFirstEventBlock, patchConfig);
650
+ Stdlib_Promise.$$catch(Main.start(persistence, undefined, true, exitAfterFirstEventBlock, patchConfig), exn => {
651
+ let toThrow = exn.RE_EXN_ID === Main.FatalError ? exn._1 : Utils.prettifyExn(exn);
652
+ setImmediate(() => {
653
+ throw toThrow;
654
+ });
655
+ return Promise.resolve();
656
+ });
644
657
  }
645
658
 
646
659
  export {
647
660
  toIndexingAddress,
661
+ getIndexingAddressesByChain,
648
662
  handleLoad,
649
663
  handleWriteBatch,
650
664
  makeInitialState,
@@ -0,0 +1,7 @@
1
+ type timeRef = float
2
+
3
+ @val @scope("performance") external now: unit => timeRef = "now"
4
+
5
+ let secondsSince = (from: timeRef): float => (now() -. from) /. 1000.
6
+
7
+ let secondsBetween = (~from: timeRef, ~to: timeRef): float => (to -. from) /. 1000.
@@ -0,0 +1,21 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ function secondsSince(from) {
5
+ return (performance.now() - from) / 1000;
6
+ }
7
+
8
+ function secondsBetween(from, to) {
9
+ return (to - from) / 1000;
10
+ }
11
+
12
+ function now(prim) {
13
+ return performance.now();
14
+ }
15
+
16
+ export {
17
+ now,
18
+ secondsSince,
19
+ secondsBetween,
20
+ }
21
+ /* No side effect */
@@ -0,0 +1,7 @@
1
+ type timeRef = float
2
+
3
+ let now: unit => timeRef
4
+
5
+ let secondsSince: timeRef => float
6
+
7
+ let secondsBetween: (~from: timeRef, ~to: timeRef) => float
@@ -28,29 +28,25 @@ module Group = {
28
28
  }
29
29
  }
30
30
 
31
- let get = (
32
- group: t<'a>,
33
- ~contractAddress,
34
- ~blockNumber,
35
- ~indexingAddresses: dict<FetchState.indexingAddress>,
36
- ) =>
31
+ // Ownership only: resolve the owning contract from the partition's reverse
32
+ // index (the partition that fetched the log), not a chain-wide snapshot. The
33
+ // `effectiveStartBlock` temporal gate now lives in `clientAddressFilter`. The
34
+ // wildcard partition has an empty index → every log falls back to `wildcard`,
35
+ // so it can never claim an address-bound contract's logs.
36
+ let get = (group: t<'a>, ~contractAddress, ~contractNameByAddress: dict<string>) =>
37
37
  switch group {
38
38
  | {wildcard, byContractName} =>
39
- switch indexingAddresses->Utils.Dict.dangerouslyGetNonOption(
39
+ switch contractNameByAddress->Utils.Dict.dangerouslyGetNonOption(
40
40
  contractAddress->Address.toString,
41
41
  ) {
42
- | Some(indexingContract) =>
43
- if indexingContract.effectiveStartBlock <= blockNumber {
44
- switch byContractName->Utils.Dict.dangerouslyGetNonOption(indexingContract.contractName) {
45
- // Fall back to the wildcard handler when the indexed contract has no
46
- // matching event for this tag. This covers addresses registered for
47
- // contracts without events (persisted for future config changes) as
48
- // well as addresses whose contract has other events but not this one.
49
- | None => wildcard
50
- | Some(_) as event => event
51
- }
52
- } else {
53
- None
42
+ | Some(contractName) =>
43
+ switch byContractName->Utils.Dict.dangerouslyGetNonOption(contractName) {
44
+ // Fall back to the wildcard handler when the owning contract has no
45
+ // matching event for this tag. This covers addresses registered for
46
+ // contracts without events (persisted for future config changes) as
47
+ // well as addresses whose contract has other events but not this one.
48
+ | None => wildcard
49
+ | Some(_) as event => event
54
50
  }
55
51
  | None => wildcard
56
52
  }
@@ -89,10 +85,10 @@ let addOrThrow = (
89
85
  }
90
86
  }
91
87
 
92
- let get = (router: t<'a>, ~tag, ~contractAddress, ~blockNumber, ~indexingAddresses) => {
88
+ let get = (router: t<'a>, ~tag, ~contractAddress, ~contractNameByAddress) => {
93
89
  switch router->Utils.Dict.dangerouslyGetNonOption(tag) {
94
90
  | None => None
95
- | Some(group) => group->Group.get(~contractAddress, ~blockNumber, ~indexingAddresses)
91
+ | Some(group) => group->Group.get(~contractAddress, ~contractNameByAddress)
96
92
  }
97
93
  }
98
94
 
@@ -39,16 +39,13 @@ function addOrThrow(group, event, contractName, isWildcard) {
39
39
  byContractName[contractName] = event;
40
40
  }
41
41
 
42
- function get(group, contractAddress, blockNumber, indexingAddresses) {
42
+ function get(group, contractAddress, contractNameByAddress) {
43
43
  let wildcard = group.wildcard;
44
- let indexingContract = indexingAddresses[contractAddress];
45
- if (indexingContract === undefined) {
44
+ let contractName = contractNameByAddress[contractAddress];
45
+ if (contractName === undefined) {
46
46
  return wildcard;
47
47
  }
48
- if (indexingContract.effectiveStartBlock > blockNumber) {
49
- return;
50
- }
51
- let event = group.byContractName[indexingContract.contractName];
48
+ let event = group.byContractName[contractName];
52
49
  if (event !== undefined) {
53
50
  return event;
54
51
  } else {
@@ -93,10 +90,10 @@ function addOrThrow$1(router, eventId, event, contractName, isWildcard, eventNam
93
90
  }
94
91
  }
95
92
 
96
- function get$1(router, tag, contractAddress, blockNumber, indexingAddresses) {
93
+ function get$1(router, tag, contractAddress, contractNameByAddress) {
97
94
  let group = router[tag];
98
95
  if (group !== undefined) {
99
- return get(group, contractAddress, blockNumber, indexingAddresses);
96
+ return get(group, contractAddress, contractNameByAddress);
100
97
  }
101
98
  }
102
99
 
@@ -52,11 +52,9 @@ let transactionFields = [
52
52
  "authorizationList",
53
53
  ]
54
54
 
55
- // Field name bit index (the code shared with the Rust store), built once.
56
- let transactionFieldCodes = TransactionStore.fieldCodes(transactionFields)
57
-
58
- let transactionFieldMask = (eventConfigs: array<Internal.eventConfig>): float =>
59
- eventConfigs->TransactionStore.mask(~codes=transactionFieldCodes)
55
+ // One event's selected transaction fields store selection bitmask. Computed
56
+ // per event at config build and cached on the event config.
57
+ let eventTransactionFieldMask = TransactionStore.makeMaskFn(transactionFields)
60
58
 
61
59
  let cleanUpRawEventFieldsInPlace: JSON.t => unit = %raw(`fields => {
62
60
  delete fields.hash
@@ -66,36 +64,6 @@ let cleanUpRawEventFieldsInPlace: JSON.t => unit = %raw(`fields => {
66
64
 
67
65
  let make = (~logger: Pino.t): Ecosystem.t => {
68
66
  name: Evm,
69
- blockFields: [
70
- "number",
71
- "timestamp",
72
- "hash",
73
- "parentHash",
74
- "nonce",
75
- "sha3Uncles",
76
- "logsBloom",
77
- "transactionsRoot",
78
- "stateRoot",
79
- "receiptsRoot",
80
- "miner",
81
- "difficulty",
82
- "totalDifficulty",
83
- "extraData",
84
- "size",
85
- "gasLimit",
86
- "gasUsed",
87
- "uncles",
88
- "baseFeePerGas",
89
- "blobGasUsed",
90
- "excessBlobGas",
91
- "parentBeaconBlockRoot",
92
- "withdrawalsRoot",
93
- "l1BlockNumber",
94
- "sendCount",
95
- "sendRoot",
96
- "mixHash",
97
- ],
98
- transactionFields,
99
67
  blockNumberName: "number",
100
68
  blockTimestampName: "timestamp",
101
69
  blockHashName: "hash",
@@ -117,7 +85,6 @@ let make = (~logger: Pino.t): Ecosystem.t => {
117
85
  s.field("block", S.option(S.object(s2 => s2.field("number", S.unknown))))
118
86
  ),
119
87
  logger,
120
- transactionFieldMask,
121
88
  // The payload carries `transaction` by batch prep (HyperSync) or inline
122
89
  // (RPC/simulate), so the event is the payload as-is.
123
90
  toEvent: eventItem => eventItem.payload->(Utils.magic: Internal.eventPayload => Internal.event),
@@ -135,10 +102,16 @@ let make = (~logger: Pino.t): Ecosystem.t => {
135
102
  ),
136
103
  toRawEvent: eventItem => {
137
104
  let payload = eventItem.payload->toPayload
105
+ let eventConfig =
106
+ eventItem.eventConfig->(Utils.magic: Internal.eventConfig => Internal.evmEventConfig)
138
107
  eventItem->RawEvent.make(
139
108
  ~block=payload.block,
140
109
  ~transaction=payload.transaction,
141
- ~params=payload.params,
110
+ // The decoder emits `{}` for zero-parameter events, which the params
111
+ // schema rejects; pass unit so it serializes to the "null" sentinel.
112
+ ~params=eventConfig.paramsMetadata->Array.length == 0
113
+ ? ()->(Utils.magic: unit => Internal.eventParams)
114
+ : payload.params,
142
115
  ~srcAddress=payload.srcAddress,
143
116
  ~cleanUpRawEventFieldsInPlace,
144
117
  )
@@ -40,11 +40,7 @@ let transactionFields = [
40
40
  "authorizationList"
41
41
  ];
42
42
 
43
- let transactionFieldCodes = TransactionStore.fieldCodes(transactionFields);
44
-
45
- function transactionFieldMask(eventConfigs) {
46
- return TransactionStore.mask(eventConfigs, transactionFieldCodes);
47
- }
43
+ let eventTransactionFieldMask = TransactionStore.makeMaskFn(transactionFields);
48
44
 
49
45
  let cleanUpRawEventFieldsInPlace = (fields => {
50
46
  delete fields.hash
@@ -55,36 +51,6 @@ let cleanUpRawEventFieldsInPlace = (fields => {
55
51
  function make(logger) {
56
52
  return {
57
53
  name: "evm",
58
- blockFields: [
59
- "number",
60
- "timestamp",
61
- "hash",
62
- "parentHash",
63
- "nonce",
64
- "sha3Uncles",
65
- "logsBloom",
66
- "transactionsRoot",
67
- "stateRoot",
68
- "receiptsRoot",
69
- "miner",
70
- "difficulty",
71
- "totalDifficulty",
72
- "extraData",
73
- "size",
74
- "gasLimit",
75
- "gasUsed",
76
- "uncles",
77
- "baseFeePerGas",
78
- "blobGasUsed",
79
- "excessBlobGas",
80
- "parentBeaconBlockRoot",
81
- "withdrawalsRoot",
82
- "l1BlockNumber",
83
- "sendCount",
84
- "sendRoot",
85
- "mixHash"
86
- ],
87
- transactionFields: transactionFields,
88
54
  blockNumberName: "number",
89
55
  blockTimestampName: "timestamp",
90
56
  blockHashName: "hash",
@@ -94,7 +60,6 @@ function make(logger) {
94
60
  onEventBlockFilterSchema: S$RescriptSchema.object(s => s.f("block", S$RescriptSchema.option(S$RescriptSchema.object(s2 => s2.f("number", S$RescriptSchema.unknown))))),
95
61
  logger: logger,
96
62
  toEvent: eventItem => eventItem.payload,
97
- transactionFieldMask: transactionFieldMask,
98
63
  toEventLogger: eventItem => Logging.createChildFrom(logger, {
99
64
  contract: eventItem.eventConfig.contractName,
100
65
  event: eventItem.eventConfig.name,
@@ -105,16 +70,16 @@ function make(logger) {
105
70
  }),
106
71
  toRawEvent: eventItem => {
107
72
  let payload = eventItem.payload;
108
- return RawEvent.make(eventItem, payload.block, payload.transaction, payload.params, payload.srcAddress, cleanUpRawEventFieldsInPlace);
73
+ let eventConfig = eventItem.eventConfig;
74
+ return RawEvent.make(eventItem, payload.block, payload.transaction, eventConfig.paramsMetadata.length === 0 ? undefined : payload.params, payload.srcAddress, cleanUpRawEventFieldsInPlace);
109
75
  }
110
76
  };
111
77
  }
112
78
 
113
79
  export {
114
80
  transactionFields,
115
- transactionFieldCodes,
116
- transactionFieldMask,
81
+ eventTransactionFieldMask,
117
82
  cleanUpRawEventFieldsInPlace,
118
83
  make,
119
84
  }
120
- /* transactionFieldCodes Not a pure module */
85
+ /* eventTransactionFieldMask Not a pure module */
@@ -21,8 +21,6 @@ let cleanUpRawEventFieldsInPlace: JSON.t => unit = %raw(`fields => {
21
21
 
22
22
  let make = (~logger: Pino.t): Ecosystem.t => {
23
23
  name: Fuel,
24
- blockFields: ["id", "height", "time"],
25
- transactionFields: ["id"],
26
24
  blockNumberName: "height",
27
25
  blockTimestampName: "time",
28
26
  blockHashName: "id",
@@ -41,8 +39,6 @@ let make = (~logger: Pino.t): Ecosystem.t => {
41
39
  s.field("block", S.option(S.object(s2 => s2.field("height", S.unknown))))
42
40
  ),
43
41
  logger,
44
- // Fuel carries the transaction inline on the payload.
45
- transactionFieldMask: _ => 0.,
46
42
  toEvent: eventItem => eventItem.payload->(Utils.magic: Internal.eventPayload => Internal.event),
47
43
  toEventLogger: eventItem =>
48
44
  Logging.createChildFrom(
@@ -13,12 +13,6 @@ let cleanUpRawEventFieldsInPlace = (fields => {
13
13
  function make(logger) {
14
14
  return {
15
15
  name: "fuel",
16
- blockFields: [
17
- "id",
18
- "height",
19
- "time"
20
- ],
21
- transactionFields: ["id"],
22
16
  blockNumberName: "height",
23
17
  blockTimestampName: "time",
24
18
  blockHashName: "id",
@@ -28,7 +22,6 @@ function make(logger) {
28
22
  onEventBlockFilterSchema: S$RescriptSchema.object(s => s.f("block", S$RescriptSchema.option(S$RescriptSchema.object(s2 => s2.f("height", S$RescriptSchema.unknown))))),
29
23
  logger: logger,
30
24
  toEvent: eventItem => eventItem.payload,
31
- transactionFieldMask: param => 0,
32
25
  toEventLogger: eventItem => Logging.createChildFrom(logger, {
33
26
  contract: eventItem.eventConfig.contractName,
34
27
  event: eventItem.eventConfig.name,
@@ -235,19 +235,19 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
235
235
  ~fromBlock,
236
236
  ~toBlock,
237
237
  ~addressesByContractName,
238
- ~indexingAddresses,
238
+ ~contractNameByAddress,
239
239
  ~knownHeight,
240
240
  ~partitionId as _,
241
241
  ~selection: FetchState.selection,
242
242
  ~retry,
243
243
  ~logger,
244
244
  ) => {
245
- let totalTimeRef = Hrtime.makeTimer()
245
+ let totalTimeRef = Performance.now()
246
246
 
247
247
  let selectionConfig = getSelectionConfig(selection)
248
248
  let recieptsSelection = selectionConfig.getRecieptsSelection(~addressesByContractName)
249
249
 
250
- let startFetchingBatchTimeRef = Hrtime.makeTimer()
250
+ let startFetchingBatchTimeRef = Performance.now()
251
251
 
252
252
  //fetch batch
253
253
  Prometheus.SourceRequestCount.increment(
@@ -305,7 +305,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
305
305
  )
306
306
  }
307
307
 
308
- let pageFetchTime = startFetchingBatchTimeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
308
+ let pageFetchTime = startFetchingBatchTimeRef->Performance.secondsSince
309
309
 
310
310
  //set height and next from block
311
311
  let knownHeight = pageUnsafe.archiveHeight
@@ -315,7 +315,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
315
315
  //In the query
316
316
  let heighestBlockQueried = pageUnsafe.nextBlock - 1
317
317
 
318
- let parsingTimeRef = Hrtime.makeTimer()
318
+ let parsingTimeRef = Performance.now()
319
319
 
320
320
  let parsedQueueItems = pageUnsafe.items->Array.map(item => {
321
321
  let {contractId: contractAddress, receipt, block, receiptIndex} = item
@@ -332,9 +332,8 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
332
332
 
333
333
  let eventConfig = switch selectionConfig.eventRouter->EventRouter.get(
334
334
  ~tag=eventId,
335
- ~indexingAddresses,
335
+ ~contractNameByAddress,
336
336
  ~contractAddress,
337
- ~blockNumber=block.height,
338
337
  ) {
339
338
  | None => {
340
339
  let logger = Logging.createChildFrom(
@@ -432,7 +431,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
432
431
  })
433
432
  })
434
433
 
435
- let parsingTimeElapsed = parsingTimeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
434
+ let parsingTimeElapsed = parsingTimeRef->Performance.secondsSince
436
435
 
437
436
  // Fuel never rolls back on reorg, so block hashes here are purely informational
438
437
  // for detect-only logging via ReorgDetection.
@@ -448,7 +447,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
448
447
  | _ => 0
449
448
  }
450
449
 
451
- let totalTimeElapsed = totalTimeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
450
+ let totalTimeElapsed = totalTimeRef->Performance.secondsSince
452
451
 
453
452
  let stats = {
454
453
  totalTimeElapsed,
@@ -480,7 +479,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
480
479
  pollingInterval: 100,
481
480
  poweredByHyperSync: true,
482
481
  getHeightOrThrow: async () => {
483
- let timerRef = Hrtime.makeTimer()
482
+ let timerRef = Performance.now()
484
483
  let height = try await client->HyperFuelClient.getHeight catch {
485
484
  | JsExn(e) =>
486
485
  switch e->JsExn.message {
@@ -492,7 +491,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
492
491
  | _ => throw(JsExn(e))
493
492
  }
494
493
  }
495
- let seconds = timerRef->Hrtime.timeSince->Hrtime.toSecondsFloat
494
+ let seconds = timerRef->Performance.secondsSince
496
495
  Prometheus.SourceRequestCount.increment(
497
496
  ~sourceName=name,
498
497
  ~chainId=chain->ChainMap.Chain.toChainId,
@@ -1,11 +1,11 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as Hrtime from "../bindings/Hrtime.res.mjs";
4
3
  import * as Source from "./Source.res.mjs";
5
4
  import * as Logging from "../Logging.res.mjs";
6
5
  import * as HyperFuel from "./HyperFuel.res.mjs";
7
6
  import * as Prometheus from "../Prometheus.res.mjs";
8
7
  import * as EventRouter from "./EventRouter.res.mjs";
8
+ import * as Performance from "../bindings/Performance.res.mjs";
9
9
  import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
10
10
  import * as ErrorHandling from "../ErrorHandling.res.mjs";
11
11
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
@@ -196,11 +196,11 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
196
196
  client = ErrorHandling.mkLogAndRaise(undefined, "Failed to instantiate the HyperFuel client", exn);
197
197
  }
198
198
  let getSelectionConfig = memoGetSelectionConfig(chain);
199
- let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, indexingAddresses, knownHeight, param, selection, retry, logger) => {
200
- let totalTimeRef = Hrtime.makeTimer();
199
+ let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, contractNameByAddress, knownHeight, param, selection, retry, logger) => {
200
+ let totalTimeRef = Performance.now();
201
201
  let selectionConfig = getSelectionConfig(selection);
202
202
  let recieptsSelection = selectionConfig.getRecieptsSelection(addressesByContractName);
203
- let startFetchingBatchTimeRef = Hrtime.makeTimer();
203
+ let startFetchingBatchTimeRef = Performance.now();
204
204
  Prometheus.SourceRequestCount.increment(name, chain, "getLogs");
205
205
  let pageUnsafe;
206
206
  try {
@@ -249,10 +249,10 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
249
249
  Error: new Error()
250
250
  };
251
251
  }
252
- let pageFetchTime = Hrtime.toSecondsFloat(Hrtime.timeSince(startFetchingBatchTimeRef));
252
+ let pageFetchTime = Performance.secondsSince(startFetchingBatchTimeRef);
253
253
  let knownHeight$1 = pageUnsafe.archiveHeight;
254
254
  let heighestBlockQueried = pageUnsafe.nextBlock - 1 | 0;
255
- let parsingTimeRef = Hrtime.makeTimer();
255
+ let parsingTimeRef = Performance.now();
256
256
  let parsedQueueItems = pageUnsafe.items.map(item => {
257
257
  let block = item.block;
258
258
  let receiptIndex = item.receiptIndex;
@@ -277,7 +277,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
277
277
  eventId = burnEventTag;
278
278
  break;
279
279
  }
280
- let eventConfig = EventRouter.get(selectionConfig.eventRouter, eventId, contractAddress, block.height, indexingAddresses);
280
+ let eventConfig = EventRouter.get(selectionConfig.eventRouter, eventId, contractAddress, contractNameByAddress);
281
281
  let eventConfig$1;
282
282
  if (eventConfig !== undefined) {
283
283
  eventConfig$1 = eventConfig;
@@ -370,7 +370,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
370
370
  }
371
371
  };
372
372
  });
373
- let parsingTimeElapsed = Hrtime.toSecondsFloat(Hrtime.timeSince(parsingTimeRef));
373
+ let parsingTimeElapsed = Performance.secondsSince(parsingTimeRef);
374
374
  let blockHashes = pageUnsafe.items.map(param => {
375
375
  let block = param.block;
376
376
  return {
@@ -386,7 +386,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
386
386
  } else {
387
387
  latestFetchedBlockTimestamp = 0;
388
388
  }
389
- let totalTimeElapsed = Hrtime.toSecondsFloat(Hrtime.timeSince(totalTimeRef));
389
+ let totalTimeElapsed = Performance.secondsSince(totalTimeRef);
390
390
  let stats_parsing$unknowntime$unknown$lpars$rpar = parsingTimeElapsed;
391
391
  let stats_page$unknownfetch$unknowntime$unknown$lpars$rpar = pageFetchTime;
392
392
  let stats = {
@@ -414,7 +414,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
414
414
  pollingInterval: 100,
415
415
  getBlockHashes: getBlockHashes,
416
416
  getHeightOrThrow: async () => {
417
- let timerRef = Hrtime.makeTimer();
417
+ let timerRef = Performance.now();
418
418
  let height;
419
419
  try {
420
420
  height = await client.getHeight();
@@ -446,7 +446,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
446
446
  throw e;
447
447
  }
448
448
  }
449
- let seconds = Hrtime.toSecondsFloat(Hrtime.timeSince(timerRef));
449
+ let seconds = Performance.secondsSince(timerRef);
450
450
  Prometheus.SourceRequestCount.increment(name, chain, "getHeight");
451
451
  Prometheus.SourceRequestCount.addSeconds(name, chain, "getHeight", seconds);
452
452
  return height;
@@ -16,6 +16,8 @@ let reraisIfRateLimited = exn =>
16
16
 
17
17
  type logsQueryPage = {
18
18
  items: array<HyperSyncClient.EventItems.item>,
19
+ // Blocks referenced by `items`, deduplicated by block number.
20
+ blocks: array<HyperSyncClient.ResponseTypes.block>,
19
21
  nextBlock: int,
20
22
  archiveHeight: int,
21
23
  rollbackGuard: option<HyperSyncClient.ResponseTypes.rollbackGuard>,
@@ -139,6 +141,7 @@ module GetLogs = {
139
141
 
140
142
  {
141
143
  items: res.items,
144
+ blocks: res.blocks,
142
145
  nextBlock: res.nextBlock,
143
146
  archiveHeight: res.archiveHeight->Option.getOr(0), //Archive Height is only None if height is 0
144
147
  rollbackGuard: res.rollbackGuard,
@@ -130,6 +130,7 @@ async function query(client, fromBlock, toBlock, logSelections, fieldSelection)
130
130
  }
131
131
  return {
132
132
  items: res.items,
133
+ blocks: res.blocks,
133
134
  nextBlock: res.nextBlock,
134
135
  archiveHeight: Stdlib_Option.getOr(res.archiveHeight, 0),
135
136
  rollbackGuard: res.rollbackGuard,