envio 3.0.0-alpha.3 → 3.0.0-alpha.5
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 +0 -1
- package/index.d.ts +333 -2
- package/index.js +4 -0
- package/package.json +13 -6
- package/rescript.json +4 -1
- package/src/ChainFetcher.res +25 -1
- package/src/ChainFetcher.res.mjs +19 -1
- package/src/Config.res +212 -19
- package/src/Config.res.mjs +228 -29
- package/src/{Indexer.res → Ctx.res} +1 -1
- package/src/Ecosystem.res +2 -2
- package/src/Ecosystem.res.mjs +1 -1
- package/src/Envio.gen.ts +1 -1
- package/src/Envio.res +1 -1
- package/src/EventProcessing.res +18 -18
- package/src/EventProcessing.res.mjs +14 -14
- package/src/GlobalState.res +29 -35
- package/src/GlobalState.res.mjs +47 -47
- package/src/GlobalStateManager.res +68 -0
- package/src/GlobalStateManager.res.mjs +75 -0
- package/src/GlobalStateManager.resi +7 -0
- package/src/Internal.res +41 -1
- package/src/LogSelection.res +33 -27
- package/src/LogSelection.res.mjs +6 -0
- package/src/Main.res +342 -0
- package/src/Main.res.mjs +289 -0
- package/src/PgStorage.gen.ts +10 -0
- package/src/PgStorage.res +24 -2
- package/src/PgStorage.res.d.mts +5 -0
- package/src/PgStorage.res.mjs +22 -1
- package/src/Types.ts +1 -1
- package/src/UserContext.res +0 -1
- package/src/UserContext.res.mjs +0 -2
- 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/Ethers.res +27 -67
- package/src/bindings/Ethers.res.mjs +18 -70
- 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/Yargs.res +8 -0
- package/src/bindings/Yargs.res.mjs +2 -0
- package/src/sources/FuelSDK.res +4 -3
- package/src/sources/HyperSyncHeightStream.res +28 -110
- package/src/sources/HyperSyncHeightStream.res.mjs +30 -63
- package/src/sources/HyperSyncSource.res +11 -13
- package/src/sources/HyperSyncSource.res.mjs +20 -20
- package/src/sources/Rpc.res +43 -0
- package/src/sources/Rpc.res.mjs +31 -0
- package/src/sources/RpcSource.res +9 -4
- package/src/sources/RpcSource.res.mjs +9 -4
- package/src/sources/Source.res +1 -0
- package/src/sources/SourceManager.res +164 -81
- package/src/sources/SourceManager.res.mjs +146 -83
- package/src/sources/{Solana.res → Svm.res} +4 -4
- package/src/sources/{Solana.res.mjs → Svm.res.mjs} +4 -4
- 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 +114 -0
- package/src/tui/components/CustomHooks.res.mjs +162 -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/bindings/Ethers.gen.ts +0 -14
- /package/src/{Indexer.res.mjs → Ctx.res.mjs} +0 -0
package/src/Config.res
CHANGED
|
@@ -18,7 +18,21 @@ type contract = {
|
|
|
18
18
|
startBlock: option<int>,
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
type codegenContract = {
|
|
22
|
+
name: string,
|
|
23
|
+
addresses: array<string>,
|
|
24
|
+
events: array<Internal.eventConfig>,
|
|
25
|
+
startBlock: option<int>,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type codegenChain = {
|
|
29
|
+
id: int,
|
|
30
|
+
contracts: array<codegenContract>,
|
|
31
|
+
sources: array<Source.t>,
|
|
32
|
+
}
|
|
33
|
+
|
|
21
34
|
type chain = {
|
|
35
|
+
name: string,
|
|
22
36
|
id: int,
|
|
23
37
|
startBlock: int,
|
|
24
38
|
endBlock?: int,
|
|
@@ -40,6 +54,9 @@ type sourceSync = {
|
|
|
40
54
|
type multichain = | @as("ordered") Ordered | @as("unordered") Unordered
|
|
41
55
|
|
|
42
56
|
type t = {
|
|
57
|
+
name: string,
|
|
58
|
+
description: option<string>,
|
|
59
|
+
handlers: string,
|
|
43
60
|
shouldRollbackOnReorg: bool,
|
|
44
61
|
shouldSaveFullHistory: bool,
|
|
45
62
|
multichain: multichain,
|
|
@@ -54,19 +71,96 @@ type t = {
|
|
|
54
71
|
userEntitiesByName: dict<Internal.entityConfig>,
|
|
55
72
|
}
|
|
56
73
|
|
|
57
|
-
let
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
let publicConfigChainSchema = S.schema(s =>
|
|
75
|
+
{
|
|
76
|
+
"id": s.matches(S.int),
|
|
77
|
+
"startBlock": s.matches(S.int),
|
|
78
|
+
"endBlock": s.matches(S.option(S.int)),
|
|
79
|
+
"maxReorgDepth": s.matches(S.option(S.int)),
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
let contractConfigSchema = S.schema(s =>
|
|
84
|
+
{
|
|
85
|
+
"abi": s.matches(S.json(~validate=false)),
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
let publicConfigEcosystemSchema = S.schema(s =>
|
|
90
|
+
{
|
|
91
|
+
"chains": s.matches(S.dict(publicConfigChainSchema)),
|
|
92
|
+
"contracts": s.matches(S.option(S.dict(contractConfigSchema))),
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
type addressFormat = | @as("lowercase") Lowercase | @as("checksum") Checksum
|
|
97
|
+
type decoder = | @as("hypersync") Hypersync | @as("viem") Viem
|
|
98
|
+
|
|
99
|
+
let publicConfigEvmSchema = S.schema(s =>
|
|
100
|
+
{
|
|
101
|
+
"chains": s.matches(S.dict(publicConfigChainSchema)),
|
|
102
|
+
"contracts": s.matches(S.option(S.dict(contractConfigSchema))),
|
|
103
|
+
"addressFormat": s.matches(S.option(S.enum([Lowercase, Checksum]))),
|
|
104
|
+
"eventDecoder": s.matches(S.option(S.enum([Hypersync, Viem]))),
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
let multichainSchema = S.enum([Ordered, Unordered])
|
|
109
|
+
|
|
110
|
+
let publicConfigSchema = S.schema(s =>
|
|
111
|
+
{
|
|
112
|
+
"name": s.matches(S.string),
|
|
113
|
+
"description": s.matches(S.option(S.string)),
|
|
114
|
+
"handlers": s.matches(S.option(S.string)),
|
|
115
|
+
"multichain": s.matches(S.option(multichainSchema)),
|
|
116
|
+
"fullBatchSize": s.matches(S.option(S.int)),
|
|
117
|
+
"rollbackOnReorg": s.matches(S.option(S.bool)),
|
|
118
|
+
"saveFullHistory": s.matches(S.option(S.bool)),
|
|
119
|
+
"rawEvents": s.matches(S.option(S.bool)),
|
|
120
|
+
"evm": s.matches(S.option(publicConfigEvmSchema)),
|
|
121
|
+
"fuel": s.matches(S.option(publicConfigEcosystemSchema)),
|
|
122
|
+
"svm": s.matches(S.option(publicConfigEcosystemSchema)),
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
let fromPublic = (
|
|
127
|
+
publicConfigJson: Js.Json.t,
|
|
128
|
+
~codegenChains: array<codegenChain>=[],
|
|
67
129
|
~maxAddrInPartition=5000,
|
|
68
130
|
~userEntities: array<Internal.entityConfig>=[],
|
|
69
131
|
) => {
|
|
132
|
+
// Parse public config
|
|
133
|
+
let publicConfig = try publicConfigJson->S.parseOrThrow(publicConfigSchema) catch {
|
|
134
|
+
| S.Raised(exn) =>
|
|
135
|
+
Js.Exn.raiseError(`Invalid internal.config.ts: ${exn->Utils.prettifyExn->Utils.magic}`)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Determine ecosystem from publicConfig (extract just chains for unified handling)
|
|
139
|
+
let (publicChainsConfig, ecosystemName) = switch (
|
|
140
|
+
publicConfig["evm"],
|
|
141
|
+
publicConfig["fuel"],
|
|
142
|
+
publicConfig["svm"],
|
|
143
|
+
) {
|
|
144
|
+
| (Some(ecosystemConfig), None, None) => (ecosystemConfig["chains"], Ecosystem.Evm)
|
|
145
|
+
| (None, Some(ecosystemConfig), None) => (ecosystemConfig["chains"], Ecosystem.Fuel)
|
|
146
|
+
| (None, None, Some(ecosystemConfig)) => (ecosystemConfig["chains"], Ecosystem.Svm)
|
|
147
|
+
| (None, None, None) =>
|
|
148
|
+
Js.Exn.raiseError("Invalid indexer config: No ecosystem configured (evm, fuel, or svm)")
|
|
149
|
+
| _ =>
|
|
150
|
+
Js.Exn.raiseError(
|
|
151
|
+
"Invalid indexer config: Multiple ecosystems are not supported for a single indexer",
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Extract EVM-specific options with defaults
|
|
156
|
+
let (lowercaseAddresses, shouldUseHypersyncClientDecoder) = switch publicConfig["evm"] {
|
|
157
|
+
| Some(evm) => (
|
|
158
|
+
evm["addressFormat"]->Option.getWithDefault(Checksum) == Lowercase,
|
|
159
|
+
evm["eventDecoder"]->Option.getWithDefault(Hypersync) == Hypersync,
|
|
160
|
+
)
|
|
161
|
+
| None => (false, true)
|
|
162
|
+
}
|
|
163
|
+
|
|
70
164
|
// Validate that lowercase addresses is not used with viem decoder
|
|
71
165
|
if lowercaseAddresses && !shouldUseHypersyncClientDecoder {
|
|
72
166
|
Js.Exn.raiseError(
|
|
@@ -74,10 +168,106 @@ let make = (
|
|
|
74
168
|
)
|
|
75
169
|
}
|
|
76
170
|
|
|
171
|
+
// Parse ABIs from public config
|
|
172
|
+
let publicContractsConfig = switch (ecosystemName, publicConfig["evm"], publicConfig["fuel"]) {
|
|
173
|
+
| (Ecosystem.Evm, Some(evm), _) => evm["contracts"]
|
|
174
|
+
| (Ecosystem.Fuel, _, Some(fuel)) => fuel["contracts"]
|
|
175
|
+
| _ => None
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
let contractsWithAbis = switch publicContractsConfig {
|
|
179
|
+
| Some(contractsDict) =>
|
|
180
|
+
contractsDict
|
|
181
|
+
->Js.Dict.entries
|
|
182
|
+
->Js.Array2.map(((contractName, contractConfig)) => {
|
|
183
|
+
let abi = contractConfig["abi"]->(Utils.magic: Js.Json.t => EvmTypes.Abi.t)
|
|
184
|
+
(contractName, abi)
|
|
185
|
+
})
|
|
186
|
+
->Js.Dict.fromArray
|
|
187
|
+
| None => Js.Dict.empty()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Index codegenChains by id for efficient lookup
|
|
191
|
+
let codegenChainById = Js.Dict.empty()
|
|
192
|
+
codegenChains->Array.forEach(codegenChain => {
|
|
193
|
+
codegenChainById->Js.Dict.set(codegenChain.id->Int.toString, codegenChain)
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
// Create a dictionary to store merged contracts with ABIs by chain id
|
|
197
|
+
let contractsByChainId: Js.Dict.t<array<contract>> = Js.Dict.empty()
|
|
198
|
+
codegenChains->Array.forEach(codegenChain => {
|
|
199
|
+
let mergedContracts = codegenChain.contracts->Array.map(codegenContract => {
|
|
200
|
+
switch contractsWithAbis->Js.Dict.get(codegenContract.name) {
|
|
201
|
+
| Some(abi) =>
|
|
202
|
+
// Parse addresses based on ecosystem and address format
|
|
203
|
+
let parsedAddresses = codegenContract.addresses->Array.map(
|
|
204
|
+
addressString => {
|
|
205
|
+
switch ecosystemName {
|
|
206
|
+
| Ecosystem.Evm =>
|
|
207
|
+
if lowercaseAddresses {
|
|
208
|
+
addressString->Address.Evm.fromStringLowercaseOrThrow
|
|
209
|
+
} else {
|
|
210
|
+
addressString->Address.Evm.fromStringOrThrow
|
|
211
|
+
}
|
|
212
|
+
| Ecosystem.Fuel | Ecosystem.Svm => addressString->Address.unsafeFromString
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
)
|
|
216
|
+
// Convert codegenContract to contract by adding abi
|
|
217
|
+
{
|
|
218
|
+
name: codegenContract.name,
|
|
219
|
+
abi,
|
|
220
|
+
addresses: parsedAddresses,
|
|
221
|
+
events: codegenContract.events,
|
|
222
|
+
startBlock: codegenContract.startBlock,
|
|
223
|
+
}
|
|
224
|
+
| None =>
|
|
225
|
+
Js.Exn.raiseError(
|
|
226
|
+
`Contract "${codegenContract.name}" is missing ABI in public config (internal.config.ts)`,
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
})
|
|
230
|
+
contractsByChainId->Js.Dict.set(codegenChain.id->Int.toString, mergedContracts)
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
// Merge codegenChains with names from publicConfig
|
|
234
|
+
let chains =
|
|
235
|
+
publicChainsConfig
|
|
236
|
+
->Js.Dict.keys
|
|
237
|
+
->Js.Array2.map(chainName => {
|
|
238
|
+
let publicChainConfig = publicChainsConfig->Js.Dict.unsafeGet(chainName)
|
|
239
|
+
let chainId = publicChainConfig["id"]
|
|
240
|
+
let codegenChain = switch codegenChainById->Js.Dict.get(chainId->Int.toString) {
|
|
241
|
+
| Some(c) => c
|
|
242
|
+
| None =>
|
|
243
|
+
Js.Exn.raiseError(`Chain with id ${chainId->Int.toString} not found in codegen chains`)
|
|
244
|
+
}
|
|
245
|
+
let mergedContracts = switch contractsByChainId->Js.Dict.get(chainId->Int.toString) {
|
|
246
|
+
| Some(contracts) => contracts
|
|
247
|
+
| None =>
|
|
248
|
+
Js.Exn.raiseError(
|
|
249
|
+
`Contracts for chain with id ${chainId->Int.toString} not found in merged contracts`,
|
|
250
|
+
)
|
|
251
|
+
}
|
|
252
|
+
{
|
|
253
|
+
name: chainName,
|
|
254
|
+
id: codegenChain.id,
|
|
255
|
+
startBlock: publicChainConfig["startBlock"],
|
|
256
|
+
endBlock: ?publicChainConfig["endBlock"],
|
|
257
|
+
maxReorgDepth: switch ecosystemName {
|
|
258
|
+
| Ecosystem.Evm => publicChainConfig["maxReorgDepth"]->Option.getWithDefault(200)
|
|
259
|
+
// Fuel doesn't have reorgs, SVM reorg handling is not supported
|
|
260
|
+
| Ecosystem.Fuel | Ecosystem.Svm => 0
|
|
261
|
+
},
|
|
262
|
+
contracts: mergedContracts,
|
|
263
|
+
sources: codegenChain.sources,
|
|
264
|
+
}
|
|
265
|
+
})
|
|
266
|
+
|
|
77
267
|
let chainMap =
|
|
78
268
|
chains
|
|
79
|
-
->Js.Array2.map(
|
|
80
|
-
(ChainMap.Chain.makeUnsafe(~chainId=
|
|
269
|
+
->Js.Array2.map(chain => {
|
|
270
|
+
(ChainMap.Chain.makeUnsafe(~chainId=chain.id), chain)
|
|
81
271
|
})
|
|
82
272
|
->ChainMap.fromArrayUnsafe
|
|
83
273
|
|
|
@@ -90,10 +280,10 @@ let make = (
|
|
|
90
280
|
})
|
|
91
281
|
})
|
|
92
282
|
|
|
93
|
-
let ecosystem = switch
|
|
283
|
+
let ecosystem = switch ecosystemName {
|
|
94
284
|
| Ecosystem.Evm => Evm.ecosystem
|
|
95
285
|
| Ecosystem.Fuel => Fuel.ecosystem
|
|
96
|
-
| Ecosystem.
|
|
286
|
+
| Ecosystem.Svm => Svm.ecosystem
|
|
97
287
|
}
|
|
98
288
|
|
|
99
289
|
let userEntitiesByName =
|
|
@@ -104,15 +294,18 @@ let make = (
|
|
|
104
294
|
->Js.Dict.fromArray
|
|
105
295
|
|
|
106
296
|
{
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
297
|
+
name: publicConfig["name"],
|
|
298
|
+
description: publicConfig["description"],
|
|
299
|
+
handlers: publicConfig["handlers"]->Option.getWithDefault("src/handlers"),
|
|
300
|
+
shouldRollbackOnReorg: publicConfig["rollbackOnReorg"]->Option.getWithDefault(true),
|
|
301
|
+
shouldSaveFullHistory: publicConfig["saveFullHistory"]->Option.getWithDefault(false),
|
|
302
|
+
multichain: publicConfig["multichain"]->Option.getWithDefault(Unordered),
|
|
110
303
|
chainMap,
|
|
111
304
|
defaultChain: chains->Array.get(0),
|
|
112
|
-
enableRawEvents,
|
|
305
|
+
enableRawEvents: publicConfig["rawEvents"]->Option.getWithDefault(false),
|
|
113
306
|
ecosystem,
|
|
114
307
|
maxAddrInPartition,
|
|
115
|
-
batchSize,
|
|
308
|
+
batchSize: publicConfig["fullBatchSize"]->Option.getWithDefault(5000),
|
|
116
309
|
lowercaseAddresses,
|
|
117
310
|
addContractNameToContractNameMapping,
|
|
118
311
|
userEntitiesByName,
|
package/src/Config.res.mjs
CHANGED
|
@@ -1,33 +1,223 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Evm from "./sources/Evm.res.mjs";
|
|
4
|
+
import * as Svm from "./sources/Svm.res.mjs";
|
|
4
5
|
import * as Fuel from "./sources/Fuel.res.mjs";
|
|
5
6
|
import * as Utils from "./Utils.res.mjs";
|
|
6
7
|
import * as Js_exn from "rescript/lib/es6/js_exn.js";
|
|
7
|
-
import * as
|
|
8
|
+
import * as Address from "./Address.res.mjs";
|
|
8
9
|
import * as Js_dict from "rescript/lib/es6/js_dict.js";
|
|
9
10
|
import * as ChainMap from "./ChainMap.res.mjs";
|
|
10
11
|
import * as Belt_Array from "rescript/lib/es6/belt_Array.js";
|
|
12
|
+
import * as Belt_Option from "rescript/lib/es6/belt_Option.js";
|
|
13
|
+
import * as Caml_option from "rescript/lib/es6/caml_option.js";
|
|
14
|
+
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
|
|
15
|
+
import * as Caml_js_exceptions from "rescript/lib/es6/caml_js_exceptions.js";
|
|
11
16
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
var publicConfigChainSchema = S$RescriptSchema.schema(function (s) {
|
|
18
|
+
return {
|
|
19
|
+
id: s.m(S$RescriptSchema.$$int),
|
|
20
|
+
startBlock: s.m(S$RescriptSchema.$$int),
|
|
21
|
+
endBlock: s.m(S$RescriptSchema.option(S$RescriptSchema.$$int)),
|
|
22
|
+
maxReorgDepth: s.m(S$RescriptSchema.option(S$RescriptSchema.$$int))
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
var contractConfigSchema = S$RescriptSchema.schema(function (s) {
|
|
27
|
+
return {
|
|
28
|
+
abi: s.m(S$RescriptSchema.json(false))
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
var publicConfigEcosystemSchema = S$RescriptSchema.schema(function (s) {
|
|
33
|
+
return {
|
|
34
|
+
chains: s.m(S$RescriptSchema.dict(publicConfigChainSchema)),
|
|
35
|
+
contracts: s.m(S$RescriptSchema.option(S$RescriptSchema.dict(contractConfigSchema)))
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
var publicConfigEvmSchema = S$RescriptSchema.schema(function (s) {
|
|
40
|
+
return {
|
|
41
|
+
chains: s.m(S$RescriptSchema.dict(publicConfigChainSchema)),
|
|
42
|
+
contracts: s.m(S$RescriptSchema.option(S$RescriptSchema.dict(contractConfigSchema))),
|
|
43
|
+
addressFormat: s.m(S$RescriptSchema.option(S$RescriptSchema.$$enum([
|
|
44
|
+
"lowercase",
|
|
45
|
+
"checksum"
|
|
46
|
+
]))),
|
|
47
|
+
eventDecoder: s.m(S$RescriptSchema.option(S$RescriptSchema.$$enum([
|
|
48
|
+
"hypersync",
|
|
49
|
+
"viem"
|
|
50
|
+
])))
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
var multichainSchema = S$RescriptSchema.$$enum([
|
|
55
|
+
"ordered",
|
|
56
|
+
"unordered"
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
var publicConfigSchema = S$RescriptSchema.schema(function (s) {
|
|
60
|
+
return {
|
|
61
|
+
name: s.m(S$RescriptSchema.string),
|
|
62
|
+
description: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
|
|
63
|
+
handlers: s.m(S$RescriptSchema.option(S$RescriptSchema.string)),
|
|
64
|
+
multichain: s.m(S$RescriptSchema.option(multichainSchema)),
|
|
65
|
+
fullBatchSize: s.m(S$RescriptSchema.option(S$RescriptSchema.$$int)),
|
|
66
|
+
rollbackOnReorg: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
67
|
+
saveFullHistory: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
68
|
+
rawEvents: s.m(S$RescriptSchema.option(S$RescriptSchema.bool)),
|
|
69
|
+
evm: s.m(S$RescriptSchema.option(publicConfigEvmSchema)),
|
|
70
|
+
fuel: s.m(S$RescriptSchema.option(publicConfigEcosystemSchema)),
|
|
71
|
+
svm: s.m(S$RescriptSchema.option(publicConfigEcosystemSchema))
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
function fromPublic(publicConfigJson, codegenChainsOpt, maxAddrInPartitionOpt, userEntitiesOpt) {
|
|
76
|
+
var codegenChains = codegenChainsOpt !== undefined ? codegenChainsOpt : [];
|
|
22
77
|
var maxAddrInPartition = maxAddrInPartitionOpt !== undefined ? maxAddrInPartitionOpt : 5000;
|
|
23
78
|
var userEntities = userEntitiesOpt !== undefined ? userEntitiesOpt : [];
|
|
24
|
-
|
|
79
|
+
var publicConfig;
|
|
80
|
+
try {
|
|
81
|
+
publicConfig = S$RescriptSchema.parseOrThrow(publicConfigJson, publicConfigSchema);
|
|
82
|
+
}
|
|
83
|
+
catch (raw_exn){
|
|
84
|
+
var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
|
|
85
|
+
if (exn.RE_EXN_ID === S$RescriptSchema.Raised) {
|
|
86
|
+
publicConfig = Js_exn.raiseError("Invalid internal.config.ts: " + Utils.prettifyExn(exn._1));
|
|
87
|
+
} else {
|
|
88
|
+
throw exn;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
var match = publicConfig.evm;
|
|
92
|
+
var match$1 = publicConfig.fuel;
|
|
93
|
+
var match$2 = publicConfig.svm;
|
|
94
|
+
var match$3 = match !== undefined ? (
|
|
95
|
+
match$1 !== undefined || match$2 !== undefined ? Js_exn.raiseError("Invalid indexer config: Multiple ecosystems are not supported for a single indexer") : [
|
|
96
|
+
Caml_option.valFromOption(match).chains,
|
|
97
|
+
"evm"
|
|
98
|
+
]
|
|
99
|
+
) : (
|
|
100
|
+
match$1 !== undefined ? (
|
|
101
|
+
match$2 !== undefined ? Js_exn.raiseError("Invalid indexer config: Multiple ecosystems are not supported for a single indexer") : [
|
|
102
|
+
Caml_option.valFromOption(match$1).chains,
|
|
103
|
+
"fuel"
|
|
104
|
+
]
|
|
105
|
+
) : (
|
|
106
|
+
match$2 !== undefined ? [
|
|
107
|
+
Caml_option.valFromOption(match$2).chains,
|
|
108
|
+
"svm"
|
|
109
|
+
] : Js_exn.raiseError("Invalid indexer config: No ecosystem configured (evm, fuel, or svm)")
|
|
110
|
+
)
|
|
111
|
+
);
|
|
112
|
+
var ecosystemName = match$3[1];
|
|
113
|
+
var publicChainsConfig = match$3[0];
|
|
114
|
+
var evm = publicConfig.evm;
|
|
115
|
+
var match$4;
|
|
116
|
+
if (evm !== undefined) {
|
|
117
|
+
var evm$1 = Caml_option.valFromOption(evm);
|
|
118
|
+
match$4 = [
|
|
119
|
+
Belt_Option.getWithDefault(evm$1.addressFormat, "checksum") === "lowercase",
|
|
120
|
+
Belt_Option.getWithDefault(evm$1.eventDecoder, "hypersync") === "hypersync"
|
|
121
|
+
];
|
|
122
|
+
} else {
|
|
123
|
+
match$4 = [
|
|
124
|
+
false,
|
|
125
|
+
true
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
var lowercaseAddresses = match$4[0];
|
|
129
|
+
if (lowercaseAddresses && !match$4[1]) {
|
|
25
130
|
Js_exn.raiseError("lowercase addresses is not supported when event_decoder is 'viem'. Please set event_decoder to 'hypersync-client' or change address_format to 'checksum'.");
|
|
26
131
|
}
|
|
27
|
-
var
|
|
132
|
+
var match$5 = publicConfig.evm;
|
|
133
|
+
var match$6 = publicConfig.fuel;
|
|
134
|
+
var publicContractsConfig;
|
|
135
|
+
switch (ecosystemName) {
|
|
136
|
+
case "evm" :
|
|
137
|
+
publicContractsConfig = match$5 !== undefined ? Caml_option.valFromOption(match$5).contracts : undefined;
|
|
138
|
+
break;
|
|
139
|
+
case "fuel" :
|
|
140
|
+
publicContractsConfig = match$6 !== undefined ? Caml_option.valFromOption(match$6).contracts : undefined;
|
|
141
|
+
break;
|
|
142
|
+
case "svm" :
|
|
143
|
+
publicContractsConfig = undefined;
|
|
144
|
+
break;
|
|
145
|
+
|
|
146
|
+
}
|
|
147
|
+
var contractsWithAbis = publicContractsConfig !== undefined ? Js_dict.fromArray(Js_dict.entries(publicContractsConfig).map(function (param) {
|
|
148
|
+
var abi = param[1].abi;
|
|
149
|
+
return [
|
|
150
|
+
param[0],
|
|
151
|
+
abi
|
|
152
|
+
];
|
|
153
|
+
})) : ({});
|
|
154
|
+
var codegenChainById = {};
|
|
155
|
+
Belt_Array.forEach(codegenChains, (function (codegenChain) {
|
|
156
|
+
codegenChainById[String(codegenChain.id)] = codegenChain;
|
|
157
|
+
}));
|
|
158
|
+
var contractsByChainId = {};
|
|
159
|
+
Belt_Array.forEach(codegenChains, (function (codegenChain) {
|
|
160
|
+
var mergedContracts = Belt_Array.map(codegenChain.contracts, (function (codegenContract) {
|
|
161
|
+
var abi = Js_dict.get(contractsWithAbis, codegenContract.name);
|
|
162
|
+
if (abi === undefined) {
|
|
163
|
+
return Js_exn.raiseError("Contract \"" + codegenContract.name + "\" is missing ABI in public config (internal.config.ts)");
|
|
164
|
+
}
|
|
165
|
+
var parsedAddresses = Belt_Array.map(codegenContract.addresses, (function (addressString) {
|
|
166
|
+
switch (ecosystemName) {
|
|
167
|
+
case "evm" :
|
|
168
|
+
if (lowercaseAddresses) {
|
|
169
|
+
return Address.Evm.fromStringLowercaseOrThrow(addressString);
|
|
170
|
+
} else {
|
|
171
|
+
return Address.Evm.fromStringOrThrow(addressString);
|
|
172
|
+
}
|
|
173
|
+
case "fuel" :
|
|
174
|
+
case "svm" :
|
|
175
|
+
return addressString;
|
|
176
|
+
|
|
177
|
+
}
|
|
178
|
+
}));
|
|
179
|
+
return {
|
|
180
|
+
name: codegenContract.name,
|
|
181
|
+
abi: Caml_option.valFromOption(abi),
|
|
182
|
+
addresses: parsedAddresses,
|
|
183
|
+
events: codegenContract.events,
|
|
184
|
+
startBlock: codegenContract.startBlock
|
|
185
|
+
};
|
|
186
|
+
}));
|
|
187
|
+
contractsByChainId[String(codegenChain.id)] = mergedContracts;
|
|
188
|
+
}));
|
|
189
|
+
var chains = Object.keys(publicChainsConfig).map(function (chainName) {
|
|
190
|
+
var publicChainConfig = publicChainsConfig[chainName];
|
|
191
|
+
var chainId = publicChainConfig.id;
|
|
192
|
+
var c = Js_dict.get(codegenChainById, String(chainId));
|
|
193
|
+
var codegenChain = c !== undefined ? c : Js_exn.raiseError("Chain with id " + String(chainId) + " not found in codegen chains");
|
|
194
|
+
var contracts = Js_dict.get(contractsByChainId, String(chainId));
|
|
195
|
+
var mergedContracts = contracts !== undefined ? contracts : Js_exn.raiseError("Contracts for chain with id " + String(chainId) + " not found in merged contracts");
|
|
196
|
+
var tmp;
|
|
197
|
+
switch (ecosystemName) {
|
|
198
|
+
case "evm" :
|
|
199
|
+
tmp = Belt_Option.getWithDefault(publicChainConfig.maxReorgDepth, 200);
|
|
200
|
+
break;
|
|
201
|
+
case "fuel" :
|
|
202
|
+
case "svm" :
|
|
203
|
+
tmp = 0;
|
|
204
|
+
break;
|
|
205
|
+
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
name: chainName,
|
|
209
|
+
id: codegenChain.id,
|
|
210
|
+
startBlock: publicChainConfig.startBlock,
|
|
211
|
+
endBlock: publicChainConfig.endBlock,
|
|
212
|
+
maxReorgDepth: tmp,
|
|
213
|
+
contracts: mergedContracts,
|
|
214
|
+
sources: codegenChain.sources
|
|
215
|
+
};
|
|
216
|
+
});
|
|
217
|
+
var chainMap = ChainMap.fromArrayUnsafe(chains.map(function (chain) {
|
|
28
218
|
return [
|
|
29
|
-
ChainMap.Chain.makeUnsafe(
|
|
30
|
-
|
|
219
|
+
ChainMap.Chain.makeUnsafe(chain.id),
|
|
220
|
+
chain
|
|
31
221
|
];
|
|
32
222
|
}));
|
|
33
223
|
var addContractNameToContractNameMapping = {};
|
|
@@ -37,16 +227,16 @@ function make(shouldRollbackOnReorgOpt, shouldSaveFullHistoryOpt, chainsOpt, ena
|
|
|
37
227
|
addContractNameToContractNameMapping[addKey] = contract.name;
|
|
38
228
|
}));
|
|
39
229
|
}));
|
|
40
|
-
var ecosystem
|
|
41
|
-
switch (
|
|
230
|
+
var ecosystem;
|
|
231
|
+
switch (ecosystemName) {
|
|
42
232
|
case "evm" :
|
|
43
|
-
ecosystem
|
|
233
|
+
ecosystem = Evm.ecosystem;
|
|
44
234
|
break;
|
|
45
235
|
case "fuel" :
|
|
46
|
-
ecosystem
|
|
236
|
+
ecosystem = Fuel.ecosystem;
|
|
47
237
|
break;
|
|
48
|
-
case "
|
|
49
|
-
ecosystem
|
|
238
|
+
case "svm" :
|
|
239
|
+
ecosystem = Svm.ecosystem;
|
|
50
240
|
break;
|
|
51
241
|
|
|
52
242
|
}
|
|
@@ -57,15 +247,18 @@ function make(shouldRollbackOnReorgOpt, shouldSaveFullHistoryOpt, chainsOpt, ena
|
|
|
57
247
|
];
|
|
58
248
|
}));
|
|
59
249
|
return {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
250
|
+
name: publicConfig.name,
|
|
251
|
+
description: publicConfig.description,
|
|
252
|
+
handlers: Belt_Option.getWithDefault(publicConfig.handlers, "src/handlers"),
|
|
253
|
+
shouldRollbackOnReorg: Belt_Option.getWithDefault(publicConfig.rollbackOnReorg, true),
|
|
254
|
+
shouldSaveFullHistory: Belt_Option.getWithDefault(publicConfig.saveFullHistory, false),
|
|
255
|
+
multichain: Belt_Option.getWithDefault(publicConfig.multichain, "unordered"),
|
|
63
256
|
chainMap: chainMap,
|
|
64
257
|
defaultChain: Belt_Array.get(chains, 0),
|
|
65
|
-
ecosystem: ecosystem
|
|
66
|
-
enableRawEvents:
|
|
258
|
+
ecosystem: ecosystem,
|
|
259
|
+
enableRawEvents: Belt_Option.getWithDefault(publicConfig.rawEvents, false),
|
|
67
260
|
maxAddrInPartition: maxAddrInPartition,
|
|
68
|
-
batchSize:
|
|
261
|
+
batchSize: Belt_Option.getWithDefault(publicConfig.fullBatchSize, 5000),
|
|
69
262
|
lowercaseAddresses: lowercaseAddresses,
|
|
70
263
|
addContractNameToContractNameMapping: addContractNameToContractNameMapping,
|
|
71
264
|
userEntitiesByName: userEntitiesByName
|
|
@@ -100,9 +293,15 @@ function getChain(config, chainId) {
|
|
|
100
293
|
}
|
|
101
294
|
|
|
102
295
|
export {
|
|
103
|
-
|
|
296
|
+
publicConfigChainSchema ,
|
|
297
|
+
contractConfigSchema ,
|
|
298
|
+
publicConfigEcosystemSchema ,
|
|
299
|
+
publicConfigEvmSchema ,
|
|
300
|
+
multichainSchema ,
|
|
301
|
+
publicConfigSchema ,
|
|
302
|
+
fromPublic ,
|
|
104
303
|
shouldSaveHistory ,
|
|
105
304
|
shouldPruneHistory ,
|
|
106
305
|
getChain ,
|
|
107
306
|
}
|
|
108
|
-
/*
|
|
307
|
+
/* publicConfigChainSchema Not a pure module */
|
package/src/Ecosystem.res
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type name = | @as("evm") Evm | @as("fuel") Fuel | @as("
|
|
1
|
+
type name = | @as("evm") Evm | @as("fuel") Fuel | @as("svm") Svm
|
|
2
2
|
|
|
3
3
|
type t = {
|
|
4
4
|
name: name,
|
|
@@ -15,7 +15,7 @@ type t = {
|
|
|
15
15
|
|
|
16
16
|
let makeOnBlockArgs = (~blockNumber: int, ~ecosystem: t, ~context): Internal.onBlockArgs => {
|
|
17
17
|
switch ecosystem.name {
|
|
18
|
-
|
|
|
18
|
+
| Svm => {slot: blockNumber, context}
|
|
19
19
|
| _ => {
|
|
20
20
|
let blockEvent = Js.Dict.empty()
|
|
21
21
|
blockEvent->Js.Dict.set(ecosystem.blockNumberName, blockNumber->Utils.magic)
|
package/src/Ecosystem.res.mjs
CHANGED
package/src/Envio.gen.ts
CHANGED
|
@@ -15,7 +15,7 @@ export type blockEvent = { readonly number: number };
|
|
|
15
15
|
|
|
16
16
|
export type fuelBlockEvent = { readonly height: number };
|
|
17
17
|
|
|
18
|
-
export type
|
|
18
|
+
export type svmOnBlockArgs<context> = { readonly slot: number; readonly context: context };
|
|
19
19
|
|
|
20
20
|
export type onBlockArgs<block,context> = { readonly block: block; readonly context: context };
|
|
21
21
|
|
package/src/Envio.res
CHANGED
|
@@ -9,7 +9,7 @@ type blockEvent = {number: int}
|
|
|
9
9
|
type fuelBlockEvent = {height: int}
|
|
10
10
|
|
|
11
11
|
@genType
|
|
12
|
-
type
|
|
12
|
+
type svmOnBlockArgs<'context> = {slot: int, context: 'context}
|
|
13
13
|
|
|
14
14
|
@genType
|
|
15
15
|
type onBlockArgs<'block, 'context> = {
|