envio 3.3.2 → 3.4.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/package.json +6 -6
- package/src/Api.res +1 -8
- package/src/Api.res.mjs +1 -5
- package/src/ChainState.res +6 -1
- package/src/ChainState.res.mjs +4 -3
- package/src/Config.res +33 -4
- package/src/Config.res.mjs +34 -5
- package/src/Core.res +30 -19
- package/src/Core.res.mjs +5 -5
- package/src/EnvioGlobal.res +0 -2
- package/src/EnvioGlobal.res.mjs +0 -1
- package/src/ExitOnCaughtUp.res +6 -2
- package/src/ExitOnCaughtUp.res.mjs +4 -0
- package/src/FetchState.res +3 -3
- package/src/HandlerRegister.res +357 -434
- package/src/HandlerRegister.res.mjs +202 -242
- package/src/HandlerRegister.resi +7 -15
- package/src/IndexerState.res +10 -0
- package/src/IndexerState.res.mjs +9 -3
- package/src/IndexerState.resi +3 -0
- package/src/Internal.res +10 -1
- package/src/Main.res.mjs +4 -4
- package/src/PgStorage.res +16 -1
- package/src/PgStorage.res.mjs +9 -1
- package/src/SimulateItems.res +61 -40
- package/src/SimulateItems.res.mjs +37 -21
- package/src/TestIndexer.res +446 -453
- package/src/TestIndexer.res.mjs +320 -343
- package/src/bindings/ClickHouse.res +68 -2
- package/src/bindings/ClickHouse.res.mjs +47 -2
- package/src/sources/EvmChain.res +1 -1
- package/src/sources/EvmChain.res.mjs +2 -2
- package/src/sources/FuelHyperSync.res +74 -0
- package/src/sources/FuelHyperSync.res.mjs +80 -0
- package/src/sources/FuelHyperSync.resi +22 -0
- package/src/sources/FuelHyperSyncClient.res +120 -0
- package/src/sources/FuelHyperSyncClient.res.mjs +71 -0
- package/src/sources/FuelHyperSyncSource.res +257 -0
- package/src/sources/FuelHyperSyncSource.res.mjs +252 -0
- package/src/sources/HyperSyncClient.res +2 -2
- package/src/sources/HyperSyncClient.res.mjs +1 -1
- package/src/sources/SvmHyperSyncClient.res +139 -102
- package/src/sources/SvmHyperSyncClient.res.mjs +45 -5
- package/src/sources/SvmHyperSyncSource.res +60 -440
- package/src/sources/SvmHyperSyncSource.res.mjs +42 -363
- package/src/TestIndexerProxyStorage.res +0 -196
- package/src/TestIndexerProxyStorage.res.mjs +0 -121
- package/src/TestIndexerWorker.res +0 -4
- package/src/TestIndexerWorker.res.mjs +0 -7
- package/src/sources/EventRouter.res +0 -165
- package/src/sources/EventRouter.res.mjs +0 -153
- package/src/sources/HyperFuel.res +0 -179
- package/src/sources/HyperFuel.res.mjs +0 -146
- package/src/sources/HyperFuel.resi +0 -36
- package/src/sources/HyperFuelClient.res +0 -127
- package/src/sources/HyperFuelClient.res.mjs +0 -20
- package/src/sources/HyperFuelSource.res +0 -502
- package/src/sources/HyperFuelSource.res.mjs +0 -481
- /package/src/sources/{HyperSyncSource.res → EvmHyperSyncSource.res} +0 -0
- /package/src/sources/{HyperSyncSource.res.mjs → EvmHyperSyncSource.res.mjs} +0 -0
|
@@ -1,502 +0,0 @@
|
|
|
1
|
-
open Source
|
|
2
|
-
|
|
3
|
-
exception EventRoutingFailed
|
|
4
|
-
|
|
5
|
-
let isUnauthorizedError = (message: string) => message->String.includes("401 Unauthorized")
|
|
6
|
-
|
|
7
|
-
let mintEventTag = "mint"
|
|
8
|
-
let burnEventTag = "burn"
|
|
9
|
-
let transferEventTag = "transfer"
|
|
10
|
-
let callEventTag = "call"
|
|
11
|
-
|
|
12
|
-
type selectionConfig = {
|
|
13
|
-
getRecieptsSelection: (
|
|
14
|
-
~addressesByContractName: dict<array<Address.t>>,
|
|
15
|
-
) => array<HyperFuelClient.QueryTypes.receiptSelection>,
|
|
16
|
-
eventRouter: EventRouter.t<Internal.fuelOnEventRegistration>,
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
let logDataReceiptTypeSelection: array<FuelSDK.receiptType> = [LogData]
|
|
20
|
-
|
|
21
|
-
// only transactions with status 1 (success)
|
|
22
|
-
let txStatusSelection = [1]
|
|
23
|
-
|
|
24
|
-
let makeGetNormalRecieptsSelection = (
|
|
25
|
-
~nonWildcardLogDataRbsByContract,
|
|
26
|
-
~nonLogDataReceiptTypesByContract,
|
|
27
|
-
~contractNames,
|
|
28
|
-
) => {
|
|
29
|
-
(~addressesByContractName) => {
|
|
30
|
-
let selection: array<HyperFuelClient.QueryTypes.receiptSelection> = []
|
|
31
|
-
|
|
32
|
-
//Instantiate each time to add new registered contract addresses
|
|
33
|
-
contractNames->Utils.Set.forEach(contractName => {
|
|
34
|
-
switch addressesByContractName->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
35
|
-
| None
|
|
36
|
-
| Some([]) => ()
|
|
37
|
-
| Some(addresses) => {
|
|
38
|
-
switch nonLogDataReceiptTypesByContract->Utils.Dict.dangerouslyGetNonOption(
|
|
39
|
-
contractName,
|
|
40
|
-
) {
|
|
41
|
-
| Some(receiptTypes) =>
|
|
42
|
-
selection
|
|
43
|
-
->Array.push({
|
|
44
|
-
rootContractId: addresses,
|
|
45
|
-
receiptType: receiptTypes,
|
|
46
|
-
txStatus: txStatusSelection,
|
|
47
|
-
})
|
|
48
|
-
->ignore
|
|
49
|
-
| None => ()
|
|
50
|
-
}
|
|
51
|
-
switch nonWildcardLogDataRbsByContract->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
52
|
-
| None
|
|
53
|
-
| Some([]) => ()
|
|
54
|
-
| Some(nonWildcardLogDataRbs) =>
|
|
55
|
-
selection
|
|
56
|
-
->Array.push({
|
|
57
|
-
rootContractId: addresses,
|
|
58
|
-
receiptType: logDataReceiptTypeSelection,
|
|
59
|
-
txStatus: txStatusSelection,
|
|
60
|
-
rb: nonWildcardLogDataRbs,
|
|
61
|
-
})
|
|
62
|
-
->ignore
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
selection
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
let makeWildcardRecieptsSelection = (~wildcardLogDataRbs, ~nonLogDataWildcardReceiptTypes) => {
|
|
73
|
-
let selection: array<HyperFuelClient.QueryTypes.receiptSelection> = []
|
|
74
|
-
|
|
75
|
-
switch nonLogDataWildcardReceiptTypes {
|
|
76
|
-
| [] => ()
|
|
77
|
-
| nonLogDataWildcardReceiptTypes =>
|
|
78
|
-
selection
|
|
79
|
-
->Array.push(
|
|
80
|
-
(
|
|
81
|
-
{
|
|
82
|
-
receiptType: nonLogDataWildcardReceiptTypes,
|
|
83
|
-
txStatus: txStatusSelection,
|
|
84
|
-
}: HyperFuelClient.QueryTypes.receiptSelection
|
|
85
|
-
),
|
|
86
|
-
)
|
|
87
|
-
->ignore
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
switch wildcardLogDataRbs {
|
|
91
|
-
| [] => ()
|
|
92
|
-
| wildcardLogDataRbs =>
|
|
93
|
-
selection
|
|
94
|
-
->Array.push(
|
|
95
|
-
(
|
|
96
|
-
{
|
|
97
|
-
receiptType: logDataReceiptTypeSelection,
|
|
98
|
-
txStatus: txStatusSelection,
|
|
99
|
-
rb: wildcardLogDataRbs,
|
|
100
|
-
}: HyperFuelClient.QueryTypes.receiptSelection
|
|
101
|
-
),
|
|
102
|
-
)
|
|
103
|
-
->ignore
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
selection
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
let getSelectionConfig = (selection: FetchState.selection, ~chain) => {
|
|
110
|
-
let eventRouter = EventRouter.empty()
|
|
111
|
-
let nonWildcardLogDataRbsByContract = Dict.make()
|
|
112
|
-
let wildcardLogDataRbs = []
|
|
113
|
-
|
|
114
|
-
// This is for non-LogData events, since they don't have rb filter and can be grouped
|
|
115
|
-
let nonLogDataReceiptTypesByContract = Dict.make()
|
|
116
|
-
let nonLogDataWildcardReceiptTypes = []
|
|
117
|
-
|
|
118
|
-
let addNonLogDataWildcardReceiptTypes = (receiptType: FuelSDK.receiptType) => {
|
|
119
|
-
nonLogDataWildcardReceiptTypes->Array.push(receiptType)->ignore
|
|
120
|
-
}
|
|
121
|
-
let addNonLogDataReceiptType = (contractName, receiptType: FuelSDK.receiptType) => {
|
|
122
|
-
switch nonLogDataReceiptTypesByContract->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
123
|
-
| None => nonLogDataReceiptTypesByContract->Dict.set(contractName, [receiptType])
|
|
124
|
-
| Some(receiptTypes) => receiptTypes->Array.push(receiptType)->ignore // Duplication prevented by EventRouter
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
let contractNames = Utils.Set.make()
|
|
129
|
-
|
|
130
|
-
selection.onEventRegistrations->Array.forEach(reg => {
|
|
131
|
-
let eventConfig =
|
|
132
|
-
reg.eventConfig->(Utils.magic: Internal.eventConfig => Internal.fuelEventConfig)
|
|
133
|
-
let contractName = eventConfig.contractName
|
|
134
|
-
let isWildcard = reg.isWildcard
|
|
135
|
-
if !isWildcard {
|
|
136
|
-
let _ = contractNames->Utils.Set.add(contractName)
|
|
137
|
-
}
|
|
138
|
-
eventRouter->EventRouter.addOrThrow(
|
|
139
|
-
eventConfig.id,
|
|
140
|
-
reg,
|
|
141
|
-
~contractName,
|
|
142
|
-
~eventName=eventConfig.name,
|
|
143
|
-
~chain,
|
|
144
|
-
~isWildcard,
|
|
145
|
-
)
|
|
146
|
-
|
|
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) => {
|
|
153
|
-
addNonLogDataWildcardReceiptTypes(Transfer)
|
|
154
|
-
addNonLogDataWildcardReceiptTypes(TransferOut)
|
|
155
|
-
}
|
|
156
|
-
| (Transfer, false) => {
|
|
157
|
-
addNonLogDataReceiptType(contractName, Transfer)
|
|
158
|
-
addNonLogDataReceiptType(contractName, TransferOut)
|
|
159
|
-
}
|
|
160
|
-
| (Call, true) => addNonLogDataWildcardReceiptTypes(Call)
|
|
161
|
-
| (Call, false) =>
|
|
162
|
-
JsError.throwWithMessage("Call receipt indexing currently supported only in wildcard mode")
|
|
163
|
-
| (LogData({logId}), _) => {
|
|
164
|
-
let rb = logId->BigInt.fromStringOrThrow
|
|
165
|
-
if isWildcard {
|
|
166
|
-
wildcardLogDataRbs->Array.push(rb)->ignore
|
|
167
|
-
} else {
|
|
168
|
-
switch nonWildcardLogDataRbsByContract->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
169
|
-
| Some(arr) => arr->Array.push(rb)
|
|
170
|
-
| None => nonWildcardLogDataRbsByContract->Dict.set(contractName, [rb])
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
{
|
|
178
|
-
getRecieptsSelection: switch selection.dependsOnAddresses {
|
|
179
|
-
| false => {
|
|
180
|
-
let recieptsSelection = makeWildcardRecieptsSelection(
|
|
181
|
-
~wildcardLogDataRbs,
|
|
182
|
-
~nonLogDataWildcardReceiptTypes,
|
|
183
|
-
)
|
|
184
|
-
(~addressesByContractName as _) => recieptsSelection
|
|
185
|
-
}
|
|
186
|
-
| true =>
|
|
187
|
-
makeGetNormalRecieptsSelection(
|
|
188
|
-
~nonWildcardLogDataRbsByContract,
|
|
189
|
-
~nonLogDataReceiptTypesByContract,
|
|
190
|
-
~contractNames,
|
|
191
|
-
)
|
|
192
|
-
},
|
|
193
|
-
eventRouter,
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
let memoGetSelectionConfig = (~chain) => {
|
|
198
|
-
let cache = Utils.WeakMap.make()
|
|
199
|
-
selection =>
|
|
200
|
-
switch cache->Utils.WeakMap.get(selection) {
|
|
201
|
-
| Some(c) => c
|
|
202
|
-
| None => {
|
|
203
|
-
let c = selection->getSelectionConfig(~chain)
|
|
204
|
-
let _ = cache->Utils.WeakMap.set(selection, c)
|
|
205
|
-
c
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
type options = {
|
|
211
|
-
chain: ChainMap.Chain.t,
|
|
212
|
-
endpointUrl: string,
|
|
213
|
-
apiToken: option<string>,
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
let make = ({chain, endpointUrl, apiToken}: options): t => {
|
|
217
|
-
let name = "HyperFuel"
|
|
218
|
-
|
|
219
|
-
let apiToken = switch apiToken {
|
|
220
|
-
| Some(token) => token
|
|
221
|
-
| None =>
|
|
222
|
-
JsError.throwWithMessage(`An Envio API token is required for using HyperFuel as a data-source.
|
|
223
|
-
Set the ENVIO_API_TOKEN environment variable in your .env file.
|
|
224
|
-
Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
let client = switch HyperFuelClient.make({url: endpointUrl, apiToken}) {
|
|
228
|
-
| client => client
|
|
229
|
-
| exception exn =>
|
|
230
|
-
exn->ErrorHandling.mkLogAndRaise(~msg="Failed to instantiate the HyperFuel client")
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
let getSelectionConfig = memoGetSelectionConfig(~chain)
|
|
234
|
-
|
|
235
|
-
let getItemsOrThrow = async (
|
|
236
|
-
~fromBlock,
|
|
237
|
-
~toBlock,
|
|
238
|
-
~addressesByContractName,
|
|
239
|
-
~contractNameByAddress,
|
|
240
|
-
~knownHeight,
|
|
241
|
-
~partitionId as _,
|
|
242
|
-
~selection: FetchState.selection,
|
|
243
|
-
~itemsTarget as _,
|
|
244
|
-
~retry,
|
|
245
|
-
~logger,
|
|
246
|
-
) => {
|
|
247
|
-
let totalTimeRef = Performance.now()
|
|
248
|
-
|
|
249
|
-
let selectionConfig = getSelectionConfig(selection)
|
|
250
|
-
let recieptsSelection = selectionConfig.getRecieptsSelection(~addressesByContractName)
|
|
251
|
-
|
|
252
|
-
let startFetchingBatchTimeRef = Performance.now()
|
|
253
|
-
|
|
254
|
-
//fetch batch
|
|
255
|
-
let pageUnsafe = try await HyperFuel.GetLogs.query(
|
|
256
|
-
~client,
|
|
257
|
-
~fromBlock,
|
|
258
|
-
~toBlock,
|
|
259
|
-
~recieptsSelection,
|
|
260
|
-
) catch {
|
|
261
|
-
| HyperFuel.GetLogs.Error(error) =>
|
|
262
|
-
throw(
|
|
263
|
-
Source.GetItemsError(
|
|
264
|
-
Source.FailedGettingItems({
|
|
265
|
-
exn: %raw(`null`),
|
|
266
|
-
attemptedToBlock: toBlock->Option.getOr(knownHeight),
|
|
267
|
-
retry: switch error {
|
|
268
|
-
| WrongInstance =>
|
|
269
|
-
let backoffMillis = switch retry {
|
|
270
|
-
| 0 => 100
|
|
271
|
-
| _ => 500 * retry
|
|
272
|
-
}
|
|
273
|
-
WithBackoff({
|
|
274
|
-
message: `Block #${fromBlock->Int.toString} not found in HyperFuel. HyperFuel has multiple instances and it's possible that they drift independently slightly from the head. Indexing should continue correctly after retrying the query in ${backoffMillis->Int.toString}ms.`,
|
|
275
|
-
backoffMillis,
|
|
276
|
-
})
|
|
277
|
-
| UnexpectedMissingParams({missingParams}) =>
|
|
278
|
-
ImpossibleForTheQuery({
|
|
279
|
-
message: `Source returned invalid data with missing required fields: ${missingParams->Array.joinUnsafe(
|
|
280
|
-
", ",
|
|
281
|
-
)}`,
|
|
282
|
-
})
|
|
283
|
-
},
|
|
284
|
-
}),
|
|
285
|
-
),
|
|
286
|
-
)
|
|
287
|
-
| exn =>
|
|
288
|
-
throw(
|
|
289
|
-
Source.GetItemsError(
|
|
290
|
-
Source.FailedGettingItems({
|
|
291
|
-
exn,
|
|
292
|
-
attemptedToBlock: toBlock->Option.getOr(knownHeight),
|
|
293
|
-
retry: WithBackoff({
|
|
294
|
-
message: `Unexpected issue while fetching events from HyperFuel client. Attempt a retry.`,
|
|
295
|
-
backoffMillis: switch retry {
|
|
296
|
-
| 0 => 500
|
|
297
|
-
| _ => 1000 * retry
|
|
298
|
-
},
|
|
299
|
-
}),
|
|
300
|
-
}),
|
|
301
|
-
),
|
|
302
|
-
)
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
let pageFetchTime = startFetchingBatchTimeRef->Performance.secondsSince
|
|
306
|
-
let requestStats = [{Source.method: "getLogs", seconds: pageFetchTime}]
|
|
307
|
-
|
|
308
|
-
//set height and next from block
|
|
309
|
-
let knownHeight = pageUnsafe.archiveHeight
|
|
310
|
-
|
|
311
|
-
//The heighest (biggest) blocknumber that was accounted for in
|
|
312
|
-
//Our query. Not necessarily the blocknumber of the last log returned
|
|
313
|
-
//In the query
|
|
314
|
-
let heighestBlockQueried = pageUnsafe.nextBlock - 1
|
|
315
|
-
|
|
316
|
-
let parsingTimeRef = Performance.now()
|
|
317
|
-
|
|
318
|
-
let parsedQueueItems = pageUnsafe.items->Array.map(item => {
|
|
319
|
-
let {contractId: contractAddress, receipt, block, receiptIndex} = item
|
|
320
|
-
|
|
321
|
-
let chainId = chain->ChainMap.Chain.toChainId
|
|
322
|
-
let eventId = switch receipt {
|
|
323
|
-
| LogData({rb}) => BigInt.toString(rb)
|
|
324
|
-
| Mint(_) => mintEventTag
|
|
325
|
-
| Burn(_) => burnEventTag
|
|
326
|
-
| Transfer(_)
|
|
327
|
-
| TransferOut(_) => transferEventTag
|
|
328
|
-
| Call(_) => callEventTag
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
let onEventRegistration = switch selectionConfig.eventRouter->EventRouter.get(
|
|
332
|
-
~tag=eventId,
|
|
333
|
-
~contractNameByAddress,
|
|
334
|
-
~contractAddress,
|
|
335
|
-
) {
|
|
336
|
-
| None => {
|
|
337
|
-
let logger = Logging.createChildFrom(
|
|
338
|
-
~logger,
|
|
339
|
-
~params={
|
|
340
|
-
"chainId": chainId,
|
|
341
|
-
"blockNumber": block.height,
|
|
342
|
-
"logIndex": receiptIndex,
|
|
343
|
-
"contractAddress": contractAddress,
|
|
344
|
-
"eventId": eventId,
|
|
345
|
-
},
|
|
346
|
-
)
|
|
347
|
-
EventRoutingFailed->ErrorHandling.mkLogAndRaise(
|
|
348
|
-
~msg="Failed to route registered event",
|
|
349
|
-
~logger,
|
|
350
|
-
)
|
|
351
|
-
}
|
|
352
|
-
| Some(onEventRegistration) => onEventRegistration
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
let eventConfig =
|
|
356
|
-
onEventRegistration.eventConfig->(
|
|
357
|
-
Utils.magic: Internal.eventConfig => Internal.fuelEventConfig
|
|
358
|
-
)
|
|
359
|
-
|
|
360
|
-
let params = switch (eventConfig, receipt) {
|
|
361
|
-
| ({kind: LogData({decode})}, LogData({data})) =>
|
|
362
|
-
try decode(data) catch {
|
|
363
|
-
| exn => {
|
|
364
|
-
let params = {
|
|
365
|
-
"chainId": chainId,
|
|
366
|
-
"blockNumber": block.height,
|
|
367
|
-
"logIndex": receiptIndex,
|
|
368
|
-
}
|
|
369
|
-
let logger = Logging.createChildFrom(~logger, ~params)
|
|
370
|
-
exn->ErrorHandling.mkLogAndRaise(
|
|
371
|
-
~msg="Failed to decode Fuel LogData receipt, please double check your ABI.",
|
|
372
|
-
~logger,
|
|
373
|
-
)
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
| (_, Mint({val, subId}))
|
|
377
|
-
| (_, Burn({val, subId})) =>
|
|
378
|
-
(
|
|
379
|
-
{
|
|
380
|
-
subId,
|
|
381
|
-
amount: val,
|
|
382
|
-
}: Internal.fuelSupplyParams
|
|
383
|
-
)->Obj.magic
|
|
384
|
-
| (_, Transfer({amount, assetId, to})) =>
|
|
385
|
-
(
|
|
386
|
-
{
|
|
387
|
-
to: to->Address.unsafeFromString,
|
|
388
|
-
assetId,
|
|
389
|
-
amount,
|
|
390
|
-
}: Internal.fuelTransferParams
|
|
391
|
-
)->Obj.magic
|
|
392
|
-
| (_, TransferOut({amount, assetId, toAddress})) =>
|
|
393
|
-
(
|
|
394
|
-
{
|
|
395
|
-
to: toAddress->Address.unsafeFromString,
|
|
396
|
-
assetId,
|
|
397
|
-
amount,
|
|
398
|
-
}: Internal.fuelTransferParams
|
|
399
|
-
)->Obj.magic
|
|
400
|
-
| (_, Call({amount, assetId, to})) =>
|
|
401
|
-
(
|
|
402
|
-
{
|
|
403
|
-
to: to->Address.unsafeFromString,
|
|
404
|
-
assetId,
|
|
405
|
-
amount,
|
|
406
|
-
}: Internal.fuelTransferParams
|
|
407
|
-
)->Obj.magic
|
|
408
|
-
// This should never happen unless there's a bug in the routing logic
|
|
409
|
-
| _ => JsError.throwWithMessage("Unexpected bug in the event routing logic")
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
Internal.Event({
|
|
413
|
-
onEventRegistration: (onEventRegistration :> Internal.onEventRegistration),
|
|
414
|
-
chain,
|
|
415
|
-
blockNumber: block.height,
|
|
416
|
-
logIndex: receiptIndex,
|
|
417
|
-
// Fuel carries the transaction inline on the payload; the store key is
|
|
418
|
-
// unused (Fuel identifies transactions by hash, kept on the payload).
|
|
419
|
-
transactionIndex: 0,
|
|
420
|
-
payload: {
|
|
421
|
-
contractName: eventConfig.contractName,
|
|
422
|
-
eventName: eventConfig.name,
|
|
423
|
-
chainId,
|
|
424
|
-
params,
|
|
425
|
-
transaction: {
|
|
426
|
-
"id": item.transactionId,
|
|
427
|
-
}->Obj.magic, // TODO: Obj.magic needed until the field selection types are not configurable for Fuel and Evm separately
|
|
428
|
-
block: block->Obj.magic,
|
|
429
|
-
srcAddress: contractAddress,
|
|
430
|
-
logIndex: receiptIndex,
|
|
431
|
-
}->Fuel.fromPayload,
|
|
432
|
-
})
|
|
433
|
-
})
|
|
434
|
-
|
|
435
|
-
let parsingTimeElapsed = parsingTimeRef->Performance.secondsSince
|
|
436
|
-
|
|
437
|
-
// Fuel never rolls back on reorg, so block hashes here are purely informational
|
|
438
|
-
// for detect-only logging via ReorgDetection.
|
|
439
|
-
let blockHashes = pageUnsafe.items->Array.map(({block}) => {
|
|
440
|
-
ReorgDetection.blockNumber: block.height,
|
|
441
|
-
blockHash: block.id,
|
|
442
|
-
})
|
|
443
|
-
|
|
444
|
-
let latestFetchedBlockTimestamp = switch pageUnsafe.items->Array.get(
|
|
445
|
-
pageUnsafe.items->Array.length - 1,
|
|
446
|
-
) {
|
|
447
|
-
| Some({block}) if block.height == heighestBlockQueried => block.time
|
|
448
|
-
| _ => 0
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
let totalTimeElapsed = totalTimeRef->Performance.secondsSince
|
|
452
|
-
|
|
453
|
-
let stats = {
|
|
454
|
-
totalTimeElapsed,
|
|
455
|
-
parsingTimeElapsed,
|
|
456
|
-
pageFetchTime,
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
{
|
|
460
|
-
latestFetchedBlockTimestamp,
|
|
461
|
-
parsedQueueItems,
|
|
462
|
-
// Fuel keeps transaction and block on the payload; no store pages.
|
|
463
|
-
transactionStore: None,
|
|
464
|
-
blockStore: None,
|
|
465
|
-
latestFetchedBlockNumber: heighestBlockQueried,
|
|
466
|
-
stats,
|
|
467
|
-
knownHeight,
|
|
468
|
-
blockHashes,
|
|
469
|
-
fromBlockQueried: fromBlock,
|
|
470
|
-
requestStats,
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
let getBlockHashes = (~blockNumbers as _, ~logger as _) =>
|
|
475
|
-
JsError.throwWithMessage("HyperFuel does not support getting block hashes")
|
|
476
|
-
|
|
477
|
-
{
|
|
478
|
-
name,
|
|
479
|
-
sourceFor: Sync,
|
|
480
|
-
chain,
|
|
481
|
-
getBlockHashes,
|
|
482
|
-
pollingInterval: 100,
|
|
483
|
-
poweredByHyperSync: true,
|
|
484
|
-
getHeightOrThrow: async () => {
|
|
485
|
-
let timerRef = Performance.now()
|
|
486
|
-
let height = try await client->HyperFuelClient.getHeight catch {
|
|
487
|
-
| JsExn(e) =>
|
|
488
|
-
switch e->JsExn.message {
|
|
489
|
-
| Some(message) if message->isUnauthorizedError =>
|
|
490
|
-
Logging.error(`Your ENVIO_API_TOKEN was rejected by HyperFuel (401 Unauthorized). The indexer will not be able to fetch events. Update the token and try again using 'envio start' or 'envio dev'. For more info: https://docs.envio.dev/docs/HyperSync/api-tokens`)
|
|
491
|
-
// Retrying an unauthorized request can never succeed, so block forever
|
|
492
|
-
let _ = await Promise.make((_, _) => ())
|
|
493
|
-
0
|
|
494
|
-
| _ => throw(JsExn(e))
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
let seconds = timerRef->Performance.secondsSince
|
|
498
|
-
{height, requestStats: [{method: "getHeight", seconds}]}
|
|
499
|
-
},
|
|
500
|
-
getItemsOrThrow,
|
|
501
|
-
}
|
|
502
|
-
}
|