envio 3.3.0-alpha.3 → 3.3.0-alpha.5

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 (53) hide show
  1. package/evm.schema.json +10 -0
  2. package/package.json +7 -7
  3. package/src/Batch.res.mjs +1 -1
  4. package/src/Bin.res +3 -0
  5. package/src/Bin.res.mjs +4 -0
  6. package/src/ChainFetching.res +1 -3
  7. package/src/ChainFetching.res.mjs +3 -3
  8. package/src/ChainState.res +44 -19
  9. package/src/ChainState.res.mjs +25 -23
  10. package/src/ChainState.resi +3 -3
  11. package/src/Config.res +3 -0
  12. package/src/Config.res.mjs +3 -1
  13. package/src/Core.res +0 -3
  14. package/src/Ecosystem.res +0 -4
  15. package/src/EventConfigBuilder.res +3 -0
  16. package/src/EventConfigBuilder.res.mjs +7 -1
  17. package/src/FetchState.res +73 -160
  18. package/src/FetchState.res.mjs +120 -222
  19. package/src/IndexingAddresses.res +105 -0
  20. package/src/IndexingAddresses.res.mjs +100 -0
  21. package/src/IndexingAddresses.resi +32 -0
  22. package/src/Internal.res +5 -0
  23. package/src/Main.res +21 -24
  24. package/src/Main.res.mjs +21 -20
  25. package/src/Metrics.res +33 -0
  26. package/src/Metrics.res.mjs +39 -0
  27. package/src/Prometheus.res +2 -20
  28. package/src/Prometheus.res.mjs +83 -95
  29. package/src/SimulateItems.res +4 -0
  30. package/src/TestIndexer.res +43 -17
  31. package/src/TestIndexer.res.mjs +16 -9
  32. package/src/bindings/Viem.res +0 -41
  33. package/src/bindings/Viem.res.mjs +1 -43
  34. package/src/sources/Evm.res +17 -39
  35. package/src/sources/Evm.res.mjs +8 -40
  36. package/src/sources/EvmChain.res +3 -1
  37. package/src/sources/EvmChain.res.mjs +2 -1
  38. package/src/sources/EvmRpcClient.res +36 -5
  39. package/src/sources/EvmRpcClient.res.mjs +7 -4
  40. package/src/sources/Fuel.res +0 -2
  41. package/src/sources/Fuel.res.mjs +0 -1
  42. package/src/sources/HyperSyncClient.res +0 -35
  43. package/src/sources/HyperSyncClient.res.mjs +1 -8
  44. package/src/sources/Rpc.res +15 -47
  45. package/src/sources/Rpc.res.mjs +25 -56
  46. package/src/sources/RpcSource.res +30 -73
  47. package/src/sources/RpcSource.res.mjs +24 -73
  48. package/src/sources/SourceManager.res +1 -1
  49. package/src/sources/SourceManager.res.mjs +1 -1
  50. package/src/sources/Svm.res +10 -17
  51. package/src/sources/Svm.res.mjs +6 -18
  52. package/src/sources/TransactionStore.res +98 -76
  53. package/src/sources/TransactionStore.res.mjs +49 -35
package/evm.schema.json CHANGED
@@ -548,6 +548,16 @@
548
548
  "null"
549
549
  ]
550
550
  },
551
+ "headers": {
552
+ "description": "Optional HTTP headers sent with every request to this RPC endpoint, e.g. an Authorization bearer token for gated endpoints. Values support ${ENV_VAR} interpolation.",
553
+ "type": [
554
+ "object",
555
+ "null"
556
+ ],
557
+ "additionalProperties": {
558
+ "type": "string"
559
+ }
560
+ },
551
561
  "initial_block_interval": {
552
562
  "description": "The starting interval in range of blocks per query",
553
563
  "type": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "3.3.0-alpha.3",
3
+ "version": "3.3.0-alpha.5",
4
4
  "type": "module",
5
5
  "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
6
6
  "bin": "./bin.mjs",
@@ -57,7 +57,7 @@
57
57
  "yargs": "17.7.2",
58
58
  "@rescript/runtime": "12.2.0",
59
59
  "rescript-schema": "9.5.1",
60
- "viem": "2.46.2",
60
+ "viem": "2.54.0",
61
61
  "dotenv": "16.4.5",
62
62
  "date-fns": "3.3.1",
63
63
  "@rescript/react": "0.14.1",
@@ -69,10 +69,10 @@
69
69
  "tsx": "4.21.0"
70
70
  },
71
71
  "optionalDependencies": {
72
- "envio-linux-x64": "3.3.0-alpha.3",
73
- "envio-linux-x64-musl": "3.3.0-alpha.3",
74
- "envio-linux-arm64": "3.3.0-alpha.3",
75
- "envio-darwin-x64": "3.3.0-alpha.3",
76
- "envio-darwin-arm64": "3.3.0-alpha.3"
72
+ "envio-linux-x64": "3.3.0-alpha.5",
73
+ "envio-linux-x64-musl": "3.3.0-alpha.5",
74
+ "envio-linux-arm64": "3.3.0-alpha.5",
75
+ "envio-darwin-x64": "3.3.0-alpha.5",
76
+ "envio-darwin-arm64": "3.3.0-alpha.5"
77
77
  }
78
78
  }
package/src/Batch.res.mjs CHANGED
@@ -27,7 +27,7 @@ function getProgressedChainsById(chainsBeforeBatch, batchSizePerChain, progressB
27
27
  let progressedChain;
28
28
  if (batchSize !== undefined) {
29
29
  let leftItems = fetchState.buffer.slice(batchSize);
30
- progressedChain = getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAfterBatch, FetchState.updateInternal(fetchState, undefined, undefined, leftItems, undefined, undefined), batchSize);
30
+ progressedChain = getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAfterBatch, FetchState.updateInternal(fetchState, undefined, leftItems, undefined, undefined), batchSize);
31
31
  } else {
32
32
  progressedChain = getChainAfterBatchIfProgressed(chainBeforeBatch, progressBlockNumberAfterBatch, chainBeforeBatch.fetchState, 0);
33
33
  }
package/src/Bin.res CHANGED
@@ -71,6 +71,9 @@ let run = async args => {
71
71
  }
72
72
  }
73
73
  } catch {
74
+ | Main.FatalError(_) =>
75
+ // Already logged with full context by Main.start's onError; just exit.
76
+ NodeJs.process->NodeJs.exitWithCode(Failure)
74
77
  | exn =>
75
78
  // Log just the exception's own message — wrapping it in "Failed at
76
79
  // initialization" and pino's err serializer buries the real cause under
package/src/Bin.res.mjs CHANGED
@@ -79,6 +79,10 @@ async function run(args) {
79
79
  }
80
80
  } catch (raw_exn) {
81
81
  let exn = Primitive_exceptions.internalToException(raw_exn);
82
+ if (exn.RE_EXN_ID === Main.FatalError) {
83
+ Process.exit(1);
84
+ return;
85
+ }
82
86
  let e = Primitive_exceptions.internalToException(exn);
83
87
  let message = e.RE_EXN_ID === "JsExn" ? Stdlib_Option.getOr(Stdlib_JsExn.message(e._1), "Failed at initialization") : "Failed at initialization";
84
88
  Logging.error(message);
@@ -11,13 +11,12 @@ type partitionQueryResponse = {
11
11
  let runContractRegistersOrThrow = async (
12
12
  ~itemsWithContractRegister: array<Internal.item>,
13
13
  ~config: Config.t,
14
- ~chainState: ChainState.t,
15
14
  ~page: option<TransactionStore.t>,
16
15
  ) => {
17
16
  // contractRegister handlers can read event.transaction, so materialise the
18
17
  // selected fields onto the payloads before running them. All items belong to
19
18
  // the chain being fetched, hence its single page store and mask.
20
- await chainState->ChainState.materializePageItems(~items=itemsWithContractRegister, ~page)
19
+ await ChainState.materializePageItems(~items=itemsWithContractRegister, ~page)
21
20
 
22
21
  let itemsWithDcs = []
23
22
 
@@ -233,7 +232,6 @@ let rec onQueryResponse = async (
233
232
  switch await runContractRegistersOrThrow(
234
233
  ~itemsWithContractRegister,
235
234
  ~config=state->IndexerState.config,
236
- ~chainState,
237
235
  ~page=transactionStore,
238
236
  ) {
239
237
  | exception exn => IndexerState.errorExit(state, exn->ErrorHandling.make)
@@ -16,8 +16,8 @@ import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
16
16
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
17
17
  import * as ContractRegisterContext from "./ContractRegisterContext.res.mjs";
18
18
 
19
- async function runContractRegistersOrThrow(itemsWithContractRegister, config, chainState, page) {
20
- await ChainState.materializePageItems(chainState, itemsWithContractRegister, page);
19
+ async function runContractRegistersOrThrow(itemsWithContractRegister, config, page) {
20
+ await ChainState.materializePageItems(itemsWithContractRegister, page);
21
21
  let itemsWithDcs = [];
22
22
  let onRegister = (item, contractAddress, contractName) => {
23
23
  let dc_registrationBlock = item.blockNumber;
@@ -145,7 +145,7 @@ async function onQueryResponse(state, param, stateId, scheduleFetch, schedulePro
145
145
  }
146
146
  let newItemsWithDcs;
147
147
  try {
148
- newItemsWithDcs = await runContractRegistersOrThrow(itemsWithContractRegister, IndexerState.config(state), chainState, transactionStore);
148
+ newItemsWithDcs = await runContractRegistersOrThrow(itemsWithContractRegister, IndexerState.config(state), transactionStore);
149
149
  } catch (raw_exn) {
150
150
  let exn = Primitive_exceptions.internalToException(raw_exn);
151
151
  return IndexerState.errorExit(state, ErrorHandling.make(exn, undefined, undefined));
@@ -5,6 +5,9 @@
5
5
  type t = {
6
6
  logger: Pino.t,
7
7
  mutable fetchState: FetchState.t,
8
+ // The chain-wide address index. Not `mutable`: the dict is mutated in place by
9
+ // register/rollback, so the reference is stable across fetchState versions.
10
+ indexingAddresses: IndexingAddresses.t,
8
11
  sourceManager: SourceManager.t,
9
12
  chainConfig: Config.chain,
10
13
  mutable isProgressAtHead: bool,
@@ -21,8 +24,6 @@ type t = {
21
24
  // transactionIndex). Fetch responses merge their page in; entries are pruned
22
25
  // as the chain progresses and dropped above the target on rollback.
23
26
  transactionStore: TransactionStore.t,
24
- // Bitmask of the transaction fields the store materialises at batch prep.
25
- transactionFieldMask: float,
26
27
  }
27
28
 
28
29
  // Per-chain shape returned by the status API.
@@ -60,6 +61,7 @@ let configAddresses = (chainConfig: Config.chain): array<Internal.indexingAddres
60
61
  let make = (
61
62
  ~chainConfig: Config.chain,
62
63
  ~fetchState: FetchState.t,
64
+ ~indexingAddresses: IndexingAddresses.t,
63
65
  ~sourceManager: SourceManager.t,
64
66
  ~reorgDetection: ReorgDetection.t,
65
67
  ~committedProgressBlockNumber: int,
@@ -67,11 +69,12 @@ let make = (
67
69
  ~numEventsProcessed=0.,
68
70
  ~timestampCaughtUpToHeadOrEndblock=None,
69
71
  ~isProgressAtHead=false,
70
- ~transactionFieldMask=0.,
72
+ ~transactionStore=TransactionStore.make(~ecosystem=Ecosystem.Evm, ~shouldChecksum=false),
71
73
  ~logger: Pino.t,
72
74
  ): t => {
73
75
  logger,
74
76
  fetchState,
77
+ indexingAddresses,
75
78
  sourceManager,
76
79
  chainConfig,
77
80
  isProgressAtHead,
@@ -81,8 +84,7 @@ let make = (
81
84
  pendingBudget: 0.,
82
85
  reorgDetection,
83
86
  safeCheckpointTracking,
84
- transactionStore: TransactionStore.make(),
85
- transactionFieldMask,
87
+ transactionStore,
86
88
  }
87
89
 
88
90
  let makeInternal = (
@@ -220,8 +222,12 @@ let makeInternal = (
220
222
  | None => ()
221
223
  }
222
224
 
225
+ let contractConfigs = IndexingAddresses.makeContractConfigs(~eventConfigs)
226
+ let indexingAddressIndex = IndexingAddresses.make(~contractConfigs, ~addresses=indexingAddresses)
227
+
223
228
  let fetchState = FetchState.make(
224
229
  ~maxAddrInPartition=config.maxAddrInPartition,
230
+ ~contractConfigs,
225
231
  ~addresses=indexingAddresses,
226
232
  ~progressBlockNumber,
227
233
  ~startBlock,
@@ -265,11 +271,13 @@ let makeInternal = (
265
271
  let evmRpcs: array<EvmChain.rpc> = rpcs->Array.map((rpc): EvmChain.rpc => {
266
272
  let syncConfig = rpc.syncConfig
267
273
  let ws = rpc.ws
274
+ let headers = rpc.headers
268
275
  {
269
276
  url: rpc.url,
270
277
  sourceFor: rpc.sourceFor,
271
278
  ?syncConfig,
272
279
  ?ws,
280
+ ?headers,
273
281
  }
274
282
  })
275
283
  EvmChain.makeSources(
@@ -314,6 +322,7 @@ let makeInternal = (
314
322
  make(
315
323
  ~chainConfig,
316
324
  ~fetchState,
325
+ ~indexingAddresses=indexingAddressIndex,
317
326
  ~sourceManager=SourceManager.make(~sources, ~isRealtime, ~reducedPollingInterval?),
318
327
  ~reorgDetection=ReorgDetection.make(
319
328
  ~chainReorgCheckpoints,
@@ -328,7 +337,10 @@ let makeInternal = (
328
337
  ~committedProgressBlockNumber=progressBlockNumber,
329
338
  ~timestampCaughtUpToHeadOrEndblock,
330
339
  ~numEventsProcessed,
331
- ~transactionFieldMask=config.ecosystem.transactionFieldMask(eventConfigs),
340
+ ~transactionStore=TransactionStore.make(
341
+ ~ecosystem=config.ecosystem.name,
342
+ ~shouldChecksum=!lowercaseAddresses,
343
+ ),
332
344
  ~logger,
333
345
  )
334
346
  }
@@ -418,7 +430,8 @@ let timestampCaughtUpToHeadOrEndblock = (cs: t) => cs.timestampCaughtUpToHeadOrE
418
430
  // Fetch-frontier reads. The FetchState is owned here; callers go through these
419
431
  // rather than reaching into it.
420
432
  let knownHeight = (cs: t) => cs.fetchState.knownHeight
421
- let indexingAddresses = (cs: t) => cs.fetchState.indexingAddresses
433
+ let contractAddresses = (cs: t, ~contractName) =>
434
+ cs.indexingAddresses->IndexingAddresses.getContractAddresses(~contractName)
422
435
  let bufferSize = (cs: t) => cs.fetchState->FetchState.bufferSize
423
436
  let bufferReadyCount = (cs: t) => cs.fetchState->FetchState.bufferReadyCount
424
437
  let getProgressPercentage = (cs: t) => cs.fetchState->FetchState.getProgressPercentage
@@ -503,18 +516,14 @@ let isAtHeadWithoutEndBlock = (cs: t) =>
503
516
  // Materialise the chain store's selected transaction fields onto a batch's
504
517
  // items at batch prep (the persistent-store path).
505
518
  let materializeBatchItems = (cs: t, ~items: array<Internal.item>) =>
506
- cs.transactionStore->TransactionStore.materializeItems(~items, ~mask=cs.transactionFieldMask)
519
+ cs.transactionStore->TransactionStore.materializeItems(~items)
507
520
 
508
521
  // Materialise a fetch-response page's transactions onto its items before
509
522
  // contract-register handlers read them. `None` pages (RPC/Fuel/Simulate keep the
510
523
  // transaction inline) are a no-op.
511
- let materializePageItems = (
512
- cs: t,
513
- ~items: array<Internal.item>,
514
- ~page: option<TransactionStore.t>,
515
- ) =>
524
+ let materializePageItems = (~items: array<Internal.item>, ~page: option<TransactionStore.t>) =>
516
525
  switch page {
517
- | Some(store) => store->TransactionStore.materializeItems(~items, ~mask=cs.transactionFieldMask)
526
+ | Some(store) => store->TransactionStore.materializeItems(~items)
518
527
  | None => Promise.resolve()
519
528
  }
520
529
 
@@ -536,12 +545,21 @@ let handleQueryResult = (
536
545
 
537
546
  let fs = switch newItemsWithDcs {
538
547
  | [] => cs.fetchState
539
- | _ => cs.fetchState->FetchState.registerDynamicContracts(newItemsWithDcs)
548
+ | _ =>
549
+ cs.fetchState->FetchState.registerDynamicContracts(
550
+ ~indexingAddresses=cs.indexingAddresses,
551
+ newItemsWithDcs,
552
+ )
540
553
  }
541
554
 
542
555
  cs.fetchState =
543
556
  fs
544
- ->FetchState.handleQueryResult(~query, ~latestFetchedBlock, ~newItems)
557
+ ->FetchState.handleQueryResult(
558
+ ~indexingAddresses=cs.indexingAddresses,
559
+ ~query,
560
+ ~latestFetchedBlock,
561
+ ~newItems,
562
+ )
545
563
  ->FetchState.updateKnownHeight(~knownHeight)
546
564
 
547
565
  // The query is no longer in flight, so release its reservation.
@@ -611,7 +629,7 @@ let toChainData = (cs: t): chainData => {
611
629
  numBatchesFetched: 0,
612
630
  startBlock: cs.fetchState.startBlock,
613
631
  endBlock: cs.fetchState.endBlock,
614
- numAddresses: cs.fetchState->FetchState.numAddresses,
632
+ numAddresses: cs.indexingAddresses->IndexingAddresses.size,
615
633
  }
616
634
 
617
635
  // Snapshot the inputs a batch build needs from this chain.
@@ -770,7 +788,11 @@ let rollback = (
770
788
  )
771
789
  | None => ()
772
790
  }
773
- cs.fetchState = cs.fetchState->FetchState.rollback(~targetBlockNumber=newProgressBlockNumber)
791
+ cs.fetchState =
792
+ cs.fetchState->FetchState.rollback(
793
+ ~indexingAddresses=cs.indexingAddresses,
794
+ ~targetBlockNumber=newProgressBlockNumber,
795
+ )
774
796
  cs.transactionStore->TransactionStore.rollback(newProgressBlockNumber)
775
797
  cs.committedProgressBlockNumber = newProgressBlockNumber
776
798
  cs.numEventsProcessed = newTotalEventsProcessed
@@ -781,7 +803,10 @@ let rollback = (
781
803
  ~blockNumber=rollbackTargetBlockNumber,
782
804
  )
783
805
  cs.fetchState =
784
- cs.fetchState->FetchState.rollback(~targetBlockNumber=rollbackTargetBlockNumber)
806
+ cs.fetchState->FetchState.rollback(
807
+ ~indexingAddresses=cs.indexingAddresses,
808
+ ~targetBlockNumber=rollbackTargetBlockNumber,
809
+ )
785
810
  cs.transactionStore->TransactionStore.rollback(rollbackTargetBlockNumber)
786
811
  cs.committedProgressBlockNumber = Pervasives.min(
787
812
  cs.committedProgressBlockNumber,
@@ -21,6 +21,7 @@ import * as HyperFuelSource from "./sources/HyperFuelSource.res.mjs";
21
21
  import * as Primitive_float from "@rescript/runtime/lib/es6/Primitive_float.js";
22
22
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
23
23
  import * as TransactionStore from "./sources/TransactionStore.res.mjs";
24
+ import * as IndexingAddresses from "./IndexingAddresses.res.mjs";
24
25
  import * as SvmHyperSyncSource from "./sources/SvmHyperSyncSource.res.mjs";
25
26
  import * as SafeCheckpointTracking from "./SafeCheckpointTracking.res.mjs";
26
27
 
@@ -38,15 +39,16 @@ function configAddresses(chainConfig) {
38
39
  return addresses;
39
40
  }
40
41
 
41
- function make(chainConfig, fetchState, sourceManager, reorgDetection, committedProgressBlockNumber, safeCheckpointTrackingOpt, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt, transactionFieldMaskOpt, logger) {
42
+ function make(chainConfig, fetchState, indexingAddresses, sourceManager, reorgDetection, committedProgressBlockNumber, safeCheckpointTrackingOpt, numEventsProcessedOpt, timestampCaughtUpToHeadOrEndblockOpt, isProgressAtHeadOpt, transactionStoreOpt, logger) {
42
43
  let safeCheckpointTracking = safeCheckpointTrackingOpt !== undefined ? Primitive_option.valFromOption(safeCheckpointTrackingOpt) : undefined;
43
44
  let numEventsProcessed = numEventsProcessedOpt !== undefined ? numEventsProcessedOpt : 0;
44
45
  let timestampCaughtUpToHeadOrEndblock = timestampCaughtUpToHeadOrEndblockOpt !== undefined ? Primitive_option.valFromOption(timestampCaughtUpToHeadOrEndblockOpt) : undefined;
45
46
  let isProgressAtHead = isProgressAtHeadOpt !== undefined ? isProgressAtHeadOpt : false;
46
- let transactionFieldMask = transactionFieldMaskOpt !== undefined ? transactionFieldMaskOpt : 0;
47
+ let transactionStore = transactionStoreOpt !== undefined ? Primitive_option.valFromOption(transactionStoreOpt) : TransactionStore.make("evm", false);
47
48
  return {
48
49
  logger: logger,
49
50
  fetchState: fetchState,
51
+ indexingAddresses: indexingAddresses,
50
52
  sourceManager: sourceManager,
51
53
  chainConfig: chainConfig,
52
54
  isProgressAtHead: isProgressAtHead,
@@ -56,8 +58,7 @@ function make(chainConfig, fetchState, sourceManager, reorgDetection, committedP
56
58
  pendingBudget: 0,
57
59
  reorgDetection: reorgDetection,
58
60
  safeCheckpointTracking: safeCheckpointTracking,
59
- transactionStore: TransactionStore.make(),
60
- transactionFieldMask: transactionFieldMask
61
+ transactionStore: transactionStore
61
62
  };
62
63
  }
63
64
 
@@ -120,7 +121,9 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
120
121
  }
121
122
  });
122
123
  }
123
- let fetchState = FetchState.make(startBlock, endBlock, eventConfigs, indexingAddresses, config.maxAddrInPartition, chainConfig.id, (config.batchSize << 1), knownHeight, progressBlockNumber, onBlockConfigs, Primitive_int.max(!config.shouldRollbackOnReorg || isInReorgThreshold ? 0 : chainConfig.maxReorgDepth, chainConfig.blockLag), Primitive_option.some(firstEventBlock));
124
+ let contractConfigs = IndexingAddresses.makeContractConfigs(eventConfigs);
125
+ let indexingAddressIndex = IndexingAddresses.make(contractConfigs, indexingAddresses);
126
+ let fetchState = FetchState.make(startBlock, endBlock, eventConfigs, contractConfigs, indexingAddresses, config.maxAddrInPartition, chainConfig.id, (config.batchSize << 1), knownHeight, progressBlockNumber, onBlockConfigs, Primitive_int.max(!config.shouldRollbackOnReorg || isInReorgThreshold ? 0 : chainConfig.maxReorgDepth, chainConfig.blockLag), Primitive_option.some(firstEventBlock));
124
127
  let chainReorgCheckpoints = Stdlib_Array.filterMap(reorgCheckpoints, reorgCheckpoint => {
125
128
  if (reorgCheckpoint.chain_id === chainConfig.id) {
126
129
  return reorgCheckpoint;
@@ -140,11 +143,13 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
140
143
  let evmRpcs = sources.rpcs.map(rpc => {
141
144
  let syncConfig = rpc.syncConfig;
142
145
  let ws = rpc.ws;
146
+ let headers = rpc.headers;
143
147
  return {
144
148
  url: rpc.url,
145
149
  sourceFor: rpc.sourceFor,
146
150
  syncConfig: syncConfig,
147
- ws: ws
151
+ ws: ws,
152
+ headers: headers
148
153
  };
149
154
  });
150
155
  sources$1 = EvmChain.makeSources(chain, evmContracts, sources.hypersync, evmRpcs, lowercaseAddresses);
@@ -176,7 +181,7 @@ function makeInternal(chainConfig, indexingAddresses, startBlock, endBlock, firs
176
181
  sources$1 = sources._0;
177
182
  break;
178
183
  }
179
- return make(chainConfig, fetchState, SourceManager.make(sources$1, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined), ReorgDetection.make(chainReorgCheckpoints, maxReorgDepth, config.shouldRollbackOnReorg), progressBlockNumber, Primitive_option.some(SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)), numEventsProcessed, Primitive_option.some(timestampCaughtUpToHeadOrEndblock), undefined, config.ecosystem.transactionFieldMask(eventConfigs), logger);
184
+ return make(chainConfig, fetchState, indexingAddressIndex, SourceManager.make(sources$1, isRealtime, undefined, undefined, undefined, reducedPollingInterval, undefined, undefined), ReorgDetection.make(chainReorgCheckpoints, maxReorgDepth, config.shouldRollbackOnReorg), progressBlockNumber, Primitive_option.some(SafeCheckpointTracking.make(maxReorgDepth, config.shouldRollbackOnReorg, chainReorgCheckpoints)), numEventsProcessed, Primitive_option.some(timestampCaughtUpToHeadOrEndblock), undefined, Primitive_option.some(TransactionStore.make(config.ecosystem.name, !lowercaseAddresses)), logger);
180
185
  }
181
186
 
182
187
  function makeFromConfig(chainConfig, config, registrations, knownHeight) {
@@ -240,8 +245,8 @@ function knownHeight(cs) {
240
245
  return cs.fetchState.knownHeight;
241
246
  }
242
247
 
243
- function indexingAddresses(cs) {
244
- return cs.fetchState.indexingAddresses;
248
+ function contractAddresses(cs, contractName) {
249
+ return IndexingAddresses.getContractAddresses(cs.indexingAddresses, contractName);
245
250
  }
246
251
 
247
252
  function bufferSize(cs) {
@@ -326,12 +331,12 @@ function isAtHeadWithoutEndBlock(cs) {
326
331
  }
327
332
 
328
333
  function materializeBatchItems(cs, items) {
329
- return TransactionStore.materializeItems(cs.transactionStore, items, cs.transactionFieldMask);
334
+ return TransactionStore.materializeItems(cs.transactionStore, items);
330
335
  }
331
336
 
332
- function materializePageItems(cs, items, page) {
337
+ function materializePageItems(items, page) {
333
338
  if (page !== undefined) {
334
- return TransactionStore.materializeItems(Primitive_option.valFromOption(page), items, cs.transactionFieldMask);
339
+ return TransactionStore.materializeItems(Primitive_option.valFromOption(page), items);
335
340
  } else {
336
341
  return Promise.resolve();
337
342
  }
@@ -341,8 +346,8 @@ function handleQueryResult(cs, query, newItems, newItemsWithDcs, latestFetchedBl
341
346
  if (page !== undefined) {
342
347
  cs.transactionStore.merge(Primitive_option.valFromOption(page));
343
348
  }
344
- let fs = newItemsWithDcs.length !== 0 ? FetchState.registerDynamicContracts(cs.fetchState, newItemsWithDcs) : cs.fetchState;
345
- cs.fetchState = FetchState.updateKnownHeight(FetchState.handleQueryResult(fs, query, latestFetchedBlock, newItems), knownHeight);
349
+ let fs = newItemsWithDcs.length !== 0 ? FetchState.registerDynamicContracts(cs.fetchState, cs.indexingAddresses, newItemsWithDcs) : cs.fetchState;
350
+ cs.fetchState = FetchState.updateKnownHeight(FetchState.handleQueryResult(fs, cs.indexingAddresses, query, latestFetchedBlock, newItems), knownHeight);
346
351
  cs.pendingBudget = Primitive_float.max(0, cs.pendingBudget - query.estResponseSize);
347
352
  }
348
353
 
@@ -376,7 +381,6 @@ function setEndBlockToFirstEvent(cs, blockNumber) {
376
381
  startBlock: init.startBlock,
377
382
  endBlock: blockNumber,
378
383
  normalSelection: init.normalSelection,
379
- indexingAddresses: init.indexingAddresses,
380
384
  contractConfigs: init.contractConfigs,
381
385
  chainId: init.chainId,
382
386
  latestOnBlockBlockNumber: init.latestOnBlockBlockNumber,
@@ -395,7 +399,6 @@ function setEndBlockToFirstEvent(cs, blockNumber) {
395
399
  startBlock: init$1.startBlock,
396
400
  endBlock: blockNumber,
397
401
  normalSelection: init$1.normalSelection,
398
- indexingAddresses: init$1.indexingAddresses,
399
402
  contractConfigs: init$1.contractConfigs,
400
403
  chainId: init$1.chainId,
401
404
  latestOnBlockBlockNumber: init$1.latestOnBlockBlockNumber,
@@ -409,7 +412,7 @@ function setEndBlockToFirstEvent(cs, blockNumber) {
409
412
  }
410
413
 
411
414
  function enterReorgThreshold(cs) {
412
- cs.fetchState = FetchState.updateInternal(cs.fetchState, undefined, undefined, undefined, cs.chainConfig.blockLag, undefined);
415
+ cs.fetchState = FetchState.updateInternal(cs.fetchState, undefined, undefined, cs.chainConfig.blockLag, undefined);
413
416
  }
414
417
 
415
418
  function toChainMetadata(cs) {
@@ -434,7 +437,7 @@ function toChainData(cs) {
434
437
  numBatchesFetched: 0,
435
438
  startBlock: cs.fetchState.startBlock,
436
439
  endBlock: cs.fetchState.endBlock,
437
- numAddresses: FetchState.numAddresses(cs.fetchState)
440
+ numAddresses: IndexingAddresses.size(cs.indexingAddresses)
438
441
  };
439
442
  }
440
443
 
@@ -457,7 +460,7 @@ function isReadyToEnterReorgThresholdAfterBatch(cs, batch) {
457
460
  function advanceAfterBatch(cs, batch, enteringReorgThreshold) {
458
461
  let chainAfterBatch = batch.progressedChainsById[cs.fetchState.chainId];
459
462
  if (chainAfterBatch !== undefined) {
460
- cs.fetchState = enteringReorgThreshold ? FetchState.updateInternal(chainAfterBatch.fetchState, undefined, undefined, undefined, cs.chainConfig.blockLag, undefined) : chainAfterBatch.fetchState;
463
+ cs.fetchState = enteringReorgThreshold ? FetchState.updateInternal(chainAfterBatch.fetchState, undefined, undefined, cs.chainConfig.blockLag, undefined) : chainAfterBatch.fetchState;
461
464
  return;
462
465
  }
463
466
  }
@@ -489,7 +492,6 @@ function applyBatchProgress(cs, batch) {
489
492
  startBlock: init.startBlock,
490
493
  endBlock: init.endBlock,
491
494
  normalSelection: init.normalSelection,
492
- indexingAddresses: init.indexingAddresses,
493
495
  contractConfigs: init.contractConfigs,
494
496
  chainId: init.chainId,
495
497
  latestOnBlockBlockNumber: init.latestOnBlockBlockNumber,
@@ -525,7 +527,7 @@ function rollback(cs, newProgressBlockNumber, eventsProcessedDiff, rollbackTarge
525
527
  if (newProgressBlockNumber === undefined) {
526
528
  if (isReorgChain) {
527
529
  cs.reorgDetection = ReorgDetection.rollbackToValidBlockNumber(cs.reorgDetection, rollbackTargetBlockNumber);
528
- cs.fetchState = FetchState.rollback(cs.fetchState, rollbackTargetBlockNumber);
530
+ cs.fetchState = FetchState.rollback(cs.fetchState, cs.indexingAddresses, rollbackTargetBlockNumber);
529
531
  cs.transactionStore.rollback(rollbackTargetBlockNumber);
530
532
  cs.committedProgressBlockNumber = Primitive_int.min(cs.committedProgressBlockNumber, rollbackTargetBlockNumber);
531
533
  return;
@@ -547,7 +549,7 @@ function rollback(cs, newProgressBlockNumber, eventsProcessedDiff, rollbackTarge
547
549
  if (safeCheckpointTracking !== undefined) {
548
550
  cs.safeCheckpointTracking = SafeCheckpointTracking.rollback(safeCheckpointTracking, newProgressBlockNumber);
549
551
  }
550
- cs.fetchState = FetchState.rollback(cs.fetchState, newProgressBlockNumber);
552
+ cs.fetchState = FetchState.rollback(cs.fetchState, cs.indexingAddresses, newProgressBlockNumber);
551
553
  cs.transactionStore.rollback(newProgressBlockNumber);
552
554
  cs.committedProgressBlockNumber = newProgressBlockNumber;
553
555
  cs.numEventsProcessed = newTotalEventsProcessed;
@@ -570,7 +572,7 @@ export {
570
572
  startFetchingQueries,
571
573
  timestampCaughtUpToHeadOrEndblock,
572
574
  knownHeight,
573
- indexingAddresses,
575
+ contractAddresses,
574
576
  bufferSize,
575
577
  bufferReadyCount,
576
578
  getProgressPercentage,
@@ -8,6 +8,7 @@ let configAddresses: Config.chain => array<Internal.indexingAddress>
8
8
  let make: (
9
9
  ~chainConfig: Config.chain,
10
10
  ~fetchState: FetchState.t,
11
+ ~indexingAddresses: IndexingAddresses.t,
11
12
  ~sourceManager: SourceManager.t,
12
13
  ~reorgDetection: ReorgDetection.t,
13
14
  ~committedProgressBlockNumber: int,
@@ -15,7 +16,7 @@ let make: (
15
16
  ~numEventsProcessed: float=?,
16
17
  ~timestampCaughtUpToHeadOrEndblock: option<Date.t>=?,
17
18
  ~isProgressAtHead: bool=?,
18
- ~transactionFieldMask: float=?,
19
+ ~transactionStore: TransactionStore.t=?,
19
20
  ~logger: Pino.t,
20
21
  ) => t
21
22
 
@@ -52,7 +53,7 @@ let timestampCaughtUpToHeadOrEndblock: t => option<Date.t>
52
53
 
53
54
  // Fetch-frontier reads.
54
55
  let knownHeight: t => int
55
- let indexingAddresses: t => dict<FetchState.indexingAddress>
56
+ let contractAddresses: (t, ~contractName: string) => array<Address.t>
56
57
  let bufferSize: t => int
57
58
  let bufferReadyCount: t => int
58
59
  let getProgressPercentage: t => float
@@ -112,7 +113,6 @@ let handleQueryResult: (
112
113
  ) => unit
113
114
  let materializeBatchItems: (t, ~items: array<Internal.item>) => promise<unit>
114
115
  let materializePageItems: (
115
- t,
116
116
  ~items: array<Internal.item>,
117
117
  ~page: option<TransactionStore.t>,
118
118
  ) => promise<unit>
package/src/Config.res CHANGED
@@ -23,6 +23,7 @@ type evmRpcConfig = {
23
23
  sourceFor: Source.sourceFor,
24
24
  syncConfig: option<sourceSyncOptions>,
25
25
  ws: option<string>,
26
+ headers: option<dict<string>>,
26
27
  }
27
28
 
28
29
  type sourceConfig =
@@ -156,6 +157,7 @@ let rpcConfigSchema = S.schema(s =>
156
157
  "url": s.matches(S.string),
157
158
  "for": s.matches(rpcSourceForSchema),
158
159
  "ws": s.matches(S.option(S.string)),
160
+ "headers": s.matches(S.option(S.dict(S.string))),
159
161
  "initialBlockInterval": s.matches(S.option(S.int)),
160
162
  "backoffMultiplicative": s.matches(S.option(S.float)),
161
163
  "accelerationAdditive": s.matches(S.option(S.int)),
@@ -907,6 +909,7 @@ let fromPublic = (publicConfigJson: JSON.t) => {
907
909
  sourceFor: parseRpcSourceFor(rpcConfig["for"]),
908
910
  syncConfig,
909
911
  ws: rpcConfig["ws"],
912
+ headers: rpcConfig["headers"],
910
913
  }
911
914
  })
912
915
  EvmSourceConfig({hypersync: publicChainConfig["hypersync"], rpcs})
@@ -81,6 +81,7 @@ let rpcConfigSchema = S$RescriptSchema.schema(s => ({
81
81
  url: s.m(S$RescriptSchema.string),
82
82
  for: s.m(rpcSourceForSchema),
83
83
  ws: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
84
+ headers: s.m(S$RescriptSchema.option(S$RescriptSchema.dict(S$RescriptSchema.string))),
84
85
  initialBlockInterval: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
85
86
  backoffMultiplicative: s.m(S$RescriptSchema.option(S$RescriptSchema.float)),
86
87
  accelerationAdditive: s.m(S$RescriptSchema.option(S$RescriptSchema.int)),
@@ -606,7 +607,8 @@ function fromPublic(publicConfigJson) {
606
607
  url: rpcConfig.url,
607
608
  sourceFor: parseRpcSourceFor(rpcConfig.for),
608
609
  syncConfig: syncConfig,
609
- ws: rpcConfig.ws
610
+ ws: rpcConfig.ws,
611
+ headers: rpcConfig.headers
610
612
  };
611
613
  });
612
614
  sourceConfig = {
package/src/Core.res CHANGED
@@ -6,7 +6,6 @@
6
6
  // tighter `Null.t` captures the exact boundary shape.
7
7
  type evmHypersyncClientCtor
8
8
  type evmRpcClientCtor
9
- type evmDecoderCtor
10
9
  type svmHypersyncClientCtor
11
10
  type hyperfuelClientCtor
12
11
  type transactionStoreCtor
@@ -18,8 +17,6 @@ type addon = {
18
17
  evmHypersyncClient: evmHypersyncClientCtor,
19
18
  @as("EvmRpcClient")
20
19
  evmRpcClient: evmRpcClientCtor,
21
- @as("EvmDecoder")
22
- evmDecoder: evmDecoderCtor,
23
20
  @as("SvmHypersyncClient")
24
21
  svmHypersyncClient: svmHypersyncClientCtor,
25
22
  @as("HyperfuelClient")
package/src/Ecosystem.res CHANGED
@@ -34,10 +34,6 @@ type t = {
34
34
  registration from an item's opaque payload. `event.transaction` is written
35
35
  onto the payload at batch prep (HyperSync) or inline (RPC/simulate). */
36
36
  toEvent: Internal.eventItem => Internal.event,
37
- /** Bitmask (as a float) of the transaction fields selected across the chain's
38
- events — the set the store materialises at batch prep. `0.` when the
39
- ecosystem carries transactions inline. */
40
- transactionFieldMask: array<Internal.eventConfig> => float,
41
37
  /** Build the per-item child logger for an event item, with
42
38
  ecosystem-specific log fields (EVM/Fuel: contract/event/address; SVM:
43
39
  program/instruction/programId). Closes over the injected logger. */
@@ -442,6 +442,7 @@ let buildEvmEventConfig = (
442
442
  startBlock: resolvedStartBlock,
443
443
  selectedBlockFields,
444
444
  selectedTransactionFields,
445
+ transactionFieldMask: Evm.eventTransactionFieldMask(selectedTransactionFields),
445
446
  sighash,
446
447
  topicCount,
447
448
  paramsMetadata: params,
@@ -500,6 +501,7 @@ let buildSvmInstructionEventConfig = (
500
501
  discriminatorByteLen,
501
502
  includeLogs,
502
503
  selectedTransactionFields,
504
+ transactionFieldMask: Svm.eventTransactionFieldMask(selectedTransactionFields),
503
505
  accountFilters,
504
506
  isInner,
505
507
  accounts,
@@ -568,6 +570,7 @@ let buildFuelEventConfig = (
568
570
  startBlock,
569
571
  // Fuel keeps the transaction inline on the payload; nothing to materialise.
570
572
  selectedTransactionFields: Utils.Set.make(),
573
+ transactionFieldMask: 0.,
571
574
  kind: fuelKind,
572
575
  }
573
576
  }