envio 3.0.0-alpha.0 → 3.0.0-alpha.10
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 +2 -2
- package/evm.schema.json +53 -57
- package/fuel.schema.json +35 -31
- package/index.d.ts +446 -1
- package/index.js +4 -0
- package/package.json +23 -11
- package/rescript.json +4 -1
- package/src/Batch.res.mjs +1 -1
- package/src/Benchmark.res +394 -0
- package/src/Benchmark.res.mjs +398 -0
- package/src/ChainFetcher.res +526 -0
- package/src/ChainFetcher.res.mjs +343 -0
- package/src/ChainManager.res +182 -0
- package/src/ChainManager.res.mjs +150 -0
- package/src/Config.res +367 -27
- package/src/Config.res.mjs +338 -28
- package/src/{Indexer.res → Ctx.res} +1 -1
- package/src/Ecosystem.res +25 -0
- package/src/Ecosystem.res.mjs +29 -0
- package/src/Env.res +252 -0
- package/src/Env.res.mjs +271 -0
- package/src/Envio.gen.ts +9 -1
- package/src/Envio.res +12 -9
- package/src/EventProcessing.res +476 -0
- package/src/EventProcessing.res.mjs +341 -0
- package/src/EventRegister.res +4 -15
- package/src/EventRegister.res.mjs +3 -9
- package/src/EventRegister.resi +2 -8
- package/src/FetchState.res +54 -29
- package/src/FetchState.res.mjs +62 -35
- package/src/GlobalState.res +1163 -0
- package/src/GlobalState.res.mjs +1196 -0
- package/src/GlobalStateManager.res +68 -0
- package/src/GlobalStateManager.res.mjs +75 -0
- package/src/GlobalStateManager.resi +7 -0
- package/src/HandlerLoader.res +89 -0
- package/src/HandlerLoader.res.mjs +79 -0
- package/src/Internal.gen.ts +3 -14
- package/src/Internal.res +45 -13
- package/src/LoadLayer.res +444 -0
- package/src/LoadLayer.res.mjs +296 -0
- package/src/LoadLayer.resi +32 -0
- package/src/LogSelection.res +33 -27
- package/src/LogSelection.res.mjs +6 -0
- package/src/Logging.res +11 -4
- package/src/Logging.res.mjs +14 -6
- package/src/Main.res +351 -0
- package/src/Main.res.mjs +312 -0
- package/src/Persistence.res +1 -2
- package/src/PgStorage.gen.ts +10 -0
- package/src/PgStorage.res +28 -34
- package/src/PgStorage.res.d.mts +5 -0
- package/src/PgStorage.res.mjs +27 -27
- package/src/Prometheus.res +8 -8
- package/src/Prometheus.res.mjs +10 -10
- package/src/ReorgDetection.res +6 -10
- package/src/ReorgDetection.res.mjs +6 -6
- package/src/TestIndexer.res +536 -0
- package/src/TestIndexer.res.mjs +412 -0
- package/src/TestIndexerProxyStorage.res +210 -0
- package/src/TestIndexerProxyStorage.res.mjs +157 -0
- package/src/Types.ts +1 -1
- package/src/UserContext.res +355 -0
- package/src/UserContext.res.mjs +236 -0
- package/src/Utils.res +28 -0
- package/src/Utils.res.mjs +18 -0
- package/src/bindings/ClickHouse.res +31 -1
- package/src/bindings/ClickHouse.res.mjs +27 -1
- package/src/bindings/DateFns.res +71 -0
- package/src/bindings/DateFns.res.mjs +22 -0
- package/src/bindings/Ethers.res +27 -67
- package/src/bindings/Ethers.res.mjs +18 -70
- package/src/bindings/EventSource.res +13 -0
- package/src/bindings/EventSource.res.mjs +2 -0
- package/src/bindings/NodeJs.res +44 -3
- package/src/bindings/NodeJs.res.mjs +11 -3
- package/src/bindings/Pino.res +21 -7
- package/src/bindings/Pino.res.mjs +11 -5
- package/src/bindings/Postgres.gen.ts +8 -0
- package/src/bindings/Postgres.res +3 -0
- package/src/bindings/Postgres.res.d.mts +5 -0
- package/src/bindings/RescriptMocha.res +123 -0
- package/src/bindings/RescriptMocha.res.mjs +18 -0
- package/src/bindings/Vitest.res +134 -0
- package/src/bindings/Vitest.res.mjs +9 -0
- package/src/bindings/Yargs.res +8 -0
- package/src/bindings/Yargs.res.mjs +2 -0
- package/src/db/InternalTable.res +2 -0
- package/src/db/InternalTable.res.mjs +1 -1
- package/src/sources/Evm.res +87 -0
- package/src/sources/Evm.res.mjs +105 -0
- package/src/sources/EvmChain.res +90 -0
- package/src/sources/EvmChain.res.mjs +57 -0
- package/src/sources/Fuel.res +19 -34
- package/src/sources/Fuel.res.mjs +34 -16
- package/src/sources/FuelSDK.res +38 -0
- package/src/sources/FuelSDK.res.mjs +29 -0
- package/src/sources/HyperFuel.res +2 -2
- package/src/sources/HyperFuel.resi +1 -1
- package/src/sources/HyperFuelClient.res +2 -2
- package/src/sources/HyperFuelSource.res +8 -8
- package/src/sources/HyperFuelSource.res.mjs +5 -5
- package/src/sources/HyperSyncHeightStream.res +97 -0
- package/src/sources/HyperSyncHeightStream.res.mjs +94 -0
- package/src/sources/HyperSyncSource.res +64 -172
- package/src/sources/HyperSyncSource.res.mjs +73 -155
- package/src/sources/Rpc.res +43 -0
- package/src/sources/Rpc.res.mjs +31 -0
- package/src/sources/RpcSource.res +32 -130
- package/src/sources/RpcSource.res.mjs +47 -121
- package/src/sources/Source.res +3 -2
- package/src/sources/SourceManager.res +183 -108
- package/src/sources/SourceManager.res.mjs +162 -99
- package/src/sources/SourceManager.resi +4 -5
- package/src/sources/Svm.res +59 -0
- package/src/sources/Svm.res.mjs +79 -0
- package/src/tui/Tui.res +266 -0
- package/src/tui/Tui.res.mjs +342 -0
- package/src/tui/bindings/Ink.res +376 -0
- package/src/tui/bindings/Ink.res.mjs +75 -0
- package/src/tui/bindings/Style.res +123 -0
- package/src/tui/bindings/Style.res.mjs +2 -0
- package/src/tui/components/BufferedProgressBar.res +40 -0
- package/src/tui/components/BufferedProgressBar.res.mjs +57 -0
- package/src/tui/components/CustomHooks.res +122 -0
- package/src/tui/components/CustomHooks.res.mjs +179 -0
- package/src/tui/components/Messages.res +41 -0
- package/src/tui/components/Messages.res.mjs +75 -0
- package/src/tui/components/SyncETA.res +193 -0
- package/src/tui/components/SyncETA.res.mjs +269 -0
- package/src/tui/components/TuiData.res +46 -0
- package/src/tui/components/TuiData.res.mjs +29 -0
- package/src/Platform.res +0 -140
- package/src/Platform.res.mjs +0 -170
- package/src/bindings/Ethers.gen.ts +0 -14
- /package/src/{Indexer.res.mjs → Ctx.res.mjs} +0 -0
package/src/Config.res
CHANGED
|
@@ -16,15 +16,45 @@ type contract = {
|
|
|
16
16
|
addresses: array<Address.t>,
|
|
17
17
|
events: array<Internal.eventConfig>,
|
|
18
18
|
startBlock: option<int>,
|
|
19
|
+
// EVM-specific: event sighashes for HyperSync queries
|
|
20
|
+
eventSignatures: array<string>,
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
type codegenContract = {
|
|
24
|
+
name: string,
|
|
25
|
+
addresses: array<string>,
|
|
26
|
+
events: array<Internal.eventConfig>,
|
|
27
|
+
startBlock: option<int>,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Source config is now parsed from internal.config.json and sources are created lazily
|
|
31
|
+
type codegenChain = {
|
|
32
|
+
id: int,
|
|
33
|
+
contracts: array<codegenContract>,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Source config parsed from internal.config.json - sources are created lazily in ChainFetcher
|
|
37
|
+
type evmRpcConfig = {
|
|
38
|
+
url: string,
|
|
39
|
+
sourceFor: Source.sourceFor,
|
|
40
|
+
syncConfig: option<sourceSyncOptions>,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type sourceConfig =
|
|
44
|
+
| EvmSourceConfig({hypersync: option<string>, rpcs: array<evmRpcConfig>})
|
|
45
|
+
| FuelSourceConfig({hypersync: string})
|
|
46
|
+
| SvmSourceConfig({rpc: string})
|
|
47
|
+
// For tests: pass custom sources directly
|
|
48
|
+
| CustomSources(array<Source.t>)
|
|
49
|
+
|
|
21
50
|
type chain = {
|
|
51
|
+
name: string,
|
|
22
52
|
id: int,
|
|
23
53
|
startBlock: int,
|
|
24
54
|
endBlock?: int,
|
|
25
55
|
maxReorgDepth: int,
|
|
26
56
|
contracts: array<contract>,
|
|
27
|
-
|
|
57
|
+
sourceConfig: sourceConfig,
|
|
28
58
|
}
|
|
29
59
|
|
|
30
60
|
type sourceSync = {
|
|
@@ -39,45 +69,325 @@ type sourceSync = {
|
|
|
39
69
|
|
|
40
70
|
type multichain = | @as("ordered") Ordered | @as("unordered") Unordered
|
|
41
71
|
|
|
72
|
+
type contractHandler = {
|
|
73
|
+
name: string,
|
|
74
|
+
handler: option<string>,
|
|
75
|
+
}
|
|
76
|
+
|
|
42
77
|
type t = {
|
|
78
|
+
name: string,
|
|
79
|
+
description: option<string>,
|
|
80
|
+
handlers: string,
|
|
81
|
+
contractHandlers: array<contractHandler>,
|
|
43
82
|
shouldRollbackOnReorg: bool,
|
|
44
83
|
shouldSaveFullHistory: bool,
|
|
45
84
|
multichain: multichain,
|
|
46
85
|
chainMap: ChainMap.t<chain>,
|
|
47
86
|
defaultChain: option<chain>,
|
|
48
|
-
|
|
87
|
+
ecosystem: Ecosystem.t,
|
|
49
88
|
enableRawEvents: bool,
|
|
50
|
-
preloadHandlers: bool,
|
|
51
89
|
maxAddrInPartition: int,
|
|
52
90
|
batchSize: int,
|
|
53
91
|
lowercaseAddresses: bool,
|
|
54
92
|
addContractNameToContractNameMapping: dict<string>,
|
|
93
|
+
userEntitiesByName: dict<Internal.entityConfig>,
|
|
55
94
|
}
|
|
56
95
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
96
|
+
// Types for parsing source config from internal.config.json
|
|
97
|
+
type rpcSourceFor = | @as("sync") Sync | @as("fallback") Fallback | @as("live") Live
|
|
98
|
+
|
|
99
|
+
let rpcSourceForSchema = S.enum([Sync, Fallback, Live])
|
|
100
|
+
|
|
101
|
+
let rpcConfigSchema = S.schema(s =>
|
|
102
|
+
{
|
|
103
|
+
"url": s.matches(S.string),
|
|
104
|
+
"for": s.matches(rpcSourceForSchema),
|
|
105
|
+
"initialBlockInterval": s.matches(S.option(S.int)),
|
|
106
|
+
"backoffMultiplicative": s.matches(S.option(S.float)),
|
|
107
|
+
"accelerationAdditive": s.matches(S.option(S.int)),
|
|
108
|
+
"intervalCeiling": s.matches(S.option(S.int)),
|
|
109
|
+
"backoffMillis": s.matches(S.option(S.int)),
|
|
110
|
+
"fallbackStallTimeout": s.matches(S.option(S.int)),
|
|
111
|
+
"queryTimeoutMillis": s.matches(S.option(S.int)),
|
|
112
|
+
}
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
let publicConfigChainSchema = S.schema(s =>
|
|
116
|
+
{
|
|
117
|
+
"id": s.matches(S.int),
|
|
118
|
+
"startBlock": s.matches(S.int),
|
|
119
|
+
"endBlock": s.matches(S.option(S.int)),
|
|
120
|
+
"maxReorgDepth": s.matches(S.option(S.int)),
|
|
121
|
+
// EVM/Fuel source config (hypersync for EVM, hyperfuel for Fuel)
|
|
122
|
+
"hypersync": s.matches(S.option(S.string)),
|
|
123
|
+
"rpcs": s.matches(S.option(S.array(rpcConfigSchema))),
|
|
124
|
+
// SVM source config
|
|
125
|
+
"rpc": s.matches(S.option(S.string)),
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
let contractEventItemSchema = S.schema(s =>
|
|
130
|
+
{
|
|
131
|
+
"event": s.matches(S.string),
|
|
132
|
+
}
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
let contractConfigSchema = S.schema(s =>
|
|
136
|
+
{
|
|
137
|
+
"abi": s.matches(S.json(~validate=false)),
|
|
138
|
+
"handler": s.matches(S.option(S.string)),
|
|
139
|
+
// EVM-specific: event signatures for HyperSync queries
|
|
140
|
+
"events": s.matches(S.option(S.array(contractEventItemSchema))),
|
|
141
|
+
}
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
let publicConfigEcosystemSchema = S.schema(s =>
|
|
145
|
+
{
|
|
146
|
+
"chains": s.matches(S.dict(publicConfigChainSchema)),
|
|
147
|
+
"contracts": s.matches(S.option(S.dict(contractConfigSchema))),
|
|
148
|
+
}
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
type addressFormat = | @as("lowercase") Lowercase | @as("checksum") Checksum
|
|
152
|
+
|
|
153
|
+
let publicConfigEvmSchema = S.schema(s =>
|
|
154
|
+
{
|
|
155
|
+
"chains": s.matches(S.dict(publicConfigChainSchema)),
|
|
156
|
+
"contracts": s.matches(S.option(S.dict(contractConfigSchema))),
|
|
157
|
+
"addressFormat": s.matches(S.option(S.enum([Lowercase, Checksum]))),
|
|
158
|
+
}
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
let multichainSchema = S.enum([Ordered, Unordered])
|
|
162
|
+
|
|
163
|
+
let publicConfigSchema = S.schema(s =>
|
|
164
|
+
{
|
|
165
|
+
"name": s.matches(S.string),
|
|
166
|
+
"description": s.matches(S.option(S.string)),
|
|
167
|
+
"handlers": s.matches(S.option(S.string)),
|
|
168
|
+
"multichain": s.matches(S.option(multichainSchema)),
|
|
169
|
+
"fullBatchSize": s.matches(S.option(S.int)),
|
|
170
|
+
"rollbackOnReorg": s.matches(S.option(S.bool)),
|
|
171
|
+
"saveFullHistory": s.matches(S.option(S.bool)),
|
|
172
|
+
"rawEvents": s.matches(S.option(S.bool)),
|
|
173
|
+
"evm": s.matches(S.option(publicConfigEvmSchema)),
|
|
174
|
+
"fuel": s.matches(S.option(publicConfigEcosystemSchema)),
|
|
175
|
+
"svm": s.matches(S.option(publicConfigEcosystemSchema)),
|
|
176
|
+
}
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
let fromPublic = (
|
|
180
|
+
publicConfigJson: Js.Json.t,
|
|
181
|
+
~codegenChains: array<codegenChain>=[],
|
|
68
182
|
~maxAddrInPartition=5000,
|
|
183
|
+
~userEntities: array<Internal.entityConfig>=[],
|
|
69
184
|
) => {
|
|
70
|
-
//
|
|
71
|
-
|
|
185
|
+
// Parse public config
|
|
186
|
+
let publicConfig = try publicConfigJson->S.parseOrThrow(publicConfigSchema) catch {
|
|
187
|
+
| S.Raised(exn) =>
|
|
188
|
+
Js.Exn.raiseError(`Invalid internal.config.ts: ${exn->Utils.prettifyExn->Utils.magic}`)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Determine ecosystem from publicConfig (extract just chains for unified handling)
|
|
192
|
+
let (publicChainsConfig, ecosystemName) = switch (
|
|
193
|
+
publicConfig["evm"],
|
|
194
|
+
publicConfig["fuel"],
|
|
195
|
+
publicConfig["svm"],
|
|
196
|
+
) {
|
|
197
|
+
| (Some(ecosystemConfig), None, None) => (ecosystemConfig["chains"], Ecosystem.Evm)
|
|
198
|
+
| (None, Some(ecosystemConfig), None) => (ecosystemConfig["chains"], Ecosystem.Fuel)
|
|
199
|
+
| (None, None, Some(ecosystemConfig)) => (ecosystemConfig["chains"], Ecosystem.Svm)
|
|
200
|
+
| (None, None, None) =>
|
|
201
|
+
Js.Exn.raiseError("Invalid indexer config: No ecosystem configured (evm, fuel, or svm)")
|
|
202
|
+
| _ =>
|
|
72
203
|
Js.Exn.raiseError(
|
|
73
|
-
"
|
|
204
|
+
"Invalid indexer config: Multiple ecosystems are not supported for a single indexer",
|
|
74
205
|
)
|
|
75
206
|
}
|
|
76
207
|
|
|
208
|
+
// Extract EVM-specific options with defaults
|
|
209
|
+
let lowercaseAddresses = switch publicConfig["evm"] {
|
|
210
|
+
| Some(evm) => evm["addressFormat"]->Option.getWithDefault(Checksum) == Lowercase
|
|
211
|
+
| None => false
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Parse ABIs from public config
|
|
215
|
+
let publicContractsConfig = switch (ecosystemName, publicConfig["evm"], publicConfig["fuel"]) {
|
|
216
|
+
| (Ecosystem.Evm, Some(evm), _) => evm["contracts"]
|
|
217
|
+
| (Ecosystem.Fuel, _, Some(fuel)) => fuel["contracts"]
|
|
218
|
+
| _ => None
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Store both ABI and event signatures for each contract (using inline tuple)
|
|
222
|
+
let contractsWithAbis: Js.Dict.t<(EvmTypes.Abi.t, array<string>)> = switch publicContractsConfig {
|
|
223
|
+
| Some(contractsDict) =>
|
|
224
|
+
contractsDict
|
|
225
|
+
->Js.Dict.entries
|
|
226
|
+
->Js.Array2.map(((contractName, contractConfig)) => {
|
|
227
|
+
let abi = contractConfig["abi"]->(Utils.magic: Js.Json.t => EvmTypes.Abi.t)
|
|
228
|
+
let eventSignatures = switch contractConfig["events"] {
|
|
229
|
+
| Some(events) => events->Array.map(eventItem => eventItem["event"])
|
|
230
|
+
| None => []
|
|
231
|
+
}
|
|
232
|
+
(contractName, (abi, eventSignatures))
|
|
233
|
+
})
|
|
234
|
+
->Js.Dict.fromArray
|
|
235
|
+
| None => Js.Dict.empty()
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Index codegenChains by id for efficient lookup
|
|
239
|
+
let codegenChainById = Js.Dict.empty()
|
|
240
|
+
codegenChains->Array.forEach(codegenChain => {
|
|
241
|
+
codegenChainById->Js.Dict.set(codegenChain.id->Int.toString, codegenChain)
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
// Create a dictionary to store merged contracts with ABIs by chain id
|
|
245
|
+
let contractsByChainId: Js.Dict.t<array<contract>> = Js.Dict.empty()
|
|
246
|
+
codegenChains->Array.forEach(codegenChain => {
|
|
247
|
+
let mergedContracts = codegenChain.contracts->Array.map(codegenContract => {
|
|
248
|
+
switch contractsWithAbis->Js.Dict.get(codegenContract.name) {
|
|
249
|
+
| Some((abi, eventSignatures)) =>
|
|
250
|
+
// Parse addresses based on ecosystem and address format
|
|
251
|
+
let parsedAddresses = codegenContract.addresses->Array.map(
|
|
252
|
+
addressString => {
|
|
253
|
+
switch ecosystemName {
|
|
254
|
+
| Ecosystem.Evm =>
|
|
255
|
+
if lowercaseAddresses {
|
|
256
|
+
addressString->Address.Evm.fromStringLowercaseOrThrow
|
|
257
|
+
} else {
|
|
258
|
+
addressString->Address.Evm.fromStringOrThrow
|
|
259
|
+
}
|
|
260
|
+
| Ecosystem.Fuel | Ecosystem.Svm => addressString->Address.unsafeFromString
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
)
|
|
264
|
+
// Convert codegenContract to contract by adding abi and eventSignatures
|
|
265
|
+
{
|
|
266
|
+
name: codegenContract.name,
|
|
267
|
+
abi,
|
|
268
|
+
addresses: parsedAddresses,
|
|
269
|
+
events: codegenContract.events,
|
|
270
|
+
startBlock: codegenContract.startBlock,
|
|
271
|
+
eventSignatures,
|
|
272
|
+
}
|
|
273
|
+
| None =>
|
|
274
|
+
Js.Exn.raiseError(
|
|
275
|
+
`Contract "${codegenContract.name}" is missing ABI in public config (internal.config.ts)`,
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
})
|
|
279
|
+
contractsByChainId->Js.Dict.set(codegenChain.id->Int.toString, mergedContracts)
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
// Helper to convert parsed RPC config to evmRpcConfig
|
|
283
|
+
let parseRpcSourceFor = (sourceFor: rpcSourceFor): Source.sourceFor => {
|
|
284
|
+
switch sourceFor {
|
|
285
|
+
| Sync => Source.Sync
|
|
286
|
+
| Fallback => Source.Fallback
|
|
287
|
+
| Live => Source.Live
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Merge codegenChains with names from publicConfig
|
|
292
|
+
let chains =
|
|
293
|
+
publicChainsConfig
|
|
294
|
+
->Js.Dict.keys
|
|
295
|
+
->Js.Array2.map(chainName => {
|
|
296
|
+
let publicChainConfig = publicChainsConfig->Js.Dict.unsafeGet(chainName)
|
|
297
|
+
let chainId = publicChainConfig["id"]
|
|
298
|
+
let codegenChain = switch codegenChainById->Js.Dict.get(chainId->Int.toString) {
|
|
299
|
+
| Some(c) => c
|
|
300
|
+
| None =>
|
|
301
|
+
Js.Exn.raiseError(`Chain with id ${chainId->Int.toString} not found in codegen chains`)
|
|
302
|
+
}
|
|
303
|
+
let mergedContracts = switch contractsByChainId->Js.Dict.get(chainId->Int.toString) {
|
|
304
|
+
| Some(contracts) => contracts
|
|
305
|
+
| None =>
|
|
306
|
+
Js.Exn.raiseError(
|
|
307
|
+
`Contracts for chain with id ${chainId->Int.toString} not found in merged contracts`,
|
|
308
|
+
)
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Build sourceConfig from the parsed chain config
|
|
312
|
+
let sourceConfig = switch ecosystemName {
|
|
313
|
+
| Ecosystem.Evm =>
|
|
314
|
+
let rpcs =
|
|
315
|
+
publicChainConfig["rpcs"]
|
|
316
|
+
->Option.getWithDefault([])
|
|
317
|
+
->Array.map((rpcConfig): evmRpcConfig => {
|
|
318
|
+
// Build syncConfig from flattened fields
|
|
319
|
+
let initialBlockInterval = rpcConfig["initialBlockInterval"]
|
|
320
|
+
let backoffMultiplicative = rpcConfig["backoffMultiplicative"]
|
|
321
|
+
let accelerationAdditive = rpcConfig["accelerationAdditive"]
|
|
322
|
+
let intervalCeiling = rpcConfig["intervalCeiling"]
|
|
323
|
+
let backoffMillis = rpcConfig["backoffMillis"]
|
|
324
|
+
let queryTimeoutMillis = rpcConfig["queryTimeoutMillis"]
|
|
325
|
+
let fallbackStallTimeout = rpcConfig["fallbackStallTimeout"]
|
|
326
|
+
let hasSyncConfig =
|
|
327
|
+
initialBlockInterval->Option.isSome ||
|
|
328
|
+
backoffMultiplicative->Option.isSome ||
|
|
329
|
+
accelerationAdditive->Option.isSome ||
|
|
330
|
+
intervalCeiling->Option.isSome ||
|
|
331
|
+
backoffMillis->Option.isSome ||
|
|
332
|
+
queryTimeoutMillis->Option.isSome ||
|
|
333
|
+
fallbackStallTimeout->Option.isSome
|
|
334
|
+
let syncConfig: option<sourceSyncOptions> = if hasSyncConfig {
|
|
335
|
+
Some({
|
|
336
|
+
?initialBlockInterval,
|
|
337
|
+
?backoffMultiplicative,
|
|
338
|
+
?accelerationAdditive,
|
|
339
|
+
?intervalCeiling,
|
|
340
|
+
?backoffMillis,
|
|
341
|
+
?queryTimeoutMillis,
|
|
342
|
+
?fallbackStallTimeout,
|
|
343
|
+
})
|
|
344
|
+
} else {
|
|
345
|
+
None
|
|
346
|
+
}
|
|
347
|
+
{
|
|
348
|
+
url: rpcConfig["url"],
|
|
349
|
+
sourceFor: parseRpcSourceFor(rpcConfig["for"]),
|
|
350
|
+
syncConfig,
|
|
351
|
+
}
|
|
352
|
+
})
|
|
353
|
+
EvmSourceConfig({hypersync: publicChainConfig["hypersync"], rpcs})
|
|
354
|
+
| Ecosystem.Fuel =>
|
|
355
|
+
switch publicChainConfig["hypersync"] {
|
|
356
|
+
| Some(hypersync) => FuelSourceConfig({hypersync: hypersync})
|
|
357
|
+
| None =>
|
|
358
|
+
Js.Exn.raiseError(
|
|
359
|
+
`Chain ${chainName} is missing hypersync endpoint in config`,
|
|
360
|
+
)
|
|
361
|
+
}
|
|
362
|
+
| Ecosystem.Svm =>
|
|
363
|
+
switch publicChainConfig["rpc"] {
|
|
364
|
+
| Some(rpc) => SvmSourceConfig({rpc: rpc})
|
|
365
|
+
| None =>
|
|
366
|
+
Js.Exn.raiseError(
|
|
367
|
+
`Chain ${chainName} is missing rpc endpoint in config`,
|
|
368
|
+
)
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
{
|
|
373
|
+
name: chainName,
|
|
374
|
+
id: codegenChain.id,
|
|
375
|
+
startBlock: publicChainConfig["startBlock"],
|
|
376
|
+
endBlock: ?publicChainConfig["endBlock"],
|
|
377
|
+
maxReorgDepth: switch ecosystemName {
|
|
378
|
+
| Ecosystem.Evm => publicChainConfig["maxReorgDepth"]->Option.getWithDefault(200)
|
|
379
|
+
// Fuel doesn't have reorgs, SVM reorg handling is not supported
|
|
380
|
+
| Ecosystem.Fuel | Ecosystem.Svm => 0
|
|
381
|
+
},
|
|
382
|
+
contracts: mergedContracts,
|
|
383
|
+
sourceConfig,
|
|
384
|
+
}
|
|
385
|
+
})
|
|
386
|
+
|
|
77
387
|
let chainMap =
|
|
78
388
|
chains
|
|
79
|
-
->Js.Array2.map(
|
|
80
|
-
(ChainMap.Chain.makeUnsafe(~chainId=
|
|
389
|
+
->Js.Array2.map(chain => {
|
|
390
|
+
(ChainMap.Chain.makeUnsafe(~chainId=chain.id), chain)
|
|
81
391
|
})
|
|
82
392
|
->ChainMap.fromArrayUnsafe
|
|
83
393
|
|
|
@@ -90,21 +400,50 @@ let make = (
|
|
|
90
400
|
})
|
|
91
401
|
})
|
|
92
402
|
|
|
93
|
-
let
|
|
403
|
+
let ecosystem = switch ecosystemName {
|
|
404
|
+
| Ecosystem.Evm => Evm.ecosystem
|
|
405
|
+
| Ecosystem.Fuel => Fuel.ecosystem
|
|
406
|
+
| Ecosystem.Svm => Svm.ecosystem
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
let userEntitiesByName =
|
|
410
|
+
userEntities
|
|
411
|
+
->Js.Array2.map(entityConfig => {
|
|
412
|
+
(entityConfig.name, entityConfig)
|
|
413
|
+
})
|
|
414
|
+
->Js.Dict.fromArray
|
|
415
|
+
|
|
416
|
+
// Extract contract handlers from the public config
|
|
417
|
+
let contractHandlers = switch publicContractsConfig {
|
|
418
|
+
| Some(contractsDict) =>
|
|
419
|
+
contractsDict
|
|
420
|
+
->Js.Dict.entries
|
|
421
|
+
->Js.Array2.map(((contractName, contractConfig)) => {
|
|
422
|
+
{
|
|
423
|
+
name: contractName,
|
|
424
|
+
handler: contractConfig["handler"],
|
|
425
|
+
}
|
|
426
|
+
})
|
|
427
|
+
| None => []
|
|
428
|
+
}
|
|
94
429
|
|
|
95
430
|
{
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
431
|
+
name: publicConfig["name"],
|
|
432
|
+
description: publicConfig["description"],
|
|
433
|
+
handlers: publicConfig["handlers"]->Option.getWithDefault("src/handlers"),
|
|
434
|
+
contractHandlers,
|
|
435
|
+
shouldRollbackOnReorg: publicConfig["rollbackOnReorg"]->Option.getWithDefault(true),
|
|
436
|
+
shouldSaveFullHistory: publicConfig["saveFullHistory"]->Option.getWithDefault(false),
|
|
437
|
+
multichain: publicConfig["multichain"]->Option.getWithDefault(Unordered),
|
|
99
438
|
chainMap,
|
|
100
439
|
defaultChain: chains->Array.get(0),
|
|
101
|
-
enableRawEvents,
|
|
102
|
-
|
|
440
|
+
enableRawEvents: publicConfig["rawEvents"]->Option.getWithDefault(false),
|
|
441
|
+
ecosystem,
|
|
103
442
|
maxAddrInPartition,
|
|
104
|
-
|
|
105
|
-
batchSize,
|
|
443
|
+
batchSize: publicConfig["fullBatchSize"]->Option.getWithDefault(5000),
|
|
106
444
|
lowercaseAddresses,
|
|
107
445
|
addContractNameToContractNameMapping,
|
|
446
|
+
userEntitiesByName,
|
|
108
447
|
}
|
|
109
448
|
}
|
|
110
449
|
|
|
@@ -122,3 +461,4 @@ let getChain = (config, ~chainId) => {
|
|
|
122
461
|
"No chain with id " ++ chain->ChainMap.Chain.toString ++ " found in config.yaml",
|
|
123
462
|
)
|
|
124
463
|
}
|
|
464
|
+
|