envio 3.3.0-alpha.8 → 3.3.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/index.d.ts +19 -0
- package/licenses/CLA.md +35 -0
- package/licenses/EULA.md +67 -0
- package/licenses/LICENSE.md +45 -0
- package/licenses/README.md +35 -0
- package/package.json +9 -8
- package/src/Batch.res.mjs +1 -1
- package/src/BatchProcessing.res +0 -7
- package/src/BatchProcessing.res.mjs +1 -8
- package/src/ChainFetching.res +30 -18
- package/src/ChainFetching.res.mjs +23 -13
- package/src/ChainState.res +205 -59
- package/src/ChainState.res.mjs +130 -27
- package/src/ChainState.resi +16 -1
- package/src/Config.res +9 -5
- package/src/Config.res.mjs +2 -2
- package/src/Core.res +20 -0
- package/src/Core.res.mjs +12 -0
- package/src/CrossChainState.res +147 -39
- package/src/CrossChainState.res.mjs +42 -10
- package/src/EffectState.res +100 -0
- package/src/EffectState.res.mjs +74 -0
- package/src/EffectState.resi +32 -0
- package/src/Envio.res +25 -7
- package/src/Envio.res.mjs +15 -19
- package/src/EnvioGlobal.res +53 -0
- package/src/EnvioGlobal.res.mjs +31 -0
- package/src/EventConfigBuilder.res +30 -56
- package/src/EventConfigBuilder.res.mjs +24 -30
- package/src/EventProcessing.res +8 -5
- package/src/EventProcessing.res.mjs +2 -1
- package/src/FetchState.res +842 -474
- package/src/FetchState.res.mjs +545 -356
- package/src/HandlerLoader.res +1 -1
- package/src/HandlerLoader.res.mjs +1 -1
- package/src/HandlerRegister.res +478 -305
- package/src/HandlerRegister.res.mjs +277 -209
- package/src/HandlerRegister.resi +11 -6
- package/src/InMemoryStore.res +14 -26
- package/src/InMemoryStore.res.mjs +6 -19
- package/src/IndexerState.res +15 -39
- package/src/IndexerState.res.mjs +18 -29
- package/src/IndexerState.resi +2 -10
- package/src/Internal.res +121 -18
- package/src/Internal.res.mjs +96 -2
- package/src/LoadLayer.res +44 -24
- package/src/LoadLayer.res.mjs +43 -20
- package/src/LoadLayer.resi +1 -0
- package/src/LogSelection.res +92 -217
- package/src/LogSelection.res.mjs +95 -184
- package/src/Main.res +29 -143
- package/src/Main.res.mjs +25 -88
- package/src/Metrics.res +1 -1
- package/src/Metrics.res.mjs +1 -1
- package/src/Persistence.res +12 -3
- package/src/PgStorage.res +155 -82
- package/src/PgStorage.res.mjs +130 -77
- package/src/Prometheus.res +20 -10
- package/src/Prometheus.res.mjs +22 -10
- package/src/PruneStaleHistory.res +146 -35
- package/src/PruneStaleHistory.res.mjs +114 -20
- package/src/RawEvent.res +2 -2
- package/src/Rollback.res +32 -13
- package/src/Rollback.res.mjs +24 -11
- package/src/RollbackCommit.res +4 -1
- package/src/RollbackCommit.res.mjs +3 -2
- package/src/SimulateDeadInputTracker.res +1 -1
- package/src/SimulateItems.res +39 -7
- package/src/SimulateItems.res.mjs +28 -9
- package/src/TestIndexer.res +2 -2
- package/src/TestIndexer.res.mjs +2 -2
- package/src/TopicFilter.res +1 -25
- package/src/TopicFilter.res.mjs +0 -74
- package/src/UserContext.res +62 -23
- package/src/UserContext.res.mjs +26 -6
- package/src/Writing.res +60 -21
- package/src/Writing.res.mjs +27 -9
- package/src/bindings/NodeJs.res +5 -0
- package/src/bindings/Viem.res +0 -5
- package/src/sources/EventRouter.res +0 -21
- package/src/sources/EventRouter.res.mjs +0 -12
- package/src/sources/Evm.res +4 -1
- package/src/sources/Evm.res.mjs +1 -1
- package/src/sources/EvmChain.res +2 -27
- package/src/sources/EvmChain.res.mjs +2 -23
- package/src/sources/EvmRpcClient.res +58 -23
- package/src/sources/EvmRpcClient.res.mjs +11 -5
- package/src/sources/Fuel.res +3 -1
- package/src/sources/Fuel.res.mjs +1 -1
- package/src/sources/HyperSync.res +9 -38
- package/src/sources/HyperSync.res.mjs +16 -28
- package/src/sources/HyperSync.resi +2 -2
- package/src/sources/HyperSyncClient.res +88 -11
- package/src/sources/HyperSyncClient.res.mjs +39 -6
- package/src/sources/HyperSyncSource.res +18 -210
- package/src/sources/HyperSyncSource.res.mjs +9 -137
- package/src/sources/Rpc.res +0 -32
- package/src/sources/Rpc.res.mjs +1 -46
- package/src/sources/RpcSource.res +129 -533
- package/src/sources/RpcSource.res.mjs +161 -379
- package/src/sources/SimulateSource.res +37 -19
- package/src/sources/SimulateSource.res.mjs +27 -10
- package/src/sources/SourceManager.res +4 -14
- package/src/sources/SourceManager.res.mjs +3 -9
- package/src/sources/SourceManager.resi +0 -2
- package/src/sources/SvmHyperSyncSource.res +13 -3
- package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
|
@@ -1,134 +1,5 @@
|
|
|
1
1
|
open Source
|
|
2
2
|
|
|
3
|
-
type selectionConfig = {
|
|
4
|
-
getLogSelectionOrThrow: (
|
|
5
|
-
~addressesByContractName: dict<array<Address.t>>,
|
|
6
|
-
) => array<LogSelection.t>,
|
|
7
|
-
fieldSelection: HyperSyncClient.QueryTypes.fieldSelection,
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
let getSelectionConfig = (selection: FetchState.selection, ~chain) => {
|
|
11
|
-
let capitalizedBlockFields = Utils.Set.make()
|
|
12
|
-
let capitalizedTransactionFields = Utils.Set.make()
|
|
13
|
-
|
|
14
|
-
let staticTopicSelectionsByContract = Dict.make()
|
|
15
|
-
let dynamicEventFiltersByContract = Dict.make()
|
|
16
|
-
let dynamicWildcardEventFiltersByContract = Dict.make()
|
|
17
|
-
let noAddressesTopicSelections = []
|
|
18
|
-
let contractNames = Utils.Set.make()
|
|
19
|
-
|
|
20
|
-
selection.onEventRegistrations
|
|
21
|
-
->(Utils.magic: array<Internal.onEventRegistration> => array<Internal.evmOnEventRegistration>)
|
|
22
|
-
->Array.forEach(reg => {
|
|
23
|
-
let eventConfig =
|
|
24
|
-
reg.eventConfig->(Utils.magic: Internal.eventConfig => Internal.evmEventConfig)
|
|
25
|
-
let contractName = eventConfig.contractName
|
|
26
|
-
let {selectedBlockFields, selectedTransactionFields} = eventConfig
|
|
27
|
-
let {dependsOnAddresses, getEventFiltersOrThrow, isWildcard} = reg
|
|
28
|
-
selectedBlockFields
|
|
29
|
-
->Utils.Set.toArray
|
|
30
|
-
->Array.forEach(name =>
|
|
31
|
-
capitalizedBlockFields
|
|
32
|
-
->Utils.Set.add((name :> string)->Utils.String.capitalize)
|
|
33
|
-
->ignore
|
|
34
|
-
)
|
|
35
|
-
selectedTransactionFields
|
|
36
|
-
->Utils.Set.toArray
|
|
37
|
-
->Array.forEach(name => {
|
|
38
|
-
// transactionIndex is read off the log (the store key), so it never needs
|
|
39
|
-
// to be requested as a transaction column — and requesting it alone would
|
|
40
|
-
// pull the whole transaction table for nothing.
|
|
41
|
-
let fieldName = (name :> string)
|
|
42
|
-
if fieldName != "transactionIndex" {
|
|
43
|
-
capitalizedTransactionFields->Utils.Set.add(fieldName->Utils.String.capitalize)->ignore
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
let eventFilters = getEventFiltersOrThrow(chain)
|
|
48
|
-
if dependsOnAddresses {
|
|
49
|
-
let _ = contractNames->Utils.Set.add(contractName)
|
|
50
|
-
switch eventFilters {
|
|
51
|
-
| Static(topicSelections) =>
|
|
52
|
-
staticTopicSelectionsByContract->Utils.Dict.pushMany(contractName, topicSelections)
|
|
53
|
-
| Dynamic(fn) =>
|
|
54
|
-
(
|
|
55
|
-
isWildcard ? dynamicWildcardEventFiltersByContract : dynamicEventFiltersByContract
|
|
56
|
-
)->Utils.Dict.push(contractName, fn)
|
|
57
|
-
}
|
|
58
|
-
} else {
|
|
59
|
-
noAddressesTopicSelections
|
|
60
|
-
->Array.pushMany(
|
|
61
|
-
switch eventFilters {
|
|
62
|
-
| Static(s) => s
|
|
63
|
-
| Dynamic(fn) => fn([])
|
|
64
|
-
},
|
|
65
|
-
)
|
|
66
|
-
->ignore
|
|
67
|
-
}
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
let fieldSelection: HyperSyncClient.QueryTypes.fieldSelection = {
|
|
71
|
-
log: [Address, Data, LogIndex, Topic0, Topic1, Topic2, Topic3],
|
|
72
|
-
block: capitalizedBlockFields
|
|
73
|
-
->Utils.Set.toArray
|
|
74
|
-
->(Utils.magic: array<string> => array<HyperSyncClient.QueryTypes.blockField>),
|
|
75
|
-
transaction: capitalizedTransactionFields
|
|
76
|
-
->Utils.Set.toArray
|
|
77
|
-
->(Utils.magic: array<string> => array<HyperSyncClient.QueryTypes.transactionField>),
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
let noAddressesLogSelection = LogSelection.make(
|
|
81
|
-
~addresses=[],
|
|
82
|
-
~topicSelections=noAddressesTopicSelections,
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
let getLogSelectionOrThrow = (~addressesByContractName): array<LogSelection.t> => {
|
|
86
|
-
let logSelections = []
|
|
87
|
-
if noAddressesLogSelection.topicSelections->Utils.Array.isEmpty->not {
|
|
88
|
-
logSelections->Array.push(noAddressesLogSelection)
|
|
89
|
-
}
|
|
90
|
-
contractNames->Utils.Set.forEach(contractName => {
|
|
91
|
-
switch addressesByContractName->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
92
|
-
| None
|
|
93
|
-
| Some([]) => ()
|
|
94
|
-
| Some(addresses) =>
|
|
95
|
-
switch staticTopicSelectionsByContract->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
96
|
-
| None => ()
|
|
97
|
-
| Some(topicSelections) =>
|
|
98
|
-
logSelections->Array.push(LogSelection.make(~addresses, ~topicSelections))
|
|
99
|
-
}
|
|
100
|
-
switch dynamicEventFiltersByContract->Utils.Dict.dangerouslyGetNonOption(contractName) {
|
|
101
|
-
| None => ()
|
|
102
|
-
| Some(fns) =>
|
|
103
|
-
logSelections->Array.push(
|
|
104
|
-
LogSelection.make(~addresses, ~topicSelections=fns->Array.flatMap(fn => fn(addresses))),
|
|
105
|
-
)
|
|
106
|
-
}
|
|
107
|
-
switch dynamicWildcardEventFiltersByContract->Utils.Dict.dangerouslyGetNonOption(
|
|
108
|
-
contractName,
|
|
109
|
-
) {
|
|
110
|
-
| None => ()
|
|
111
|
-
| Some(fns) =>
|
|
112
|
-
logSelections->Array.push(
|
|
113
|
-
LogSelection.make(
|
|
114
|
-
~addresses=[],
|
|
115
|
-
~topicSelections=fns->Array.flatMap(fn => fn(addresses)),
|
|
116
|
-
),
|
|
117
|
-
)
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
})
|
|
121
|
-
logSelections
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
{
|
|
125
|
-
getLogSelectionOrThrow,
|
|
126
|
-
fieldSelection,
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
let memoGetSelectionConfig = (~chain) =>
|
|
131
|
-
Utils.WeakMap.memoize(selection => selection->getSelectionConfig(~chain))
|
|
132
3
|
|
|
133
4
|
// Surfaced by HyperSyncClient.getHeight (Rust) when HyperSync rejects the API
|
|
134
5
|
// token. The corrupted-token test feeds the real server error through this
|
|
@@ -138,8 +9,8 @@ let isUnauthorizedError = (message: string) => message->String.includes("401 Una
|
|
|
138
9
|
type options = {
|
|
139
10
|
chain: ChainMap.Chain.t,
|
|
140
11
|
endpointUrl: string,
|
|
141
|
-
|
|
142
|
-
|
|
12
|
+
// The chain's registrations, indexed by their sequential `index`.
|
|
13
|
+
onEventRegistrations: array<Internal.evmOnEventRegistration>,
|
|
143
14
|
apiToken: option<string>,
|
|
144
15
|
clientTimeoutMillis: int,
|
|
145
16
|
lowercaseAddresses: bool,
|
|
@@ -152,8 +23,7 @@ let make = (
|
|
|
152
23
|
{
|
|
153
24
|
chain,
|
|
154
25
|
endpointUrl,
|
|
155
|
-
|
|
156
|
-
eventRouter,
|
|
26
|
+
onEventRegistrations,
|
|
157
27
|
apiToken,
|
|
158
28
|
clientTimeoutMillis,
|
|
159
29
|
lowercaseAddresses,
|
|
@@ -164,8 +34,6 @@ let make = (
|
|
|
164
34
|
): t => {
|
|
165
35
|
let name = "HyperSync"
|
|
166
36
|
|
|
167
|
-
let getSelectionConfig = memoGetSelectionConfig(~chain)
|
|
168
|
-
|
|
169
37
|
let apiToken = switch apiToken {
|
|
170
38
|
| Some(token) => token
|
|
171
39
|
| None =>
|
|
@@ -178,7 +46,9 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
178
46
|
~url=endpointUrl,
|
|
179
47
|
~apiToken,
|
|
180
48
|
~httpReqTimeoutMillis=clientTimeoutMillis,
|
|
181
|
-
~
|
|
49
|
+
~eventRegistrations=HyperSyncClient.Registration.fromOnEventRegistrations(
|
|
50
|
+
onEventRegistrations,
|
|
51
|
+
),
|
|
182
52
|
~enableChecksumAddresses=!lowercaseAddresses,
|
|
183
53
|
~serializationFormat,
|
|
184
54
|
~enableQueryCaching,
|
|
@@ -191,15 +61,11 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
191
61
|
)
|
|
192
62
|
}
|
|
193
63
|
|
|
194
|
-
exception UndefinedValue
|
|
195
|
-
|
|
196
64
|
let makeEventBatchQueueItem = (
|
|
197
65
|
item: HyperSyncClient.EventItems.item,
|
|
198
|
-
~params: Internal.eventParams,
|
|
199
66
|
~onEventRegistration: Internal.evmOnEventRegistration,
|
|
200
67
|
): Internal.item => {
|
|
201
68
|
let {transactionIndex, logIndex, srcAddress} = item
|
|
202
|
-
let chainId = chain->ChainMap.Chain.toChainId
|
|
203
69
|
|
|
204
70
|
Internal.Event({
|
|
205
71
|
onEventRegistration: (onEventRegistration :> Internal.onEventRegistration),
|
|
@@ -212,8 +78,8 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
212
78
|
payload: {
|
|
213
79
|
contractName: onEventRegistration.eventConfig.contractName,
|
|
214
80
|
eventName: onEventRegistration.eventConfig.name,
|
|
215
|
-
chainId,
|
|
216
|
-
params,
|
|
81
|
+
chainId: chain->ChainMap.Chain.toChainId,
|
|
82
|
+
params: item.params,
|
|
217
83
|
srcAddress,
|
|
218
84
|
logIndex,
|
|
219
85
|
}->Evm.fromPayload,
|
|
@@ -224,23 +90,16 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
224
90
|
~fromBlock,
|
|
225
91
|
~toBlock,
|
|
226
92
|
~addressesByContractName,
|
|
227
|
-
~contractNameByAddress,
|
|
93
|
+
~contractNameByAddress as _,
|
|
228
94
|
~knownHeight,
|
|
229
95
|
~partitionId as _,
|
|
230
|
-
~selection,
|
|
96
|
+
~selection: FetchState.selection,
|
|
231
97
|
~itemsTarget,
|
|
232
98
|
~retry,
|
|
233
|
-
~logger,
|
|
99
|
+
~logger as _,
|
|
234
100
|
) => {
|
|
235
101
|
let totalTimeRef = Performance.now()
|
|
236
102
|
|
|
237
|
-
let selectionConfig = selection->getSelectionConfig
|
|
238
|
-
|
|
239
|
-
let logSelections = try selectionConfig.getLogSelectionOrThrow(~addressesByContractName) catch {
|
|
240
|
-
| exn =>
|
|
241
|
-
exn->ErrorHandling.mkLogAndRaise(~logger, ~msg="Failed getting log selection for the query")
|
|
242
|
-
}
|
|
243
|
-
|
|
244
103
|
let startFetchingBatchTimeRef = Performance.now()
|
|
245
104
|
|
|
246
105
|
//fetch batch
|
|
@@ -248,9 +107,9 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
248
107
|
~client,
|
|
249
108
|
~fromBlock,
|
|
250
109
|
~toBlock,
|
|
251
|
-
~logSelections,
|
|
252
|
-
~fieldSelection=selectionConfig.fieldSelection,
|
|
253
110
|
~maxNumLogs=itemsTarget,
|
|
111
|
+
~registrationIndexes=selection.onEventRegistrations->Array.map(reg => reg.index),
|
|
112
|
+
~addressesByContractName,
|
|
254
113
|
) catch {
|
|
255
114
|
| HyperSync.GetLogs.Error(error) =>
|
|
256
115
|
throw(
|
|
@@ -320,63 +179,12 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`)
|
|
|
320
179
|
})
|
|
321
180
|
let getBlock = blockNumber => blocksByNumber->Utils.Map.unsafeGet(blockNumber)
|
|
322
181
|
|
|
323
|
-
let handleDecodeFailure = (
|
|
324
|
-
~onEventRegistration: Internal.evmOnEventRegistration,
|
|
325
|
-
~logIndex,
|
|
326
|
-
~blockNumber,
|
|
327
|
-
~chainId,
|
|
328
|
-
~exn,
|
|
329
|
-
) => {
|
|
330
|
-
if !onEventRegistration.isWildcard {
|
|
331
|
-
//Wildcard events can be parsed as undefined if the number of topics
|
|
332
|
-
//don't match the event with the given topic0
|
|
333
|
-
//Non wildcard events should be expected to be parsed
|
|
334
|
-
let msg = `Event ${onEventRegistration.eventConfig.name} was unexpectedly parsed as undefined`
|
|
335
|
-
let logger = Logging.createChildFrom(
|
|
336
|
-
~logger,
|
|
337
|
-
~params={
|
|
338
|
-
"chainId": chainId,
|
|
339
|
-
"blockNumber": blockNumber,
|
|
340
|
-
"logIndex": logIndex,
|
|
341
|
-
"decoder": "hypersync-client",
|
|
342
|
-
},
|
|
343
|
-
)
|
|
344
|
-
exn->ErrorHandling.mkLogAndRaise(~msg, ~logger)
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
182
|
pageUnsafe.items->Array.forEach(item => {
|
|
349
|
-
let
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
~topicCount=item.topicCount,
|
|
355
|
-
),
|
|
356
|
-
~contractNameByAddress,
|
|
357
|
-
~contractAddress=item.srcAddress,
|
|
358
|
-
)
|
|
359
|
-
|
|
360
|
-
switch maybeEventConfig {
|
|
361
|
-
| None => () //ignore events that aren't registered
|
|
362
|
-
| Some(onEventRegistration) =>
|
|
363
|
-
switch item.params
|
|
364
|
-
->Nullable.toOption
|
|
365
|
-
->Option.flatMap(Dict.get(_, onEventRegistration.eventConfig.contractName)) {
|
|
366
|
-
| Some(params) =>
|
|
367
|
-
parsedQueueItems
|
|
368
|
-
->Array.push(makeEventBatchQueueItem(item, ~params, ~onEventRegistration))
|
|
369
|
-
->ignore
|
|
370
|
-
| None =>
|
|
371
|
-
handleDecodeFailure(
|
|
372
|
-
~onEventRegistration,
|
|
373
|
-
~logIndex=item.logIndex,
|
|
374
|
-
~blockNumber=item.blockNumber,
|
|
375
|
-
~chainId,
|
|
376
|
-
~exn=UndefinedValue,
|
|
377
|
-
)
|
|
378
|
-
}
|
|
379
|
-
}
|
|
183
|
+
let onEventRegistration =
|
|
184
|
+
onEventRegistrations->Array.getUnsafe(item.onEventRegistrationIndex)
|
|
185
|
+
parsedQueueItems
|
|
186
|
+
->Array.push(makeEventBatchQueueItem(item, ~onEventRegistration))
|
|
187
|
+
->ignore
|
|
380
188
|
})
|
|
381
189
|
|
|
382
190
|
let parsingTimeElapsed = parsingTimeRef->Performance.secondsSince
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as Utils from "../Utils.res.mjs";
|
|
4
3
|
import * as Source from "./Source.res.mjs";
|
|
5
4
|
import * as Logging from "../Logging.res.mjs";
|
|
6
5
|
import * as HyperSync from "./HyperSync.res.mjs";
|
|
7
|
-
import * as EventRouter from "./EventRouter.res.mjs";
|
|
8
6
|
import * as Performance from "../bindings/Performance.res.mjs";
|
|
9
|
-
import * as LogSelection from "../LogSelection.res.mjs";
|
|
10
7
|
import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
|
|
11
8
|
import * as ErrorHandling from "../ErrorHandling.res.mjs";
|
|
12
9
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
@@ -16,118 +13,27 @@ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js
|
|
|
16
13
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
17
14
|
import * as HyperSyncHeightStream from "./HyperSyncHeightStream.res.mjs";
|
|
18
15
|
|
|
19
|
-
function getSelectionConfig(selection, chain) {
|
|
20
|
-
let capitalizedBlockFields = new Set();
|
|
21
|
-
let capitalizedTransactionFields = new Set();
|
|
22
|
-
let staticTopicSelectionsByContract = {};
|
|
23
|
-
let dynamicEventFiltersByContract = {};
|
|
24
|
-
let dynamicWildcardEventFiltersByContract = {};
|
|
25
|
-
let noAddressesTopicSelections = [];
|
|
26
|
-
let contractNames = new Set();
|
|
27
|
-
selection.onEventRegistrations.forEach(reg => {
|
|
28
|
-
let eventConfig = reg.eventConfig;
|
|
29
|
-
let contractName = eventConfig.contractName;
|
|
30
|
-
Array.from(eventConfig.selectedBlockFields).forEach(name => {
|
|
31
|
-
capitalizedBlockFields.add(Utils.$$String.capitalize(name));
|
|
32
|
-
});
|
|
33
|
-
Array.from(eventConfig.selectedTransactionFields).forEach(name => {
|
|
34
|
-
if (name !== "transactionIndex") {
|
|
35
|
-
capitalizedTransactionFields.add(Utils.$$String.capitalize(name));
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
let eventFilters = reg.getEventFiltersOrThrow(chain);
|
|
40
|
-
if (reg.dependsOnAddresses) {
|
|
41
|
-
contractNames.add(contractName);
|
|
42
|
-
if (eventFilters.TAG === "Static") {
|
|
43
|
-
return Utils.Dict.pushMany(staticTopicSelectionsByContract, contractName, eventFilters._0);
|
|
44
|
-
} else {
|
|
45
|
-
return Utils.Dict.push(reg.isWildcard ? dynamicWildcardEventFiltersByContract : dynamicEventFiltersByContract, contractName, eventFilters._0);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
let tmp;
|
|
49
|
-
tmp = eventFilters.TAG === "Static" ? eventFilters._0 : eventFilters._0([]);
|
|
50
|
-
noAddressesTopicSelections.push(...tmp);
|
|
51
|
-
});
|
|
52
|
-
let fieldSelection_block = Array.from(capitalizedBlockFields);
|
|
53
|
-
let fieldSelection_transaction = Array.from(capitalizedTransactionFields);
|
|
54
|
-
let fieldSelection_log = [
|
|
55
|
-
"Address",
|
|
56
|
-
"Data",
|
|
57
|
-
"LogIndex",
|
|
58
|
-
"Topic0",
|
|
59
|
-
"Topic1",
|
|
60
|
-
"Topic2",
|
|
61
|
-
"Topic3"
|
|
62
|
-
];
|
|
63
|
-
let fieldSelection = {
|
|
64
|
-
block: fieldSelection_block,
|
|
65
|
-
transaction: fieldSelection_transaction,
|
|
66
|
-
log: fieldSelection_log
|
|
67
|
-
};
|
|
68
|
-
let noAddressesLogSelection = LogSelection.make([], noAddressesTopicSelections);
|
|
69
|
-
let getLogSelectionOrThrow = addressesByContractName => {
|
|
70
|
-
let logSelections = [];
|
|
71
|
-
if (!Utils.$$Array.isEmpty(noAddressesLogSelection.topicSelections)) {
|
|
72
|
-
logSelections.push(noAddressesLogSelection);
|
|
73
|
-
}
|
|
74
|
-
contractNames.forEach(contractName => {
|
|
75
|
-
let addresses = addressesByContractName[contractName];
|
|
76
|
-
if (addresses === undefined) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
if (addresses.length === 0) {
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
let topicSelections = staticTopicSelectionsByContract[contractName];
|
|
83
|
-
if (topicSelections !== undefined) {
|
|
84
|
-
logSelections.push(LogSelection.make(addresses, topicSelections));
|
|
85
|
-
}
|
|
86
|
-
let fns = dynamicEventFiltersByContract[contractName];
|
|
87
|
-
if (fns !== undefined) {
|
|
88
|
-
logSelections.push(LogSelection.make(addresses, fns.flatMap(fn => fn(addresses))));
|
|
89
|
-
}
|
|
90
|
-
let fns$1 = dynamicWildcardEventFiltersByContract[contractName];
|
|
91
|
-
if (fns$1 !== undefined) {
|
|
92
|
-
logSelections.push(LogSelection.make([], fns$1.flatMap(fn => fn(addresses))));
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
return logSelections;
|
|
97
|
-
};
|
|
98
|
-
return {
|
|
99
|
-
getLogSelectionOrThrow: getLogSelectionOrThrow,
|
|
100
|
-
fieldSelection: fieldSelection
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function memoGetSelectionConfig(chain) {
|
|
105
|
-
return Utils.$$WeakMap.memoize(selection => getSelectionConfig(selection, chain));
|
|
106
|
-
}
|
|
107
|
-
|
|
108
16
|
function isUnauthorizedError(message) {
|
|
109
17
|
return message.includes("401 Unauthorized");
|
|
110
18
|
}
|
|
111
19
|
|
|
112
20
|
function make(param) {
|
|
113
21
|
let apiToken = param.apiToken;
|
|
114
|
-
let
|
|
22
|
+
let onEventRegistrations = param.onEventRegistrations;
|
|
115
23
|
let endpointUrl = param.endpointUrl;
|
|
116
24
|
let chain = param.chain;
|
|
117
25
|
let name = "HyperSync";
|
|
118
|
-
let getSelectionConfig = memoGetSelectionConfig(chain);
|
|
119
26
|
let apiToken$1 = apiToken !== undefined ? apiToken : Stdlib_JsError.throwWithMessage(`An Envio API token is required for using HyperSync as a data-source.
|
|
120
27
|
Set the ENVIO_API_TOKEN environment variable in your .env file.
|
|
121
28
|
Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
122
29
|
let client;
|
|
123
30
|
try {
|
|
124
|
-
client = HyperSyncClient.make(endpointUrl, apiToken$1, param.clientTimeoutMillis,
|
|
31
|
+
client = HyperSyncClient.make(endpointUrl, apiToken$1, param.clientTimeoutMillis, HyperSyncClient.Registration.fromOnEventRegistrations(onEventRegistrations), !param.lowercaseAddresses, param.serializationFormat, param.enableQueryCaching, undefined, undefined, undefined, param.logLevel);
|
|
125
32
|
} catch (raw_exn) {
|
|
126
33
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
127
34
|
client = ErrorHandling.mkLogAndRaise(undefined, "Failed to instantiate the hypersync client, please double check your ABI", exn);
|
|
128
35
|
}
|
|
129
|
-
let
|
|
130
|
-
let makeEventBatchQueueItem = (item, params, onEventRegistration) => {
|
|
36
|
+
let makeEventBatchQueueItem = (item, onEventRegistration) => {
|
|
131
37
|
let logIndex = item.logIndex;
|
|
132
38
|
return {
|
|
133
39
|
kind: 0,
|
|
@@ -139,27 +45,19 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
139
45
|
payload: {
|
|
140
46
|
contractName: onEventRegistration.eventConfig.contractName,
|
|
141
47
|
eventName: onEventRegistration.eventConfig.name,
|
|
142
|
-
params: params,
|
|
48
|
+
params: item.params,
|
|
143
49
|
chainId: chain,
|
|
144
50
|
srcAddress: item.srcAddress,
|
|
145
51
|
logIndex: logIndex
|
|
146
52
|
}
|
|
147
53
|
};
|
|
148
54
|
};
|
|
149
|
-
let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName,
|
|
55
|
+
let getItemsOrThrow = async (fromBlock, toBlock, addressesByContractName, param, knownHeight, param$1, selection, itemsTarget, retry, param$2) => {
|
|
150
56
|
let totalTimeRef = Performance.now();
|
|
151
|
-
let selectionConfig = getSelectionConfig(selection);
|
|
152
|
-
let logSelections;
|
|
153
|
-
try {
|
|
154
|
-
logSelections = selectionConfig.getLogSelectionOrThrow(addressesByContractName);
|
|
155
|
-
} catch (raw_exn) {
|
|
156
|
-
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
157
|
-
logSelections = ErrorHandling.mkLogAndRaise(logger, "Failed getting log selection for the query", exn);
|
|
158
|
-
}
|
|
159
57
|
let startFetchingBatchTimeRef = Performance.now();
|
|
160
58
|
let pageUnsafe;
|
|
161
59
|
try {
|
|
162
|
-
pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock,
|
|
60
|
+
pageUnsafe = await HyperSync.GetLogs.query(client, fromBlock, toBlock, itemsTarget, selection.onEventRegistrations.map(reg => reg.index), addressesByContractName);
|
|
163
61
|
} catch (raw_error) {
|
|
164
62
|
let error = Primitive_exceptions.internalToException(raw_error);
|
|
165
63
|
if (error.RE_EXN_ID === HyperSync.GetLogs.$$Error) {
|
|
@@ -221,32 +119,8 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
221
119
|
blocksByNumber.set(block.number, block);
|
|
222
120
|
});
|
|
223
121
|
pageUnsafe.items.forEach(item => {
|
|
224
|
-
let
|
|
225
|
-
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
let params = Stdlib_Option.flatMap(Primitive_option.fromNullable(item.params), __x => __x[maybeEventConfig.eventConfig.contractName]);
|
|
229
|
-
if (params !== undefined) {
|
|
230
|
-
parsedQueueItems.push(makeEventBatchQueueItem(item, Primitive_option.valFromOption(params), maybeEventConfig));
|
|
231
|
-
return;
|
|
232
|
-
} else {
|
|
233
|
-
let logIndex = item.logIndex;
|
|
234
|
-
let blockNumber = item.blockNumber;
|
|
235
|
-
let exn = {
|
|
236
|
-
RE_EXN_ID: UndefinedValue
|
|
237
|
-
};
|
|
238
|
-
if (maybeEventConfig.isWildcard) {
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
let msg = `Event ` + maybeEventConfig.eventConfig.name + ` was unexpectedly parsed as undefined`;
|
|
242
|
-
let logger$1 = Logging.createChildFrom(logger, {
|
|
243
|
-
chainId: chain,
|
|
244
|
-
blockNumber: blockNumber,
|
|
245
|
-
logIndex: logIndex,
|
|
246
|
-
decoder: "hypersync-client"
|
|
247
|
-
});
|
|
248
|
-
return ErrorHandling.mkLogAndRaise(logger$1, msg, exn);
|
|
249
|
-
}
|
|
122
|
+
let onEventRegistration = onEventRegistrations[item.onEventRegistrationIndex];
|
|
123
|
+
parsedQueueItems.push(makeEventBatchQueueItem(item, onEventRegistration));
|
|
250
124
|
});
|
|
251
125
|
let parsingTimeElapsed = Performance.secondsSince(parsingTimeRef);
|
|
252
126
|
let blockHashes = [];
|
|
@@ -355,9 +229,7 @@ Learn more or get a free Envio API token at: https://envio.dev/app/api-tokens`);
|
|
|
355
229
|
}
|
|
356
230
|
|
|
357
231
|
export {
|
|
358
|
-
getSelectionConfig,
|
|
359
|
-
memoGetSelectionConfig,
|
|
360
232
|
isUnauthorizedError,
|
|
361
233
|
make,
|
|
362
234
|
}
|
|
363
|
-
/*
|
|
235
|
+
/* Logging Not a pure module */
|
package/src/sources/Rpc.res
CHANGED
|
@@ -82,38 +82,6 @@ let decimalFloatSchema: S.schema<float> = S.string->S.transform(s => {
|
|
|
82
82
|
})
|
|
83
83
|
|
|
84
84
|
module GetLogs = {
|
|
85
|
-
@unboxed
|
|
86
|
-
type topicFilter = Single(hex) | Multiple(array<hex>) | @as(null) Null
|
|
87
|
-
type topicQuery = array<topicFilter>
|
|
88
|
-
|
|
89
|
-
let makeTopicQuery = (~topic0=[], ~topic1=[], ~topic2=[], ~topic3=[]) => {
|
|
90
|
-
let topics = [topic0, topic1, topic2, topic3]
|
|
91
|
-
|
|
92
|
-
let isLastTopicEmpty = () =>
|
|
93
|
-
switch topics->Utils.Array.last {
|
|
94
|
-
| Some([]) => true
|
|
95
|
-
| _ => false
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
//Remove all empty topics from the end of the array
|
|
99
|
-
while isLastTopicEmpty() {
|
|
100
|
-
topics->Array.pop->ignore
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
let toTopicFilter = topic => {
|
|
104
|
-
switch topic {
|
|
105
|
-
| [] => Null
|
|
106
|
-
| [single] => Single(single->EvmTypes.Hex.toString)
|
|
107
|
-
| multiple => Multiple(multiple->EvmTypes.Hex.toStrings)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
topics->Array.map(toTopicFilter)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
let mapTopicQuery = ({topic0, topic1, topic2, topic3}: Internal.topicSelection): topicQuery =>
|
|
115
|
-
makeTopicQuery(~topic0, ~topic1, ~topic2, ~topic3)
|
|
116
|
-
|
|
117
85
|
type log = {
|
|
118
86
|
address: Address.t,
|
|
119
87
|
topics: array<hex>,
|
package/src/sources/Rpc.res.mjs
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Rest from "../vendored/Rest.res.mjs";
|
|
4
4
|
import * as Viem from "viem";
|
|
5
|
-
import * as Utils from "../Utils.res.mjs";
|
|
6
5
|
import * as Address from "../Address.res.mjs";
|
|
7
6
|
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
8
7
|
import * as Stdlib_BigInt from "@rescript/runtime/lib/es6/Stdlib_BigInt.js";
|
|
@@ -95,51 +94,7 @@ let decimalFloatSchema = S$RescriptSchema.transform(S$RescriptSchema.string, s =
|
|
|
95
94
|
}
|
|
96
95
|
}));
|
|
97
96
|
|
|
98
|
-
|
|
99
|
-
let topic0 = topic0Opt !== undefined ? topic0Opt : [];
|
|
100
|
-
let topic1 = topic1Opt !== undefined ? topic1Opt : [];
|
|
101
|
-
let topic2 = topic2Opt !== undefined ? topic2Opt : [];
|
|
102
|
-
let topic3 = topic3Opt !== undefined ? topic3Opt : [];
|
|
103
|
-
let topics = [
|
|
104
|
-
topic0,
|
|
105
|
-
topic1,
|
|
106
|
-
topic2,
|
|
107
|
-
topic3
|
|
108
|
-
];
|
|
109
|
-
let isLastTopicEmpty = () => {
|
|
110
|
-
let match = Utils.$$Array.last(topics);
|
|
111
|
-
if (match !== undefined) {
|
|
112
|
-
return match.length === 0;
|
|
113
|
-
} else {
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
while (isLastTopicEmpty()) {
|
|
118
|
-
topics.pop();
|
|
119
|
-
};
|
|
120
|
-
let toTopicFilter = topic => {
|
|
121
|
-
let len = topic.length;
|
|
122
|
-
if (len !== 1) {
|
|
123
|
-
if (len !== 0) {
|
|
124
|
-
return topic;
|
|
125
|
-
} else {
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
let single = topic[0];
|
|
130
|
-
return single;
|
|
131
|
-
};
|
|
132
|
-
return topics.map(toTopicFilter);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function mapTopicQuery(param) {
|
|
136
|
-
return makeTopicQuery(param.topic0, param.topic1, param.topic2, param.topic3);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
let GetLogs = {
|
|
140
|
-
makeTopicQuery: makeTopicQuery,
|
|
141
|
-
mapTopicQuery: mapTopicQuery
|
|
142
|
-
};
|
|
97
|
+
let GetLogs = {};
|
|
143
98
|
|
|
144
99
|
let blockSchema = S$RescriptSchema.object(s => ({
|
|
145
100
|
difficulty: s.f("difficulty", S$RescriptSchema.$$null(hexBigintSchema)),
|