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.
- package/evm.schema.json +10 -0
- package/package.json +7 -7
- package/src/Batch.res.mjs +1 -1
- package/src/BatchProcessing.res +5 -0
- package/src/BatchProcessing.res.mjs +6 -0
- package/src/ChainState.res +41 -7
- package/src/ChainState.res.mjs +22 -18
- package/src/ChainState.resi +3 -1
- package/src/Config.res +3 -0
- package/src/Config.res.mjs +3 -1
- package/src/Core.res +0 -3
- package/src/ExitOnCaughtUp.res +10 -2
- package/src/ExitOnCaughtUp.res.mjs +10 -1
- package/src/FetchState.res +63 -133
- package/src/FetchState.res.mjs +107 -166
- package/src/IndexerState.res +4 -0
- package/src/IndexerState.res.mjs +8 -1
- package/src/IndexerState.resi +1 -0
- package/src/IndexingAddresses.res +105 -0
- package/src/IndexingAddresses.res.mjs +100 -0
- package/src/IndexingAddresses.resi +32 -0
- package/src/Main.res +4 -15
- package/src/Main.res.mjs +6 -14
- package/src/Metrics.res +33 -0
- package/src/Metrics.res.mjs +39 -0
- package/src/Prometheus.res +2 -20
- package/src/Prometheus.res.mjs +83 -95
- package/src/SimulateDeadInputTracker.res +85 -0
- package/src/SimulateDeadInputTracker.res.mjs +73 -0
- package/src/SimulateDeadInputTracker.resi +12 -0
- package/src/SimulateItems.res +23 -42
- package/src/SimulateItems.res.mjs +12 -30
- package/src/TestIndexer.res +3 -27
- package/src/TestIndexer.res.mjs +2 -9
- package/src/bindings/Viem.res +0 -41
- package/src/bindings/Viem.res.mjs +1 -43
- package/src/sources/Evm.res +7 -36
- package/src/sources/Evm.res.mjs +4 -36
- package/src/sources/EvmChain.res +4 -2
- package/src/sources/EvmChain.res.mjs +3 -2
- package/src/sources/EvmRpcClient.res +36 -5
- package/src/sources/EvmRpcClient.res.mjs +7 -4
- package/src/sources/HyperSyncClient.res +0 -35
- package/src/sources/HyperSyncClient.res.mjs +1 -8
- package/src/sources/Rpc.res +15 -47
- package/src/sources/Rpc.res.mjs +25 -56
- package/src/sources/RpcSource.res +289 -204
- package/src/sources/RpcSource.res.mjs +293 -303
- package/src/sources/SimulateSource.res +1 -0
- package/src/sources/SimulateSource.res.mjs +2 -1
- package/src/sources/Source.res +4 -0
- package/src/sources/Svm.res +7 -15
- package/src/sources/Svm.res.mjs +4 -15
- package/src/sources/TransactionStore.res +14 -2
- 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
|
|
108
|
-
let
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
|
114
|
-
if (
|
|
221
|
+
let match$2 = execResult.slice(1);
|
|
222
|
+
if (match$2.length !== 2) {
|
|
115
223
|
return;
|
|
116
224
|
}
|
|
117
|
-
let
|
|
118
|
-
if (
|
|
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
|
|
159
|
-
if (
|
|
160
|
-
return
|
|
229
|
+
let toBlock = match$2[1];
|
|
230
|
+
if (toBlock === undefined) {
|
|
231
|
+
return;
|
|
161
232
|
}
|
|
162
|
-
let match$
|
|
163
|
-
|
|
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
|
-
|
|
166
|
-
|
|
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
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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
|
|
245
|
-
|
|
246
|
-
|
|
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
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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
|
-
|
|
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
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
let
|
|
295
|
-
let
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
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
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
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
|
-
|
|
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
|
|
1041
|
-
let suggestedBlockInterval =
|
|
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
|
|
1047
|
-
let match$
|
|
1048
|
-
let latestFetchedBlockInfo = match$
|
|
1049
|
-
let
|
|
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
|
|
1052
|
-
mutSuggestedBlockIntervals[partitionId] = Primitive_int.min(executedBlockInterval + syncConfig.accelerationAdditive | 0,
|
|
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(
|
|
1075
|
-
let log = param
|
|
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
|
|
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
|
-
|
|
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,
|