envio 3.0.2 → 3.1.0-rc.0
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/README.md +0 -1
- package/evm.schema.json +15 -8
- package/fuel.schema.json +19 -12
- package/index.d.ts +0 -2
- package/package.json +6 -7
- package/rescript.json +1 -1
- package/src/Batch.res +4 -214
- package/src/Batch.res.mjs +6 -165
- package/src/ChainFetcher.res +4 -5
- package/src/ChainFetcher.res.mjs +6 -7
- package/src/ChainManager.res +10 -9
- package/src/ChainManager.res.mjs +6 -10
- package/src/Config.res +9 -25
- package/src/Config.res.mjs +17 -27
- package/src/Core.res +7 -0
- package/src/Ctx.res +1 -0
- package/src/Env.res +0 -1
- package/src/Env.res.mjs +0 -3
- package/src/EventConfigBuilder.res +13 -123
- package/src/EventConfigBuilder.res.mjs +6 -73
- package/src/EventProcessing.res +5 -29
- package/src/EventProcessing.res.mjs +11 -20
- package/src/EventUtils.res +0 -27
- package/src/EventUtils.res.mjs +0 -24
- package/src/FetchState.res +1 -11
- package/src/FetchState.res.mjs +2 -16
- package/src/GlobalState.res +23 -37
- package/src/GlobalState.res.mjs +10 -38
- package/src/HandlerLoader.res +6 -5
- package/src/HandlerLoader.res.mjs +27 -9
- package/src/HandlerRegister.res +1 -12
- package/src/HandlerRegister.res.mjs +1 -6
- package/src/HandlerRegister.resi +1 -1
- package/src/Hasura.res +96 -32
- package/src/Hasura.res.mjs +93 -38
- package/src/InMemoryStore.res +181 -45
- package/src/InMemoryStore.res.mjs +143 -40
- package/src/InMemoryTable.res +147 -247
- package/src/InMemoryTable.res.mjs +131 -230
- package/src/Internal.res +10 -34
- package/src/Internal.res.mjs +9 -3
- package/src/LoadLayer.res +5 -5
- package/src/LoadLayer.res.mjs +5 -5
- package/src/Main.res +4 -6
- package/src/Main.res.mjs +26 -15
- package/src/Persistence.res +7 -132
- package/src/Persistence.res.mjs +1 -102
- package/src/PgStorage.res +57 -40
- package/src/PgStorage.res.mjs +60 -34
- package/src/ReorgDetection.res +35 -58
- package/src/ReorgDetection.res.mjs +21 -29
- package/src/SimulateItems.res.mjs +21 -3
- package/src/Sink.res +2 -2
- package/src/Sink.res.mjs +1 -1
- package/src/TableIndices.res +9 -2
- package/src/TableIndices.res.mjs +7 -1
- package/src/TestIndexer.res +53 -60
- package/src/TestIndexer.res.mjs +77 -63
- package/src/TestIndexerProxyStorage.res +4 -14
- package/src/TestIndexerProxyStorage.res.mjs +1 -5
- package/src/UserContext.res +2 -4
- package/src/UserContext.res.mjs +4 -5
- package/src/Utils.res +0 -2
- package/src/Utils.res.mjs +0 -3
- package/src/bindings/ClickHouse.res +45 -38
- package/src/bindings/ClickHouse.res.mjs +16 -17
- package/src/bindings/Vitest.res +3 -0
- package/src/db/InternalTable.res +59 -18
- package/src/db/InternalTable.res.mjs +82 -51
- package/src/db/Table.res +9 -2
- package/src/db/Table.res.mjs +10 -7
- package/src/sources/EvmChain.res +32 -9
- package/src/sources/EvmChain.res.mjs +31 -4
- package/src/sources/HyperFuelSource.res +14 -57
- package/src/sources/HyperFuelSource.res.mjs +18 -38
- package/src/sources/HyperSync.res +36 -101
- package/src/sources/HyperSync.res.mjs +42 -96
- package/src/sources/HyperSync.resi +4 -22
- package/src/sources/HyperSyncClient.res +67 -245
- package/src/sources/HyperSyncClient.res.mjs +47 -46
- package/src/sources/HyperSyncSource.res +76 -147
- package/src/sources/HyperSyncSource.res.mjs +61 -114
- package/src/sources/RpcSource.res +43 -22
- package/src/sources/RpcSource.res.mjs +50 -35
- package/src/sources/SimulateSource.res +1 -7
- package/src/sources/SimulateSource.res.mjs +1 -7
- package/src/sources/Source.res +8 -1
- package/src/sources/SourceManager.res +9 -0
- package/src/sources/SourceManager.res.mjs +10 -0
- package/src/sources/SourceManager.resi +2 -0
- package/svm.schema.json +11 -4
|
@@ -5,13 +5,9 @@ type selectionConfig = {
|
|
|
5
5
|
~addressesByContractName: dict<array<Address.t>>,
|
|
6
6
|
) => array<LogSelection.t>,
|
|
7
7
|
fieldSelection: HyperSyncClient.QueryTypes.fieldSelection,
|
|
8
|
-
nonOptionalBlockFieldNames: array<string>,
|
|
9
|
-
nonOptionalTransactionFieldNames: array<string>,
|
|
10
8
|
}
|
|
11
9
|
|
|
12
10
|
let getSelectionConfig = (selection: FetchState.selection, ~chain) => {
|
|
13
|
-
let nonOptionalBlockFieldNames = Utils.Set.make()
|
|
14
|
-
let nonOptionalTransactionFieldNames = Utils.Set.make()
|
|
15
11
|
let capitalizedBlockFields = Utils.Set.make()
|
|
16
12
|
let capitalizedTransactionFields = Utils.Set.make()
|
|
17
13
|
|
|
@@ -33,22 +29,18 @@ let getSelectionConfig = (selection: FetchState.selection, ~chain) => {
|
|
|
33
29
|
}) => {
|
|
34
30
|
selectedBlockFields
|
|
35
31
|
->Utils.Set.toArray
|
|
36
|
-
->Array.forEach(name =>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
capitalizedBlockFields->Utils.Set.add(nameStr->Utils.String.capitalize)->ignore
|
|
42
|
-
})
|
|
32
|
+
->Array.forEach(name =>
|
|
33
|
+
capitalizedBlockFields
|
|
34
|
+
->Utils.Set.add((name :> string)->Utils.String.capitalize)
|
|
35
|
+
->ignore
|
|
36
|
+
)
|
|
43
37
|
selectedTransactionFields
|
|
44
38
|
->Utils.Set.toArray
|
|
45
|
-
->Array.forEach(name =>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
capitalizedTransactionFields->Utils.Set.add(nameStr->Utils.String.capitalize)->ignore
|
|
51
|
-
})
|
|
39
|
+
->Array.forEach(name =>
|
|
40
|
+
capitalizedTransactionFields
|
|
41
|
+
->Utils.Set.add((name :> string)->Utils.String.capitalize)
|
|
42
|
+
->ignore
|
|
43
|
+
)
|
|
52
44
|
|
|
53
45
|
let eventFilters = getEventFiltersOrThrow(chain)
|
|
54
46
|
if dependsOnAddresses {
|
|
@@ -130,8 +122,6 @@ let getSelectionConfig = (selection: FetchState.selection, ~chain) => {
|
|
|
130
122
|
{
|
|
131
123
|
getLogSelectionOrThrow,
|
|
132
124
|
fieldSelection,
|
|
133
|
-
nonOptionalBlockFieldNames: nonOptionalBlockFieldNames->Utils.Set.toArray,
|
|
134
|
-
nonOptionalTransactionFieldNames: nonOptionalTransactionFieldNames->Utils.Set.toArray,
|
|
135
125
|
}
|
|
136
126
|
}
|
|
137
127
|
|
|
@@ -141,7 +131,7 @@ let memoGetSelectionConfig = (~chain) =>
|
|
|
141
131
|
type options = {
|
|
142
132
|
chain: ChainMap.Chain.t,
|
|
143
133
|
endpointUrl: string,
|
|
144
|
-
|
|
134
|
+
allEventParams: array<HyperSyncClient.Decoder.eventParamsInput>,
|
|
145
135
|
eventRouter: EventRouter.t<Internal.evmEventConfig>,
|
|
146
136
|
apiToken: option<string>,
|
|
147
137
|
clientMaxRetries: int,
|
|
@@ -149,13 +139,14 @@ type options = {
|
|
|
149
139
|
lowercaseAddresses: bool,
|
|
150
140
|
serializationFormat: HyperSyncClient.serializationFormat,
|
|
151
141
|
enableQueryCaching: bool,
|
|
142
|
+
logLevel: HyperSyncClient.logLevel,
|
|
152
143
|
}
|
|
153
144
|
|
|
154
145
|
let make = (
|
|
155
146
|
{
|
|
156
147
|
chain,
|
|
157
148
|
endpointUrl,
|
|
158
|
-
|
|
149
|
+
allEventParams,
|
|
159
150
|
eventRouter,
|
|
160
151
|
apiToken,
|
|
161
152
|
clientMaxRetries,
|
|
@@ -163,6 +154,7 @@ let make = (
|
|
|
163
154
|
lowercaseAddresses,
|
|
164
155
|
serializationFormat,
|
|
165
156
|
enableQueryCaching,
|
|
157
|
+
logLevel,
|
|
166
158
|
}: options,
|
|
167
159
|
): t => {
|
|
168
160
|
let name = "HyperSync"
|
|
@@ -177,45 +169,32 @@ Set the ENVIO_API_TOKEN environment variable in your .env file.
|
|
|
177
169
|
Learn more or get a free API token at: https://envio.dev/app/api-tokens`)
|
|
178
170
|
}
|
|
179
171
|
|
|
180
|
-
let client = HyperSyncClient.make(
|
|
172
|
+
let client = switch HyperSyncClient.make(
|
|
181
173
|
~url=endpointUrl,
|
|
182
174
|
~apiToken,
|
|
183
175
|
~maxNumRetries=clientMaxRetries,
|
|
184
176
|
~httpReqTimeoutMillis=clientTimeoutMillis,
|
|
177
|
+
~eventParams=allEventParams,
|
|
185
178
|
~enableChecksumAddresses=!lowercaseAddresses,
|
|
186
179
|
~serializationFormat,
|
|
187
180
|
~enableQueryCaching,
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
switch HyperSyncClient.Decoder.fromSignatures(allEventSignatures) {
|
|
196
|
-
| exception exn =>
|
|
197
|
-
exn->ErrorHandling.mkLogAndRaise(
|
|
198
|
-
~msg="Failed to instantiate a decoder from hypersync client, please double check your ABI",
|
|
199
|
-
)
|
|
200
|
-
| decoder =>
|
|
201
|
-
if lowercaseAddresses {
|
|
202
|
-
decoder.disableChecksummedAddresses()
|
|
203
|
-
} else {
|
|
204
|
-
decoder.enableChecksummedAddresses()
|
|
205
|
-
}
|
|
206
|
-
decoder
|
|
207
|
-
}
|
|
208
|
-
}
|
|
181
|
+
~logLevel,
|
|
182
|
+
) {
|
|
183
|
+
| client => client
|
|
184
|
+
| exception exn =>
|
|
185
|
+
exn->ErrorHandling.mkLogAndRaise(
|
|
186
|
+
~msg="Failed to instantiate the hypersync client, please double check your ABI",
|
|
187
|
+
)
|
|
209
188
|
}
|
|
210
189
|
|
|
211
190
|
exception UndefinedValue
|
|
212
191
|
|
|
213
192
|
let makeEventBatchQueueItem = (
|
|
214
|
-
item:
|
|
193
|
+
item: HyperSyncClient.EventItems.item,
|
|
215
194
|
~params: Internal.eventParams,
|
|
216
195
|
~eventConfig: Internal.evmEventConfig,
|
|
217
196
|
): Internal.item => {
|
|
218
|
-
let {block,
|
|
197
|
+
let {block, transaction, logIndex, srcAddress} = item
|
|
219
198
|
let chainId = chain->ChainMap.Chain.toChainId
|
|
220
199
|
|
|
221
200
|
Internal.Event({
|
|
@@ -223,7 +202,7 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`)
|
|
|
223
202
|
timestamp: block.timestamp->Belt.Option.getUnsafe,
|
|
224
203
|
chain,
|
|
225
204
|
blockNumber: block.number->Belt.Option.getUnsafe,
|
|
226
|
-
logIndex
|
|
205
|
+
logIndex,
|
|
227
206
|
event: {
|
|
228
207
|
contractName: eventConfig.contractName,
|
|
229
208
|
eventName: eventConfig.name,
|
|
@@ -231,8 +210,8 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`)
|
|
|
231
210
|
params,
|
|
232
211
|
transaction,
|
|
233
212
|
block: block->(Utils.magic: HyperSyncClient.ResponseTypes.block => Internal.eventBlock),
|
|
234
|
-
srcAddress
|
|
235
|
-
logIndex
|
|
213
|
+
srcAddress,
|
|
214
|
+
logIndex,
|
|
236
215
|
}->Internal.fromGenericEvent,
|
|
237
216
|
})
|
|
238
217
|
}
|
|
@@ -248,7 +227,6 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`)
|
|
|
248
227
|
~retry,
|
|
249
228
|
~logger,
|
|
250
229
|
) => {
|
|
251
|
-
let mkLogAndRaise = ErrorHandling.mkLogAndRaise(~logger, ...)
|
|
252
230
|
let totalTimeRef = Hrtime.makeTimer()
|
|
253
231
|
|
|
254
232
|
let selectionConfig = selection->getSelectionConfig
|
|
@@ -272,8 +250,6 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`)
|
|
|
272
250
|
~toBlock,
|
|
273
251
|
~logSelections,
|
|
274
252
|
~fieldSelection=selectionConfig.fieldSelection,
|
|
275
|
-
~nonOptionalBlockFieldNames=selectionConfig.nonOptionalBlockFieldNames,
|
|
276
|
-
~nonOptionalTransactionFieldNames=selectionConfig.nonOptionalTransactionFieldNames,
|
|
277
253
|
) catch {
|
|
278
254
|
| HyperSync.GetLogs.Error(error) =>
|
|
279
255
|
throw(
|
|
@@ -329,64 +305,6 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`)
|
|
|
329
305
|
//In the query
|
|
330
306
|
let heighestBlockQueried = pageUnsafe.nextBlock - 1
|
|
331
307
|
|
|
332
|
-
let lastBlockQueriedPromise = switch pageUnsafe.rollbackGuard {
|
|
333
|
-
//In the case a rollbackGuard is returned (this only happens at the head for unconfirmed blocks)
|
|
334
|
-
//use these values
|
|
335
|
-
| Some({blockNumber, timestamp, hash}) =>
|
|
336
|
-
(
|
|
337
|
-
{
|
|
338
|
-
blockNumber,
|
|
339
|
-
blockTimestamp: timestamp,
|
|
340
|
-
blockHash: hash,
|
|
341
|
-
}: ReorgDetection.blockDataWithTimestamp
|
|
342
|
-
)->Promise.resolve
|
|
343
|
-
| None =>
|
|
344
|
-
//The optional block and timestamp of the last item returned by the query
|
|
345
|
-
//(Optional in the case that there are no logs returned in the query)
|
|
346
|
-
switch pageUnsafe.items->Belt.Array.get(pageUnsafe.items->Belt.Array.length - 1) {
|
|
347
|
-
| Some({block}) if block.number->Belt.Option.getUnsafe == heighestBlockQueried =>
|
|
348
|
-
//If the last log item in the current page is equal to the
|
|
349
|
-
//heighest block acounted for in the query. Simply return this
|
|
350
|
-
//value without making an extra query
|
|
351
|
-
|
|
352
|
-
(
|
|
353
|
-
{
|
|
354
|
-
blockNumber: block.number->Belt.Option.getUnsafe,
|
|
355
|
-
blockTimestamp: block.timestamp->Belt.Option.getUnsafe,
|
|
356
|
-
blockHash: block.hash->Belt.Option.getUnsafe,
|
|
357
|
-
}: ReorgDetection.blockDataWithTimestamp
|
|
358
|
-
)->Promise.resolve
|
|
359
|
-
//If it does not match it means that there were no matching logs in the last
|
|
360
|
-
//block so we should fetch the block data
|
|
361
|
-
| Some(_)
|
|
362
|
-
| None =>
|
|
363
|
-
//If there were no logs at all in the current page query then fetch the
|
|
364
|
-
//timestamp of the heighest block accounted for
|
|
365
|
-
HyperSync.queryBlockData(
|
|
366
|
-
~client,
|
|
367
|
-
~blockNumber=heighestBlockQueried,
|
|
368
|
-
~sourceName=name,
|
|
369
|
-
~chainId=chain->ChainMap.Chain.toChainId,
|
|
370
|
-
~logger,
|
|
371
|
-
)->Promise.thenResolve(res =>
|
|
372
|
-
switch res {
|
|
373
|
-
| Ok(Some(blockData)) => blockData
|
|
374
|
-
| Ok(None) =>
|
|
375
|
-
mkLogAndRaise(
|
|
376
|
-
Not_found,
|
|
377
|
-
~msg=`Failure, blockData for block ${heighestBlockQueried->Int.toString} unexpectedly returned None`,
|
|
378
|
-
)
|
|
379
|
-
| Error(e) =>
|
|
380
|
-
HyperSync.queryErrorToMsq(e)
|
|
381
|
-
->Obj.magic
|
|
382
|
-
->mkLogAndRaise(
|
|
383
|
-
~msg=`Failed to query blockData for block ${heighestBlockQueried->Int.toString}`,
|
|
384
|
-
)
|
|
385
|
-
}
|
|
386
|
-
)
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
308
|
let parsingTimeRef = Hrtime.makeTimer()
|
|
391
309
|
|
|
392
310
|
//Parse page items into queue items
|
|
@@ -417,47 +335,29 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`)
|
|
|
417
335
|
}
|
|
418
336
|
}
|
|
419
337
|
|
|
420
|
-
|
|
421
|
-
let parsedEvents = switch await getHscDecoder().decodeEvents(pageUnsafe.events) {
|
|
422
|
-
| exception exn =>
|
|
423
|
-
exn->mkLogAndRaise(
|
|
424
|
-
~msg="Failed to parse events using hypersync client, please double check your ABI.",
|
|
425
|
-
)
|
|
426
|
-
| parsedEvents => parsedEvents
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
pageUnsafe.items->Belt.Array.forEachWithIndex((index, item) => {
|
|
430
|
-
let {block, log} = item
|
|
338
|
+
pageUnsafe.items->Belt.Array.forEach(item => {
|
|
431
339
|
let chainId = chain->ChainMap.Chain.toChainId
|
|
432
|
-
let topic0 = log.topics->Utils.Array.firstUnsafe
|
|
433
340
|
let maybeEventConfig =
|
|
434
341
|
eventRouter->EventRouter.get(
|
|
435
342
|
~tag=EventRouter.getEvmEventId(
|
|
436
|
-
~sighash=topic0->EvmTypes.Hex.toString,
|
|
437
|
-
~topicCount=
|
|
343
|
+
~sighash=item.topic0->EvmTypes.Hex.toString,
|
|
344
|
+
~topicCount=item.topicCount,
|
|
438
345
|
),
|
|
439
346
|
~indexingAddresses,
|
|
440
|
-
~contractAddress=
|
|
441
|
-
~blockNumber=block.number->Belt.Option.getUnsafe,
|
|
347
|
+
~contractAddress=item.srcAddress,
|
|
348
|
+
~blockNumber=item.block.number->Belt.Option.getUnsafe,
|
|
442
349
|
)
|
|
443
|
-
let maybeDecodedEvent = parsedEvents->Array.getUnsafe(index)
|
|
444
350
|
|
|
445
|
-
switch (maybeEventConfig,
|
|
351
|
+
switch (maybeEventConfig, item.params) {
|
|
446
352
|
| (Some(eventConfig), Value(decoded)) =>
|
|
447
353
|
parsedQueueItems
|
|
448
|
-
->Array.push(
|
|
449
|
-
makeEventBatchQueueItem(
|
|
450
|
-
item,
|
|
451
|
-
~params=decoded->eventConfig.convertHyperSyncEventArgs,
|
|
452
|
-
~eventConfig,
|
|
453
|
-
),
|
|
454
|
-
)
|
|
354
|
+
->Array.push(makeEventBatchQueueItem(item, ~params=decoded, ~eventConfig))
|
|
455
355
|
->ignore
|
|
456
356
|
| (Some(eventConfig), Null | Undefined) =>
|
|
457
357
|
handleDecodeFailure(
|
|
458
358
|
~eventConfig,
|
|
459
|
-
~logIndex=
|
|
460
|
-
~blockNumber=block.number->Belt.Option.getUnsafe,
|
|
359
|
+
~logIndex=item.logIndex,
|
|
360
|
+
~blockNumber=item.block.number->Belt.Option.getUnsafe,
|
|
461
361
|
~chainId,
|
|
462
362
|
~exn=UndefinedValue,
|
|
463
363
|
)
|
|
@@ -467,14 +367,43 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`)
|
|
|
467
367
|
|
|
468
368
|
let parsingTimeElapsed = parsingTimeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
|
|
469
369
|
|
|
470
|
-
|
|
370
|
+
// Collect (blockNumber, blockHash) pairs we already have from the response —
|
|
371
|
+
// one per item's block plus, when present, the rollbackGuard's head block
|
|
372
|
+
// and the parent of the range's first block. Duplicates are allowed; reorg
|
|
373
|
+
// detection notices same-block-number-different-hash collisions itself.
|
|
374
|
+
let blockHashes = []
|
|
375
|
+
pageUnsafe.items->Belt.Array.forEach(({block}) => {
|
|
376
|
+
switch (block.number, block.hash) {
|
|
377
|
+
| (Some(blockNumber), Some(blockHash)) =>
|
|
378
|
+
blockHashes->Array.push({ReorgDetection.blockNumber, blockHash})->ignore
|
|
379
|
+
| _ => ()
|
|
380
|
+
}
|
|
381
|
+
})
|
|
382
|
+
switch pageUnsafe.rollbackGuard {
|
|
383
|
+
| None => ()
|
|
384
|
+
| Some({blockNumber, hash, firstBlockNumber, firstParentHash}) => {
|
|
385
|
+
blockHashes->Array.push({ReorgDetection.blockNumber, blockHash: hash})->ignore
|
|
386
|
+
blockHashes
|
|
387
|
+
->Array.push({
|
|
388
|
+
ReorgDetection.blockNumber: firstBlockNumber - 1,
|
|
389
|
+
blockHash: firstParentHash,
|
|
390
|
+
})
|
|
391
|
+
->ignore
|
|
392
|
+
}
|
|
393
|
+
}
|
|
471
394
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
395
|
+
// Best-effort timestamp for the queried-range head: prefer the rollbackGuard
|
|
396
|
+
// (set at the head for unconfirmed blocks), otherwise the last item if it
|
|
397
|
+
// happens to be in the range's last block. 0 is a tolerated placeholder
|
|
398
|
+
// when neither is available (FetchState already uses 0 in several spots).
|
|
399
|
+
let latestFetchedBlockTimestamp = switch pageUnsafe.rollbackGuard {
|
|
400
|
+
| Some({timestamp}) => timestamp
|
|
401
|
+
| None =>
|
|
402
|
+
switch pageUnsafe.items->Belt.Array.get(pageUnsafe.items->Belt.Array.length - 1) {
|
|
403
|
+
| Some({block}) if block.number->Belt.Option.getUnsafe == heighestBlockQueried =>
|
|
404
|
+
block.timestamp->Belt.Option.getUnsafe
|
|
405
|
+
| _ => 0
|
|
406
|
+
}
|
|
478
407
|
}
|
|
479
408
|
|
|
480
409
|
let totalTimeElapsed = totalTimeRef->Hrtime.timeSince->Hrtime.toSecondsFloat
|
|
@@ -486,12 +415,12 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`)
|
|
|
486
415
|
}
|
|
487
416
|
|
|
488
417
|
{
|
|
489
|
-
latestFetchedBlockTimestamp
|
|
418
|
+
latestFetchedBlockTimestamp,
|
|
490
419
|
parsedQueueItems,
|
|
491
|
-
latestFetchedBlockNumber:
|
|
420
|
+
latestFetchedBlockNumber: heighestBlockQueried,
|
|
492
421
|
stats,
|
|
493
422
|
knownHeight,
|
|
494
|
-
|
|
423
|
+
blockHashes,
|
|
495
424
|
fromBlockQueried: fromBlock,
|
|
496
425
|
}
|
|
497
426
|
}
|
|
@@ -5,7 +5,6 @@ import * as Utils from "../Utils.res.mjs";
|
|
|
5
5
|
import * as Hrtime from "../bindings/Hrtime.res.mjs";
|
|
6
6
|
import * as Source from "./Source.res.mjs";
|
|
7
7
|
import * as Logging from "../Logging.res.mjs";
|
|
8
|
-
import * as Internal from "../Internal.res.mjs";
|
|
9
8
|
import * as HyperSync from "./HyperSync.res.mjs";
|
|
10
9
|
import * as Belt_Array from "@rescript/runtime/lib/es6/Belt_Array.js";
|
|
11
10
|
import * as Prometheus from "../Prometheus.res.mjs";
|
|
@@ -20,8 +19,6 @@ import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_excep
|
|
|
20
19
|
import * as HyperSyncHeightStream from "./HyperSyncHeightStream.res.mjs";
|
|
21
20
|
|
|
22
21
|
function getSelectionConfig(selection, chain) {
|
|
23
|
-
let nonOptionalBlockFieldNames = new Set();
|
|
24
|
-
let nonOptionalTransactionFieldNames = new Set();
|
|
25
22
|
let capitalizedBlockFields = new Set();
|
|
26
23
|
let capitalizedTransactionFields = new Set();
|
|
27
24
|
let staticTopicSelectionsByContract = {};
|
|
@@ -32,15 +29,9 @@ function getSelectionConfig(selection, chain) {
|
|
|
32
29
|
selection.eventConfigs.forEach(param => {
|
|
33
30
|
let contractName = param.contractName;
|
|
34
31
|
Array.from(param.selectedBlockFields).forEach(name => {
|
|
35
|
-
if (!Internal.evmNullableBlockFields.has(name)) {
|
|
36
|
-
nonOptionalBlockFieldNames.add(name);
|
|
37
|
-
}
|
|
38
32
|
capitalizedBlockFields.add(Utils.$$String.capitalize(name));
|
|
39
33
|
});
|
|
40
34
|
Array.from(param.selectedTransactionFields).forEach(name => {
|
|
41
|
-
if (!Internal.evmNullableTransactionFields.has(name)) {
|
|
42
|
-
nonOptionalTransactionFieldNames.add(name);
|
|
43
|
-
}
|
|
44
35
|
capitalizedTransactionFields.add(Utils.$$String.capitalize(name));
|
|
45
36
|
});
|
|
46
37
|
let eventFilters = param.getEventFiltersOrThrow(chain);
|
|
@@ -104,9 +95,7 @@ function getSelectionConfig(selection, chain) {
|
|
|
104
95
|
};
|
|
105
96
|
return {
|
|
106
97
|
getLogSelectionOrThrow: getLogSelectionOrThrow,
|
|
107
|
-
fieldSelection: fieldSelection
|
|
108
|
-
nonOptionalBlockFieldNames: Array.from(nonOptionalBlockFieldNames),
|
|
109
|
-
nonOptionalTransactionFieldNames: Array.from(nonOptionalTransactionFieldNames)
|
|
98
|
+
fieldSelection: fieldSelection
|
|
110
99
|
};
|
|
111
100
|
}
|
|
112
101
|
|
|
@@ -115,10 +104,8 @@ function memoGetSelectionConfig(chain) {
|
|
|
115
104
|
}
|
|
116
105
|
|
|
117
106
|
function make(param) {
|
|
118
|
-
let lowercaseAddresses = param.lowercaseAddresses;
|
|
119
107
|
let apiToken = param.apiToken;
|
|
120
108
|
let eventRouter = param.eventRouter;
|
|
121
|
-
let allEventSignatures = param.allEventSignatures;
|
|
122
109
|
let endpointUrl = param.endpointUrl;
|
|
123
110
|
let chain = param.chain;
|
|
124
111
|
let name = "HyperSync";
|
|
@@ -126,54 +113,37 @@ function make(param) {
|
|
|
126
113
|
let apiToken$1 = apiToken !== undefined ? apiToken : Stdlib_JsError.throwWithMessage(`An API token is required for using HyperSync as a data-source.
|
|
127
114
|
Set the ENVIO_API_TOKEN environment variable in your .env file.
|
|
128
115
|
Learn more or get a free API token at: https://envio.dev/app/api-tokens`);
|
|
129
|
-
let client
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return decoder;
|
|
137
|
-
}
|
|
138
|
-
let decoder$1;
|
|
139
|
-
try {
|
|
140
|
-
decoder$1 = HyperSyncClient.Decoder.fromSignatures(allEventSignatures);
|
|
141
|
-
} catch (raw_exn) {
|
|
142
|
-
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
143
|
-
return ErrorHandling.mkLogAndRaise(undefined, "Failed to instantiate a decoder from hypersync client, please double check your ABI", exn);
|
|
144
|
-
}
|
|
145
|
-
if (lowercaseAddresses) {
|
|
146
|
-
decoder$1.disableChecksummedAddresses();
|
|
147
|
-
} else {
|
|
148
|
-
decoder$1.enableChecksummedAddresses();
|
|
149
|
-
}
|
|
150
|
-
return decoder$1;
|
|
151
|
-
};
|
|
116
|
+
let client;
|
|
117
|
+
try {
|
|
118
|
+
client = HyperSyncClient.make(endpointUrl, apiToken$1, param.clientTimeoutMillis, param.clientMaxRetries, param.allEventParams, !param.lowercaseAddresses, param.serializationFormat, param.enableQueryCaching, undefined, undefined, undefined, param.logLevel);
|
|
119
|
+
} catch (raw_exn) {
|
|
120
|
+
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
121
|
+
client = ErrorHandling.mkLogAndRaise(undefined, "Failed to instantiate the hypersync client, please double check your ABI", exn);
|
|
122
|
+
}
|
|
152
123
|
let UndefinedValue = /* @__PURE__ */Primitive_exceptions.create("UndefinedValue");
|
|
153
124
|
let makeEventBatchQueueItem = (item, params, eventConfig) => {
|
|
154
125
|
let block = item.block;
|
|
155
|
-
let
|
|
126
|
+
let logIndex = item.logIndex;
|
|
156
127
|
return {
|
|
157
128
|
kind: 0,
|
|
158
129
|
eventConfig: eventConfig,
|
|
159
130
|
timestamp: block.timestamp,
|
|
160
131
|
chain: chain,
|
|
161
132
|
blockNumber: block.number,
|
|
162
|
-
logIndex:
|
|
133
|
+
logIndex: logIndex,
|
|
163
134
|
event: {
|
|
164
135
|
contractName: eventConfig.contractName,
|
|
165
136
|
eventName: eventConfig.name,
|
|
166
137
|
params: params,
|
|
167
138
|
chainId: chain,
|
|
168
|
-
srcAddress:
|
|
169
|
-
logIndex:
|
|
139
|
+
srcAddress: item.srcAddress,
|
|
140
|
+
logIndex: logIndex,
|
|
170
141
|
transaction: item.transaction,
|
|
171
142
|
block: block
|
|
172
143
|
}
|
|
173
144
|
};
|
|
174
145
|
};
|
|
175
146
|
let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, indexingAddresses, knownHeight, param, selection, retry, logger) => {
|
|
176
|
-
let mkLogAndRaise = (extra, extra$1) => ErrorHandling.mkLogAndRaise(logger, extra, extra$1);
|
|
177
147
|
let totalTimeRef = Hrtime.makeTimer();
|
|
178
148
|
let selectionConfig = getSelectionConfig(selection);
|
|
179
149
|
let logSelections;
|
|
@@ -187,7 +157,7 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`);
|
|
|
187
157
|
Prometheus.SourceRequestCount.increment(name, chain, "getLogs");
|
|
188
158
|
let pageUnsafe;
|
|
189
159
|
try {
|
|
190
|
-
pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, logSelections, selectionConfig.fieldSelection
|
|
160
|
+
pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, logSelections, selectionConfig.fieldSelection);
|
|
191
161
|
} catch (raw_error) {
|
|
192
162
|
let error = Primitive_exceptions.internalToException(raw_error);
|
|
193
163
|
if (error.RE_EXN_ID === HyperSync.GetLogs.$$Error) {
|
|
@@ -235,73 +205,22 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`);
|
|
|
235
205
|
let pageFetchTime = Hrtime.toSecondsFloat(Hrtime.timeSince(startFetchingBatchTimeRef));
|
|
236
206
|
let knownHeight$1 = pageUnsafe.archiveHeight;
|
|
237
207
|
let heighestBlockQueried = pageUnsafe.nextBlock - 1 | 0;
|
|
238
|
-
let match = pageUnsafe.rollbackGuard;
|
|
239
|
-
let lastBlockQueriedPromise;
|
|
240
|
-
if (match !== undefined) {
|
|
241
|
-
lastBlockQueriedPromise = Promise.resolve({
|
|
242
|
-
blockHash: match.hash,
|
|
243
|
-
blockNumber: match.blockNumber,
|
|
244
|
-
blockTimestamp: match.timestamp
|
|
245
|
-
});
|
|
246
|
-
} else {
|
|
247
|
-
let match$1 = Belt_Array.get(pageUnsafe.items, pageUnsafe.items.length - 1 | 0);
|
|
248
|
-
let exit = 0;
|
|
249
|
-
if (match$1 !== undefined) {
|
|
250
|
-
let block = match$1.block;
|
|
251
|
-
if (block.number === heighestBlockQueried) {
|
|
252
|
-
lastBlockQueriedPromise = Promise.resolve({
|
|
253
|
-
blockHash: block.hash,
|
|
254
|
-
blockNumber: block.number,
|
|
255
|
-
blockTimestamp: block.timestamp
|
|
256
|
-
});
|
|
257
|
-
} else {
|
|
258
|
-
exit = 1;
|
|
259
|
-
}
|
|
260
|
-
} else {
|
|
261
|
-
exit = 1;
|
|
262
|
-
}
|
|
263
|
-
if (exit === 1) {
|
|
264
|
-
lastBlockQueriedPromise = HyperSync.queryBlockData(client, heighestBlockQueried, name, chain, logger).then(res => {
|
|
265
|
-
if (res.TAG !== "Ok") {
|
|
266
|
-
return mkLogAndRaise(`Failed to query blockData for block ` + heighestBlockQueried.toString(), HyperSync.queryErrorToMsq(res._0));
|
|
267
|
-
}
|
|
268
|
-
let blockData = res._0;
|
|
269
|
-
if (blockData !== undefined) {
|
|
270
|
-
return blockData;
|
|
271
|
-
} else {
|
|
272
|
-
return mkLogAndRaise(`Failure, blockData for block ` + heighestBlockQueried.toString() + ` unexpectedly returned None`, {
|
|
273
|
-
RE_EXN_ID: "Not_found"
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
208
|
let parsingTimeRef = Hrtime.makeTimer();
|
|
280
209
|
let parsedQueueItems = [];
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
} catch (raw_exn$1) {
|
|
285
|
-
let exn$1 = Primitive_exceptions.internalToException(raw_exn$1);
|
|
286
|
-
parsedEvents = mkLogAndRaise("Failed to parse events using hypersync client, please double check your ABI.", exn$1);
|
|
287
|
-
}
|
|
288
|
-
Belt_Array.forEachWithIndex(pageUnsafe.items, (index, item) => {
|
|
289
|
-
let block = item.block;
|
|
290
|
-
let log = item.log;
|
|
291
|
-
let topic0 = Utils.$$Array.firstUnsafe(log.topics);
|
|
292
|
-
let maybeEventConfig = EventRouter.get(eventRouter, EventRouter.getEvmEventId(topic0, log.topics.length), log.address, block.number, indexingAddresses);
|
|
293
|
-
let maybeDecodedEvent = parsedEvents[index];
|
|
210
|
+
Belt_Array.forEach(pageUnsafe.items, item => {
|
|
211
|
+
let maybeEventConfig = EventRouter.get(eventRouter, EventRouter.getEvmEventId(item.topic0, item.topicCount), item.srcAddress, item.block.number, indexingAddresses);
|
|
212
|
+
let match = item.params;
|
|
294
213
|
if (maybeEventConfig === undefined) {
|
|
295
214
|
return;
|
|
296
215
|
}
|
|
297
|
-
if (
|
|
298
|
-
|
|
216
|
+
if (match == null) {
|
|
217
|
+
match === null;
|
|
299
218
|
} else {
|
|
300
|
-
parsedQueueItems.push(makeEventBatchQueueItem(item,
|
|
219
|
+
parsedQueueItems.push(makeEventBatchQueueItem(item, match, maybeEventConfig));
|
|
301
220
|
return;
|
|
302
221
|
}
|
|
303
|
-
let logIndex =
|
|
304
|
-
let blockNumber = block.number;
|
|
222
|
+
let logIndex = item.logIndex;
|
|
223
|
+
let blockNumber = item.block.number;
|
|
305
224
|
let exn = {
|
|
306
225
|
RE_EXN_ID: UndefinedValue
|
|
307
226
|
};
|
|
@@ -318,15 +237,43 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`);
|
|
|
318
237
|
ErrorHandling.mkLogAndRaise(logger$1, msg, exn);
|
|
319
238
|
});
|
|
320
239
|
let parsingTimeElapsed = Hrtime.toSecondsFloat(Hrtime.timeSince(parsingTimeRef));
|
|
321
|
-
let
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
240
|
+
let blockHashes = [];
|
|
241
|
+
Belt_Array.forEach(pageUnsafe.items, param => {
|
|
242
|
+
let block = param.block;
|
|
243
|
+
let match = block.number;
|
|
244
|
+
let match$1 = block.hash;
|
|
245
|
+
if (match !== undefined && match$1 !== undefined) {
|
|
246
|
+
blockHashes.push({
|
|
247
|
+
blockHash: match$1,
|
|
248
|
+
blockNumber: match
|
|
249
|
+
});
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
let match = pageUnsafe.rollbackGuard;
|
|
254
|
+
if (match !== undefined) {
|
|
255
|
+
blockHashes.push({
|
|
256
|
+
blockHash: match.hash,
|
|
257
|
+
blockNumber: match.blockNumber
|
|
258
|
+
});
|
|
259
|
+
blockHashes.push({
|
|
260
|
+
blockHash: match.firstParentHash,
|
|
261
|
+
blockNumber: match.firstBlockNumber - 1 | 0
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
let match$1 = pageUnsafe.rollbackGuard;
|
|
265
|
+
let latestFetchedBlockTimestamp;
|
|
266
|
+
if (match$1 !== undefined) {
|
|
267
|
+
latestFetchedBlockTimestamp = match$1.timestamp;
|
|
268
|
+
} else {
|
|
269
|
+
let match$2 = Belt_Array.get(pageUnsafe.items, pageUnsafe.items.length - 1 | 0);
|
|
270
|
+
if (match$2 !== undefined) {
|
|
271
|
+
let block = match$2.block;
|
|
272
|
+
latestFetchedBlockTimestamp = block.number === heighestBlockQueried ? block.timestamp : 0;
|
|
273
|
+
} else {
|
|
274
|
+
latestFetchedBlockTimestamp = 0;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
330
277
|
let totalTimeElapsed = Hrtime.toSecondsFloat(Hrtime.timeSince(totalTimeRef));
|
|
331
278
|
let stats_parsing$unknowntime$unknown$lpars$rpar = parsingTimeElapsed;
|
|
332
279
|
let stats_page$unknownfetch$unknowntime$unknown$lpars$rpar = pageFetchTime;
|
|
@@ -337,11 +284,11 @@ Learn more or get a free API token at: https://envio.dev/app/api-tokens`);
|
|
|
337
284
|
};
|
|
338
285
|
return {
|
|
339
286
|
knownHeight: knownHeight$1,
|
|
340
|
-
|
|
287
|
+
blockHashes: blockHashes,
|
|
341
288
|
parsedQueueItems: parsedQueueItems,
|
|
342
289
|
fromBlockQueried: fromBlock,
|
|
343
|
-
latestFetchedBlockNumber:
|
|
344
|
-
latestFetchedBlockTimestamp:
|
|
290
|
+
latestFetchedBlockNumber: heighestBlockQueried,
|
|
291
|
+
latestFetchedBlockTimestamp: latestFetchedBlockTimestamp,
|
|
345
292
|
stats: stats
|
|
346
293
|
};
|
|
347
294
|
};
|