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
@@ -8,7 +8,6 @@ import * as Source from "./Source.res.mjs";
8
8
  import * as Address from "../Address.res.mjs";
9
9
  import * as Logging from "../Logging.res.mjs";
10
10
  import * as Internal from "../Internal.res.mjs";
11
- import * as FetchState from "../FetchState.res.mjs";
12
11
  import * as LazyLoader from "../LazyLoader.res.mjs";
13
12
  import * as Prometheus from "../Prometheus.res.mjs";
14
13
  import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
@@ -77,6 +76,43 @@ async function getKnownRawBlockWithBackoff(client, sourceName, chain, blockNumbe
77
76
  return Stdlib_Option.getOrThrow(result, undefined);
78
77
  }
79
78
 
79
+ function getErrorMessage(exn) {
80
+ if (exn.RE_EXN_ID === Rpc.JsonRpcError) {
81
+ return exn._1.message;
82
+ }
83
+ if (exn.RE_EXN_ID !== "JsExn") {
84
+ return;
85
+ }
86
+ try {
87
+ let message = exn._1.error.message;
88
+ S$RescriptSchema.assertOrThrow(message, S$RescriptSchema.string);
89
+ return message;
90
+ } catch (exn$1) {
91
+ return;
92
+ }
93
+ }
94
+
95
+ let patterns = [
96
+ /more than \d+ logs/i,
97
+ /\d+ logs returned/i,
98
+ /too many logs/i,
99
+ /query returned more than \d+ results/i,
100
+ /query exceeds max results/i,
101
+ /response size should not/i,
102
+ /(backend )?response too large/i,
103
+ /logs matched by query exceeds limit/i,
104
+ /block range is too wide/i
105
+ ];
106
+
107
+ function isResponseTooLargeError(exn) {
108
+ let message = getErrorMessage(exn);
109
+ if (message !== undefined) {
110
+ return patterns.some(re => re.test(message));
111
+ } else {
112
+ return false;
113
+ }
114
+ }
115
+
80
116
  let suggestedRangeRegExp = /retry with the range (\d+)-(\d+)/;
81
117
 
82
118
  let blockRangeLimitRegExp = /limited to a (\d+) blocks range/;
@@ -103,289 +139,288 @@ let publicNodeRegExp = /maximum block range: (\d+)/;
103
139
 
104
140
  let hyperliquidRegExp = /query exceeds max block range (\d+)/;
105
141
 
106
- function parseMessageForBlockRange(message) {
107
- let extractBlockRange = (execResult, isMaxRange) => {
108
- let match = execResult.slice(1);
109
- if (match.length !== 1) {
110
- return;
142
+ function getSuggestedBlockIntervalFromExn(exn) {
143
+ let message = getErrorMessage(exn);
144
+ if (message !== undefined) {
145
+ let extractBlockRange = (execResult, isMaxRange) => {
146
+ let match = execResult.slice(1);
147
+ if (match.length !== 1) {
148
+ return;
149
+ }
150
+ let blockRangeLimit = match[0];
151
+ if (blockRangeLimit === undefined) {
152
+ return;
153
+ }
154
+ let blockRangeLimit$1 = Stdlib_Int.fromString(blockRangeLimit, undefined);
155
+ if (blockRangeLimit$1 !== undefined && blockRangeLimit$1 > 0) {
156
+ return [
157
+ blockRangeLimit$1,
158
+ isMaxRange
159
+ ];
160
+ }
161
+ };
162
+ let execResult = suggestedRangeRegExp.exec(message);
163
+ if (execResult == null) {
164
+ let execResult$1 = blockRangeLimitRegExp.exec(message);
165
+ if (!(execResult$1 == null)) {
166
+ return extractBlockRange(execResult$1, true);
167
+ }
168
+ let execResult$2 = alchemyRangeRegExp.exec(message);
169
+ if (!(execResult$2 == null)) {
170
+ return extractBlockRange(execResult$2, true);
171
+ }
172
+ let execResult$3 = cloudflareRangeRegExp.exec(message);
173
+ if (!(execResult$3 == null)) {
174
+ return extractBlockRange(execResult$3, true);
175
+ }
176
+ let execResult$4 = thirdwebRangeRegExp.exec(message);
177
+ if (!(execResult$4 == null)) {
178
+ return extractBlockRange(execResult$4, true);
179
+ }
180
+ let execResult$5 = blockpiRangeRegExp.exec(message);
181
+ if (!(execResult$5 == null)) {
182
+ return extractBlockRange(execResult$5, true);
183
+ }
184
+ let execResult$6 = maxAllowedBlocksRegExp.exec(message);
185
+ if (!(execResult$6 == null)) {
186
+ return extractBlockRange(execResult$6, true);
187
+ }
188
+ let match = baseRangeRegExp.exec(message);
189
+ if (!(match == null)) {
190
+ return [
191
+ 2000,
192
+ true
193
+ ];
194
+ }
195
+ let execResult$7 = blastPaidRegExp.exec(message);
196
+ if (!(execResult$7 == null)) {
197
+ return extractBlockRange(execResult$7, true);
198
+ }
199
+ let match$1 = chainstackRegExp.exec(message);
200
+ if (!(match$1 == null)) {
201
+ return [
202
+ 10000,
203
+ true
204
+ ];
205
+ }
206
+ let execResult$8 = coinbaseRegExp.exec(message);
207
+ if (!(execResult$8 == null)) {
208
+ return extractBlockRange(execResult$8, true);
209
+ }
210
+ let execResult$9 = publicNodeRegExp.exec(message);
211
+ if (!(execResult$9 == null)) {
212
+ return extractBlockRange(execResult$9, true);
213
+ }
214
+ let execResult$10 = hyperliquidRegExp.exec(message);
215
+ if (!(execResult$10 == null)) {
216
+ return extractBlockRange(execResult$10, true);
217
+ } else {
218
+ return;
219
+ }
111
220
  }
112
- let blockRangeLimit = match[0];
113
- if (blockRangeLimit === undefined) {
221
+ let match$2 = execResult.slice(1);
222
+ if (match$2.length !== 2) {
114
223
  return;
115
224
  }
116
- let blockRangeLimit$1 = Stdlib_Int.fromString(blockRangeLimit, undefined);
117
- if (blockRangeLimit$1 !== undefined && blockRangeLimit$1 > 0) {
118
- return [
119
- blockRangeLimit$1,
120
- isMaxRange
121
- ];
122
- }
123
- };
124
- let execResult = suggestedRangeRegExp.exec(message);
125
- if (execResult == null) {
126
- let execResult$1 = blockRangeLimitRegExp.exec(message);
127
- if (!(execResult$1 == null)) {
128
- return extractBlockRange(execResult$1, true);
129
- }
130
- let execResult$2 = alchemyRangeRegExp.exec(message);
131
- if (!(execResult$2 == null)) {
132
- return extractBlockRange(execResult$2, true);
133
- }
134
- let execResult$3 = cloudflareRangeRegExp.exec(message);
135
- if (!(execResult$3 == null)) {
136
- return extractBlockRange(execResult$3, true);
137
- }
138
- let execResult$4 = thirdwebRangeRegExp.exec(message);
139
- if (!(execResult$4 == null)) {
140
- return extractBlockRange(execResult$4, true);
141
- }
142
- let execResult$5 = blockpiRangeRegExp.exec(message);
143
- if (!(execResult$5 == null)) {
144
- return extractBlockRange(execResult$5, true);
145
- }
146
- let execResult$6 = maxAllowedBlocksRegExp.exec(message);
147
- if (!(execResult$6 == null)) {
148
- return extractBlockRange(execResult$6, true);
149
- }
150
- let match = baseRangeRegExp.exec(message);
151
- if (!(match == null)) {
152
- return [
153
- 2000,
154
- true
155
- ];
225
+ let fromBlock = match$2[0];
226
+ if (fromBlock === undefined) {
227
+ return;
156
228
  }
157
- let execResult$7 = blastPaidRegExp.exec(message);
158
- if (!(execResult$7 == null)) {
159
- return extractBlockRange(execResult$7, true);
229
+ let toBlock = match$2[1];
230
+ if (toBlock === undefined) {
231
+ return;
160
232
  }
161
- let match$1 = chainstackRegExp.exec(message);
162
- if (!(match$1 == null)) {
233
+ let match$3 = Stdlib_Int.fromString(fromBlock, undefined);
234
+ let match$4 = Stdlib_Int.fromString(toBlock, undefined);
235
+ if (match$3 !== undefined && match$4 !== undefined && match$4 >= match$3) {
163
236
  return [
164
- 10000,
165
- true
237
+ (match$4 - match$3 | 0) + 1 | 0,
238
+ false
166
239
  ];
167
- }
168
- let execResult$8 = coinbaseRegExp.exec(message);
169
- if (!(execResult$8 == null)) {
170
- return extractBlockRange(execResult$8, true);
171
- }
172
- let execResult$9 = publicNodeRegExp.exec(message);
173
- if (!(execResult$9 == null)) {
174
- return extractBlockRange(execResult$9, true);
175
- }
176
- let execResult$10 = hyperliquidRegExp.exec(message);
177
- if (!(execResult$10 == null)) {
178
- return extractBlockRange(execResult$10, true);
179
240
  } else {
180
241
  return;
181
242
  }
182
243
  }
183
- let match$2 = execResult.slice(1);
184
- if (match$2.length !== 2) {
185
- return;
186
- }
187
- let fromBlock = match$2[0];
188
- if (fromBlock === undefined) {
189
- return;
190
- }
191
- let toBlock = match$2[1];
192
- if (toBlock === undefined) {
193
- return;
194
- }
195
- let match$3 = Stdlib_Int.fromString(fromBlock, undefined);
196
- let match$4 = Stdlib_Int.fromString(toBlock, undefined);
197
- if (match$3 !== undefined && match$4 !== undefined && match$4 >= match$3) {
198
- return [
199
- (match$4 - match$3 | 0) + 1 | 0,
200
- false
201
- ];
202
- }
203
244
  }
204
245
 
205
- function getSuggestedBlockIntervalFromExn(exn) {
206
- if (exn.RE_EXN_ID === Rpc.JsonRpcError) {
207
- return parseMessageForBlockRange(exn._1.message);
208
- }
209
- if (exn.RE_EXN_ID !== "JsExn") {
210
- return;
211
- }
212
- try {
213
- let message = exn._1.error.message;
214
- S$RescriptSchema.assertOrThrow(message, S$RescriptSchema.string);
215
- return parseMessageForBlockRange(message);
216
- } catch (exn$1) {
217
- return;
218
- }
246
+ let maxSuggestedBlockIntervalKey = "max";
247
+
248
+ function getSourceMaxBlockInterval(mutSuggestedBlockIntervals, intervalCeiling) {
249
+ return Stdlib_Option.getOr(mutSuggestedBlockIntervals[maxSuggestedBlockIntervalKey], intervalCeiling);
219
250
  }
220
251
 
221
- let maxSuggestedBlockIntervalKey = "max";
252
+ function mergeAndDedupItems(itemsPerSelection) {
253
+ let seen = new Set();
254
+ let merged = [];
255
+ itemsPerSelection.forEach(items => {
256
+ items.forEach(item => {
257
+ let key = item.log.blockNumber.toString() + `-` + item.log.logIndex.toString();
258
+ if (!seen.has(key)) {
259
+ seen.add(key);
260
+ merged.push(item);
261
+ return;
262
+ }
263
+ });
264
+ });
265
+ return merged;
266
+ }
222
267
 
223
- function getNextPage(fromBlock, toBlock, addresses, topicQuery, loadBlock, sc, rpcClient, mutSuggestedBlockIntervals, partitionId, sourceName, chainId) {
268
+ function getNextPage(fromBlock, toBlock, logSelections, loadBlock, sc, rpcClient, mutSuggestedBlockIntervals, partitionId, sourceName, chainId) {
224
269
  let queryTimoutPromise = Time.resolvePromiseAfterDelay(sc.queryTimeoutMillis).then(() => Promise.reject({
225
270
  RE_EXN_ID: QueryTimout,
226
271
  _1: `Query took longer than ` + (sc.queryTimeoutMillis / 1000 | 0).toString() + ` seconds`
227
272
  }));
228
273
  let latestFetchedBlockPromise = loadBlock(toBlock);
229
- Prometheus.SourceRequestCount.increment(sourceName, chainId, "eth_getLogs");
230
- let logsPromise = rpcClient.getLogs({
231
- fromBlock: fromBlock,
232
- toBlock: toBlock,
233
- addresses: addresses,
234
- topics: topicQuery.map(filter => {
235
- if (filter === null) {
236
- return null;
237
- } else if (typeof filter === "string") {
238
- return [filter];
239
- } else {
240
- return filter;
241
- }
242
- })
243
- }).then(async items => ({
244
- items: items,
245
- latestFetchedBlockInfo: await latestFetchedBlockPromise
246
- }));
274
+ let queryLogs = param => {
275
+ Prometheus.SourceRequestCount.increment(sourceName, chainId, "eth_getLogs");
276
+ return rpcClient.getLogs({
277
+ fromBlock: fromBlock,
278
+ toBlock: toBlock,
279
+ addresses: param.addresses,
280
+ topics: param.topicQuery.map(filter => {
281
+ if (filter === null) {
282
+ return null;
283
+ } else if (typeof filter === "string") {
284
+ return [filter];
285
+ } else {
286
+ return filter;
287
+ }
288
+ })
289
+ });
290
+ };
291
+ let len = logSelections.length;
292
+ let logsPromise;
293
+ if (len !== 1) {
294
+ logsPromise = len !== 0 ? Promise.all(logSelections.map(queryLogs)).then(async itemsPerSelection => ({
295
+ items: mergeAndDedupItems(itemsPerSelection),
296
+ latestFetchedBlockInfo: await latestFetchedBlockPromise
297
+ })) : latestFetchedBlockPromise.then(latestFetchedBlockInfo => ({
298
+ items: [],
299
+ latestFetchedBlockInfo: latestFetchedBlockInfo
300
+ }));
301
+ } else {
302
+ let logSelection = logSelections[0];
303
+ logsPromise = queryLogs(logSelection).then(async items => ({
304
+ items: items,
305
+ latestFetchedBlockInfo: await latestFetchedBlockPromise
306
+ }));
307
+ }
247
308
  return Stdlib_Promise.$$catch(Promise.race([
248
309
  queryTimoutPromise,
249
310
  logsPromise
250
311
  ]), err => {
251
- let match = getSuggestedBlockIntervalFromExn(err);
252
- if (match !== undefined) {
253
- let nextBlockIntervalTry = match[0];
254
- mutSuggestedBlockIntervals[match[1] ? maxSuggestedBlockIntervalKey : partitionId] = nextBlockIntervalTry;
312
+ let executedBlockInterval = (toBlock - fromBlock | 0) + 1 | 0;
313
+ let shrunkBlockInterval = Primitive_int.max(1, executedBlockInterval * sc.backoffMultiplicative | 0);
314
+ let throwFailedGettingItems = retry => {
255
315
  throw {
256
316
  RE_EXN_ID: Source.GetItemsError,
257
317
  _1: {
258
318
  TAG: "FailedGettingItems",
259
319
  exn: err,
260
320
  attemptedToBlock: toBlock,
261
- retry: {
262
- TAG: "WithSuggestedToBlock",
263
- toBlock: (fromBlock + nextBlockIntervalTry | 0) - 1 | 0
264
- }
321
+ retry: retry
265
322
  },
266
323
  Error: new Error()
267
324
  };
268
- }
269
- let executedBlockInterval = (toBlock - fromBlock | 0) + 1 | 0;
270
- let nextBlockIntervalTry$1 = executedBlockInterval * sc.backoffMultiplicative | 0;
271
- mutSuggestedBlockIntervals[partitionId] = nextBlockIntervalTry$1;
272
- throw {
273
- RE_EXN_ID: Source.GetItemsError,
274
- _1: {
275
- TAG: "FailedGettingItems",
276
- exn: err,
277
- attemptedToBlock: toBlock,
278
- retry: {
325
+ };
326
+ let throwResize = interval => throwFailedGettingItems({
327
+ TAG: "WithSuggestedToBlock",
328
+ toBlock: (fromBlock + interval | 0) - 1 | 0
329
+ });
330
+ let match = getSuggestedBlockIntervalFromExn(err);
331
+ if (match === undefined) {
332
+ if (executedBlockInterval > 1 && isResponseTooLargeError(err)) {
333
+ mutSuggestedBlockIntervals[partitionId] = shrunkBlockInterval;
334
+ return throwResize(shrunkBlockInterval);
335
+ } else {
336
+ mutSuggestedBlockIntervals[partitionId] = shrunkBlockInterval;
337
+ return throwFailedGettingItems({
279
338
  TAG: "WithBackoff",
280
339
  message: `Failed getting data for the block range. Will try smaller block range for the next attempt.`,
281
340
  backoffMillis: sc.backoffMillis
282
- }
283
- },
284
- Error: new Error()
285
- };
341
+ });
342
+ }
343
+ }
344
+ let interval = match[0];
345
+ if (match[1]) {
346
+ let capped = Primitive_int.min(getSourceMaxBlockInterval(mutSuggestedBlockIntervals, sc.intervalCeiling), interval);
347
+ mutSuggestedBlockIntervals[maxSuggestedBlockIntervalKey] = capped;
348
+ return throwResize(capped);
349
+ }
350
+ mutSuggestedBlockIntervals[partitionId] = interval;
351
+ return throwResize(interval);
286
352
  });
287
353
  }
288
354
 
289
355
  function getSelectionConfig(selection, chain) {
290
- let staticTopicSelections = [];
291
- let dynamicEventFilters = [];
292
- selection.eventConfigs.forEach(param => {
293
- let s = param.getEventFiltersOrThrow(chain);
294
- if (s.TAG === "Static") {
295
- staticTopicSelections.push(...s._0);
296
- return;
297
- }
298
- dynamicEventFilters.push(s._0);
299
- });
300
- let match = LogSelection.compressTopicSelections(staticTopicSelections);
301
- let len = match.length;
302
- let getLogSelectionOrThrow;
303
- if (len !== 1) {
304
- if (len !== 0) {
305
- throw {
306
- RE_EXN_ID: Source.GetItemsError,
307
- _1: {
308
- TAG: "UnsupportedSelection",
309
- message: "RPC data-source currently supports event filters only when there's a single wildcard event. Please, create a GitHub issue if it's a blocker for you."
310
- },
311
- Error: new Error()
312
- };
313
- }
314
- let len$1 = dynamicEventFilters.length;
315
- if (len$1 !== 1) {
316
- if (len$1 !== 0) {
317
- throw {
318
- RE_EXN_ID: Source.GetItemsError,
319
- _1: {
320
- TAG: "UnsupportedSelection",
321
- message: "RPC data-source currently supports event filters only when there's a single wildcard event. Please, create a GitHub issue if it's a blocker for you."
322
- },
323
- Error: new Error()
324
- };
356
+ let evmEventConfigs = selection.eventConfigs;
357
+ if (Utils.$$Array.isEmpty(evmEventConfigs)) {
358
+ throw {
359
+ RE_EXN_ID: Source.GetItemsError,
360
+ _1: {
361
+ TAG: "UnsupportedSelection",
362
+ message: "Invalid events configuration for the partition. Nothing to fetch. Please, report to the Envio team."
363
+ },
364
+ Error: new Error()
365
+ };
366
+ }
367
+ let noAddressTopicSelections = [];
368
+ let staticByContract = {};
369
+ let dynamicByContract = {};
370
+ let dynamicWildcardByContract = {};
371
+ let contractNames = new Set();
372
+ evmEventConfigs.forEach(param => {
373
+ let contractName = param.contractName;
374
+ let eventFilters = param.getEventFiltersOrThrow(chain);
375
+ if (param.dependsOnAddresses) {
376
+ contractNames.add(contractName);
377
+ if (eventFilters.TAG === "Static") {
378
+ return Utils.Dict.pushMany(staticByContract, contractName, eventFilters._0);
379
+ } else {
380
+ return Utils.Dict.push(param.isWildcard ? dynamicWildcardByContract : dynamicByContract, contractName, eventFilters._0);
325
381
  }
326
- throw {
327
- RE_EXN_ID: Source.GetItemsError,
328
- _1: {
329
- TAG: "UnsupportedSelection",
330
- message: "Invalid events configuration for the partition. Nothing to fetch. Please, report to the Envio team."
331
- },
332
- Error: new Error()
333
- };
334
382
  }
335
- let dynamicEventFilter = dynamicEventFilters[0];
336
- if (selection.eventConfigs.length === 1) {
337
- let eventConfig = Utils.$$Array.firstUnsafe(selection.eventConfigs);
338
- getLogSelectionOrThrow = addressesByContractName => {
339
- let addresses = FetchState.addressesByContractNameGetAll(addressesByContractName);
340
- let match = dynamicEventFilter(addresses);
341
- if (match.length !== 1) {
342
- throw {
343
- RE_EXN_ID: Source.GetItemsError,
344
- _1: {
345
- TAG: "UnsupportedSelection",
346
- message: "RPC data-source currently doesn't support an array of event filters. Please, create a GitHub issue if it's a blocker for you."
347
- },
348
- Error: new Error()
349
- };
383
+ let tmp;
384
+ tmp = eventFilters.TAG === "Static" ? eventFilters._0 : eventFilters._0([]);
385
+ noAddressTopicSelections.push(...tmp);
386
+ });
387
+ let toLogSelections = (addresses, topicSelections) => LogSelection.compressTopicSelections(topicSelections).map(topicSelection => ({
388
+ addresses: addresses,
389
+ topicQuery: Rpc.GetLogs.mapTopicQuery(topicSelection)
390
+ }));
391
+ let noAddressLogSelections = toLogSelections(undefined, noAddressTopicSelections);
392
+ let getLogSelectionsOrThrow = contractNames.size === 0 ? param => noAddressLogSelections : addressesByContractName => {
393
+ let logSelections = noAddressLogSelections.slice();
394
+ contractNames.forEach(contractName => {
395
+ let addresses = addressesByContractName[contractName];
396
+ if (addresses === undefined) {
397
+ return;
350
398
  }
351
- return {
352
- addresses: eventConfig.isWildcard ? undefined : addresses,
353
- topicQuery: Rpc.GetLogs.mapTopicQuery(match[0])
354
- };
355
- };
356
- } else {
357
- throw {
358
- RE_EXN_ID: Source.GetItemsError,
359
- _1: {
360
- TAG: "UnsupportedSelection",
361
- message: "RPC data-source currently supports event filters only when there's a single wildcard event. Please, create a GitHub issue if it's a blocker for you."
362
- },
363
- Error: new Error()
364
- };
365
- }
366
- } else {
367
- let topicSelection = match[0];
368
- if (dynamicEventFilters.length !== 0) {
369
- throw {
370
- RE_EXN_ID: Source.GetItemsError,
371
- _1: {
372
- TAG: "UnsupportedSelection",
373
- message: "RPC data-source currently supports event filters only when there's a single wildcard event. Please, create a GitHub issue if it's a blocker for you."
374
- },
375
- Error: new Error()
376
- };
377
- }
378
- let topicQuery = Rpc.GetLogs.mapTopicQuery(topicSelection);
379
- getLogSelectionOrThrow = addressesByContractName => {
380
- let addresses = FetchState.addressesByContractNameGetAll(addressesByContractName);
381
- return {
382
- addresses: addresses.length !== 0 ? addresses : undefined,
383
- topicQuery: topicQuery
384
- };
399
+ if (addresses.length === 0) {
400
+ return;
401
+ }
402
+ let addressedTopicSelections = [];
403
+ let s = staticByContract[contractName];
404
+ if (s !== undefined) {
405
+ addressedTopicSelections.push(...s);
406
+ }
407
+ let fns = dynamicByContract[contractName];
408
+ if (fns !== undefined) {
409
+ fns.forEach(fn => {
410
+ addressedTopicSelections.push(...fn(addresses));
411
+ });
412
+ }
413
+ logSelections.push(...toLogSelections(addresses, addressedTopicSelections));
414
+ let fns$1 = dynamicWildcardByContract[contractName];
415
+ if (fns$1 !== undefined) {
416
+ logSelections.push(...toLogSelections(undefined, fns$1.flatMap(fn => fn(addresses))));
417
+ return;
418
+ }
419
+ });
420
+ return logSelections;
385
421
  };
386
- }
387
422
  return {
388
- getLogSelectionOrThrow: getLogSelectionOrThrow
423
+ getLogSelectionsOrThrow: getLogSelectionsOrThrow
389
424
  };
390
425
  }
391
426
 
@@ -1005,21 +1040,21 @@ function make(param) {
1005
1040
  Error: new Error()
1006
1041
  };
1007
1042
  }, lowercaseAddresses);
1008
- let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, contractNameByAddress, knownHeight, partitionId, selection, retry, param) => {
1043
+ let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, contractNameByAddress, knownHeight, partitionId, selection, param, retry, param$1) => {
1009
1044
  let startFetchingBatchTimeRef = Performance.now();
1010
- let maxSuggestedBlockInterval = mutSuggestedBlockIntervals[maxSuggestedBlockIntervalKey];
1011
- let suggestedBlockInterval = maxSuggestedBlockInterval !== undefined ? maxSuggestedBlockInterval : Stdlib_Option.getOr(mutSuggestedBlockIntervals[partitionId], syncConfig.initialBlockInterval);
1045
+ let sourceMaxBlockInterval = getSourceMaxBlockInterval(mutSuggestedBlockIntervals, syncConfig.intervalCeiling);
1046
+ let suggestedBlockInterval = Primitive_int.min(Stdlib_Option.getOr(mutSuggestedBlockIntervals[partitionId], syncConfig.initialBlockInterval), sourceMaxBlockInterval);
1012
1047
  let toBlock$1 = toBlock !== undefined ? Primitive_int.min(toBlock, knownHeight) : knownHeight;
1013
1048
  let suggestedToBlock = Primitive_int.max(Primitive_int.min((fromBlock + suggestedBlockInterval | 0) - 1 | 0, toBlock$1), fromBlock);
1014
1049
  let firstBlockParentPromise = fromBlock > 0 ? LazyLoader.get(blockLoader.contents, fromBlock - 1 | 0).then(json => parseBlockInfo(json)) : Promise.resolve(undefined);
1015
1050
  let match = getSelectionConfig(selection);
1016
- let match$1 = match.getLogSelectionOrThrow(addressesByContractName);
1017
- let match$2 = await getNextPage(fromBlock, suggestedToBlock, match$1.addresses, match$1.topicQuery, blockNumber => LazyLoader.get(blockLoader.contents, blockNumber).then(parseBlockInfo), syncConfig, rpcClient, mutSuggestedBlockIntervals, partitionId, name, chain);
1018
- let latestFetchedBlockInfo = match$2.latestFetchedBlockInfo;
1019
- let items = match$2.items;
1051
+ let logSelections = match.getLogSelectionsOrThrow(addressesByContractName);
1052
+ let match$1 = await getNextPage(fromBlock, suggestedToBlock, logSelections, blockNumber => LazyLoader.get(blockLoader.contents, blockNumber).then(parseBlockInfo), syncConfig, rpcClient, mutSuggestedBlockIntervals, partitionId, name, chain);
1053
+ let latestFetchedBlockInfo = match$1.latestFetchedBlockInfo;
1054
+ let items = match$1.items;
1020
1055
  let executedBlockInterval = (suggestedToBlock - fromBlock | 0) + 1 | 0;
1021
- if (executedBlockInterval >= suggestedBlockInterval && !(maxSuggestedBlockIntervalKey in mutSuggestedBlockIntervals)) {
1022
- mutSuggestedBlockIntervals[partitionId] = Primitive_int.min(executedBlockInterval + syncConfig.accelerationAdditive | 0, syncConfig.intervalCeiling);
1056
+ if (executedBlockInterval >= suggestedBlockInterval) {
1057
+ mutSuggestedBlockIntervals[partitionId] = Primitive_int.min(executedBlockInterval + syncConfig.accelerationAdditive | 0, sourceMaxBlockInterval);
1023
1058
  }
1024
1059
  let parsedQueueItems = await Promise.all(Stdlib_Array.filterMap(items, param => {
1025
1060
  let log = param.log;
@@ -1190,8 +1225,12 @@ export {
1190
1225
  getKnownRawBlock,
1191
1226
  parseBlockInfo,
1192
1227
  getKnownRawBlockWithBackoff,
1228
+ getErrorMessage,
1229
+ isResponseTooLargeError,
1193
1230
  getSuggestedBlockIntervalFromExn,
1194
1231
  maxSuggestedBlockIntervalKey,
1232
+ getSourceMaxBlockInterval,
1233
+ mergeAndDedupItems,
1195
1234
  getNextPage,
1196
1235
  getSelectionConfig,
1197
1236
  memoGetSelectionConfig,
@@ -6,6 +6,7 @@ let make = (~items: array<Internal.item>, ~endBlock: int, ~chain: ChainMap.Chain
6
6
 
7
7
  {
8
8
  name: "SimulateSource",
9
+ simulateItems: items,
9
10
  sourceFor: Sync,
10
11
  chain,
11
12
  poweredByHyperSync: false,
@@ -25,6 +26,7 @@ let make = (~items: array<Internal.item>, ~endBlock: int, ~chain: ChainMap.Chain
25
26
  ~knownHeight as _,
26
27
  ~partitionId as _,
27
28
  ~selection as _,
29
+ ~itemsTarget as _,
28
30
  ~retry as _,
29
31
  ~logger as _,
30
32
  ) => {
@@ -17,7 +17,7 @@ function make(items, endBlock, chain) {
17
17
  _0: []
18
18
  }),
19
19
  getHeightOrThrow: () => Promise.resolve(Primitive_int.max(endBlock, 1)),
20
- getItemsOrThrow: (param, param$1, param$2, param$3, param$4, param$5, param$6, param$7, param$8) => {
20
+ getItemsOrThrow: (param, param$1, param$2, param$3, param$4, param$5, param$6, param$7, param$8, param$9) => {
21
21
  let result = delivered.contents ? [] : (delivered.contents = true, items);
22
22
  let reportedHeight = Primitive_int.max(endBlock, 1);
23
23
  return Promise.resolve({
@@ -32,7 +32,8 @@ function make(items, endBlock, chain) {
32
32
  "total time elapsed (s)": 0
33
33
  }
34
34
  });
35
- }
35
+ },
36
+ simulateItems: items
36
37
  };
37
38
  }
38
39