envio 3.3.0-alpha.7 → 3.3.0-alpha.8

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 (89) hide show
  1. package/index.d.ts +23 -5
  2. package/package.json +6 -6
  3. package/src/Api.res +1 -1
  4. package/src/Api.res.mjs +1 -1
  5. package/src/ChainFetching.res +21 -10
  6. package/src/ChainFetching.res.mjs +11 -10
  7. package/src/ChainState.res +328 -165
  8. package/src/ChainState.res.mjs +205 -100
  9. package/src/ChainState.resi +16 -7
  10. package/src/Config.res +11 -27
  11. package/src/Config.res.mjs +8 -7
  12. package/src/Core.res +7 -0
  13. package/src/CrossChainState.res +53 -80
  14. package/src/CrossChainState.res.mjs +43 -59
  15. package/src/CrossChainState.resi +1 -1
  16. package/src/Ecosystem.res +3 -3
  17. package/src/Ecosystem.res.mjs +3 -3
  18. package/src/Envio.res +14 -9
  19. package/src/EventConfigBuilder.res +105 -56
  20. package/src/EventConfigBuilder.res.mjs +69 -33
  21. package/src/EventProcessing.res +19 -15
  22. package/src/EventProcessing.res.mjs +13 -12
  23. package/src/FetchState.res +375 -171
  24. package/src/FetchState.res.mjs +249 -251
  25. package/src/HandlerLoader.res +7 -112
  26. package/src/HandlerLoader.res.mjs +1 -87
  27. package/src/HandlerRegister.res +209 -6
  28. package/src/HandlerRegister.res.mjs +90 -5
  29. package/src/HandlerRegister.resi +13 -2
  30. package/src/IndexerState.res +6 -3
  31. package/src/IndexerState.res.mjs +3 -3
  32. package/src/IndexerState.resi +1 -1
  33. package/src/IndexingAddresses.res +10 -7
  34. package/src/IndexingAddresses.res.mjs +8 -7
  35. package/src/IndexingAddresses.resi +3 -1
  36. package/src/Internal.res +82 -36
  37. package/src/Internal.res.mjs +11 -1
  38. package/src/Main.res +22 -23
  39. package/src/Main.res.mjs +15 -17
  40. package/src/Metrics.res +43 -2
  41. package/src/Metrics.res.mjs +39 -3
  42. package/src/Prometheus.res +0 -35
  43. package/src/Prometheus.res.mjs +33 -68
  44. package/src/RawEvent.res +7 -2
  45. package/src/RawEvent.res.mjs +4 -4
  46. package/src/SimulateItems.res +20 -7
  47. package/src/SimulateItems.res.mjs +7 -11
  48. package/src/TestIndexer.res +1 -1
  49. package/src/TestIndexer.res.mjs +1 -1
  50. package/src/sources/BlockStore.res +46 -0
  51. package/src/sources/BlockStore.res.mjs +24 -0
  52. package/src/sources/EventRouter.res +19 -12
  53. package/src/sources/EventRouter.res.mjs +7 -5
  54. package/src/sources/Evm.res +54 -4
  55. package/src/sources/Evm.res.mjs +43 -4
  56. package/src/sources/EvmChain.res +14 -18
  57. package/src/sources/EvmChain.res.mjs +12 -13
  58. package/src/sources/FieldMask.res +39 -0
  59. package/src/sources/FieldMask.res.mjs +42 -0
  60. package/src/sources/Fuel.res +5 -2
  61. package/src/sources/Fuel.res.mjs +4 -3
  62. package/src/sources/HyperFuelSource.res +31 -40
  63. package/src/sources/HyperFuelSource.res.mjs +52 -44
  64. package/src/sources/HyperSync.res +31 -9
  65. package/src/sources/HyperSync.res.mjs +47 -31
  66. package/src/sources/HyperSync.resi +10 -3
  67. package/src/sources/HyperSyncClient.res +15 -4
  68. package/src/sources/HyperSyncHeightStream.res +1 -8
  69. package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
  70. package/src/sources/HyperSyncSource.res +37 -58
  71. package/src/sources/HyperSyncSource.res.mjs +42 -42
  72. package/src/sources/RpcSource.res +91 -82
  73. package/src/sources/RpcSource.res.mjs +76 -45
  74. package/src/sources/RpcWebSocketHeightStream.res +0 -5
  75. package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
  76. package/src/sources/SimulateSource.res +5 -3
  77. package/src/sources/SimulateSource.res.mjs +12 -4
  78. package/src/sources/Source.res +19 -5
  79. package/src/sources/SourceManager.res +62 -6
  80. package/src/sources/SourceManager.res.mjs +55 -8
  81. package/src/sources/SourceManager.resi +10 -0
  82. package/src/sources/Svm.res +14 -10
  83. package/src/sources/Svm.res.mjs +23 -6
  84. package/src/sources/SvmHyperSyncClient.res +5 -6
  85. package/src/sources/SvmHyperSyncSource.res +82 -41
  86. package/src/sources/SvmHyperSyncSource.res.mjs +86 -41
  87. package/src/sources/TransactionStore.res +6 -107
  88. package/src/sources/TransactionStore.res.mjs +5 -86
  89. package/svm.schema.json +19 -0
@@ -103,7 +103,7 @@ function getEvmEventId(sighash, topicCount) {
103
103
 
104
104
  function fromEvmEventModsOrThrow(events, chain) {
105
105
  let router = {};
106
- events.forEach(config => addOrThrow$1(router, config.id, config, config.contractName, config.isWildcard, config.name, chain));
106
+ events.forEach(config => addOrThrow$1(router, config.eventConfig.id, config, config.eventConfig.contractName, config.isWildcard, config.eventConfig.name, chain));
107
107
  return router;
108
108
  }
109
109
 
@@ -118,12 +118,14 @@ function getSvmEventId(programId, discriminator) {
118
118
  function fromSvmEventConfigsOrThrow(events, chain) {
119
119
  let router = {};
120
120
  events.forEach(config => {
121
- let routerTag = getSvmEventId(config.programId, config.discriminator);
122
- addOrThrow$1(router, routerTag, config, config.contractName, config.isWildcard, config.name, chain);
121
+ let eventConfig = config.eventConfig;
122
+ let routerTag = getSvmEventId(eventConfig.programId, eventConfig.discriminator);
123
+ addOrThrow$1(router, routerTag, config, eventConfig.contractName, config.isWildcard, eventConfig.name, chain);
123
124
  });
124
125
  let byProgram = {};
125
126
  events.forEach(config => {
126
- let key = config.programId;
127
+ let eventConfig = config.eventConfig;
128
+ let key = eventConfig.programId;
127
129
  let s = byProgram[key];
128
130
  let set;
129
131
  if (s !== undefined) {
@@ -133,7 +135,7 @@ function fromSvmEventConfigsOrThrow(events, chain) {
133
135
  byProgram[key] = s$1;
134
136
  set = s$1;
135
137
  }
136
- set.add(config.discriminatorByteLen);
138
+ set.add(eventConfig.discriminatorByteLen);
137
139
  });
138
140
  let ordering = Object.entries(byProgram).map(param => {
139
141
  let sorted = Array.from(param[1]).toSorted((a, b) => b - a | 0);
@@ -10,7 +10,9 @@ type payload = {
10
10
  srcAddress: Address.t,
11
11
  logIndex: int,
12
12
  transaction?: Internal.eventTransaction,
13
- block: Internal.eventBlock,
13
+ // HyperSync omits `block` (it lives raw in the per-chain store and is written
14
+ // onto the payload at batch prep); RPC/simulate build it inline.
15
+ block?: Internal.eventBlock,
14
16
  }
15
17
  external fromPayload: payload => Internal.eventPayload = "%identity"
16
18
  external toPayload: Internal.eventPayload => payload = "%identity"
@@ -27,6 +29,42 @@ let transactionFields =
27
29
  // per event at config build and cached on the event config.
28
30
  let eventTransactionFieldMask = TransactionStore.makeMaskFn(transactionFields)
29
31
 
32
+ // Ordered block field names. The index of each is the field code shared with the
33
+ // Rust store (`EvmBlockField`) — keep this order in sync.
34
+ let blockFields = [
35
+ "number",
36
+ "timestamp",
37
+ "hash",
38
+ "parentHash",
39
+ "nonce",
40
+ "sha3Uncles",
41
+ "logsBloom",
42
+ "transactionsRoot",
43
+ "stateRoot",
44
+ "receiptsRoot",
45
+ "miner",
46
+ "difficulty",
47
+ "totalDifficulty",
48
+ "extraData",
49
+ "size",
50
+ "gasLimit",
51
+ "gasUsed",
52
+ "uncles",
53
+ "baseFeePerGas",
54
+ "blobGasUsed",
55
+ "excessBlobGas",
56
+ "parentBeaconBlockRoot",
57
+ "withdrawalsRoot",
58
+ "l1BlockNumber",
59
+ "sendCount",
60
+ "sendRoot",
61
+ "mixHash",
62
+ ]
63
+
64
+ // One event's selected block fields → store selection bitmask. Computed per
65
+ // event at config build and cached on the event config.
66
+ let eventBlockFieldMask = BlockStore.makeMaskFn(blockFields)
67
+
30
68
  let cleanUpRawEventFieldsInPlace: JSON.t => unit = %raw(`fields => {
31
69
  delete fields.hash
32
70
  delete fields.number
@@ -63,8 +101,8 @@ let make = (~logger: Pino.t): Ecosystem.t => {
63
101
  Logging.createChildFrom(
64
102
  ~logger,
65
103
  ~params={
66
- "contract": eventItem.eventConfig.contractName,
67
- "event": eventItem.eventConfig.name,
104
+ "contract": eventItem.onEventRegistration.eventConfig.contractName,
105
+ "event": eventItem.onEventRegistration.eventConfig.name,
68
106
  "chainId": eventItem.chain->ChainMap.Chain.toChainId,
69
107
  "block": eventItem.blockNumber,
70
108
  "logIndex": eventItem.logIndex,
@@ -74,7 +112,17 @@ let make = (~logger: Pino.t): Ecosystem.t => {
74
112
  toRawEvent: eventItem => {
75
113
  let payload = eventItem.payload->toPayload
76
114
  let eventConfig =
77
- eventItem.eventConfig->(Utils.magic: Internal.eventConfig => Internal.evmEventConfig)
115
+ eventItem.onEventRegistration.eventConfig->(
116
+ Utils.magic: Internal.eventConfig => Internal.evmEventConfig
117
+ )
118
+ // Store-backed payloads get `block` written at batch prep and inline
119
+ // sources carry it from the start, with hash/timestamp always selected —
120
+ // so both are present by the time a raw event is built.
121
+ let header = switch payload.block {
122
+ | Some(block) => block->(Utils.magic: Internal.eventBlock => {"hash": string, "timestamp": int})
123
+ | None =>
124
+ JsError.throwWithMessage("Unexpected case: The event block is missing for a raw event")
125
+ }
78
126
  eventItem->RawEvent.make(
79
127
  ~block=payload.block,
80
128
  ~transaction=payload.transaction,
@@ -84,6 +132,8 @@ let make = (~logger: Pino.t): Ecosystem.t => {
84
132
  ? ()->(Utils.magic: unit => Internal.eventParams)
85
133
  : payload.params,
86
134
  ~srcAddress=payload.srcAddress,
135
+ ~blockHash=header["hash"],
136
+ ~blockTimestamp=header["timestamp"],
87
137
  ~cleanUpRawEventFieldsInPlace,
88
138
  )
89
139
  },
@@ -3,11 +3,46 @@
3
3
  import * as Logging from "../Logging.res.mjs";
4
4
  import * as Internal from "../Internal.res.mjs";
5
5
  import * as RawEvent from "../RawEvent.res.mjs";
6
+ import * as BlockStore from "./BlockStore.res.mjs";
7
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
8
+ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
6
9
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
7
10
  import * as TransactionStore from "./TransactionStore.res.mjs";
8
11
 
9
12
  let eventTransactionFieldMask = TransactionStore.makeMaskFn(Internal.allEvmTransactionFields);
10
13
 
14
+ let blockFields = [
15
+ "number",
16
+ "timestamp",
17
+ "hash",
18
+ "parentHash",
19
+ "nonce",
20
+ "sha3Uncles",
21
+ "logsBloom",
22
+ "transactionsRoot",
23
+ "stateRoot",
24
+ "receiptsRoot",
25
+ "miner",
26
+ "difficulty",
27
+ "totalDifficulty",
28
+ "extraData",
29
+ "size",
30
+ "gasLimit",
31
+ "gasUsed",
32
+ "uncles",
33
+ "baseFeePerGas",
34
+ "blobGasUsed",
35
+ "excessBlobGas",
36
+ "parentBeaconBlockRoot",
37
+ "withdrawalsRoot",
38
+ "l1BlockNumber",
39
+ "sendCount",
40
+ "sendRoot",
41
+ "mixHash"
42
+ ];
43
+
44
+ let eventBlockFieldMask = BlockStore.makeMaskFn(blockFields);
45
+
11
46
  let cleanUpRawEventFieldsInPlace = (fields => {
12
47
  delete fields.hash
13
48
  delete fields.number
@@ -27,8 +62,8 @@ function make(logger) {
27
62
  logger: logger,
28
63
  toEvent: eventItem => eventItem.payload,
29
64
  toEventLogger: eventItem => Logging.createChildFrom(logger, {
30
- contract: eventItem.eventConfig.contractName,
31
- event: eventItem.eventConfig.name,
65
+ contract: eventItem.onEventRegistration.eventConfig.contractName,
66
+ event: eventItem.onEventRegistration.eventConfig.name,
32
67
  chainId: eventItem.chain,
33
68
  block: eventItem.blockNumber,
34
69
  logIndex: eventItem.logIndex,
@@ -36,8 +71,10 @@ function make(logger) {
36
71
  }),
37
72
  toRawEvent: eventItem => {
38
73
  let payload = eventItem.payload;
39
- let eventConfig = eventItem.eventConfig;
40
- return RawEvent.make(eventItem, payload.block, payload.transaction, eventConfig.paramsMetadata.length === 0 ? undefined : payload.params, payload.srcAddress, cleanUpRawEventFieldsInPlace);
74
+ let eventConfig = eventItem.onEventRegistration.eventConfig;
75
+ let block = payload.block;
76
+ let header = block !== undefined ? Primitive_option.valFromOption(block) : Stdlib_JsError.throwWithMessage("Unexpected case: The event block is missing for a raw event");
77
+ return RawEvent.make(eventItem, payload.block, payload.transaction, eventConfig.paramsMetadata.length === 0 ? undefined : payload.params, payload.srcAddress, header.hash, header.timestamp, cleanUpRawEventFieldsInPlace);
41
78
  }
42
79
  };
43
80
  }
@@ -47,6 +84,8 @@ let transactionFields = Internal.allEvmTransactionFields;
47
84
  export {
48
85
  transactionFields,
49
86
  eventTransactionFieldMask,
87
+ blockFields,
88
+ eventBlockFieldMask,
50
89
  cleanUpRawEventFieldsInPlace,
51
90
  make,
52
91
  }
@@ -39,39 +39,35 @@ let getSyncConfig = (
39
39
  }
40
40
  }
41
41
 
42
- let collectEventParams = (contracts: array<Internal.evmContractConfig>): array<
42
+ let collectEventParams = (onEventRegistrations: array<Internal.evmOnEventRegistration>): array<
43
43
  HyperSyncClient.Decoder.eventParamsInput,
44
44
  > => {
45
45
  let result = []
46
- contracts->Array.forEach(contract => {
47
- contract.events->Array.forEach(event => {
48
- result
49
- ->Array.push({
50
- HyperSyncClient.Decoder.sighash: event.sighash,
51
- topicCount: event.topicCount,
52
- eventName: event.name,
53
- contractName: contract.name,
54
- params: event.paramsMetadata,
55
- })
56
- ->ignore
46
+ onEventRegistrations->Array.forEach(reg => {
47
+ let event = reg.eventConfig->(Utils.magic: Internal.eventConfig => Internal.evmEventConfig)
48
+ result
49
+ ->Array.push({
50
+ HyperSyncClient.Decoder.sighash: event.sighash,
51
+ topicCount: event.topicCount,
52
+ eventName: event.name,
53
+ contractName: event.contractName,
54
+ params: event.paramsMetadata,
57
55
  })
56
+ ->ignore
58
57
  })
59
58
  result
60
59
  }
61
60
 
62
61
  let makeSources = (
63
62
  ~chain,
64
- ~contracts: array<Internal.evmContractConfig>,
63
+ ~onEventRegistrations: array<Internal.evmOnEventRegistration>,
65
64
  ~hyperSync,
66
65
  ~rpcs: array<rpc>,
67
66
  ~lowercaseAddresses,
68
67
  ) => {
69
- let eventRouter =
70
- contracts
71
- ->Array.flatMap(contract => contract.events)
72
- ->EventRouter.fromEvmEventModsOrThrow(~chain)
68
+ let eventRouter = onEventRegistrations->EventRouter.fromEvmEventModsOrThrow(~chain)
73
69
 
74
- let allEventParams = collectEventParams(contracts)
70
+ let allEventParams = collectEventParams(onEventRegistrations)
75
71
 
76
72
  let sources = switch hyperSync {
77
73
  | Some(endpointUrl) => [
@@ -20,25 +20,24 @@ function getSyncConfig(param) {
20
20
  };
21
21
  }
22
22
 
23
- function collectEventParams(contracts) {
23
+ function collectEventParams(onEventRegistrations) {
24
24
  let result = [];
25
- contracts.forEach(contract => {
26
- contract.events.forEach(event => {
27
- result.push({
28
- sighash: event.sighash,
29
- topicCount: event.topicCount,
30
- eventName: event.name,
31
- contractName: contract.name,
32
- params: event.paramsMetadata
33
- });
25
+ onEventRegistrations.forEach(reg => {
26
+ let event = reg.eventConfig;
27
+ result.push({
28
+ sighash: event.sighash,
29
+ topicCount: event.topicCount,
30
+ eventName: event.name,
31
+ contractName: event.contractName,
32
+ params: event.paramsMetadata
34
33
  });
35
34
  });
36
35
  return result;
37
36
  }
38
37
 
39
- function makeSources(chain, contracts, hyperSync, rpcs, lowercaseAddresses) {
40
- let eventRouter = EventRouter.fromEvmEventModsOrThrow(contracts.flatMap(contract => contract.events), chain);
41
- let allEventParams = collectEventParams(contracts);
38
+ function makeSources(chain, onEventRegistrations, hyperSync, rpcs, lowercaseAddresses) {
39
+ let eventRouter = EventRouter.fromEvmEventModsOrThrow(onEventRegistrations, chain);
40
+ let allEventParams = collectEventParams(onEventRegistrations);
42
41
  let sources = hyperSync !== undefined ? [HyperSyncSource.make({
43
42
  chain: chain,
44
43
  endpointUrl: hyperSync,
@@ -0,0 +1,39 @@
1
+ // Selection-bitmask helpers shared by the per-chain field stores
2
+ // (`TransactionStore`, `BlockStore`). A field's bit index is its position in the
3
+ // ecosystem's ordered field-name array — the same code the Rust store uses.
4
+
5
+ // Field-name → bit-index map from an ordered field-name array.
6
+ let fieldCodes = (fields: array<string>): dict<int> => {
7
+ let codes = Dict.make()
8
+ fields->Array.forEachWithIndex((name, i) => codes->Dict.set(name, i))
9
+ codes
10
+ }
11
+
12
+ let pow2: int => float = %raw(`c => Math.pow(2, c)`)
13
+
14
+ // One event's selected fields as a bitmask float (bit `code` set ⇔ selected).
15
+ // Each field appears once, so summing `pow2(code)` sets distinct bits with no
16
+ // overlap; the result stays exact in f64 (codes span 0..31, so a mask is at most
17
+ // 2^32-1).
18
+ let maskFromFields = (selectedFields: Utils.Set.t<string>, ~codes: dict<int>): float => {
19
+ let mask = ref(0.)
20
+ selectedFields->Utils.Set.forEach(name =>
21
+ switch codes->Utils.Dict.dangerouslyGetNonOption(name) {
22
+ | Some(code) => mask := mask.contents +. pow2(code)
23
+ | None => ()
24
+ }
25
+ )
26
+ mask.contents
27
+ }
28
+
29
+ // Build an ecosystem's per-event mask function from its ordered field-name
30
+ // array. The field codes are derived once and closed over.
31
+ let makeMaskFn = (fields: array<string>): (Utils.Set.t<string> => float) => {
32
+ let codes = fieldCodes(fields)
33
+ selectedFields => selectedFields->maskFromFields(~codes)
34
+ }
35
+
36
+ // Bitwise OR of two per-event masks. Masks fit in 32 bits (≤32 fields), so
37
+ // `>>> 0` recovers the unsigned value that a plain `|` renders negative once bit
38
+ // 31 is set.
39
+ let orMask: (float, float) => float = %raw(`(a, b) => (a | b) >>> 0`)
@@ -0,0 +1,42 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ function fieldCodes(fields) {
5
+ let codes = {};
6
+ fields.forEach((name, i) => {
7
+ codes[name] = i;
8
+ });
9
+ return codes;
10
+ }
11
+
12
+ let pow2 = (c => Math.pow(2, c));
13
+
14
+ function maskFromFields(selectedFields, codes) {
15
+ let mask = {
16
+ contents: 0
17
+ };
18
+ selectedFields.forEach(name => {
19
+ let code = codes[name];
20
+ if (code !== undefined) {
21
+ mask.contents = mask.contents + pow2(code);
22
+ return;
23
+ }
24
+ });
25
+ return mask.contents;
26
+ }
27
+
28
+ function makeMaskFn(fields) {
29
+ let codes = fieldCodes(fields);
30
+ return selectedFields => maskFromFields(selectedFields, codes);
31
+ }
32
+
33
+ let orMask = ((a, b) => (a | b) >>> 0);
34
+
35
+ export {
36
+ fieldCodes,
37
+ pow2,
38
+ maskFromFields,
39
+ makeMaskFn,
40
+ orMask,
41
+ }
42
+ /* No side effect */
@@ -44,8 +44,8 @@ let make = (~logger: Pino.t): Ecosystem.t => {
44
44
  Logging.createChildFrom(
45
45
  ~logger,
46
46
  ~params={
47
- "contract": eventItem.eventConfig.contractName,
48
- "event": eventItem.eventConfig.name,
47
+ "contract": eventItem.onEventRegistration.eventConfig.contractName,
48
+ "event": eventItem.onEventRegistration.eventConfig.name,
49
49
  "chainId": eventItem.chain->ChainMap.Chain.toChainId,
50
50
  "block": eventItem.blockNumber,
51
51
  "logIndex": eventItem.logIndex,
@@ -54,11 +54,14 @@ let make = (~logger: Pino.t): Ecosystem.t => {
54
54
  ),
55
55
  toRawEvent: eventItem => {
56
56
  let payload = eventItem.payload->toPayload
57
+ let header = payload.block->(Utils.magic: Internal.eventBlock => {"id": string, "time": int})
57
58
  eventItem->RawEvent.make(
58
59
  ~block=payload.block,
59
60
  ~transaction=payload.transaction,
60
61
  ~params=payload.params,
61
62
  ~srcAddress=payload.srcAddress,
63
+ ~blockHash=header["id"],
64
+ ~blockTimestamp=header["time"],
62
65
  ~cleanUpRawEventFieldsInPlace,
63
66
  )
64
67
  },
@@ -23,8 +23,8 @@ function make(logger) {
23
23
  logger: logger,
24
24
  toEvent: eventItem => eventItem.payload,
25
25
  toEventLogger: eventItem => Logging.createChildFrom(logger, {
26
- contract: eventItem.eventConfig.contractName,
27
- event: eventItem.eventConfig.name,
26
+ contract: eventItem.onEventRegistration.eventConfig.contractName,
27
+ event: eventItem.onEventRegistration.eventConfig.name,
28
28
  chainId: eventItem.chain,
29
29
  block: eventItem.blockNumber,
30
30
  logIndex: eventItem.logIndex,
@@ -32,7 +32,8 @@ function make(logger) {
32
32
  }),
33
33
  toRawEvent: eventItem => {
34
34
  let payload = eventItem.payload;
35
- return RawEvent.make(eventItem, payload.block, payload.transaction, payload.params, payload.srcAddress, cleanUpRawEventFieldsInPlace);
35
+ let header = payload.block;
36
+ return RawEvent.make(eventItem, payload.block, payload.transaction, payload.params, payload.srcAddress, header.id, header.time, cleanUpRawEventFieldsInPlace);
36
37
  }
37
38
  };
38
39
  }
@@ -13,7 +13,7 @@ type selectionConfig = {
13
13
  getRecieptsSelection: (
14
14
  ~addressesByContractName: dict<array<Address.t>>,
15
15
  ) => array<HyperFuelClient.QueryTypes.receiptSelection>,
16
- eventRouter: EventRouter.t<Internal.fuelEventConfig>,
16
+ eventRouter: EventRouter.t<Internal.fuelOnEventRegistration>,
17
17
  }
18
18
 
19
19
  let logDataReceiptTypeSelection: array<FuelSDK.receiptType> = [LogData]
@@ -127,39 +127,40 @@ let getSelectionConfig = (selection: FetchState.selection, ~chain) => {
127
127
 
128
128
  let contractNames = Utils.Set.make()
129
129
 
130
- selection.eventConfigs
131
- ->(Utils.magic: array<Internal.eventConfig> => array<Internal.fuelEventConfig>)
132
- ->Array.forEach(eventConfig => {
130
+ selection.onEventRegistrations->Array.forEach(reg => {
131
+ let eventConfig =
132
+ reg.eventConfig->(Utils.magic: Internal.eventConfig => Internal.fuelEventConfig)
133
133
  let contractName = eventConfig.contractName
134
- if !eventConfig.isWildcard {
134
+ let isWildcard = reg.isWildcard
135
+ if !isWildcard {
135
136
  let _ = contractNames->Utils.Set.add(contractName)
136
137
  }
137
138
  eventRouter->EventRouter.addOrThrow(
138
139
  eventConfig.id,
139
- eventConfig,
140
+ reg,
140
141
  ~contractName,
141
142
  ~eventName=eventConfig.name,
142
143
  ~chain,
143
- ~isWildcard=eventConfig.isWildcard,
144
+ ~isWildcard,
144
145
  )
145
146
 
146
- switch eventConfig {
147
- | {kind: Mint, isWildcard: true} => addNonLogDataWildcardReceiptTypes(Mint)
148
- | {kind: Mint} => addNonLogDataReceiptType(contractName, Mint)
149
- | {kind: Burn, isWildcard: true} => addNonLogDataWildcardReceiptTypes(Burn)
150
- | {kind: Burn} => addNonLogDataReceiptType(contractName, Burn)
151
- | {kind: Transfer, isWildcard: true} => {
147
+ switch (eventConfig.kind, isWildcard) {
148
+ | (Mint, true) => addNonLogDataWildcardReceiptTypes(Mint)
149
+ | (Mint, false) => addNonLogDataReceiptType(contractName, Mint)
150
+ | (Burn, true) => addNonLogDataWildcardReceiptTypes(Burn)
151
+ | (Burn, false) => addNonLogDataReceiptType(contractName, Burn)
152
+ | (Transfer, true) => {
152
153
  addNonLogDataWildcardReceiptTypes(Transfer)
153
154
  addNonLogDataWildcardReceiptTypes(TransferOut)
154
155
  }
155
- | {kind: Transfer} => {
156
+ | (Transfer, false) => {
156
157
  addNonLogDataReceiptType(contractName, Transfer)
157
158
  addNonLogDataReceiptType(contractName, TransferOut)
158
159
  }
159
- | {kind: Call, isWildcard: true} => addNonLogDataWildcardReceiptTypes(Call)
160
- | {kind: Call} =>
160
+ | (Call, true) => addNonLogDataWildcardReceiptTypes(Call)
161
+ | (Call, false) =>
161
162
  JsError.throwWithMessage("Call receipt indexing currently supported only in wildcard mode")
162
- | {kind: LogData({logId}), isWildcard} => {
163
+ | (LogData({logId}), _) => {
163
164
  let rb = logId->BigInt.fromStringOrThrow
164
165
  if isWildcard {
165
166
  wildcardLogDataRbs->Array.push(rb)->ignore
@@ -251,11 +252,6 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
251
252
  let startFetchingBatchTimeRef = Performance.now()
252
253
 
253
254
  //fetch batch
254
- Prometheus.SourceRequestCount.increment(
255
- ~sourceName=name,
256
- ~chainId=chain->ChainMap.Chain.toChainId,
257
- ~method="getLogs",
258
- )
259
255
  let pageUnsafe = try await HyperFuel.GetLogs.query(
260
256
  ~client,
261
257
  ~fromBlock,
@@ -307,6 +303,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
307
303
  }
308
304
 
309
305
  let pageFetchTime = startFetchingBatchTimeRef->Performance.secondsSince
306
+ let requestStats = [{Source.method: "getLogs", seconds: pageFetchTime}]
310
307
 
311
308
  //set height and next from block
312
309
  let knownHeight = pageUnsafe.archiveHeight
@@ -331,7 +328,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
331
328
  | Call(_) => callEventTag
332
329
  }
333
330
 
334
- let eventConfig = switch selectionConfig.eventRouter->EventRouter.get(
331
+ let onEventRegistration = switch selectionConfig.eventRouter->EventRouter.get(
335
332
  ~tag=eventId,
336
333
  ~contractNameByAddress,
337
334
  ~contractAddress,
@@ -352,9 +349,14 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
352
349
  ~logger,
353
350
  )
354
351
  }
355
- | Some(eventConfig) => eventConfig
352
+ | Some(onEventRegistration) => onEventRegistration
356
353
  }
357
354
 
355
+ let eventConfig =
356
+ onEventRegistration.eventConfig->(
357
+ Utils.magic: Internal.eventConfig => Internal.fuelEventConfig
358
+ )
359
+
358
360
  let params = switch (eventConfig, receipt) {
359
361
  | ({kind: LogData({decode})}, LogData({data})) =>
360
362
  try decode(data) catch {
@@ -408,11 +410,9 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
408
410
  }
409
411
 
410
412
  Internal.Event({
411
- eventConfig: (eventConfig :> Internal.eventConfig),
412
- timestamp: block.time,
413
+ onEventRegistration: (onEventRegistration :> Internal.onEventRegistration),
413
414
  chain,
414
415
  blockNumber: block.height,
415
- blockHash: block.id,
416
416
  logIndex: receiptIndex,
417
417
  // Fuel carries the transaction inline on the payload; the store key is
418
418
  // unused (Fuel identifies transactions by hash, kept on the payload).
@@ -459,13 +459,15 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
459
459
  {
460
460
  latestFetchedBlockTimestamp,
461
461
  parsedQueueItems,
462
- // Fuel keeps transaction on the payload; no store page.
462
+ // Fuel keeps transaction and block on the payload; no store pages.
463
463
  transactionStore: None,
464
+ blockStore: None,
464
465
  latestFetchedBlockNumber: heighestBlockQueried,
465
466
  stats,
466
467
  knownHeight,
467
468
  blockHashes,
468
469
  fromBlockQueried: fromBlock,
470
+ requestStats,
469
471
  }
470
472
  }
471
473
 
@@ -493,18 +495,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
493
495
  }
494
496
  }
495
497
  let seconds = timerRef->Performance.secondsSince
496
- Prometheus.SourceRequestCount.increment(
497
- ~sourceName=name,
498
- ~chainId=chain->ChainMap.Chain.toChainId,
499
- ~method="getHeight",
500
- )
501
- Prometheus.SourceRequestCount.addSeconds(
502
- ~sourceName=name,
503
- ~chainId=chain->ChainMap.Chain.toChainId,
504
- ~method="getHeight",
505
- ~seconds,
506
- )
507
- height
498
+ {height, requestStats: [{method: "getHeight", seconds}]}
508
499
  },
509
500
  getItemsOrThrow,
510
501
  }