envio 3.3.0-alpha.6 → 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 (93) hide show
  1. package/index.d.ts +23 -5
  2. package/package.json +6 -6
  3. package/src/Address.res +5 -2
  4. package/src/Address.res.mjs +3 -1
  5. package/src/Api.res +1 -1
  6. package/src/Api.res.mjs +1 -1
  7. package/src/ChainFetching.res +34 -34
  8. package/src/ChainFetching.res.mjs +29 -29
  9. package/src/ChainState.res +328 -165
  10. package/src/ChainState.res.mjs +205 -100
  11. package/src/ChainState.resi +16 -7
  12. package/src/Config.res +55 -27
  13. package/src/Config.res.mjs +46 -7
  14. package/src/ContractRegisterContext.res +2 -12
  15. package/src/ContractRegisterContext.res.mjs +3 -5
  16. package/src/Core.res +7 -0
  17. package/src/CrossChainState.res +54 -79
  18. package/src/CrossChainState.res.mjs +45 -60
  19. package/src/CrossChainState.resi +1 -1
  20. package/src/Ecosystem.res +3 -3
  21. package/src/Ecosystem.res.mjs +3 -3
  22. package/src/Envio.res +14 -9
  23. package/src/EventConfigBuilder.res +105 -56
  24. package/src/EventConfigBuilder.res.mjs +69 -33
  25. package/src/EventProcessing.res +19 -15
  26. package/src/EventProcessing.res.mjs +13 -12
  27. package/src/FetchState.res +383 -182
  28. package/src/FetchState.res.mjs +260 -264
  29. package/src/HandlerLoader.res +7 -112
  30. package/src/HandlerLoader.res.mjs +1 -87
  31. package/src/HandlerRegister.res +209 -6
  32. package/src/HandlerRegister.res.mjs +90 -5
  33. package/src/HandlerRegister.resi +13 -2
  34. package/src/IndexerState.res +6 -3
  35. package/src/IndexerState.res.mjs +3 -3
  36. package/src/IndexerState.resi +1 -1
  37. package/src/IndexingAddresses.res +10 -7
  38. package/src/IndexingAddresses.res.mjs +8 -7
  39. package/src/IndexingAddresses.resi +3 -1
  40. package/src/Internal.res +82 -36
  41. package/src/Internal.res.mjs +11 -1
  42. package/src/Main.res +22 -23
  43. package/src/Main.res.mjs +15 -17
  44. package/src/Metrics.res +43 -2
  45. package/src/Metrics.res.mjs +39 -3
  46. package/src/Prometheus.res +0 -35
  47. package/src/Prometheus.res.mjs +33 -68
  48. package/src/RawEvent.res +7 -2
  49. package/src/RawEvent.res.mjs +4 -4
  50. package/src/SimulateItems.res +26 -8
  51. package/src/SimulateItems.res.mjs +11 -14
  52. package/src/TestIndexer.res +1 -1
  53. package/src/TestIndexer.res.mjs +1 -1
  54. package/src/sources/BlockStore.res +46 -0
  55. package/src/sources/BlockStore.res.mjs +24 -0
  56. package/src/sources/EventRouter.res +19 -12
  57. package/src/sources/EventRouter.res.mjs +7 -5
  58. package/src/sources/Evm.res +54 -4
  59. package/src/sources/Evm.res.mjs +43 -4
  60. package/src/sources/EvmChain.res +14 -18
  61. package/src/sources/EvmChain.res.mjs +12 -13
  62. package/src/sources/FieldMask.res +39 -0
  63. package/src/sources/FieldMask.res.mjs +42 -0
  64. package/src/sources/Fuel.res +5 -2
  65. package/src/sources/Fuel.res.mjs +4 -3
  66. package/src/sources/HyperFuelSource.res +32 -40
  67. package/src/sources/HyperFuelSource.res.mjs +53 -45
  68. package/src/sources/HyperSync.res +35 -9
  69. package/src/sources/HyperSync.res.mjs +52 -35
  70. package/src/sources/HyperSync.resi +11 -3
  71. package/src/sources/HyperSyncClient.res +15 -4
  72. package/src/sources/HyperSyncHeightStream.res +1 -8
  73. package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
  74. package/src/sources/HyperSyncSource.res +39 -58
  75. package/src/sources/HyperSyncSource.res.mjs +44 -44
  76. package/src/sources/RpcSource.res +114 -92
  77. package/src/sources/RpcSource.res.mjs +77 -46
  78. package/src/sources/RpcWebSocketHeightStream.res +0 -5
  79. package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
  80. package/src/sources/SimulateSource.res +6 -3
  81. package/src/sources/SimulateSource.res.mjs +13 -5
  82. package/src/sources/Source.res +25 -5
  83. package/src/sources/SourceManager.res +66 -3
  84. package/src/sources/SourceManager.res.mjs +55 -7
  85. package/src/sources/SourceManager.resi +10 -0
  86. package/src/sources/Svm.res +15 -10
  87. package/src/sources/Svm.res.mjs +24 -7
  88. package/src/sources/SvmHyperSyncClient.res +5 -6
  89. package/src/sources/SvmHyperSyncSource.res +84 -41
  90. package/src/sources/SvmHyperSyncSource.res.mjs +90 -43
  91. package/src/sources/TransactionStore.res +6 -107
  92. package/src/sources/TransactionStore.res.mjs +5 -86
  93. package/svm.schema.json +19 -0
package/index.d.ts CHANGED
@@ -979,13 +979,24 @@ export type SvmInstructionParams = {
979
979
  readonly extraAccounts: readonly string[];
980
980
  };
981
981
 
982
- /** Block context for a matched instruction. */
982
+ /** Permissive fallback shape for an instruction's `block`. The generated
983
+ * per-instruction type narrows this to `slot`/`hash` (always present) and
984
+ * `time` (always present but possibly `undefined`), plus the selected
985
+ * `field_selection.block_fields`. */
983
986
  export type SvmInstructionBlock = {
984
987
  /** Slot this instruction's block was matched in. */
985
988
  readonly slot: number;
986
- readonly time: number;
987
- /** Always empty for now — reserved for the future reorg-guard route. */
989
+ /** Unix block time (seconds). Absent when HyperSync/Solana doesn't report a
990
+ * block time for this slot. */
991
+ readonly time?: number;
992
+ /** Block hash. */
988
993
  readonly hash: string;
994
+ /** Block height. Select via `field_selection.block_fields`. */
995
+ readonly height?: number;
996
+ /** Parent slot. Select via `field_selection.block_fields`. */
997
+ readonly parentSlot?: number;
998
+ /** Parent block hash. Select via `field_selection.block_fields`. */
999
+ readonly parentHash?: string;
989
1000
  };
990
1001
 
991
1002
  export type SvmTokenBalance = {
@@ -1016,6 +1027,7 @@ export type SvmLog = {
1016
1027
  export type SvmInstruction<
1017
1028
  Params extends SvmInstructionParams = SvmInstructionParams,
1018
1029
  Tx = SvmTransaction,
1030
+ Block = SvmInstructionBlock,
1019
1031
  > = {
1020
1032
  /** Program name as declared under `programs[].name` in `config.yaml`. */
1021
1033
  readonly programName: string;
@@ -1041,7 +1053,12 @@ export type SvmInstruction<
1041
1053
  /** Present when the instruction's `include_logs` is `true`; only logs
1042
1054
  * scoped to this exact instruction (matching `instruction_address`). */
1043
1055
  readonly logs?: readonly SvmLog[];
1044
- readonly block: SvmInstructionBlock;
1056
+ /** The block this instruction's slot belongs to. Carries `slot`/`hash`
1057
+ * (always present) and `time` (always present but possibly `undefined`),
1058
+ * plus the fields selected via this instruction's
1059
+ * `field_selection.block_fields`; unselected fields are typed as
1060
+ * `FieldNotSelected<...>`. */
1061
+ readonly block: Block;
1045
1062
  };
1046
1063
 
1047
1064
  /** Arguments passed to handlers registered via `indexer.onInstruction`. */
@@ -1315,7 +1332,8 @@ type SvmEcosystem<Config extends IndexerConfigTypes = GlobalConfig> =
1315
1332
  Config,
1316
1333
  SvmInstruction<
1317
1334
  SvmParamsFromProgramTable<Programs[P][I]>,
1318
- Programs[P][I]["transaction"]
1335
+ Programs[P][I]["transaction"],
1336
+ Programs[P][I]["block"]
1319
1337
  >
1320
1338
  >,
1321
1339
  ) => Promise<void>,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "envio",
3
- "version": "3.3.0-alpha.6",
3
+ "version": "3.3.0-alpha.8",
4
4
  "type": "module",
5
5
  "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
6
6
  "bin": "./bin.mjs",
@@ -69,10 +69,10 @@
69
69
  "tsx": "4.21.0"
70
70
  },
71
71
  "optionalDependencies": {
72
- "envio-linux-x64": "3.3.0-alpha.6",
73
- "envio-linux-x64-musl": "3.3.0-alpha.6",
74
- "envio-linux-arm64": "3.3.0-alpha.6",
75
- "envio-darwin-x64": "3.3.0-alpha.6",
76
- "envio-darwin-arm64": "3.3.0-alpha.6"
72
+ "envio-linux-x64": "3.3.0-alpha.8",
73
+ "envio-linux-x64-musl": "3.3.0-alpha.8",
74
+ "envio-linux-arm64": "3.3.0-alpha.8",
75
+ "envio-darwin-x64": "3.3.0-alpha.8",
76
+ "envio-darwin-arm64": "3.3.0-alpha.8"
77
77
  }
78
78
  }
package/src/Address.res CHANGED
@@ -11,8 +11,11 @@ module Evm = {
11
11
  external fromStringOrThrow: string => t = "getAddress"
12
12
 
13
13
  // NOTE: the function is named to be overshadowed by the one below, so that we don't have to import viem in the handler code
14
+ // strict:false checks only the 20-byte hex shape, not EIP-55 checksum casing —
15
+ // since we're about to lowercase it anyway, an all-uppercase or wrongly-cased
16
+ // input address is just as valid as one that's already lowercase.
14
17
  @module("viem")
15
- external fromStringLowercaseOrThrow: string => bool = "isAddress"
18
+ external fromStringLowercaseOrThrow: (string, {"strict": bool}) => bool = "isAddress"
16
19
 
17
20
  // Reassign since the function might be used in the handler code
18
21
  // and we don't want to have a "viem" import there. It's needed to keep "viem" a dependency
@@ -20,7 +23,7 @@ module Evm = {
20
23
  // Also, we want a custom error message, which is searchable in our codebase.
21
24
  // Validate that the string is a proper address but return a lowercased value
22
25
  let fromStringLowercaseOrThrow = string => {
23
- if fromStringLowercaseOrThrow(string) {
26
+ if fromStringLowercaseOrThrow(string, {"strict": false}) {
24
27
  unsafeFromString(string->String.toLowerCase)
25
28
  } else {
26
29
  JsError.throwWithMessage(
@@ -7,7 +7,9 @@ import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
7
7
  let schema = S$RescriptSchema.setName(S$RescriptSchema.string, "Address");
8
8
 
9
9
  function fromStringLowercaseOrThrow(string) {
10
- if (Viem.isAddress(string)) {
10
+ if (Viem.isAddress(string, {
11
+ strict: false
12
+ })) {
11
13
  return string.toLowerCase();
12
14
  } else {
13
15
  return Stdlib_JsError.throwWithMessage(`Address "` + string + `" is invalid. Expected a 20-byte hex string starting with 0x.`);
package/src/Api.res CHANGED
@@ -9,7 +9,7 @@ let createTestIndexer: unit => unknown = () => {
9
9
  NodeJs.Path.getDirname(NodeJs.ImportMeta.importMeta),
10
10
  "TestIndexerWorker.res.mjs",
11
11
  )->NodeJs.Path.toString
12
- TestIndexer.makeCreateTestIndexer(~config=Config.loadWithoutRegistrations(), ~workerPath)()->(
12
+ TestIndexer.makeCreateTestIndexer(~config=Config.load(), ~workerPath)()->(
13
13
  Utils.magic: TestIndexer.t<'a> => unknown
14
14
  )
15
15
  }
package/src/Api.res.mjs CHANGED
@@ -10,7 +10,7 @@ let indexer = Main.getGlobalIndexer();
10
10
 
11
11
  function createTestIndexer() {
12
12
  let workerPath = Path.join(NodeJs.Path.getDirname(import.meta), "TestIndexerWorker.res.mjs");
13
- return TestIndexer.makeCreateTestIndexer(Config.loadWithoutRegistrations(), workerPath)();
13
+ return TestIndexer.makeCreateTestIndexer(Config.load(), workerPath)();
14
14
  }
15
15
 
16
16
  export {
@@ -11,12 +11,18 @@ type partitionQueryResponse = {
11
11
  let runContractRegistersOrThrow = async (
12
12
  ~itemsWithContractRegister: array<Internal.item>,
13
13
  ~config: Config.t,
14
- ~page: option<TransactionStore.t>,
14
+ ~transactionStore: option<TransactionStore.t>,
15
+ ~blockStore: option<BlockStore.t>,
15
16
  ) => {
16
- // contractRegister handlers can read event.transaction, so materialise the
17
- // selected fields onto the payloads before running them. All items belong to
18
- // the chain being fetched, hence its single page store and mask.
19
- await ChainState.materializePageItems(~items=itemsWithContractRegister, ~page)
17
+ // contractRegister handlers can read event.transaction and event.block, so
18
+ // materialise the selected fields onto the payloads before running them. All
19
+ // items belong to the chain being fetched, hence its single page stores.
20
+ await ChainState.materializePageItems(
21
+ ~items=itemsWithContractRegister,
22
+ ~transactionStore,
23
+ ~blockStore,
24
+ ~ecosystem=config.ecosystem.name,
25
+ )
20
26
 
21
27
  let itemsWithDcs = []
22
28
 
@@ -44,8 +50,8 @@ let runContractRegistersOrThrow = async (
44
50
  let item = itemsWithContractRegister->Array.getUnsafe(idx)
45
51
  let eventItem = item->Internal.castUnsafeEventItem
46
52
  let contractRegister = switch eventItem {
47
- | {eventConfig: {contractRegister: Some(contractRegister)}} => contractRegister
48
- | {eventConfig: {contractRegister: None, name: eventName}} =>
53
+ | {onEventRegistration: {contractRegister: Some(contractRegister)}} => contractRegister
54
+ | {onEventRegistration: {contractRegister: None, eventConfig: {name: eventName}}} =>
49
55
  // Unexpected case, since we should pass only events with contract register to this function
50
56
  JsError.throwWithMessage("Contract register is not set for event " ++ eventName)
51
57
  }
@@ -113,6 +119,7 @@ let rec onQueryResponse = async (
113
119
  let {
114
120
  parsedQueueItems,
115
121
  transactionStore,
122
+ blockStore,
116
123
  latestFetchedBlockNumber,
117
124
  latestFetchedBlockTimestamp,
118
125
  stats,
@@ -140,6 +147,20 @@ let rec onQueryResponse = async (
140
147
  ~blockRangeSize=latestFetchedBlockNumber - fromBlockQueried + 1,
141
148
  )
142
149
 
150
+ let numContractRegisterEvents = parsedQueueItems->Array.reduce(0, (count, item) => {
151
+ let eventItem = item->Internal.castUnsafeEventItem
152
+ eventItem.onEventRegistration.contractRegister !== None ? count + 1 : count
153
+ })
154
+ Logging.trace({
155
+ "msg": "Finished querying",
156
+ "chainId": chain->ChainMap.Chain.toChainId,
157
+ "partitionId": query.partitionId,
158
+ "fromBlock": fromBlockQueried,
159
+ "toBlock": latestFetchedBlockNumber,
160
+ "numEvents": parsedQueueItems->Array.length,
161
+ "numContractRegisterEvents": numContractRegisterEvents,
162
+ })
163
+
143
164
  let reorgResult = chainState->ChainState.registerReorgGuard(~blockHashes, ~knownHeight)
144
165
 
145
166
  let rollbackWithReorgDetectedBlockNumber = switch reorgResult {
@@ -196,7 +217,7 @@ let rec onQueryResponse = async (
196
217
  for idx in 0 to parsedQueueItems->Array.length - 1 {
197
218
  let item = parsedQueueItems->Array.getUnsafe(idx)
198
219
  let eventItem = item->Internal.castUnsafeEventItem
199
- if eventItem.eventConfig.contractRegister !== None {
220
+ if eventItem.onEventRegistration.contractRegister !== None {
200
221
  itemsWithContractRegister->Array.push(item)
201
222
  }
202
223
  // TODO: Don't really need to keep it in the queue
@@ -220,6 +241,7 @@ let rec onQueryResponse = async (
220
241
  },
221
242
  ~query,
222
243
  ~transactionStore,
244
+ ~blockStore,
223
245
  )
224
246
  ChainMetadata.stage(state)
225
247
  scheduleFetch()
@@ -232,7 +254,8 @@ let rec onQueryResponse = async (
232
254
  switch await runContractRegistersOrThrow(
233
255
  ~itemsWithContractRegister,
234
256
  ~config=state->IndexerState.config,
235
- ~page=transactionStore,
257
+ ~transactionStore,
258
+ ~blockStore,
236
259
  ) {
237
260
  | exception exn => IndexerState.errorExit(state, exn->ErrorHandling.make)
238
261
  | newItemsWithDcs => proceed(~newItemsWithDcs)
@@ -250,6 +273,7 @@ and applyQueryResponse = (
250
273
  ~latestFetchedBlock,
251
274
  ~query,
252
275
  ~transactionStore,
276
+ ~blockStore,
253
277
  ) => {
254
278
  let chainState = state->IndexerState.getChainState(~chain)
255
279
  let wasFetchingAtHead = chainState->ChainState.isFetchingAtHead
@@ -261,6 +285,7 @@ and applyQueryResponse = (
261
285
  ~newItemsWithDcs,
262
286
  ~knownHeight,
263
287
  ~transactionStore,
288
+ ~blockStore,
264
289
  )
265
290
 
266
291
  // In auto-exit mode, set endBlock to the first event's block when events arrive.
@@ -334,15 +359,6 @@ let fetchChain = async (
334
359
  // there's nothing to fetch. During backfill any such chain is idle.
335
360
  let reducedPolling = !isRealtime
336
361
 
337
- // Accumulated across all queries dispatched in this tick so their per-query
338
- // results collapse into a single completion log instead of one per query.
339
- let dispatchedCount = switch action {
340
- | FetchState.Ready(queries) => queries->Array.length
341
- | WaitingForNewBlock | NothingToQuery => 0
342
- }
343
- let fetchedByPartition = Dict.make()
344
- let fetchedCount = ref(0)
345
-
346
362
  // Owns its error boundary: launch doesn't catch, so any failure here (the
347
363
  // query, response handling, or dispatch itself) must stop the indexer.
348
364
  try {
@@ -368,22 +384,6 @@ let fetchChain = async (
368
384
  ~knownHeight=chainState->ChainState.knownHeight,
369
385
  ~isRealtime,
370
386
  )
371
- fetchedCount := fetchedCount.contents + 1
372
- fetchedByPartition->Dict.set(
373
- query.partitionId,
374
- {
375
- "fromBlock": response.fromBlockQueried,
376
- "toBlock": response.latestFetchedBlockNumber,
377
- "numEvents": response.parsedQueueItems->Array.length,
378
- },
379
- )
380
- if dispatchedCount > 0 && fetchedCount.contents === dispatchedCount {
381
- Logging.trace({
382
- "msg": "Finished querying",
383
- "chainId": chain->ChainMap.Chain.toChainId,
384
- "partitions": fetchedByPartition,
385
- })
386
- }
387
387
  await onQueryResponse(
388
388
  state,
389
389
  {chain, response, query},
@@ -6,6 +6,7 @@ import * as Ecosystem from "./Ecosystem.res.mjs";
6
6
  import * as ChainState from "./ChainState.res.mjs";
7
7
  import * as Prometheus from "./Prometheus.res.mjs";
8
8
  import * as IndexerState from "./IndexerState.res.mjs";
9
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
9
10
  import * as ChainMetadata from "./ChainMetadata.res.mjs";
10
11
  import * as ErrorHandling from "./ErrorHandling.res.mjs";
11
12
  import * as SourceManager from "./sources/SourceManager.res.mjs";
@@ -16,8 +17,8 @@ import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
16
17
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
17
18
  import * as ContractRegisterContext from "./ContractRegisterContext.res.mjs";
18
19
 
19
- async function runContractRegistersOrThrow(itemsWithContractRegister, config, page) {
20
- await ChainState.materializePageItems(itemsWithContractRegister, page);
20
+ async function runContractRegistersOrThrow(itemsWithContractRegister, config, transactionStore, blockStore) {
21
+ await ChainState.materializePageItems(itemsWithContractRegister, transactionStore, blockStore, config.ecosystem.name);
21
22
  let itemsWithDcs = [];
22
23
  let onRegister = (item, contractAddress, contractName) => {
23
24
  let dc_registrationBlock = item.blockNumber;
@@ -37,9 +38,9 @@ async function runContractRegistersOrThrow(itemsWithContractRegister, config, pa
37
38
  let promises = [];
38
39
  for (let idx = 0, idx_finish = itemsWithContractRegister.length; idx < idx_finish; ++idx) {
39
40
  let item = itemsWithContractRegister[idx];
40
- let match = item.eventConfig;
41
+ let match = item.onEventRegistration;
41
42
  let contractRegister = match.contractRegister;
42
- let contractRegister$1 = contractRegister !== undefined ? contractRegister : Stdlib_JsError.throwWithMessage("Contract register is not set for event " + match.name);
43
+ let contractRegister$1 = contractRegister !== undefined ? contractRegister : Stdlib_JsError.throwWithMessage("Contract register is not set for event " + match.eventConfig.name);
43
44
  let errorMessage = "Event contractRegister failed, please fix the error to keep the indexer running smoothly";
44
45
  try {
45
46
  let params = {
@@ -71,10 +72,10 @@ async function runContractRegistersOrThrow(itemsWithContractRegister, config, pa
71
72
  return itemsWithDcs;
72
73
  }
73
74
 
74
- function applyQueryResponse(state, chain, newItems, newItemsWithDcs, knownHeight, latestFetchedBlock, query, transactionStore) {
75
+ function applyQueryResponse(state, chain, newItems, newItemsWithDcs, knownHeight, latestFetchedBlock, query, transactionStore, blockStore) {
75
76
  let chainState = IndexerState.getChainState(state, chain);
76
77
  let wasFetchingAtHead = ChainState.isFetchingAtHead(chainState);
77
- ChainState.handleQueryResult(chainState, query, newItems, newItemsWithDcs, latestFetchedBlock, knownHeight, transactionStore);
78
+ ChainState.handleQueryResult(chainState, query, newItems, newItemsWithDcs, latestFetchedBlock, knownHeight, transactionStore, blockStore);
78
79
  if (IndexerState.exitAfterFirstEventBlock(state) && newItems.length !== 0) {
79
80
  ChainState.setEndBlockToFirstEvent(chainState, newItems[0].blockNumber);
80
81
  }
@@ -94,13 +95,31 @@ async function onQueryResponse(state, param, stateId, scheduleFetch, schedulePro
94
95
  let stats = response.stats;
95
96
  let latestFetchedBlockTimestamp = response.latestFetchedBlockTimestamp;
96
97
  let latestFetchedBlockNumber = response.latestFetchedBlockNumber;
98
+ let fromBlockQueried = response.fromBlockQueried;
99
+ let blockStore = response.blockStore;
97
100
  let transactionStore = response.transactionStore;
98
101
  let parsedQueueItems = response.parsedQueueItems;
99
102
  let knownHeight = response.knownHeight;
100
103
  if (knownHeight > ChainState.knownHeight(chainState)) {
101
104
  Prometheus.SourceHeight.set(SourceManager.getActiveSource(ChainState.sourceManager(chainState)).name, ChainState.chainConfig(chainState).id, knownHeight);
102
105
  }
103
- Prometheus.FetchingBlockRange.increment(chain, stats["total time elapsed (s)"], Stdlib_Option.getOr(stats["parsing time (s)"], 0), parsedQueueItems.length, (latestFetchedBlockNumber - response.fromBlockQueried | 0) + 1 | 0);
106
+ Prometheus.FetchingBlockRange.increment(chain, stats["total time elapsed (s)"], Stdlib_Option.getOr(stats["parsing time (s)"], 0), parsedQueueItems.length, (latestFetchedBlockNumber - fromBlockQueried | 0) + 1 | 0);
107
+ let numContractRegisterEvents = Stdlib_Array.reduce(parsedQueueItems, 0, (count, item) => {
108
+ if (item.onEventRegistration.contractRegister !== undefined) {
109
+ return count + 1 | 0;
110
+ } else {
111
+ return count;
112
+ }
113
+ });
114
+ Logging.trace({
115
+ msg: "Finished querying",
116
+ chainId: chain,
117
+ partitionId: query.partitionId,
118
+ fromBlock: fromBlockQueried,
119
+ toBlock: latestFetchedBlockNumber,
120
+ numEvents: parsedQueueItems.length,
121
+ numContractRegisterEvents: numContractRegisterEvents
122
+ });
104
123
  let reorgResult = ChainState.registerReorgGuard(chainState, response.blockHashes, knownHeight);
105
124
  let rollbackWithReorgDetectedBlockNumber;
106
125
  if (typeof reorgResult !== "object") {
@@ -124,7 +143,7 @@ async function onQueryResponse(state, param, stateId, scheduleFetch, schedulePro
124
143
  let newItems = [];
125
144
  for (let idx = 0, idx_finish = parsedQueueItems.length; idx < idx_finish; ++idx) {
126
145
  let item = parsedQueueItems[idx];
127
- if (item.eventConfig.contractRegister !== undefined) {
146
+ if (item.onEventRegistration.contractRegister !== undefined) {
128
147
  itemsWithContractRegister.push(item);
129
148
  }
130
149
  newItems.push(item);
@@ -134,7 +153,7 @@ async function onQueryResponse(state, param, stateId, scheduleFetch, schedulePro
134
153
  applyQueryResponse(state, chain, newItems, newItemsWithDcs, knownHeight, {
135
154
  blockNumber: latestFetchedBlockNumber,
136
155
  blockTimestamp: latestFetchedBlockTimestamp
137
- }, query, transactionStore);
156
+ }, query, transactionStore, blockStore);
138
157
  ChainMetadata.stage(state);
139
158
  scheduleFetch();
140
159
  return scheduleProcessing();
@@ -145,7 +164,7 @@ async function onQueryResponse(state, param, stateId, scheduleFetch, schedulePro
145
164
  }
146
165
  let newItemsWithDcs;
147
166
  try {
148
- newItemsWithDcs = await runContractRegistersOrThrow(itemsWithContractRegister, IndexerState.config(state), transactionStore);
167
+ newItemsWithDcs = await runContractRegistersOrThrow(itemsWithContractRegister, IndexerState.config(state), transactionStore, blockStore);
149
168
  } catch (raw_exn) {
150
169
  let exn = Primitive_exceptions.internalToException(raw_exn);
151
170
  return IndexerState.errorExit(state, ErrorHandling.make(exn, undefined, undefined));
@@ -176,29 +195,10 @@ async function fetchChain(state, chain, action, stateId, scheduleFetch, schedule
176
195
  let isRealtime = IndexerState.isRealtime(state);
177
196
  let sourceManager = ChainState.sourceManager(chainState);
178
197
  let reducedPolling = !isRealtime;
179
- let dispatchedCount;
180
- dispatchedCount = typeof action !== "object" ? 0 : action._0.length;
181
- let fetchedByPartition = {};
182
- let fetchedCount = {
183
- contents: 0
184
- };
185
198
  try {
186
199
  return await ChainState.dispatch(chainState, async query => {
187
200
  try {
188
201
  let response = await SourceManager.executeQuery(sourceManager, query, ChainState.knownHeight(chainState), isRealtime);
189
- fetchedCount.contents = fetchedCount.contents + 1 | 0;
190
- fetchedByPartition[query.partitionId] = {
191
- fromBlock: response.fromBlockQueried,
192
- toBlock: response.latestFetchedBlockNumber,
193
- numEvents: response.parsedQueueItems.length
194
- };
195
- if (dispatchedCount > 0 && fetchedCount.contents === dispatchedCount) {
196
- Logging.trace({
197
- msg: "Finished querying",
198
- chainId: chain,
199
- partitions: fetchedByPartition
200
- });
201
- }
202
202
  return await onQueryResponse(state, {
203
203
  chain: chain,
204
204
  response: response,