envio 3.3.0-alpha.5 → 3.3.0-alpha.7

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 (50) hide show
  1. package/package.json +6 -6
  2. package/src/Address.res +5 -2
  3. package/src/Address.res.mjs +3 -1
  4. package/src/BatchProcessing.res +5 -0
  5. package/src/BatchProcessing.res.mjs +6 -0
  6. package/src/ChainFetching.res +14 -25
  7. package/src/ChainFetching.res.mjs +19 -20
  8. package/src/ChainState.res +4 -4
  9. package/src/ChainState.res.mjs +2 -2
  10. package/src/ChainState.resi +1 -1
  11. package/src/Config.res +44 -0
  12. package/src/Config.res.mjs +38 -0
  13. package/src/ContractRegisterContext.res +2 -12
  14. package/src/ContractRegisterContext.res.mjs +3 -5
  15. package/src/CrossChainState.res +5 -3
  16. package/src/CrossChainState.res.mjs +5 -4
  17. package/src/ExitOnCaughtUp.res +10 -2
  18. package/src/ExitOnCaughtUp.res.mjs +10 -1
  19. package/src/FetchState.res +49 -52
  20. package/src/FetchState.res.mjs +45 -47
  21. package/src/IndexerState.res +4 -0
  22. package/src/IndexerState.res.mjs +8 -1
  23. package/src/IndexerState.resi +1 -0
  24. package/src/SimulateDeadInputTracker.res +85 -0
  25. package/src/SimulateDeadInputTracker.res.mjs +73 -0
  26. package/src/SimulateDeadInputTracker.resi +12 -0
  27. package/src/SimulateItems.res +29 -43
  28. package/src/SimulateItems.res.mjs +16 -33
  29. package/src/TestIndexer.res +3 -27
  30. package/src/TestIndexer.res.mjs +2 -9
  31. package/src/sources/EvmChain.res +1 -1
  32. package/src/sources/EvmChain.res.mjs +1 -1
  33. package/src/sources/HyperFuelSource.res +1 -0
  34. package/src/sources/HyperFuelSource.res.mjs +1 -1
  35. package/src/sources/HyperSync.res +4 -0
  36. package/src/sources/HyperSync.res.mjs +5 -4
  37. package/src/sources/HyperSync.resi +1 -0
  38. package/src/sources/HyperSyncSource.res +2 -0
  39. package/src/sources/HyperSyncSource.res.mjs +2 -2
  40. package/src/sources/RpcSource.res +287 -146
  41. package/src/sources/RpcSource.res.mjs +286 -247
  42. package/src/sources/SimulateSource.res +2 -0
  43. package/src/sources/SimulateSource.res.mjs +3 -2
  44. package/src/sources/Source.res +10 -0
  45. package/src/sources/SourceManager.res +7 -0
  46. package/src/sources/SourceManager.res.mjs +2 -1
  47. package/src/sources/Svm.res +1 -0
  48. package/src/sources/Svm.res.mjs +1 -1
  49. package/src/sources/SvmHyperSyncSource.res +2 -0
  50. package/src/sources/SvmHyperSyncSource.res.mjs +4 -2
@@ -0,0 +1,73 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Utils from "./Utils.res.mjs";
4
+ import * as ChainMap from "./ChainMap.res.mjs";
5
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
6
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
7
+
8
+ function itemKey(item) {
9
+ if (item.kind === 0) {
10
+ return item.chain.toString() + `:` + item.blockNumber.toString() + `:` + item.logIndex.toString();
11
+ } else {
12
+ return "";
13
+ }
14
+ }
15
+
16
+ function makeFromConfig(config) {
17
+ let entries = ChainMap.values(config.chainMap).flatMap(chainConfig => {
18
+ let sources = chainConfig.sourceConfig;
19
+ if (sources.TAG === "CustomSources") {
20
+ return sources._0.flatMap(source => Stdlib_Option.getOr(source.simulateItems, []).map((item, index) => ({
21
+ chainId: chainConfig.id,
22
+ index: index,
23
+ key: itemKey(item)
24
+ })));
25
+ } else {
26
+ return [];
27
+ }
28
+ });
29
+ if (entries.length !== 0) {
30
+ return {
31
+ unprocessed: entries
32
+ };
33
+ }
34
+ }
35
+
36
+ function recordProcessed(t, batch) {
37
+ let processedKeys = new Set(batch.items.map(itemKey));
38
+ t.unprocessed = t.unprocessed.filter(entry => !processedKeys.has(entry.key));
39
+ }
40
+
41
+ function unroutedByChain(t) {
42
+ let indicesByChain = {};
43
+ let chainOrder = [];
44
+ t.unprocessed.forEach(entry => {
45
+ let key = entry.chainId.toString();
46
+ if (Stdlib_Option.isNone(indicesByChain[key])) {
47
+ chainOrder.push(entry.chainId);
48
+ }
49
+ Utils.Dict.push(indicesByChain, key, entry.index);
50
+ });
51
+ return chainOrder.map(chainId => [
52
+ chainId,
53
+ indicesByChain[chainId.toString()]
54
+ ]);
55
+ }
56
+
57
+ function failureMessage(t) {
58
+ let byChain = unroutedByChain(t);
59
+ if (byChain.length === 0) {
60
+ return;
61
+ }
62
+ let count = Stdlib_Array.reduce(byChain, 0, (acc, param) => acc + param[1].length | 0);
63
+ let itemWord = count === 1 ? "item" : "items";
64
+ let lines = byChain.map(param => ` - chain ` + param[0].toString() + `: ` + param[1].map(index => index.toString()).join(", ")).join("\n");
65
+ return `simulate: ` + count.toString() + ` ` + itemWord + ` you passed to simulate never reached a handler, so nothing ran for them. Each was filtered out before the handler — usually a non-wildcard srcAddress that isn't indexed for the contract, or a where/block filter that excluded the event. Unrouted items, by index in each chain's simulate array:\n` + lines;
66
+ }
67
+
68
+ export {
69
+ makeFromConfig,
70
+ recordProcessed,
71
+ failureMessage,
72
+ }
73
+ /* Utils Not a pure module */
@@ -0,0 +1,12 @@
1
+ type t
2
+
3
+ // Builds a tracker from the run's config, seeded with every item each simulate
4
+ // source provided. None when no chain has a simulate source.
5
+ let makeFromConfig: Config.t => option<t>
6
+
7
+ // Drop the batch's items from the not-yet-routed set, matched by event coordinate.
8
+ let recordProcessed: (t, ~batch: Batch.t) => unit
9
+
10
+ // The error to fail the run with when items never reached a handler, listing them
11
+ // by chain and index within that chain's `simulate` array. None when all routed.
12
+ let failureMessage: t => option<string>
@@ -216,9 +216,13 @@ let deriveSrcAddress = (
216
216
  ~providedSrcAddress: option<Address.t>,
217
217
  ~eventConfig: Internal.eventConfig,
218
218
  ~chainConfig: Config.chain,
219
+ ~config: Config.t,
219
220
  ): Address.t => {
220
221
  switch providedSrcAddress {
221
- | Some(addr) => addr
222
+ // Canonicalize to the configured casing; the fallback addresses below already
223
+ // come from the parsed config and need no normalization. Relaxed (not
224
+ // Config.normalizeUserAddress) so test placeholders like "0xfoo" are allowed.
225
+ | Some(addr) => config->Config.normalizeSimulateAddress(addr)
222
226
  | None =>
223
227
  if eventConfig.isWildcard {
224
228
  dummySrcAddress
@@ -231,46 +235,6 @@ let deriveSrcAddress = (
231
235
  }
232
236
  }
233
237
 
234
- // A non-wildcard event is gated by `clientAddressFilter` on srcAddress ownership,
235
- // so a simulate item whose srcAddress isn't indexed on this chain would be
236
- // silently dropped (handler never runs). Fail loudly instead.
237
- //
238
- // `config` must already have handler registrations applied, otherwise an event
239
- // made wildcard purely through `indexer.onEvent({ wildcard: true })` reads back
240
- // as non-wildcard and gets wrongly rejected.
241
- let validateSrcAddresses = (
242
- ~simulateItems: array<JSON.t>,
243
- ~config: Config.t,
244
- ~chainConfig: Config.chain,
245
- ~indexingAddresses: array<Internal.indexingAddress>,
246
- ): unit => {
247
- let known = Utils.Set.make()
248
- indexingAddresses->Array.forEach(ia => known->Utils.Set.add(ia.address->Address.toString)->ignore)
249
- simulateItems->Array.forEach(rawJson => {
250
- let raw = rawJson->(Utils.magic: JSON.t => rawSimulateItem)
251
- switch (raw->getContract, raw->getEvent) {
252
- | (Some(contractName), Some(eventName)) =>
253
- switch findEventConfig(~config, ~contractName, ~eventName) {
254
- | Some(eventConfig) if !eventConfig.isWildcard =>
255
- let item = rawJson->(Utils.magic: JSON.t => Envio.evmSimulateItem)
256
- let srcAddress = deriveSrcAddress(
257
- ~providedSrcAddress=item.srcAddress,
258
- ~eventConfig,
259
- ~chainConfig,
260
- )
261
- if !(known->Utils.Set.has(srcAddress->Address.toString)) {
262
- JsError.throwWithMessage(
263
- `simulate: ${contractName}.${eventName} resolved to address ${srcAddress->Address.toString}, which isn't indexed on chain ${chainConfig.id->Int.toString}. ` ++
264
- `Provide a "srcAddress" configured or registered for ${contractName} on this chain, or use a wildcard event.`,
265
- )
266
- }
267
- | _ => ()
268
- }
269
- | _ => ()
270
- }
271
- })
272
- }
273
-
274
238
  let parse = (~simulateItems: array<JSON.t>, ~config: Config.t, ~chainConfig: Config.chain): array<
275
239
  Internal.item,
276
240
  > => {
@@ -281,8 +245,11 @@ let parse = (~simulateItems: array<JSON.t>, ~config: Config.t, ~chainConfig: Con
281
245
  let currentLogIndex = ref(0)
282
246
 
283
247
  let items = []
248
+ // Coordinate "block:logIndex" -> the index of the first item that claimed it,
249
+ // used to reject two items resolving to the same (block, logIndex).
250
+ let seenCoordinates = Dict.make()
284
251
 
285
- simulateItems->Array.forEach(rawJson => {
252
+ simulateItems->Array.forEachWithIndex((rawJson, itemIndex) => {
286
253
  let raw = rawJson->(Utils.magic: JSON.t => rawSimulateItem)
287
254
 
288
255
  switch (raw->getContract, raw->getEvent) {
@@ -306,8 +273,14 @@ let parse = (~simulateItems: array<JSON.t>, ~config: Config.t, ~chainConfig: Con
306
273
  }
307
274
  let params = paramsJson->S.convertOrThrow(eventConfig.simulateParamsSchema)
308
275
 
276
+ // An explicit logIndex advances the auto-increment counter past itself, so a
277
+ // later item that omits logIndex picks up after it instead of colliding.
309
278
  let logIndex = switch item.logIndex {
310
- | Some(li) => li
279
+ | Some(li) =>
280
+ if li >= currentLogIndex.contents {
281
+ currentLogIndex := li + 1
282
+ }
283
+ li
311
284
  | None =>
312
285
  let li = currentLogIndex.contents
313
286
  currentLogIndex := li + 1
@@ -318,6 +291,7 @@ let parse = (~simulateItems: array<JSON.t>, ~config: Config.t, ~chainConfig: Con
318
291
  ~providedSrcAddress=item.srcAddress,
319
292
  ~eventConfig,
320
293
  ~chainConfig,
294
+ ~config,
321
295
  )
322
296
 
323
297
  let rawItem = rawJson->(Utils.magic: JSON.t => {..})
@@ -345,6 +319,18 @@ let parse = (~simulateItems: array<JSON.t>, ~config: Config.t, ~chainConfig: Con
345
319
  // Update currentBlock for subsequent items
346
320
  currentBlock := blockNumber
347
321
 
322
+ // A simulate item must land on a distinct (block, logIndex): event ordering
323
+ // and the dead-input tracker both key on it. Catch explicit duplicates and
324
+ // explicit-vs-auto-increment collisions here, naming both offending indices.
325
+ let coordinate = `${blockNumber->Int.toString}:${logIndex->Int.toString}`
326
+ switch seenCoordinates->Dict.get(coordinate) {
327
+ | Some(firstIndex) =>
328
+ JsError.throwWithMessage(
329
+ `simulate: items at index ${firstIndex->Int.toString} and ${itemIndex->Int.toString} on chain ${chainId->Int.toString} both resolve to block ${blockNumber->Int.toString}, logIndex ${logIndex->Int.toString}. Give each item a distinct logIndex (or omit logIndex so they auto-increment).`,
330
+ )
331
+ | None => seenCoordinates->Dict.set(coordinate, itemIndex)
332
+ }
333
+
348
334
  items
349
335
  ->Array.push(
350
336
  Internal.Event({
@@ -1,5 +1,6 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Config from "./Config.res.mjs";
3
4
  import * as Address from "./Address.res.mjs";
4
5
  import * as ChainMap from "./ChainMap.res.mjs";
5
6
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
@@ -150,9 +151,9 @@ function firstContractAddress(chainConfig, contractName) {
150
151
  return found.contents;
151
152
  }
152
153
 
153
- function deriveSrcAddress(providedSrcAddress, eventConfig, chainConfig) {
154
+ function deriveSrcAddress(providedSrcAddress, eventConfig, chainConfig, config) {
154
155
  if (providedSrcAddress !== undefined) {
155
- return Primitive_option.valFromOption(providedSrcAddress);
156
+ return Config.normalizeSimulateAddress(config, Primitive_option.valFromOption(providedSrcAddress));
156
157
  }
157
158
  if (eventConfig.isWildcard) {
158
159
  return dummySrcAddress;
@@ -165,34 +166,6 @@ function deriveSrcAddress(providedSrcAddress, eventConfig, chainConfig) {
165
166
  }
166
167
  }
167
168
 
168
- function validateSrcAddresses(simulateItems, config, chainConfig, indexingAddresses) {
169
- let known = new Set();
170
- indexingAddresses.forEach(ia => {
171
- known.add(ia.address);
172
- });
173
- simulateItems.forEach(rawJson => {
174
- let match = rawJson.contract;
175
- let match$1 = rawJson.event;
176
- if (match === undefined) {
177
- return;
178
- }
179
- if (match$1 === undefined) {
180
- return;
181
- }
182
- let eventConfig = findEventConfig(config, match, match$1);
183
- if (eventConfig === undefined) {
184
- return;
185
- }
186
- if (eventConfig.isWildcard) {
187
- return;
188
- }
189
- let srcAddress = deriveSrcAddress(rawJson.srcAddress, eventConfig, chainConfig);
190
- if (!known.has(srcAddress)) {
191
- return Stdlib_JsError.throwWithMessage(`simulate: ` + match + `.` + match$1 + ` resolved to address ` + srcAddress + `, which isn't indexed on chain ` + chainConfig.id.toString() + `. ` + (`Provide a "srcAddress" configured or registered for ` + match + ` on this chain, or use a wildcard event.`));
192
- }
193
- });
194
- }
195
-
196
169
  function parse(simulateItems, config, chainConfig) {
197
170
  let chain = ChainMap.Chain.makeUnsafe(chainConfig.id);
198
171
  let chainId = chainConfig.id;
@@ -204,7 +177,8 @@ function parse(simulateItems, config, chainConfig) {
204
177
  contents: 0
205
178
  };
206
179
  let items = [];
207
- simulateItems.forEach(rawJson => {
180
+ let seenCoordinates = {};
181
+ simulateItems.forEach((rawJson, itemIndex) => {
208
182
  let match = rawJson.contract;
209
183
  let match$1 = rawJson.event;
210
184
  if (match === undefined) {
@@ -221,13 +195,16 @@ function parse(simulateItems, config, chainConfig) {
221
195
  let li = rawJson.logIndex;
222
196
  let logIndex;
223
197
  if (li !== undefined) {
198
+ if (li >= currentLogIndex.contents) {
199
+ currentLogIndex.contents = li + 1 | 0;
200
+ }
224
201
  logIndex = li;
225
202
  } else {
226
203
  let li$1 = currentLogIndex.contents;
227
204
  currentLogIndex.contents = li$1 + 1 | 0;
228
205
  logIndex = li$1;
229
206
  }
230
- let srcAddress = deriveSrcAddress(rawJson.srcAddress, eventConfig, chainConfig);
207
+ let srcAddress = deriveSrcAddress(rawJson.srcAddress, eventConfig, chainConfig, config);
231
208
  let blockJson = rawJson.block;
232
209
  let blockJson$1 = (blockJson == null) ? undefined : Primitive_option.some(blockJson);
233
210
  let transactionJson = rawJson.transaction;
@@ -272,6 +249,13 @@ function parse(simulateItems, config, chainConfig) {
272
249
  break;
273
250
  }
274
251
  currentBlock.contents = blockNumber;
252
+ let coordinate = blockNumber.toString() + `:` + logIndex.toString();
253
+ let firstIndex = seenCoordinates[coordinate];
254
+ if (firstIndex !== undefined) {
255
+ Stdlib_JsError.throwWithMessage(`simulate: items at index ` + firstIndex.toString() + ` and ` + itemIndex.toString() + ` on chain ` + chainId.toString() + ` both resolve to block ` + blockNumber.toString() + `, logIndex ` + logIndex.toString() + `. Give each item a distinct logIndex (or omit logIndex so they auto-increment).`);
256
+ } else {
257
+ seenCoordinates[coordinate] = itemIndex;
258
+ }
275
259
  items.push({
276
260
  kind: 0,
277
261
  eventConfig: eventConfig,
@@ -360,7 +344,6 @@ export {
360
344
  dummySrcAddress,
361
345
  firstContractAddress,
362
346
  deriveSrcAddress,
363
- validateSrcAddresses,
364
347
  parse,
365
348
  patchConfig,
366
349
  }
@@ -667,11 +667,7 @@ let makeCreateTestIndexer = (~config: Config.t, ~workerPath: string): (
667
667
  Int.compare(aId, bId)
668
668
  })
669
669
 
670
- // Parse and validate the block ranges upfront before starting any
671
- // workers. srcAddress validation can't run here: it depends on which
672
- // events are wildcard, and `config` reflects config.yaml only —
673
- // handler-level `wildcard: true` takes effect only once registrations
674
- // are applied.
670
+ // Parse and validate the block ranges upfront before starting any workers.
675
671
  let chainEntries = sortedChainKeys->Array.map(chainIdStr => {
676
672
  let rawChainConfig = rawChains->Dict.getUnsafe(chainIdStr)
677
673
  let chainId = switch chainIdStr->Int.fromString {
@@ -868,26 +864,6 @@ let initTestWorker = () => {
868
864
  }
869
865
 
870
866
  let patchConfig = (config: Config.t, _registrations) => {
871
- // `config` here has handler registrations applied, so `isWildcard`
872
- // reflects `indexer.onEvent({ wildcard: true })` — which the main thread
873
- // can't see. Validate srcAddresses against it before patching in the
874
- // simulate source.
875
- switch simulate {
876
- | Some(simulateItems) =>
877
- let chainConfig = config.chainMap->ChainMap.get(ChainMap.Chain.makeUnsafe(~chainId))
878
- let indexingAddresses =
879
- initialState.chains
880
- ->Array.find(c => c.id == chainId)
881
- ->Option.mapOr([], c => c.indexingAddresses)
882
- SimulateItems.validateSrcAddresses(
883
- ~simulateItems,
884
- ~config,
885
- ~chainConfig,
886
- ~indexingAddresses,
887
- )
888
- | None => ()
889
- }
890
-
891
867
  let config = SimulateItems.patchConfig(~config, ~processConfig)
892
868
 
893
869
  // In auto-exit mode, set batchSize=1 to process one block checkpoint at a time
@@ -900,8 +876,8 @@ let initTestWorker = () => {
900
876
  Main.start(~persistence, ~isTest=true, ~patchConfig, ~exitAfterFirstEventBlock)
901
877
  ->Promise.catch(exn => {
902
878
  // `Main.start` rejects on any fatal error: a runtime failure arrives wrapped
903
- // in `Main.FatalError` (already logged), a setup throw (e.g. patchConfig's
904
- // srcAddress validation) arrives raw. The parent only learns of failures
879
+ // in `Main.FatalError` (already logged), a setup throw (e.g. an invalid
880
+ // simulate item) arrives raw. The parent only learns of failures
905
881
  // through the worker `error` event, which fires on an *uncaught* exception.
906
882
  // Throwing synchronously in this catch would just reject the catch's own
907
883
  // promise (swallowed by `ignore`); `setImmediate` re-throws outside the
@@ -586,11 +586,9 @@ function initTestWorker() {
586
586
  Process.exit(1);
587
587
  return;
588
588
  }
589
- let initialState = workerData.initialState;
590
589
  let simulate = workerData.simulate;
591
590
  let endBlock = workerData.endBlock;
592
- let chainId = workerData.chainId;
593
- let chainIdStr = chainId.toString();
591
+ let chainIdStr = workerData.chainId.toString();
594
592
  let exitAfterFirstEventBlock = Stdlib_Option.isNone(endBlock);
595
593
  let resolvedChainDict = {};
596
594
  resolvedChainDict["startBlock"] = workerData.startBlock;
@@ -605,7 +603,7 @@ function initTestWorker() {
605
603
  let processConfig = {
606
604
  chains: resolvedChainsDict
607
605
  };
608
- let proxy = TestIndexerProxyStorage.make(parentPort, initialState);
606
+ let proxy = TestIndexerProxyStorage.make(parentPort, workerData.initialState);
609
607
  let storage = TestIndexerProxyStorage.makeStorage(proxy);
610
608
  let config = Config.loadWithoutRegistrations();
611
609
  let persistence = Persistence.make(config.userEntities, config.allEnums, storage);
@@ -615,11 +613,6 @@ function initTestWorker() {
615
613
  Logging.setLogLevel("silent");
616
614
  }
617
615
  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
- }
623
616
  let config$1 = SimulateItems.patchConfig(config, processConfig);
624
617
  if (exitAfterFirstEventBlock) {
625
618
  return {
@@ -32,7 +32,7 @@ let getSyncConfig = (
32
32
  intervalCeiling: Env.Configurable.SyncConfig.intervalCeiling->Option.getOr(
33
33
  intervalCeiling->Option.getOr(10_000),
34
34
  ),
35
- backoffMillis: backoffMillis->Option.getOr(5000),
35
+ backoffMillis: backoffMillis->Option.getOr(2000),
36
36
  queryTimeoutMillis,
37
37
  fallbackStallTimeout: fallbackStallTimeout->Option.getOr(queryTimeoutMillis / 2),
38
38
  pollingInterval: pollingInterval->Option.getOr(1000),
@@ -13,7 +13,7 @@ function getSyncConfig(param) {
13
13
  backoffMultiplicative: Stdlib_Option.getOr(Env.Configurable.SyncConfig.backoffMultiplicative, Stdlib_Option.getOr(param.backoffMultiplicative, 0.8)),
14
14
  accelerationAdditive: Stdlib_Option.getOr(Env.Configurable.SyncConfig.accelerationAdditive, Stdlib_Option.getOr(param.accelerationAdditive, 500)),
15
15
  intervalCeiling: Stdlib_Option.getOr(Env.Configurable.SyncConfig.intervalCeiling, Stdlib_Option.getOr(param.intervalCeiling, 10000)),
16
- backoffMillis: Stdlib_Option.getOr(param.backoffMillis, 5000),
16
+ backoffMillis: Stdlib_Option.getOr(param.backoffMillis, 2000),
17
17
  queryTimeoutMillis: queryTimeoutMillis,
18
18
  fallbackStallTimeout: Stdlib_Option.getOr(param.fallbackStallTimeout, queryTimeoutMillis / 2 | 0),
19
19
  pollingInterval: Stdlib_Option.getOr(param.pollingInterval, 1000)
@@ -239,6 +239,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
239
239
  ~knownHeight,
240
240
  ~partitionId as _,
241
241
  ~selection: FetchState.selection,
242
+ ~itemsTarget as _,
242
243
  ~retry,
243
244
  ~logger,
244
245
  ) => {
@@ -196,7 +196,7 @@ 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, contractNameByAddress, knownHeight, param, selection, retry, logger) => {
199
+ let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, contractNameByAddress, knownHeight, param, selection, param$1, retry, logger) => {
200
200
  let totalTimeRef = Performance.now();
201
201
  let selectionConfig = getSelectionConfig(selection);
202
202
  let recieptsSelection = selectionConfig.getRecieptsSelection(addressesByContractName);
@@ -64,6 +64,7 @@ module GetLogs = {
64
64
  ~toBlockInclusive,
65
65
  ~addressesWithTopics,
66
66
  ~fieldSelection,
67
+ ~maxNumLogs,
67
68
  ): HyperSyncClient.QueryTypes.query => {
68
69
  fromBlock,
69
70
  toBlockExclusive: ?switch toBlockInclusive {
@@ -72,6 +73,7 @@ module GetLogs = {
72
73
  },
73
74
  logs: addressesWithTopics,
74
75
  fieldSelection,
76
+ maxNumLogs,
75
77
  }
76
78
 
77
79
  // Rust encodes structured failures as a JSON payload in the napi error's
@@ -105,6 +107,7 @@ module GetLogs = {
105
107
  ~toBlock,
106
108
  ~logSelections: array<LogSelection.t>,
107
109
  ~fieldSelection,
110
+ ~maxNumLogs,
108
111
  ): logsQueryPage => {
109
112
  let addressesWithTopics = logSelections->Array.flatMap(({addresses, topicSelections}) =>
110
113
  topicSelections->Array.map(({topic0, topic1, topic2, topic3}) => {
@@ -123,6 +126,7 @@ module GetLogs = {
123
126
  ~toBlockInclusive=toBlock,
124
127
  ~addressesWithTopics,
125
128
  ~fieldSelection,
129
+ ~maxNumLogs,
126
130
  )
127
131
 
128
132
  let (res, transactionStore) = switch await client.getEventItems(~query) {
@@ -62,12 +62,13 @@ function mapExn(queryResponse) {
62
62
 
63
63
  let $$Error = /* @__PURE__ */Primitive_exceptions.create("HyperSync.GetLogs.Error");
64
64
 
65
- function makeRequestBody(fromBlock, toBlockInclusive, addressesWithTopics, fieldSelection) {
65
+ function makeRequestBody(fromBlock, toBlockInclusive, addressesWithTopics, fieldSelection, maxNumLogs) {
66
66
  return {
67
67
  fromBlock: fromBlock,
68
68
  toBlock: toBlockInclusive !== undefined ? toBlockInclusive + 1 | 0 : undefined,
69
69
  logs: addressesWithTopics,
70
- fieldSelection: fieldSelection
70
+ fieldSelection: fieldSelection,
71
+ maxNumLogs: maxNumLogs
71
72
  };
72
73
  }
73
74
 
@@ -92,7 +93,7 @@ function extractMissingParams(exn) {
92
93
  }
93
94
  }
94
95
 
95
- async function query(client, fromBlock, toBlock, logSelections, fieldSelection) {
96
+ async function query(client, fromBlock, toBlock, logSelections, fieldSelection, maxNumLogs) {
96
97
  let addressesWithTopics = logSelections.flatMap(param => {
97
98
  let addresses = param.addresses;
98
99
  return param.topicSelections.map(param => {
@@ -100,7 +101,7 @@ async function query(client, fromBlock, toBlock, logSelections, fieldSelection)
100
101
  return HyperSyncClient.QueryTypes.makeLogSelection(addresses, topics);
101
102
  });
102
103
  });
103
- let query$1 = makeRequestBody(fromBlock, toBlock, addressesWithTopics, fieldSelection);
104
+ let query$1 = makeRequestBody(fromBlock, toBlock, addressesWithTopics, fieldSelection, maxNumLogs);
104
105
  let match;
105
106
  try {
106
107
  match = await client.getEventItems(query$1);
@@ -33,6 +33,7 @@ module GetLogs: {
33
33
  ~toBlock: option<int>,
34
34
  ~logSelections: array<LogSelection.t>,
35
35
  ~fieldSelection: HyperSyncClient.QueryTypes.fieldSelection,
36
+ ~maxNumLogs: int,
36
37
  ) => promise<logsQueryPage>
37
38
  }
38
39
 
@@ -232,6 +232,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
232
232
  ~knownHeight,
233
233
  ~partitionId as _,
234
234
  ~selection,
235
+ ~itemsTarget,
235
236
  ~retry,
236
237
  ~logger,
237
238
  ) => {
@@ -258,6 +259,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
258
259
  ~toBlock,
259
260
  ~logSelections,
260
261
  ~fieldSelection=selectionConfig.fieldSelection,
262
+ ~maxNumLogs=itemsTarget,
261
263
  ) catch {
262
264
  | HyperSync.GetLogs.Error(error) =>
263
265
  throw(
@@ -149,7 +149,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
149
149
  }
150
150
  };
151
151
  };
152
- let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, contractNameByAddress, knownHeight, param, selection, retry, logger) => {
152
+ let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, contractNameByAddress, knownHeight, param, selection, itemsTarget, retry, logger) => {
153
153
  let totalTimeRef = Performance.now();
154
154
  let selectionConfig = getSelectionConfig(selection);
155
155
  let logSelections;
@@ -163,7 +163,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
163
163
  Prometheus.SourceRequestCount.increment(name, chain, "getLogs");
164
164
  let pageUnsafe;
165
165
  try {
166
- pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, logSelections, selectionConfig.fieldSelection);
166
+ pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, logSelections, selectionConfig.fieldSelection, itemsTarget);
167
167
  } catch (raw_error) {
168
168
  let error = Primitive_exceptions.internalToException(raw_error);
169
169
  if (error.RE_EXN_ID === HyperSync.GetLogs.$$Error) {