envio 3.3.0-alpha.7 → 3.3.0-alpha.9
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/index.d.ts +23 -5
- package/package.json +6 -6
- package/src/Api.res +1 -1
- package/src/Api.res.mjs +1 -1
- package/src/ChainFetching.res +21 -10
- package/src/ChainFetching.res.mjs +11 -10
- package/src/ChainState.res +401 -171
- package/src/ChainState.res.mjs +270 -104
- package/src/ChainState.resi +19 -7
- package/src/Config.res +11 -27
- package/src/Config.res.mjs +8 -7
- package/src/Core.res +7 -0
- package/src/CrossChainState.res +82 -82
- package/src/CrossChainState.res.mjs +52 -59
- package/src/CrossChainState.resi +1 -1
- package/src/Ecosystem.res +3 -3
- package/src/Ecosystem.res.mjs +3 -3
- package/src/Envio.res +14 -9
- package/src/EnvioGlobal.res +53 -0
- package/src/EnvioGlobal.res.mjs +31 -0
- package/src/EventConfigBuilder.res +117 -69
- package/src/EventConfigBuilder.res.mjs +71 -34
- package/src/EventProcessing.res +19 -15
- package/src/EventProcessing.res.mjs +13 -12
- package/src/FetchState.res +410 -185
- package/src/FetchState.res.mjs +268 -253
- package/src/HandlerLoader.res +8 -113
- package/src/HandlerLoader.res.mjs +2 -88
- package/src/HandlerRegister.res +518 -144
- package/src/HandlerRegister.res.mjs +285 -133
- package/src/HandlerRegister.resi +24 -8
- package/src/IndexerState.res +6 -3
- package/src/IndexerState.res.mjs +3 -3
- package/src/IndexerState.resi +1 -1
- package/src/IndexingAddresses.res +10 -7
- package/src/IndexingAddresses.res.mjs +8 -7
- package/src/IndexingAddresses.resi +3 -1
- package/src/Internal.res +104 -39
- package/src/Internal.res.mjs +11 -1
- package/src/LogSelection.res +102 -165
- package/src/LogSelection.res.mjs +101 -116
- package/src/Main.res +49 -164
- package/src/Main.res.mjs +39 -104
- package/src/Metrics.res +43 -2
- package/src/Metrics.res.mjs +39 -3
- package/src/Prometheus.res +0 -35
- package/src/Prometheus.res.mjs +33 -68
- package/src/RawEvent.res +7 -2
- package/src/RawEvent.res.mjs +4 -4
- package/src/RollbackCommit.res +4 -1
- package/src/RollbackCommit.res.mjs +3 -2
- package/src/SimulateItems.res +20 -7
- package/src/SimulateItems.res.mjs +7 -11
- package/src/TestIndexer.res +1 -1
- package/src/TestIndexer.res.mjs +1 -1
- package/src/sources/BlockStore.res +46 -0
- package/src/sources/BlockStore.res.mjs +24 -0
- package/src/sources/EventRouter.res +19 -12
- package/src/sources/EventRouter.res.mjs +7 -5
- package/src/sources/Evm.res +58 -5
- package/src/sources/Evm.res.mjs +44 -5
- package/src/sources/EvmChain.res +14 -18
- package/src/sources/EvmChain.res.mjs +12 -13
- package/src/sources/FieldMask.res +39 -0
- package/src/sources/FieldMask.res.mjs +42 -0
- package/src/sources/Fuel.res +8 -3
- package/src/sources/Fuel.res.mjs +5 -4
- package/src/sources/HyperFuelSource.res +31 -40
- package/src/sources/HyperFuelSource.res.mjs +52 -44
- package/src/sources/HyperSync.res +31 -9
- package/src/sources/HyperSync.res.mjs +47 -31
- package/src/sources/HyperSync.resi +10 -3
- package/src/sources/HyperSyncClient.res +15 -4
- package/src/sources/HyperSyncHeightStream.res +1 -8
- package/src/sources/HyperSyncHeightStream.res.mjs +0 -2
- package/src/sources/HyperSyncSource.res +58 -90
- package/src/sources/HyperSyncSource.res.mjs +57 -66
- package/src/sources/RpcSource.res +118 -120
- package/src/sources/RpcSource.res.mjs +92 -74
- package/src/sources/RpcWebSocketHeightStream.res +0 -5
- package/src/sources/RpcWebSocketHeightStream.res.mjs +0 -2
- package/src/sources/SimulateSource.res +5 -3
- package/src/sources/SimulateSource.res.mjs +12 -4
- package/src/sources/Source.res +19 -5
- package/src/sources/SourceManager.res +60 -10
- package/src/sources/SourceManager.res.mjs +54 -8
- package/src/sources/SourceManager.resi +10 -0
- package/src/sources/Svm.res +14 -10
- package/src/sources/Svm.res.mjs +23 -6
- package/src/sources/SvmHyperSyncClient.res +5 -6
- package/src/sources/SvmHyperSyncSource.res +82 -41
- package/src/sources/SvmHyperSyncSource.res.mjs +86 -41
- package/src/sources/TransactionStore.res +6 -107
- package/src/sources/TransactionStore.res.mjs +5 -86
- package/svm.schema.json +19 -0
|
@@ -13,7 +13,7 @@ type selectionConfig = {
|
|
|
13
13
|
getRecieptsSelection: (
|
|
14
14
|
~addressesByContractName: dict<array<Address.t>>,
|
|
15
15
|
) => array<HyperFuelClient.QueryTypes.receiptSelection>,
|
|
16
|
-
eventRouter: EventRouter.t<Internal.
|
|
16
|
+
eventRouter: EventRouter.t<Internal.fuelOnEventRegistration>,
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
let logDataReceiptTypeSelection: array<FuelSDK.receiptType> = [LogData]
|
|
@@ -127,39 +127,40 @@ let getSelectionConfig = (selection: FetchState.selection, ~chain) => {
|
|
|
127
127
|
|
|
128
128
|
let contractNames = Utils.Set.make()
|
|
129
129
|
|
|
130
|
-
selection.
|
|
131
|
-
|
|
132
|
-
|
|
130
|
+
selection.onEventRegistrations->Array.forEach(reg => {
|
|
131
|
+
let eventConfig =
|
|
132
|
+
reg.eventConfig->(Utils.magic: Internal.eventConfig => Internal.fuelEventConfig)
|
|
133
133
|
let contractName = eventConfig.contractName
|
|
134
|
-
|
|
134
|
+
let isWildcard = reg.isWildcard
|
|
135
|
+
if !isWildcard {
|
|
135
136
|
let _ = contractNames->Utils.Set.add(contractName)
|
|
136
137
|
}
|
|
137
138
|
eventRouter->EventRouter.addOrThrow(
|
|
138
139
|
eventConfig.id,
|
|
139
|
-
|
|
140
|
+
reg,
|
|
140
141
|
~contractName,
|
|
141
142
|
~eventName=eventConfig.name,
|
|
142
143
|
~chain,
|
|
143
|
-
~isWildcard
|
|
144
|
+
~isWildcard,
|
|
144
145
|
)
|
|
145
146
|
|
|
146
|
-
switch eventConfig {
|
|
147
|
-
|
|
|
148
|
-
|
|
|
149
|
-
|
|
|
150
|
-
|
|
|
151
|
-
|
|
|
147
|
+
switch (eventConfig.kind, isWildcard) {
|
|
148
|
+
| (Mint, true) => addNonLogDataWildcardReceiptTypes(Mint)
|
|
149
|
+
| (Mint, false) => addNonLogDataReceiptType(contractName, Mint)
|
|
150
|
+
| (Burn, true) => addNonLogDataWildcardReceiptTypes(Burn)
|
|
151
|
+
| (Burn, false) => addNonLogDataReceiptType(contractName, Burn)
|
|
152
|
+
| (Transfer, true) => {
|
|
152
153
|
addNonLogDataWildcardReceiptTypes(Transfer)
|
|
153
154
|
addNonLogDataWildcardReceiptTypes(TransferOut)
|
|
154
155
|
}
|
|
155
|
-
|
|
|
156
|
+
| (Transfer, false) => {
|
|
156
157
|
addNonLogDataReceiptType(contractName, Transfer)
|
|
157
158
|
addNonLogDataReceiptType(contractName, TransferOut)
|
|
158
159
|
}
|
|
159
|
-
|
|
|
160
|
-
|
|
|
160
|
+
| (Call, true) => addNonLogDataWildcardReceiptTypes(Call)
|
|
161
|
+
| (Call, false) =>
|
|
161
162
|
JsError.throwWithMessage("Call receipt indexing currently supported only in wildcard mode")
|
|
162
|
-
|
|
|
163
|
+
| (LogData({logId}), _) => {
|
|
163
164
|
let rb = logId->BigInt.fromStringOrThrow
|
|
164
165
|
if isWildcard {
|
|
165
166
|
wildcardLogDataRbs->Array.push(rb)->ignore
|
|
@@ -251,11 +252,6 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
251
252
|
let startFetchingBatchTimeRef = Performance.now()
|
|
252
253
|
|
|
253
254
|
//fetch batch
|
|
254
|
-
Prometheus.SourceRequestCount.increment(
|
|
255
|
-
~sourceName=name,
|
|
256
|
-
~chainId=chain->ChainMap.Chain.toChainId,
|
|
257
|
-
~method="getLogs",
|
|
258
|
-
)
|
|
259
255
|
let pageUnsafe = try await HyperFuel.GetLogs.query(
|
|
260
256
|
~client,
|
|
261
257
|
~fromBlock,
|
|
@@ -307,6 +303,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
307
303
|
}
|
|
308
304
|
|
|
309
305
|
let pageFetchTime = startFetchingBatchTimeRef->Performance.secondsSince
|
|
306
|
+
let requestStats = [{Source.method: "getLogs", seconds: pageFetchTime}]
|
|
310
307
|
|
|
311
308
|
//set height and next from block
|
|
312
309
|
let knownHeight = pageUnsafe.archiveHeight
|
|
@@ -331,7 +328,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
331
328
|
| Call(_) => callEventTag
|
|
332
329
|
}
|
|
333
330
|
|
|
334
|
-
let
|
|
331
|
+
let onEventRegistration = switch selectionConfig.eventRouter->EventRouter.get(
|
|
335
332
|
~tag=eventId,
|
|
336
333
|
~contractNameByAddress,
|
|
337
334
|
~contractAddress,
|
|
@@ -352,9 +349,14 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
352
349
|
~logger,
|
|
353
350
|
)
|
|
354
351
|
}
|
|
355
|
-
| Some(
|
|
352
|
+
| Some(onEventRegistration) => onEventRegistration
|
|
356
353
|
}
|
|
357
354
|
|
|
355
|
+
let eventConfig =
|
|
356
|
+
onEventRegistration.eventConfig->(
|
|
357
|
+
Utils.magic: Internal.eventConfig => Internal.fuelEventConfig
|
|
358
|
+
)
|
|
359
|
+
|
|
358
360
|
let params = switch (eventConfig, receipt) {
|
|
359
361
|
| ({kind: LogData({decode})}, LogData({data})) =>
|
|
360
362
|
try decode(data) catch {
|
|
@@ -408,11 +410,9 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
408
410
|
}
|
|
409
411
|
|
|
410
412
|
Internal.Event({
|
|
411
|
-
|
|
412
|
-
timestamp: block.time,
|
|
413
|
+
onEventRegistration: (onEventRegistration :> Internal.onEventRegistration),
|
|
413
414
|
chain,
|
|
414
415
|
blockNumber: block.height,
|
|
415
|
-
blockHash: block.id,
|
|
416
416
|
logIndex: receiptIndex,
|
|
417
417
|
// Fuel carries the transaction inline on the payload; the store key is
|
|
418
418
|
// unused (Fuel identifies transactions by hash, kept on the payload).
|
|
@@ -459,13 +459,15 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
459
459
|
{
|
|
460
460
|
latestFetchedBlockTimestamp,
|
|
461
461
|
parsedQueueItems,
|
|
462
|
-
// Fuel keeps transaction on the payload; no store
|
|
462
|
+
// Fuel keeps transaction and block on the payload; no store pages.
|
|
463
463
|
transactionStore: None,
|
|
464
|
+
blockStore: None,
|
|
464
465
|
latestFetchedBlockNumber: heighestBlockQueried,
|
|
465
466
|
stats,
|
|
466
467
|
knownHeight,
|
|
467
468
|
blockHashes,
|
|
468
469
|
fromBlockQueried: fromBlock,
|
|
470
|
+
requestStats,
|
|
469
471
|
}
|
|
470
472
|
}
|
|
471
473
|
|
|
@@ -493,18 +495,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
493
495
|
}
|
|
494
496
|
}
|
|
495
497
|
let seconds = timerRef->Performance.secondsSince
|
|
496
|
-
|
|
497
|
-
~sourceName=name,
|
|
498
|
-
~chainId=chain->ChainMap.Chain.toChainId,
|
|
499
|
-
~method="getHeight",
|
|
500
|
-
)
|
|
501
|
-
Prometheus.SourceRequestCount.addSeconds(
|
|
502
|
-
~sourceName=name,
|
|
503
|
-
~chainId=chain->ChainMap.Chain.toChainId,
|
|
504
|
-
~method="getHeight",
|
|
505
|
-
~seconds,
|
|
506
|
-
)
|
|
507
|
-
height
|
|
498
|
+
{height, requestStats: [{method: "getHeight", seconds}]}
|
|
508
499
|
},
|
|
509
500
|
getItemsOrThrow,
|
|
510
501
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import * as Source from "./Source.res.mjs";
|
|
4
4
|
import * as Logging from "../Logging.res.mjs";
|
|
5
5
|
import * as HyperFuel from "./HyperFuel.res.mjs";
|
|
6
|
-
import * as Prometheus from "../Prometheus.res.mjs";
|
|
7
6
|
import * as EventRouter from "./EventRouter.res.mjs";
|
|
8
7
|
import * as Performance from "../bindings/Performance.res.mjs";
|
|
9
8
|
import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
|
|
@@ -101,41 +100,43 @@ function getSelectionConfig(selection, chain) {
|
|
|
101
100
|
}
|
|
102
101
|
};
|
|
103
102
|
let contractNames = new Set();
|
|
104
|
-
selection.
|
|
103
|
+
selection.onEventRegistrations.forEach(reg => {
|
|
104
|
+
let eventConfig = reg.eventConfig;
|
|
105
105
|
let contractName = eventConfig.contractName;
|
|
106
|
-
|
|
106
|
+
let isWildcard = reg.isWildcard;
|
|
107
|
+
if (!isWildcard) {
|
|
107
108
|
contractNames.add(contractName);
|
|
108
109
|
}
|
|
109
|
-
EventRouter.addOrThrow(eventRouter, eventConfig.id,
|
|
110
|
-
let isWildcard = eventConfig.isWildcard;
|
|
111
|
-
if (isWildcard) {
|
|
112
|
-
let tmp = eventConfig.kind;
|
|
113
|
-
if (typeof tmp !== "object") {
|
|
114
|
-
switch (tmp) {
|
|
115
|
-
case "Mint" :
|
|
116
|
-
return addNonLogDataWildcardReceiptTypes(11);
|
|
117
|
-
case "Burn" :
|
|
118
|
-
return addNonLogDataWildcardReceiptTypes(12);
|
|
119
|
-
case "Transfer" :
|
|
120
|
-
addNonLogDataWildcardReceiptTypes(7);
|
|
121
|
-
return addNonLogDataWildcardReceiptTypes(8);
|
|
122
|
-
case "Call" :
|
|
123
|
-
return addNonLogDataWildcardReceiptTypes(0);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
110
|
+
EventRouter.addOrThrow(eventRouter, eventConfig.id, reg, contractName, isWildcard, eventConfig.name, chain);
|
|
127
111
|
let match = eventConfig.kind;
|
|
128
112
|
if (typeof match !== "object") {
|
|
129
113
|
switch (match) {
|
|
130
114
|
case "Mint" :
|
|
131
|
-
|
|
115
|
+
if (isWildcard) {
|
|
116
|
+
return addNonLogDataWildcardReceiptTypes(11);
|
|
117
|
+
} else {
|
|
118
|
+
return addNonLogDataReceiptType(contractName, 11);
|
|
119
|
+
}
|
|
132
120
|
case "Burn" :
|
|
133
|
-
|
|
121
|
+
if (isWildcard) {
|
|
122
|
+
return addNonLogDataWildcardReceiptTypes(12);
|
|
123
|
+
} else {
|
|
124
|
+
return addNonLogDataReceiptType(contractName, 12);
|
|
125
|
+
}
|
|
134
126
|
case "Transfer" :
|
|
135
|
-
|
|
136
|
-
|
|
127
|
+
if (isWildcard) {
|
|
128
|
+
addNonLogDataWildcardReceiptTypes(7);
|
|
129
|
+
return addNonLogDataWildcardReceiptTypes(8);
|
|
130
|
+
} else {
|
|
131
|
+
addNonLogDataReceiptType(contractName, 7);
|
|
132
|
+
return addNonLogDataReceiptType(contractName, 8);
|
|
133
|
+
}
|
|
137
134
|
case "Call" :
|
|
138
|
-
|
|
135
|
+
if (isWildcard) {
|
|
136
|
+
return addNonLogDataWildcardReceiptTypes(0);
|
|
137
|
+
} else {
|
|
138
|
+
return Stdlib_JsError.throwWithMessage("Call receipt indexing currently supported only in wildcard mode");
|
|
139
|
+
}
|
|
139
140
|
}
|
|
140
141
|
} else {
|
|
141
142
|
let rb = BigInt(match.logId);
|
|
@@ -181,7 +182,6 @@ function memoGetSelectionConfig(chain) {
|
|
|
181
182
|
function make(param) {
|
|
182
183
|
let apiToken = param.apiToken;
|
|
183
184
|
let chain = param.chain;
|
|
184
|
-
let name = "HyperFuel";
|
|
185
185
|
let apiToken$1 = apiToken !== undefined ? apiToken : Stdlib_JsError.throwWithMessage(`An Envio API token is required for using HyperFuel as a data-source.
|
|
186
186
|
Set the ENVIO_API_TOKEN environment variable in your .env file.
|
|
187
187
|
Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
@@ -201,7 +201,6 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
201
201
|
let selectionConfig = getSelectionConfig(selection);
|
|
202
202
|
let recieptsSelection = selectionConfig.getRecieptsSelection(addressesByContractName);
|
|
203
203
|
let startFetchingBatchTimeRef = Performance.now();
|
|
204
|
-
Prometheus.SourceRequestCount.increment(name, chain, "getLogs");
|
|
205
204
|
let pageUnsafe;
|
|
206
205
|
try {
|
|
207
206
|
pageUnsafe = await HyperFuel.GetLogs.query(client, fromBlock, toBlock, recieptsSelection);
|
|
@@ -250,6 +249,10 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
250
249
|
};
|
|
251
250
|
}
|
|
252
251
|
let pageFetchTime = Performance.secondsSince(startFetchingBatchTimeRef);
|
|
252
|
+
let requestStats = [{
|
|
253
|
+
method: "getLogs",
|
|
254
|
+
seconds: pageFetchTime
|
|
255
|
+
}];
|
|
253
256
|
let knownHeight$1 = pageUnsafe.archiveHeight;
|
|
254
257
|
let heighestBlockQueried = pageUnsafe.nextBlock - 1 | 0;
|
|
255
258
|
let parsingTimeRef = Performance.now();
|
|
@@ -277,10 +280,10 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
277
280
|
eventId = burnEventTag;
|
|
278
281
|
break;
|
|
279
282
|
}
|
|
280
|
-
let
|
|
281
|
-
let
|
|
282
|
-
if (
|
|
283
|
-
|
|
283
|
+
let onEventRegistration = EventRouter.get(selectionConfig.eventRouter, eventId, contractAddress, contractNameByAddress);
|
|
284
|
+
let onEventRegistration$1;
|
|
285
|
+
if (onEventRegistration !== undefined) {
|
|
286
|
+
onEventRegistration$1 = onEventRegistration;
|
|
284
287
|
} else {
|
|
285
288
|
let logger$1 = Logging.createChildFrom(logger, {
|
|
286
289
|
chainId: chain,
|
|
@@ -289,11 +292,12 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
289
292
|
contractAddress: contractAddress,
|
|
290
293
|
eventId: eventId
|
|
291
294
|
});
|
|
292
|
-
|
|
295
|
+
onEventRegistration$1 = ErrorHandling.mkLogAndRaise(logger$1, "Failed to route registered event", {
|
|
293
296
|
RE_EXN_ID: EventRoutingFailed
|
|
294
297
|
});
|
|
295
298
|
}
|
|
296
|
-
let
|
|
299
|
+
let eventConfig = onEventRegistration$1.eventConfig;
|
|
300
|
+
let match = eventConfig.kind;
|
|
297
301
|
let params;
|
|
298
302
|
let exit = 0;
|
|
299
303
|
if (typeof match !== "object" || receipt.receiptType !== 6) {
|
|
@@ -349,16 +353,14 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
349
353
|
}
|
|
350
354
|
return {
|
|
351
355
|
kind: 0,
|
|
352
|
-
|
|
353
|
-
timestamp: block.time,
|
|
356
|
+
onEventRegistration: onEventRegistration$1,
|
|
354
357
|
chain: chain,
|
|
355
358
|
blockNumber: block.height,
|
|
356
|
-
blockHash: block.id,
|
|
357
359
|
logIndex: receiptIndex,
|
|
358
360
|
transactionIndex: 0,
|
|
359
361
|
payload: {
|
|
360
|
-
contractName: eventConfig
|
|
361
|
-
eventName: eventConfig
|
|
362
|
+
contractName: eventConfig.contractName,
|
|
363
|
+
eventName: eventConfig.name,
|
|
362
364
|
params: params,
|
|
363
365
|
chainId: chain,
|
|
364
366
|
srcAddress: contractAddress,
|
|
@@ -399,15 +401,17 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
399
401
|
blockHashes: blockHashes,
|
|
400
402
|
parsedQueueItems: parsedQueueItems,
|
|
401
403
|
transactionStore: undefined,
|
|
404
|
+
blockStore: undefined,
|
|
402
405
|
fromBlockQueried: fromBlock,
|
|
403
406
|
latestFetchedBlockNumber: heighestBlockQueried,
|
|
404
407
|
latestFetchedBlockTimestamp: latestFetchedBlockTimestamp,
|
|
405
|
-
stats: stats
|
|
408
|
+
stats: stats,
|
|
409
|
+
requestStats: requestStats
|
|
406
410
|
};
|
|
407
411
|
};
|
|
408
412
|
let getBlockHashes = (param, param$1) => Stdlib_JsError.throwWithMessage("HyperFuel does not support getting block hashes");
|
|
409
413
|
return {
|
|
410
|
-
name:
|
|
414
|
+
name: "HyperFuel",
|
|
411
415
|
sourceFor: "Sync",
|
|
412
416
|
chain: chain,
|
|
413
417
|
poweredByHyperSync: true,
|
|
@@ -447,9 +451,13 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
447
451
|
}
|
|
448
452
|
}
|
|
449
453
|
let seconds = Performance.secondsSince(timerRef);
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
454
|
+
return {
|
|
455
|
+
height: height,
|
|
456
|
+
requestStats: [{
|
|
457
|
+
method: "getHeight",
|
|
458
|
+
seconds: seconds
|
|
459
|
+
}]
|
|
460
|
+
};
|
|
453
461
|
},
|
|
454
462
|
getItemsOrThrow: getItemsOrThrow
|
|
455
463
|
};
|
|
@@ -16,13 +16,15 @@ let reraisIfRateLimited = exn =>
|
|
|
16
16
|
|
|
17
17
|
type logsQueryPage = {
|
|
18
18
|
items: array<HyperSyncClient.EventItems.item>,
|
|
19
|
-
//
|
|
20
|
-
blocks: array<HyperSyncClient.
|
|
19
|
+
// Block headers referenced by `items`, deduplicated by block number.
|
|
20
|
+
blocks: array<HyperSyncClient.EventItems.blockHeader>,
|
|
21
21
|
nextBlock: int,
|
|
22
22
|
archiveHeight: int,
|
|
23
23
|
rollbackGuard: option<HyperSyncClient.ResponseTypes.rollbackGuard>,
|
|
24
24
|
// Page store owning this page's raw transactions.
|
|
25
25
|
transactionStore: TransactionStore.t,
|
|
26
|
+
// Page store owning this page's raw blocks.
|
|
27
|
+
blockStore: BlockStore.t,
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
type missingParams = {
|
|
@@ -129,7 +131,7 @@ module GetLogs = {
|
|
|
129
131
|
~maxNumLogs,
|
|
130
132
|
)
|
|
131
133
|
|
|
132
|
-
let (res, transactionStore) = switch await client.getEventItems(~query) {
|
|
134
|
+
let (res, transactionStore, blockStore) = switch await client.getEventItems(~query) {
|
|
133
135
|
| res => res
|
|
134
136
|
| exception exn =>
|
|
135
137
|
reraisIfRateLimited(exn)
|
|
@@ -150,6 +152,7 @@ module GetLogs = {
|
|
|
150
152
|
archiveHeight: res.archiveHeight->Option.getOr(0), //Archive Height is only None if height is 0
|
|
151
153
|
rollbackGuard: res.rollbackGuard,
|
|
152
154
|
transactionStore,
|
|
155
|
+
blockStore,
|
|
153
156
|
}
|
|
154
157
|
}
|
|
155
158
|
}
|
|
@@ -206,6 +209,7 @@ module BlockData = {
|
|
|
206
209
|
~sourceName,
|
|
207
210
|
~chainId,
|
|
208
211
|
~logger,
|
|
212
|
+
~requestStats: array<Source.requestStat>,
|
|
209
213
|
): queryResponse<array<ReorgDetection.blockDataWithTimestamp>> => {
|
|
210
214
|
let body = makeRequestBody(~fromBlock, ~toBlock)
|
|
211
215
|
|
|
@@ -218,7 +222,7 @@ module BlockData = {
|
|
|
218
222
|
},
|
|
219
223
|
)
|
|
220
224
|
|
|
221
|
-
|
|
225
|
+
let timerRef = Performance.now()
|
|
222
226
|
let maybeSuccessfulRes = switch await client.get(~query=body) {
|
|
223
227
|
| exception exn =>
|
|
224
228
|
reraisIfRateLimited(exn)
|
|
@@ -226,6 +230,9 @@ module BlockData = {
|
|
|
226
230
|
| res if res.nextBlock <= fromBlock => None
|
|
227
231
|
| res => Some(res)
|
|
228
232
|
}
|
|
233
|
+
requestStats
|
|
234
|
+
->Array.push({Source.method: "getBlockHashes", seconds: timerRef->Performance.secondsSince})
|
|
235
|
+
->ignore
|
|
229
236
|
|
|
230
237
|
// If the block is not found, retry the query. This can occur since replicas of hypersync might not have caught up yet
|
|
231
238
|
switch maybeSuccessfulRes {
|
|
@@ -235,7 +242,15 @@ module BlockData = {
|
|
|
235
242
|
`Block #${fromBlock->Int.toString} not found in HyperSync. HyperSync has multiple instances and it's possible that they drift independently slightly from the head. Indexing should continue correctly after retrying the query in ${delayMilliseconds->Int.toString}ms.`,
|
|
236
243
|
)
|
|
237
244
|
await Time.resolvePromiseAfterDelay(~delayMilliseconds)
|
|
238
|
-
await queryBlockData(
|
|
245
|
+
await queryBlockData(
|
|
246
|
+
~client,
|
|
247
|
+
~fromBlock,
|
|
248
|
+
~toBlock,
|
|
249
|
+
~sourceName,
|
|
250
|
+
~chainId,
|
|
251
|
+
~logger,
|
|
252
|
+
~requestStats,
|
|
253
|
+
)
|
|
239
254
|
}
|
|
240
255
|
| Some(res) =>
|
|
241
256
|
switch res->convertResponse {
|
|
@@ -248,6 +263,7 @@ module BlockData = {
|
|
|
248
263
|
~sourceName,
|
|
249
264
|
~chainId,
|
|
250
265
|
~logger,
|
|
266
|
+
~requestStats,
|
|
251
267
|
)
|
|
252
268
|
restRes->Result.map(rest => datas->Array.concat(rest))
|
|
253
269
|
}
|
|
@@ -262,8 +278,9 @@ module BlockData = {
|
|
|
262
278
|
~sourceName,
|
|
263
279
|
~chainId,
|
|
264
280
|
~logger,
|
|
265
|
-
) => {
|
|
266
|
-
|
|
281
|
+
): (queryResponse<array<ReorgDetection.blockDataWithTimestamp>>, array<Source.requestStat>) => {
|
|
282
|
+
let requestStats = []
|
|
283
|
+
let result = switch blockNumbers->Array.get(0) {
|
|
267
284
|
| None => Ok([])
|
|
268
285
|
| Some(firstBlock) => {
|
|
269
286
|
let fromBlock = ref(firstBlock)
|
|
@@ -291,6 +308,7 @@ module BlockData = {
|
|
|
291
308
|
~sourceName,
|
|
292
309
|
~chainId,
|
|
293
310
|
~logger,
|
|
311
|
+
~requestStats,
|
|
294
312
|
)
|
|
295
313
|
let filtered = res->Result.map(datas => {
|
|
296
314
|
datas->Array.filter(data => set->Utils.Set.delete(data.blockNumber))
|
|
@@ -305,10 +323,12 @@ module BlockData = {
|
|
|
305
323
|
filtered
|
|
306
324
|
}
|
|
307
325
|
}
|
|
326
|
+
(result, requestStats)
|
|
308
327
|
}
|
|
309
328
|
}
|
|
310
329
|
|
|
311
|
-
let queryBlockData = (~client, ~blockNumber, ~sourceName, ~chainId, ~logger) =>
|
|
330
|
+
let queryBlockData = (~client, ~blockNumber, ~sourceName, ~chainId, ~logger) => {
|
|
331
|
+
let requestStats = []
|
|
312
332
|
BlockData.queryBlockData(
|
|
313
333
|
~client,
|
|
314
334
|
~fromBlock=blockNumber,
|
|
@@ -316,5 +336,7 @@ let queryBlockData = (~client, ~blockNumber, ~sourceName, ~chainId, ~logger) =>
|
|
|
316
336
|
~sourceName,
|
|
317
337
|
~chainId,
|
|
318
338
|
~logger,
|
|
319
|
-
|
|
339
|
+
~requestStats,
|
|
340
|
+
)->Promise.thenResolve(res => (res->Result.map(res => res->Array.get(0)), requestStats))
|
|
341
|
+
}
|
|
320
342
|
let queryBlockDataMulti = BlockData.queryBlockDataMulti
|
|
@@ -4,8 +4,8 @@ import * as Time from "../Time.res.mjs";
|
|
|
4
4
|
import * as Utils from "../Utils.res.mjs";
|
|
5
5
|
import * as Source from "./Source.res.mjs";
|
|
6
6
|
import * as Logging from "../Logging.res.mjs";
|
|
7
|
-
import * as Prometheus from "../Prometheus.res.mjs";
|
|
8
7
|
import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
|
|
8
|
+
import * as Performance from "../bindings/Performance.res.mjs";
|
|
9
9
|
import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
|
|
10
10
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
11
11
|
import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
|
|
@@ -135,7 +135,8 @@ async function query(client, fromBlock, toBlock, logSelections, fieldSelection,
|
|
|
135
135
|
nextBlock: res.nextBlock,
|
|
136
136
|
archiveHeight: Stdlib_Option.getOr(res.archiveHeight, 0),
|
|
137
137
|
rollbackGuard: res.rollbackGuard,
|
|
138
|
-
transactionStore: match[1]
|
|
138
|
+
transactionStore: match[1],
|
|
139
|
+
blockStore: match[2]
|
|
139
140
|
};
|
|
140
141
|
}
|
|
141
142
|
|
|
@@ -191,14 +192,14 @@ function convertResponse(res) {
|
|
|
191
192
|
}));
|
|
192
193
|
}
|
|
193
194
|
|
|
194
|
-
async function queryBlockData(client, fromBlock, toBlock, sourceName, chainId, logger) {
|
|
195
|
+
async function queryBlockData(client, fromBlock, toBlock, sourceName, chainId, logger, requestStats) {
|
|
195
196
|
let body = makeRequestBody$1(fromBlock, toBlock);
|
|
196
197
|
let logger$1 = Logging.createChildFrom(logger, {
|
|
197
198
|
logType: "HyperSync get block hash query",
|
|
198
199
|
fromBlock: fromBlock,
|
|
199
200
|
toBlock: toBlock
|
|
200
201
|
});
|
|
201
|
-
|
|
202
|
+
let timerRef = Performance.now();
|
|
202
203
|
let maybeSuccessfulRes;
|
|
203
204
|
let exit = 0;
|
|
204
205
|
let res;
|
|
@@ -213,6 +214,10 @@ async function queryBlockData(client, fromBlock, toBlock, sourceName, chainId, l
|
|
|
213
214
|
if (exit === 1) {
|
|
214
215
|
maybeSuccessfulRes = res.nextBlock <= fromBlock ? undefined : res;
|
|
215
216
|
}
|
|
217
|
+
requestStats.push({
|
|
218
|
+
method: "getBlockHashes",
|
|
219
|
+
seconds: Performance.secondsSince(timerRef)
|
|
220
|
+
});
|
|
216
221
|
if (maybeSuccessfulRes !== undefined) {
|
|
217
222
|
let err = convertResponse(maybeSuccessfulRes);
|
|
218
223
|
if (err.TAG !== "Ok") {
|
|
@@ -222,48 +227,59 @@ async function queryBlockData(client, fromBlock, toBlock, sourceName, chainId, l
|
|
|
222
227
|
return err;
|
|
223
228
|
}
|
|
224
229
|
let datas = err._0;
|
|
225
|
-
let restRes = await queryBlockData(client, maybeSuccessfulRes.nextBlock, toBlock, sourceName, chainId, logger$1);
|
|
230
|
+
let restRes = await queryBlockData(client, maybeSuccessfulRes.nextBlock, toBlock, sourceName, chainId, logger$1, requestStats);
|
|
226
231
|
return Stdlib_Result.map(restRes, rest => datas.concat(rest));
|
|
227
232
|
}
|
|
228
233
|
Logging.childInfo(logger$1, `Block #` + fromBlock.toString() + ` not found in HyperSync. HyperSync has multiple instances and it's possible that they drift independently slightly from the head. Indexing should continue correctly after retrying the query in ` + (100).toString() + `ms.`);
|
|
229
234
|
await Time.resolvePromiseAfterDelay(100);
|
|
230
|
-
return await queryBlockData(client, fromBlock, toBlock, sourceName, chainId, logger$1);
|
|
235
|
+
return await queryBlockData(client, fromBlock, toBlock, sourceName, chainId, logger$1, requestStats);
|
|
231
236
|
}
|
|
232
237
|
|
|
233
238
|
async function queryBlockDataMulti(client, blockNumbers, sourceName, chainId, logger) {
|
|
239
|
+
let requestStats = [];
|
|
234
240
|
let firstBlock = blockNumbers[0];
|
|
235
|
-
|
|
236
|
-
|
|
241
|
+
let result;
|
|
242
|
+
if (firstBlock !== undefined) {
|
|
243
|
+
let fromBlock = firstBlock;
|
|
244
|
+
let toBlock = firstBlock;
|
|
245
|
+
let set = new Set();
|
|
246
|
+
for (let idx = 0, idx_finish = blockNumbers.length; idx < idx_finish; ++idx) {
|
|
247
|
+
let blockNumber = blockNumbers[idx];
|
|
248
|
+
if (blockNumber < fromBlock) {
|
|
249
|
+
fromBlock = blockNumber;
|
|
250
|
+
}
|
|
251
|
+
if (blockNumber > toBlock) {
|
|
252
|
+
toBlock = blockNumber;
|
|
253
|
+
}
|
|
254
|
+
set.add(blockNumber);
|
|
255
|
+
}
|
|
256
|
+
if ((toBlock - fromBlock | 0) > 1000) {
|
|
257
|
+
Stdlib_JsError.throwWithMessage(`Invalid block data request. Range of block numbers is too large. Max range is 1000. Requested range: ` + fromBlock.toString() + `-` + toBlock.toString());
|
|
258
|
+
}
|
|
259
|
+
let res = await queryBlockData(client, fromBlock, toBlock, sourceName, chainId, logger, requestStats);
|
|
260
|
+
let filtered = Stdlib_Result.map(res, datas => datas.filter(data => set.delete(data.blockNumber)));
|
|
261
|
+
if (set.size > 0) {
|
|
262
|
+
Stdlib_JsError.throwWithMessage(`Invalid response. Failed to get block data for block numbers: ` + Array.from(set).join(", "));
|
|
263
|
+
}
|
|
264
|
+
result = filtered;
|
|
265
|
+
} else {
|
|
266
|
+
result = {
|
|
237
267
|
TAG: "Ok",
|
|
238
268
|
_0: []
|
|
239
269
|
};
|
|
240
270
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
let blockNumber = blockNumbers[idx];
|
|
246
|
-
if (blockNumber < fromBlock) {
|
|
247
|
-
fromBlock = blockNumber;
|
|
248
|
-
}
|
|
249
|
-
if (blockNumber > toBlock) {
|
|
250
|
-
toBlock = blockNumber;
|
|
251
|
-
}
|
|
252
|
-
set.add(blockNumber);
|
|
253
|
-
}
|
|
254
|
-
if ((toBlock - fromBlock | 0) > 1000) {
|
|
255
|
-
Stdlib_JsError.throwWithMessage(`Invalid block data request. Range of block numbers is too large. Max range is 1000. Requested range: ` + fromBlock.toString() + `-` + toBlock.toString());
|
|
256
|
-
}
|
|
257
|
-
let res = await queryBlockData(client, fromBlock, toBlock, sourceName, chainId, logger);
|
|
258
|
-
let filtered = Stdlib_Result.map(res, datas => datas.filter(data => set.delete(data.blockNumber)));
|
|
259
|
-
if (set.size > 0) {
|
|
260
|
-
Stdlib_JsError.throwWithMessage(`Invalid response. Failed to get block data for block numbers: ` + Array.from(set).join(", "));
|
|
261
|
-
}
|
|
262
|
-
return filtered;
|
|
271
|
+
return [
|
|
272
|
+
result,
|
|
273
|
+
requestStats
|
|
274
|
+
];
|
|
263
275
|
}
|
|
264
276
|
|
|
265
277
|
function queryBlockData$1(client, blockNumber, sourceName, chainId, logger) {
|
|
266
|
-
|
|
278
|
+
let requestStats = [];
|
|
279
|
+
return queryBlockData(client, blockNumber, blockNumber, sourceName, chainId, logger, requestStats).then(res => [
|
|
280
|
+
Stdlib_Result.map(res, res => res[0]),
|
|
281
|
+
requestStats
|
|
282
|
+
]);
|
|
267
283
|
}
|
|
268
284
|
|
|
269
285
|
let GetLogs = {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
type logsQueryPage = {
|
|
2
2
|
items: array<HyperSyncClient.EventItems.item>,
|
|
3
|
-
blocks: array<HyperSyncClient.
|
|
3
|
+
blocks: array<HyperSyncClient.EventItems.blockHeader>,
|
|
4
4
|
nextBlock: int,
|
|
5
5
|
archiveHeight: int,
|
|
6
6
|
rollbackGuard: option<HyperSyncClient.ResponseTypes.rollbackGuard>,
|
|
7
7
|
transactionStore: TransactionStore.t,
|
|
8
|
+
blockStore: BlockStore.t,
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
type missingParams = {
|
|
@@ -43,7 +44,10 @@ let queryBlockData: (
|
|
|
43
44
|
~sourceName: string,
|
|
44
45
|
~chainId: int,
|
|
45
46
|
~logger: Pino.t,
|
|
46
|
-
) => promise<
|
|
47
|
+
) => promise<(
|
|
48
|
+
queryResponse<option<ReorgDetection.blockDataWithTimestamp>>,
|
|
49
|
+
array<Source.requestStat>,
|
|
50
|
+
)>
|
|
47
51
|
|
|
48
52
|
let queryBlockDataMulti: (
|
|
49
53
|
~client: HyperSyncClient.t,
|
|
@@ -51,6 +55,9 @@ let queryBlockDataMulti: (
|
|
|
51
55
|
~sourceName: string,
|
|
52
56
|
~chainId: int,
|
|
53
57
|
~logger: Pino.t,
|
|
54
|
-
) => promise<
|
|
58
|
+
) => promise<(
|
|
59
|
+
queryResponse<array<ReorgDetection.blockDataWithTimestamp>>,
|
|
60
|
+
array<Source.requestStat>,
|
|
61
|
+
)>
|
|
55
62
|
|
|
56
63
|
let mapExn: queryResponse<'a> => result<'a, exn>
|
|
@@ -254,11 +254,19 @@ module EventItems = {
|
|
|
254
254
|
params: Nullable.t<dict<Internal.eventParams>>,
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
// The always-needed block fields, one per block number. The block's remaining
|
|
258
|
+
// fields live raw in the block store and are materialised on demand.
|
|
259
|
+
type blockHeader = {
|
|
260
|
+
number: int,
|
|
261
|
+
timestamp: int,
|
|
262
|
+
hash: string,
|
|
263
|
+
}
|
|
264
|
+
|
|
257
265
|
type response = {
|
|
258
266
|
archiveHeight: option<int>,
|
|
259
267
|
nextBlock: int,
|
|
260
|
-
// One
|
|
261
|
-
blocks: array<
|
|
268
|
+
// One header per block number referenced by `items`.
|
|
269
|
+
blocks: array<blockHeader>,
|
|
262
270
|
items: array<item>,
|
|
263
271
|
rollbackGuard: option<ResponseTypes.rollbackGuard>,
|
|
264
272
|
}
|
|
@@ -266,8 +274,11 @@ module EventItems = {
|
|
|
266
274
|
|
|
267
275
|
type t = {
|
|
268
276
|
get: (~query: query) => promise<queryResponse>,
|
|
269
|
-
// Returns the response plus
|
|
270
|
-
|
|
277
|
+
// Returns the response plus page stores owning this page's raw transactions
|
|
278
|
+
// and blocks.
|
|
279
|
+
getEventItems: (
|
|
280
|
+
~query: query,
|
|
281
|
+
) => promise<(EventItems.response, TransactionStore.t, BlockStore.t)>,
|
|
271
282
|
getHeight: unit => promise<int>,
|
|
272
283
|
}
|
|
273
284
|
|