envio 3.3.0-alpha.4 → 3.3.0-alpha.6

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 (55) 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/BatchProcessing.res +5 -0
  5. package/src/BatchProcessing.res.mjs +6 -0
  6. package/src/ChainState.res +41 -7
  7. package/src/ChainState.res.mjs +22 -18
  8. package/src/ChainState.resi +3 -1
  9. package/src/Config.res +3 -0
  10. package/src/Config.res.mjs +3 -1
  11. package/src/Core.res +0 -3
  12. package/src/ExitOnCaughtUp.res +10 -2
  13. package/src/ExitOnCaughtUp.res.mjs +10 -1
  14. package/src/FetchState.res +63 -133
  15. package/src/FetchState.res.mjs +107 -166
  16. package/src/IndexerState.res +4 -0
  17. package/src/IndexerState.res.mjs +8 -1
  18. package/src/IndexerState.resi +1 -0
  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/Main.res +4 -15
  23. package/src/Main.res.mjs +6 -14
  24. package/src/Metrics.res +33 -0
  25. package/src/Metrics.res.mjs +39 -0
  26. package/src/Prometheus.res +2 -20
  27. package/src/Prometheus.res.mjs +83 -95
  28. package/src/SimulateDeadInputTracker.res +85 -0
  29. package/src/SimulateDeadInputTracker.res.mjs +73 -0
  30. package/src/SimulateDeadInputTracker.resi +12 -0
  31. package/src/SimulateItems.res +23 -42
  32. package/src/SimulateItems.res.mjs +12 -30
  33. package/src/TestIndexer.res +3 -27
  34. package/src/TestIndexer.res.mjs +2 -9
  35. package/src/bindings/Viem.res +0 -41
  36. package/src/bindings/Viem.res.mjs +1 -43
  37. package/src/sources/Evm.res +7 -36
  38. package/src/sources/Evm.res.mjs +4 -36
  39. package/src/sources/EvmChain.res +4 -2
  40. package/src/sources/EvmChain.res.mjs +3 -2
  41. package/src/sources/EvmRpcClient.res +36 -5
  42. package/src/sources/EvmRpcClient.res.mjs +7 -4
  43. package/src/sources/HyperSyncClient.res +0 -35
  44. package/src/sources/HyperSyncClient.res.mjs +1 -8
  45. package/src/sources/Rpc.res +15 -47
  46. package/src/sources/Rpc.res.mjs +25 -56
  47. package/src/sources/RpcSource.res +289 -204
  48. package/src/sources/RpcSource.res.mjs +293 -303
  49. package/src/sources/SimulateSource.res +1 -0
  50. package/src/sources/SimulateSource.res.mjs +2 -1
  51. package/src/sources/Source.res +4 -0
  52. package/src/sources/Svm.res +7 -15
  53. package/src/sources/Svm.res.mjs +4 -15
  54. package/src/sources/TransactionStore.res +14 -2
  55. package/src/sources/TransactionStore.res.mjs +10 -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";
@@ -21,7 +20,6 @@ import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
21
20
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
22
21
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
23
22
  import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
24
- import * as HyperSyncClient from "./HyperSyncClient.res.mjs";
25
23
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
26
24
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
27
25
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
@@ -78,6 +76,43 @@ async function getKnownRawBlockWithBackoff(client, sourceName, chain, blockNumbe
78
76
  return Stdlib_Option.getOrThrow(result, undefined);
79
77
  }
80
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
+
81
116
  let suggestedRangeRegExp = /retry with the range (\d+)-(\d+)/;
82
117
 
83
118
  let blockRangeLimitRegExp = /limited to a (\d+) blocks range/;
@@ -104,281 +139,288 @@ let publicNodeRegExp = /maximum block range: (\d+)/;
104
139
 
105
140
  let hyperliquidRegExp = /query exceeds max block range (\d+)/;
106
141
 
107
- function parseMessageForBlockRange(message) {
108
- let extractBlockRange = (execResult, isMaxRange) => {
109
- let match = execResult.slice(1);
110
- if (match.length !== 1) {
111
- 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
+ }
112
220
  }
113
- let blockRangeLimit = match[0];
114
- if (blockRangeLimit === undefined) {
221
+ let match$2 = execResult.slice(1);
222
+ if (match$2.length !== 2) {
115
223
  return;
116
224
  }
117
- let blockRangeLimit$1 = Stdlib_Int.fromString(blockRangeLimit, undefined);
118
- if (blockRangeLimit$1 !== undefined && blockRangeLimit$1 > 0) {
119
- return [
120
- blockRangeLimit$1,
121
- isMaxRange
122
- ];
123
- }
124
- };
125
- let execResult = suggestedRangeRegExp.exec(message);
126
- if (execResult == null) {
127
- let execResult$1 = blockRangeLimitRegExp.exec(message);
128
- if (!(execResult$1 == null)) {
129
- return extractBlockRange(execResult$1, true);
130
- }
131
- let execResult$2 = alchemyRangeRegExp.exec(message);
132
- if (!(execResult$2 == null)) {
133
- return extractBlockRange(execResult$2, true);
134
- }
135
- let execResult$3 = cloudflareRangeRegExp.exec(message);
136
- if (!(execResult$3 == null)) {
137
- return extractBlockRange(execResult$3, true);
138
- }
139
- let execResult$4 = thirdwebRangeRegExp.exec(message);
140
- if (!(execResult$4 == null)) {
141
- return extractBlockRange(execResult$4, true);
142
- }
143
- let execResult$5 = blockpiRangeRegExp.exec(message);
144
- if (!(execResult$5 == null)) {
145
- return extractBlockRange(execResult$5, true);
146
- }
147
- let execResult$6 = maxAllowedBlocksRegExp.exec(message);
148
- if (!(execResult$6 == null)) {
149
- return extractBlockRange(execResult$6, true);
150
- }
151
- let match = baseRangeRegExp.exec(message);
152
- if (!(match == null)) {
153
- return [
154
- 2000,
155
- true
156
- ];
225
+ let fromBlock = match$2[0];
226
+ if (fromBlock === undefined) {
227
+ return;
157
228
  }
158
- let execResult$7 = blastPaidRegExp.exec(message);
159
- if (!(execResult$7 == null)) {
160
- return extractBlockRange(execResult$7, true);
229
+ let toBlock = match$2[1];
230
+ if (toBlock === undefined) {
231
+ return;
161
232
  }
162
- let match$1 = chainstackRegExp.exec(message);
163
- 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) {
164
236
  return [
165
- 10000,
166
- true
237
+ (match$4 - match$3 | 0) + 1 | 0,
238
+ false
167
239
  ];
168
- }
169
- let execResult$8 = coinbaseRegExp.exec(message);
170
- if (!(execResult$8 == null)) {
171
- return extractBlockRange(execResult$8, true);
172
- }
173
- let execResult$9 = publicNodeRegExp.exec(message);
174
- if (!(execResult$9 == null)) {
175
- return extractBlockRange(execResult$9, true);
176
- }
177
- let execResult$10 = hyperliquidRegExp.exec(message);
178
- if (!(execResult$10 == null)) {
179
- return extractBlockRange(execResult$10, true);
180
240
  } else {
181
241
  return;
182
242
  }
183
243
  }
184
- let match$2 = execResult.slice(1);
185
- if (match$2.length !== 2) {
186
- return;
187
- }
188
- let fromBlock = match$2[0];
189
- if (fromBlock === undefined) {
190
- return;
191
- }
192
- let toBlock = match$2[1];
193
- if (toBlock === undefined) {
194
- return;
195
- }
196
- let match$3 = Stdlib_Int.fromString(fromBlock, undefined);
197
- let match$4 = Stdlib_Int.fromString(toBlock, undefined);
198
- if (match$3 !== undefined && match$4 !== undefined && match$4 >= match$3) {
199
- return [
200
- (match$4 - match$3 | 0) + 1 | 0,
201
- false
202
- ];
203
- }
204
244
  }
205
245
 
206
- function getSuggestedBlockIntervalFromExn(exn) {
207
- if (exn.RE_EXN_ID === Rpc.JsonRpcError) {
208
- return parseMessageForBlockRange(exn._1.message);
209
- }
210
- if (exn.RE_EXN_ID !== "JsExn") {
211
- return;
212
- }
213
- try {
214
- let message = exn._1.error.message;
215
- S$RescriptSchema.assertOrThrow(message, S$RescriptSchema.string);
216
- return parseMessageForBlockRange(message);
217
- } catch (exn$1) {
218
- return;
219
- }
246
+ let maxSuggestedBlockIntervalKey = "max";
247
+
248
+ function getSourceMaxBlockInterval(mutSuggestedBlockIntervals, intervalCeiling) {
249
+ return Stdlib_Option.getOr(mutSuggestedBlockIntervals[maxSuggestedBlockIntervalKey], intervalCeiling);
220
250
  }
221
251
 
222
- 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
+ }
223
267
 
224
- function getNextPage(fromBlock, toBlock, addresses, topicQuery, loadBlock, sc, client, mutSuggestedBlockIntervals, partitionId, sourceName, chainId) {
268
+ function getNextPage(fromBlock, toBlock, logSelections, loadBlock, sc, rpcClient, mutSuggestedBlockIntervals, partitionId, sourceName, chainId) {
225
269
  let queryTimoutPromise = Time.resolvePromiseAfterDelay(sc.queryTimeoutMillis).then(() => Promise.reject({
226
270
  RE_EXN_ID: QueryTimout,
227
271
  _1: `Query took longer than ` + (sc.queryTimeoutMillis / 1000 | 0).toString() + ` seconds`
228
272
  }));
229
273
  let latestFetchedBlockPromise = loadBlock(toBlock);
230
- Prometheus.SourceRequestCount.increment(sourceName, chainId, "eth_getLogs");
231
- let logsPromise = Rpc.getLogs(client, {
232
- fromBlock: fromBlock,
233
- toBlock: toBlock,
234
- address: addresses,
235
- topics: topicQuery
236
- }).then(async logs => ({
237
- logs: logs,
238
- latestFetchedBlockInfo: await latestFetchedBlockPromise
239
- }));
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
+ }
240
308
  return Stdlib_Promise.$$catch(Promise.race([
241
309
  queryTimoutPromise,
242
310
  logsPromise
243
311
  ]), err => {
244
- let match = getSuggestedBlockIntervalFromExn(err);
245
- if (match !== undefined) {
246
- let nextBlockIntervalTry = match[0];
247
- 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 => {
248
315
  throw {
249
316
  RE_EXN_ID: Source.GetItemsError,
250
317
  _1: {
251
318
  TAG: "FailedGettingItems",
252
319
  exn: err,
253
320
  attemptedToBlock: toBlock,
254
- retry: {
255
- TAG: "WithSuggestedToBlock",
256
- toBlock: (fromBlock + nextBlockIntervalTry | 0) - 1 | 0
257
- }
321
+ retry: retry
258
322
  },
259
323
  Error: new Error()
260
324
  };
261
- }
262
- let executedBlockInterval = (toBlock - fromBlock | 0) + 1 | 0;
263
- let nextBlockIntervalTry$1 = executedBlockInterval * sc.backoffMultiplicative | 0;
264
- mutSuggestedBlockIntervals[partitionId] = nextBlockIntervalTry$1;
265
- throw {
266
- RE_EXN_ID: Source.GetItemsError,
267
- _1: {
268
- TAG: "FailedGettingItems",
269
- exn: err,
270
- attemptedToBlock: toBlock,
271
- 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({
272
338
  TAG: "WithBackoff",
273
339
  message: `Failed getting data for the block range. Will try smaller block range for the next attempt.`,
274
340
  backoffMillis: sc.backoffMillis
275
- }
276
- },
277
- Error: new Error()
278
- };
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);
279
352
  });
280
353
  }
281
354
 
282
355
  function getSelectionConfig(selection, chain) {
283
- let staticTopicSelections = [];
284
- let dynamicEventFilters = [];
285
- selection.eventConfigs.forEach(param => {
286
- let s = param.getEventFiltersOrThrow(chain);
287
- if (s.TAG === "Static") {
288
- staticTopicSelections.push(...s._0);
289
- return;
290
- }
291
- dynamicEventFilters.push(s._0);
292
- });
293
- let match = LogSelection.compressTopicSelections(staticTopicSelections);
294
- let len = match.length;
295
- let getLogSelectionOrThrow;
296
- if (len !== 1) {
297
- if (len !== 0) {
298
- throw {
299
- RE_EXN_ID: Source.GetItemsError,
300
- _1: {
301
- TAG: "UnsupportedSelection",
302
- 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."
303
- },
304
- Error: new Error()
305
- };
306
- }
307
- let len$1 = dynamicEventFilters.length;
308
- if (len$1 !== 1) {
309
- if (len$1 !== 0) {
310
- throw {
311
- RE_EXN_ID: Source.GetItemsError,
312
- _1: {
313
- TAG: "UnsupportedSelection",
314
- 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."
315
- },
316
- Error: new Error()
317
- };
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);
318
381
  }
319
- throw {
320
- RE_EXN_ID: Source.GetItemsError,
321
- _1: {
322
- TAG: "UnsupportedSelection",
323
- message: "Invalid events configuration for the partition. Nothing to fetch. Please, report to the Envio team."
324
- },
325
- Error: new Error()
326
- };
327
382
  }
328
- let dynamicEventFilter = dynamicEventFilters[0];
329
- if (selection.eventConfigs.length === 1) {
330
- let eventConfig = Utils.$$Array.firstUnsafe(selection.eventConfigs);
331
- getLogSelectionOrThrow = addressesByContractName => {
332
- let addresses = FetchState.addressesByContractNameGetAll(addressesByContractName);
333
- let match = dynamicEventFilter(addresses);
334
- if (match.length !== 1) {
335
- throw {
336
- RE_EXN_ID: Source.GetItemsError,
337
- _1: {
338
- TAG: "UnsupportedSelection",
339
- 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."
340
- },
341
- Error: new Error()
342
- };
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;
343
398
  }
344
- return {
345
- addresses: eventConfig.isWildcard ? undefined : addresses,
346
- topicQuery: Rpc.GetLogs.mapTopicQuery(match[0])
347
- };
348
- };
349
- } else {
350
- throw {
351
- RE_EXN_ID: Source.GetItemsError,
352
- _1: {
353
- TAG: "UnsupportedSelection",
354
- 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."
355
- },
356
- Error: new Error()
357
- };
358
- }
359
- } else {
360
- let topicSelection = match[0];
361
- if (dynamicEventFilters.length !== 0) {
362
- throw {
363
- RE_EXN_ID: Source.GetItemsError,
364
- _1: {
365
- TAG: "UnsupportedSelection",
366
- 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."
367
- },
368
- Error: new Error()
369
- };
370
- }
371
- let topicQuery = Rpc.GetLogs.mapTopicQuery(topicSelection);
372
- getLogSelectionOrThrow = addressesByContractName => {
373
- let addresses = FetchState.addressesByContractNameGetAll(addressesByContractName);
374
- return {
375
- addresses: addresses.length !== 0 ? addresses : undefined,
376
- topicQuery: topicQuery
377
- };
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;
378
421
  };
379
- }
380
422
  return {
381
- getLogSelectionOrThrow: getLogSelectionOrThrow
423
+ getLogSelectionsOrThrow: getLogSelectionsOrThrow
382
424
  };
383
425
  }
384
426
 
@@ -918,8 +960,8 @@ function makeThrowingGetEventTransaction(getTransactionJson, getReceiptJson, low
918
960
  }
919
961
 
920
962
  function make(param) {
963
+ let headers = param.headers;
921
964
  let lowercaseAddresses = param.lowercaseAddresses;
922
- let allEventParams = param.allEventParams;
923
965
  let eventRouter = param.eventRouter;
924
966
  let chain = param.chain;
925
967
  let url = param.url;
@@ -929,8 +971,8 @@ function make(param) {
929
971
  let name = `RPC (` + urlHost + `)`;
930
972
  let getSelectionConfig = memoGetSelectionConfig(chain);
931
973
  let mutSuggestedBlockIntervals = {};
932
- let client = Rpc.makeClient(url);
933
- let rpcClient = EvmRpcClient.make(url, undefined);
974
+ let client = Rpc.makeClient(url, headers);
975
+ let rpcClient = EvmRpcClient.make(url, !lowercaseAddresses, undefined, headers, param.allEventParams);
934
976
  let makeTransactionLoader = () => LazyLoader.make(transactionHash => {
935
977
  Prometheus.SourceRequestCount.increment(name, chain, "eth_getTransactionByHash");
936
978
  return Rest.fetch(Rpc.GetTransactionByHash.rawRoute, transactionHash, client);
@@ -998,88 +1040,31 @@ function make(param) {
998
1040
  Error: new Error()
999
1041
  };
1000
1042
  }, lowercaseAddresses);
1001
- let convertLogToHyperSyncEvent = log => {
1002
- let hyperSyncLog_removed = log.removed;
1003
- let hyperSyncLog_logIndex = log.logIndex;
1004
- let hyperSyncLog_transactionIndex = log.transactionIndex;
1005
- let hyperSyncLog_transactionHash = log.transactionHash;
1006
- let hyperSyncLog_blockHash = log.blockHash;
1007
- let hyperSyncLog_blockNumber = log.blockNumber;
1008
- let hyperSyncLog_address = Primitive_option.some(log.address);
1009
- let hyperSyncLog_data = log.data;
1010
- let hyperSyncLog_topics = log.topics;
1011
- let hyperSyncLog = {
1012
- removed: hyperSyncLog_removed,
1013
- logIndex: hyperSyncLog_logIndex,
1014
- transactionIndex: hyperSyncLog_transactionIndex,
1015
- transactionHash: hyperSyncLog_transactionHash,
1016
- blockHash: hyperSyncLog_blockHash,
1017
- blockNumber: hyperSyncLog_blockNumber,
1018
- address: hyperSyncLog_address,
1019
- data: hyperSyncLog_data,
1020
- topics: hyperSyncLog_topics
1021
- };
1022
- return {
1023
- log: hyperSyncLog
1024
- };
1025
- };
1026
- let hscDecoder = {
1027
- contents: undefined
1028
- };
1029
- let getHscDecoder = () => {
1030
- let decoder = hscDecoder.contents;
1031
- if (decoder !== undefined) {
1032
- return decoder;
1033
- }
1034
- let decoder$1 = HyperSyncClient.Decoder.fromParams(allEventParams, !lowercaseAddresses);
1035
- hscDecoder.contents = decoder$1;
1036
- return decoder$1;
1037
- };
1038
1043
  let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, contractNameByAddress, knownHeight, partitionId, selection, retry, param) => {
1039
1044
  let startFetchingBatchTimeRef = Performance.now();
1040
- let maxSuggestedBlockInterval = mutSuggestedBlockIntervals[maxSuggestedBlockIntervalKey];
1041
- 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);
1042
1047
  let toBlock$1 = toBlock !== undefined ? Primitive_int.min(toBlock, knownHeight) : knownHeight;
1043
1048
  let suggestedToBlock = Primitive_int.max(Primitive_int.min((fromBlock + suggestedBlockInterval | 0) - 1 | 0, toBlock$1), fromBlock);
1044
1049
  let firstBlockParentPromise = fromBlock > 0 ? LazyLoader.get(blockLoader.contents, fromBlock - 1 | 0).then(json => parseBlockInfo(json)) : Promise.resolve(undefined);
1045
1050
  let match = getSelectionConfig(selection);
1046
- let match$1 = match.getLogSelectionOrThrow(addressesByContractName);
1047
- let match$2 = await getNextPage(fromBlock, suggestedToBlock, match$1.addresses, match$1.topicQuery, blockNumber => LazyLoader.get(blockLoader.contents, blockNumber).then(parseBlockInfo), syncConfig, client, mutSuggestedBlockIntervals, partitionId, name, chain);
1048
- let latestFetchedBlockInfo = match$2.latestFetchedBlockInfo;
1049
- let logs = match$2.logs;
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;
1050
1055
  let executedBlockInterval = (suggestedToBlock - fromBlock | 0) + 1 | 0;
1051
- if (executedBlockInterval >= suggestedBlockInterval && !(maxSuggestedBlockIntervalKey in mutSuggestedBlockIntervals)) {
1052
- mutSuggestedBlockIntervals[partitionId] = Primitive_int.min(executedBlockInterval + syncConfig.accelerationAdditive | 0, syncConfig.intervalCeiling);
1053
- }
1054
- let hyperSyncEvents = logs.map(convertLogToHyperSyncEvent);
1055
- let parsedEvents;
1056
- try {
1057
- parsedEvents = await getHscDecoder().decodeLogs(hyperSyncEvents);
1058
- } catch (raw_exn) {
1059
- let exn = Primitive_exceptions.internalToException(raw_exn);
1060
- throw {
1061
- RE_EXN_ID: Source.GetItemsError,
1062
- _1: {
1063
- TAG: "FailedGettingItems",
1064
- exn: exn,
1065
- attemptedToBlock: toBlock$1,
1066
- retry: {
1067
- TAG: "ImpossibleForTheQuery",
1068
- message: "Failed to parse events using hypersync client decoder. Please double-check your ABI."
1069
- }
1070
- },
1071
- Error: new Error()
1072
- };
1056
+ if (executedBlockInterval >= suggestedBlockInterval) {
1057
+ mutSuggestedBlockIntervals[partitionId] = Primitive_int.min(executedBlockInterval + syncConfig.accelerationAdditive | 0, sourceMaxBlockInterval);
1073
1058
  }
1074
- let parsedQueueItems = await Promise.all(Stdlib_Array.filterMap(Stdlib_Array.zip(logs, parsedEvents), param => {
1075
- let log = param[0];
1059
+ let parsedQueueItems = await Promise.all(Stdlib_Array.filterMap(items, param => {
1060
+ let log = param.log;
1076
1061
  let topic0 = Stdlib_Option.getOr(log.topics[0], "0x0");
1077
1062
  let routedAddress = lowercaseAddresses ? Address.Evm.fromAddressLowercaseOrThrow(log.address) : Address.Evm.fromAddressOrThrow(log.address);
1078
1063
  let eventConfig = EventRouter.get(eventRouter, EventRouter.getEvmEventId(topic0, log.topics.length), routedAddress, contractNameByAddress);
1079
1064
  if (eventConfig === undefined) {
1080
1065
  return;
1081
1066
  }
1082
- let decoded = Stdlib_Option.flatMap(Primitive_option.fromNullable(param[1]), __x => __x[eventConfig.contractName]);
1067
+ let decoded = Stdlib_Option.flatMap(Primitive_option.fromNullable(param.params), __x => __x[eventConfig.contractName]);
1083
1068
  if (decoded === undefined) {
1084
1069
  return;
1085
1070
  }
@@ -1165,7 +1150,8 @@ function make(param) {
1165
1150
  if (optFirstBlockParent !== undefined) {
1166
1151
  pushBlockInfo(optFirstBlockParent);
1167
1152
  }
1168
- logs.forEach(log => {
1153
+ items.forEach(param => {
1154
+ let log = param.log;
1169
1155
  blockHashes.push({
1170
1156
  blockHash: log.blockHash,
1171
1157
  blockNumber: log.blockNumber
@@ -1239,8 +1225,12 @@ export {
1239
1225
  getKnownRawBlock,
1240
1226
  parseBlockInfo,
1241
1227
  getKnownRawBlockWithBackoff,
1228
+ getErrorMessage,
1229
+ isResponseTooLargeError,
1242
1230
  getSuggestedBlockIntervalFromExn,
1243
1231
  maxSuggestedBlockIntervalKey,
1232
+ getSourceMaxBlockInterval,
1233
+ mergeAndDedupItems,
1244
1234
  getNextPage,
1245
1235
  getSelectionConfig,
1246
1236
  memoGetSelectionConfig,