envio 3.0.0-alpha.2 → 3.0.0-alpha.20
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 +164 -30
- package/bin.mjs +49 -0
- package/evm.schema.json +79 -169
- package/fuel.schema.json +50 -21
- package/index.d.ts +497 -1
- package/index.js +4 -0
- package/package.json +42 -31
- package/rescript.json +4 -1
- package/src/Batch.res +11 -8
- package/src/Batch.res.mjs +11 -9
- package/src/ChainFetcher.res +531 -0
- package/src/ChainFetcher.res.mjs +339 -0
- package/src/ChainManager.res +190 -0
- package/src/ChainManager.res.mjs +166 -0
- package/src/Change.res +3 -3
- package/src/Config.gen.ts +19 -0
- package/src/Config.res +737 -22
- package/src/Config.res.mjs +703 -26
- package/src/{Indexer.res → Ctx.res} +1 -1
- package/src/Ecosystem.res +9 -124
- package/src/Ecosystem.res.mjs +19 -160
- package/src/Env.res +30 -74
- package/src/Env.res.mjs +25 -87
- package/src/Envio.gen.ts +3 -1
- package/src/Envio.res +20 -9
- package/src/EventProcessing.res +469 -0
- package/src/EventProcessing.res.mjs +337 -0
- package/src/EvmTypes.gen.ts +6 -0
- package/src/EvmTypes.res +1 -0
- package/src/FetchState.res +1256 -639
- package/src/FetchState.res.mjs +1135 -612
- package/src/GlobalState.res +1190 -0
- package/src/GlobalState.res.mjs +1183 -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/HandlerRegister.res +357 -0
- package/src/HandlerRegister.res.mjs +299 -0
- package/src/{EventRegister.resi → HandlerRegister.resi} +13 -13
- package/src/Hasura.res +111 -175
- package/src/Hasura.res.mjs +88 -150
- package/src/InMemoryStore.res +1 -1
- package/src/InMemoryStore.res.mjs +3 -3
- package/src/InMemoryTable.res +1 -1
- package/src/InMemoryTable.res.mjs +1 -1
- package/src/Internal.gen.ts +4 -0
- package/src/Internal.res +230 -12
- package/src/Internal.res.mjs +115 -1
- 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 +21 -7
- package/src/Logging.res.mjs +16 -8
- package/src/Main.res +377 -0
- package/src/Main.res.mjs +339 -0
- package/src/Persistence.res +7 -21
- package/src/Persistence.res.mjs +3 -3
- package/src/PgStorage.gen.ts +10 -0
- package/src/PgStorage.res +116 -69
- package/src/PgStorage.res.d.mts +5 -0
- package/src/PgStorage.res.mjs +93 -50
- package/src/Prometheus.res +294 -224
- package/src/Prometheus.res.mjs +353 -340
- package/src/ReorgDetection.res +6 -10
- package/src/ReorgDetection.res.mjs +6 -6
- package/src/SafeCheckpointTracking.res +4 -4
- package/src/SafeCheckpointTracking.res.mjs +2 -2
- package/src/Sink.res +4 -2
- package/src/Sink.res.mjs +2 -1
- package/src/TableIndices.res +0 -1
- package/src/TestIndexer.res +692 -0
- package/src/TestIndexer.res.mjs +527 -0
- package/src/TestIndexerProxyStorage.res +205 -0
- package/src/TestIndexerProxyStorage.res.mjs +151 -0
- package/src/TopicFilter.res +1 -1
- package/src/Types.ts +1 -1
- package/src/UserContext.res +424 -0
- package/src/UserContext.res.mjs +279 -0
- package/src/Utils.res +97 -26
- package/src/Utils.res.mjs +91 -44
- package/src/bindings/BigInt.res +10 -0
- package/src/bindings/BigInt.res.mjs +15 -0
- package/src/bindings/ClickHouse.res +120 -23
- package/src/bindings/ClickHouse.res.mjs +118 -28
- package/src/bindings/DateFns.res +74 -0
- package/src/bindings/DateFns.res.mjs +22 -0
- package/src/bindings/EventSource.res +8 -1
- package/src/bindings/EventSource.res.mjs +8 -1
- package/src/bindings/Express.res +1 -0
- package/src/bindings/Hrtime.res +14 -1
- package/src/bindings/Hrtime.res.mjs +22 -2
- package/src/bindings/Hrtime.resi +4 -0
- package/src/bindings/Lodash.res +0 -1
- package/src/bindings/NodeJs.res +49 -3
- package/src/bindings/NodeJs.res.mjs +11 -3
- package/src/bindings/Pino.res +24 -10
- package/src/bindings/Pino.res.mjs +14 -8
- package/src/bindings/Postgres.gen.ts +8 -0
- package/src/bindings/Postgres.res +5 -1
- package/src/bindings/Postgres.res.d.mts +5 -0
- package/src/bindings/PromClient.res +0 -10
- package/src/bindings/PromClient.res.mjs +0 -3
- package/src/bindings/Vitest.res +142 -0
- package/src/bindings/Vitest.res.mjs +9 -0
- package/src/bindings/WebSocket.res +27 -0
- package/src/bindings/WebSocket.res.mjs +2 -0
- package/src/bindings/Yargs.res +8 -0
- package/src/bindings/Yargs.res.mjs +2 -0
- package/src/db/EntityHistory.res +7 -7
- package/src/db/EntityHistory.res.mjs +9 -9
- package/src/db/InternalTable.res +59 -111
- package/src/db/InternalTable.res.mjs +73 -104
- package/src/db/Table.res +27 -8
- package/src/db/Table.res.mjs +25 -14
- package/src/sources/Evm.res +84 -0
- package/src/sources/Evm.res.mjs +105 -0
- package/src/sources/EvmChain.res +94 -0
- package/src/sources/EvmChain.res.mjs +60 -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 +33 -13
- package/src/sources/HyperFuelSource.res.mjs +24 -16
- package/src/sources/HyperSync.res +36 -6
- package/src/sources/HyperSync.res.mjs +9 -7
- package/src/sources/HyperSync.resi +4 -0
- package/src/sources/HyperSyncClient.res +1 -1
- package/src/sources/HyperSyncHeightStream.res +47 -116
- package/src/sources/HyperSyncHeightStream.res.mjs +46 -73
- package/src/sources/HyperSyncSource.res +118 -139
- package/src/sources/HyperSyncSource.res.mjs +104 -121
- package/src/sources/Rpc.res +86 -14
- package/src/sources/Rpc.res.mjs +101 -9
- package/src/sources/RpcSource.res +621 -364
- package/src/sources/RpcSource.res.mjs +843 -410
- package/src/sources/RpcWebSocketHeightStream.res +181 -0
- package/src/sources/RpcWebSocketHeightStream.res.mjs +196 -0
- package/src/sources/Source.res +7 -5
- package/src/sources/SourceManager.res +325 -225
- package/src/sources/SourceManager.res.mjs +314 -171
- package/src/sources/SourceManager.resi +17 -6
- package/src/sources/Svm.res +81 -0
- package/src/sources/Svm.res.mjs +90 -0
- package/src/tui/Tui.res +247 -0
- package/src/tui/Tui.res.mjs +337 -0
- package/src/tui/bindings/Ink.res +371 -0
- package/src/tui/bindings/Ink.res.mjs +72 -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 +174 -0
- package/src/tui/components/SyncETA.res.mjs +263 -0
- package/src/tui/components/TuiData.res +47 -0
- package/src/tui/components/TuiData.res.mjs +34 -0
- package/svm.schema.json +112 -0
- package/bin.js +0 -48
- package/src/EventRegister.res +0 -241
- package/src/EventRegister.res.mjs +0 -240
- package/src/bindings/Ethers.gen.ts +0 -14
- package/src/bindings/Ethers.res +0 -204
- package/src/bindings/Ethers.res.mjs +0 -130
- /package/src/{Indexer.res.mjs → Ctx.res.mjs} +0 -0
package/src/Main.res
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
open Belt
|
|
2
|
+
|
|
3
|
+
type chainData = {
|
|
4
|
+
chainId: float,
|
|
5
|
+
poweredByHyperSync: bool,
|
|
6
|
+
firstEventBlockNumber: option<int>,
|
|
7
|
+
latestProcessedBlock: option<int>,
|
|
8
|
+
timestampCaughtUpToHeadOrEndblock: option<Js.Date.t>,
|
|
9
|
+
numEventsProcessed: float,
|
|
10
|
+
latestFetchedBlockNumber: int,
|
|
11
|
+
// Need this for API backwards compatibility
|
|
12
|
+
@as("currentBlockHeight")
|
|
13
|
+
knownHeight: int,
|
|
14
|
+
numBatchesFetched: int,
|
|
15
|
+
startBlock: int,
|
|
16
|
+
endBlock: option<int>,
|
|
17
|
+
numAddresses: int,
|
|
18
|
+
}
|
|
19
|
+
@tag("status")
|
|
20
|
+
type state =
|
|
21
|
+
| @as("disabled") Disabled({})
|
|
22
|
+
| @as("initializing") Initializing({})
|
|
23
|
+
| @as("active")
|
|
24
|
+
Active({
|
|
25
|
+
envioVersion: string,
|
|
26
|
+
chains: array<chainData>,
|
|
27
|
+
indexerStartTime: Js.Date.t,
|
|
28
|
+
isPreRegisteringDynamicContracts: bool,
|
|
29
|
+
isUnorderedMultichainMode: bool,
|
|
30
|
+
rollbackOnReorg: bool,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
let chainDataSchema = S.schema((s): chainData => {
|
|
34
|
+
chainId: s.matches(S.float),
|
|
35
|
+
poweredByHyperSync: s.matches(S.bool),
|
|
36
|
+
firstEventBlockNumber: s.matches(S.option(S.int)),
|
|
37
|
+
latestProcessedBlock: s.matches(S.option(S.int)),
|
|
38
|
+
timestampCaughtUpToHeadOrEndblock: s.matches(S.option(S.datetime(S.string))),
|
|
39
|
+
numEventsProcessed: s.matches(S.float),
|
|
40
|
+
latestFetchedBlockNumber: s.matches(S.int),
|
|
41
|
+
knownHeight: s.matches(S.int),
|
|
42
|
+
numBatchesFetched: s.matches(S.int),
|
|
43
|
+
startBlock: s.matches(S.int),
|
|
44
|
+
endBlock: s.matches(S.option(S.int)),
|
|
45
|
+
numAddresses: s.matches(S.int),
|
|
46
|
+
})
|
|
47
|
+
let stateSchema = S.union([
|
|
48
|
+
S.literal(Disabled({})),
|
|
49
|
+
S.literal(Initializing({})),
|
|
50
|
+
S.schema(s => Active({
|
|
51
|
+
envioVersion: s.matches(S.string),
|
|
52
|
+
chains: s.matches(S.array(chainDataSchema)),
|
|
53
|
+
indexerStartTime: s.matches(S.datetime(S.string)),
|
|
54
|
+
// Keep the field, since Dev Console expects it to be present
|
|
55
|
+
isPreRegisteringDynamicContracts: false,
|
|
56
|
+
isUnorderedMultichainMode: s.matches(S.bool),
|
|
57
|
+
rollbackOnReorg: s.matches(S.bool),
|
|
58
|
+
})),
|
|
59
|
+
])
|
|
60
|
+
|
|
61
|
+
let globalGsManagerRef: ref<option<GlobalStateManager.t>> = ref(None)
|
|
62
|
+
|
|
63
|
+
let getGlobalIndexer = (~config: Config.t): 'indexer => {
|
|
64
|
+
let indexer = Utils.Object.createNullObject()
|
|
65
|
+
|
|
66
|
+
indexer
|
|
67
|
+
->Utils.Object.definePropertyWithValue("name", {enumerable: true, value: config.name})
|
|
68
|
+
->Utils.Object.definePropertyWithValue(
|
|
69
|
+
"description",
|
|
70
|
+
{enumerable: true, value: config.description},
|
|
71
|
+
)
|
|
72
|
+
->ignore
|
|
73
|
+
|
|
74
|
+
let chainIds = []
|
|
75
|
+
|
|
76
|
+
// Build chains object with chain ID as string key
|
|
77
|
+
let chains = Utils.Object.createNullObject()
|
|
78
|
+
config.chainMap
|
|
79
|
+
->ChainMap.values
|
|
80
|
+
->Array.forEach(chainConfig => {
|
|
81
|
+
let chainIdStr = chainConfig.id->Int.toString
|
|
82
|
+
|
|
83
|
+
chainIds->Js.Array2.push(chainConfig.id)->ignore
|
|
84
|
+
|
|
85
|
+
let chainObj = Utils.Object.createNullObject()
|
|
86
|
+
chainObj
|
|
87
|
+
->Utils.Object.definePropertyWithValue("id", {enumerable: true, value: chainConfig.id})
|
|
88
|
+
->Utils.Object.definePropertyWithValue(
|
|
89
|
+
"startBlock",
|
|
90
|
+
{enumerable: true, value: chainConfig.startBlock},
|
|
91
|
+
)
|
|
92
|
+
->Utils.Object.definePropertyWithValue(
|
|
93
|
+
"endBlock",
|
|
94
|
+
{enumerable: true, value: chainConfig.endBlock},
|
|
95
|
+
)
|
|
96
|
+
->Utils.Object.definePropertyWithValue("name", {enumerable: true, value: chainConfig.name})
|
|
97
|
+
->Utils.Object.defineProperty(
|
|
98
|
+
"isLive",
|
|
99
|
+
{
|
|
100
|
+
enumerable: true,
|
|
101
|
+
get: () => {
|
|
102
|
+
switch globalGsManagerRef.contents {
|
|
103
|
+
| None => false
|
|
104
|
+
| Some(gsManager) =>
|
|
105
|
+
let state = gsManager->GlobalStateManager.getState
|
|
106
|
+
let chain = ChainMap.Chain.makeUnsafe(~chainId=chainConfig.id)
|
|
107
|
+
let chainFetcher = state.chainManager.chainFetchers->ChainMap.get(chain)
|
|
108
|
+
chainFetcher->ChainFetcher.isReady
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
)
|
|
113
|
+
->ignore
|
|
114
|
+
|
|
115
|
+
// Add contracts to chain object
|
|
116
|
+
chainConfig.contracts->Array.forEach(contract => {
|
|
117
|
+
let contractObj = Utils.Object.createNullObject()
|
|
118
|
+
contractObj
|
|
119
|
+
->Utils.Object.definePropertyWithValue("name", {enumerable: true, value: contract.name})
|
|
120
|
+
->Utils.Object.definePropertyWithValue("abi", {enumerable: true, value: contract.abi})
|
|
121
|
+
->Utils.Object.defineProperty(
|
|
122
|
+
"addresses",
|
|
123
|
+
{
|
|
124
|
+
enumerable: true,
|
|
125
|
+
get: () => {
|
|
126
|
+
switch globalGsManagerRef.contents {
|
|
127
|
+
| None => contract.addresses
|
|
128
|
+
| Some(gsManager) => {
|
|
129
|
+
let state = gsManager->GlobalStateManager.getState
|
|
130
|
+
let chain = ChainMap.Chain.makeUnsafe(~chainId=chainConfig.id)
|
|
131
|
+
let chainFetcher = state.chainManager.chainFetchers->ChainMap.get(chain)
|
|
132
|
+
let indexingContracts = chainFetcher.fetchState.indexingContracts
|
|
133
|
+
|
|
134
|
+
// Collect all addresses for this contract name from indexingContracts
|
|
135
|
+
let addresses = []
|
|
136
|
+
let values = indexingContracts->Js.Dict.values
|
|
137
|
+
for idx in 0 to values->Array.length - 1 {
|
|
138
|
+
let indexingContract = values->Js.Array2.unsafe_get(idx)
|
|
139
|
+
if indexingContract.contractName === contract.name {
|
|
140
|
+
addresses->Array.push(indexingContract.address)->ignore
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
addresses
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
)
|
|
149
|
+
->ignore
|
|
150
|
+
|
|
151
|
+
chainObj
|
|
152
|
+
->Utils.Object.definePropertyWithValue(contract.name, {enumerable: true, value: contractObj})
|
|
153
|
+
->ignore
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
// Primary key is chain ID as string
|
|
157
|
+
chains
|
|
158
|
+
->Utils.Object.definePropertyWithValue(chainIdStr, {enumerable: true, value: chainObj})
|
|
159
|
+
->ignore
|
|
160
|
+
|
|
161
|
+
// If chain has a name different from ID, add non-enumerable alias
|
|
162
|
+
if chainConfig.name !== chainIdStr {
|
|
163
|
+
chains
|
|
164
|
+
->Utils.Object.definePropertyWithValue(chainConfig.name, {enumerable: false, value: chainObj})
|
|
165
|
+
->ignore
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
indexer
|
|
169
|
+
->Utils.Object.definePropertyWithValue("chainIds", {enumerable: true, value: chainIds})
|
|
170
|
+
->ignore
|
|
171
|
+
indexer->Utils.Object.definePropertyWithValue("chains", {enumerable: true, value: chains})->ignore
|
|
172
|
+
|
|
173
|
+
indexer->(Utils.magic: 'a => 'indexer)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let startServer = (~getState, ~ctx: Ctx.t, ~isDevelopmentMode: bool) => {
|
|
177
|
+
open Express
|
|
178
|
+
|
|
179
|
+
let app = make()
|
|
180
|
+
|
|
181
|
+
let consoleCorsMiddleware = (req, res, next) => {
|
|
182
|
+
switch req.headers->Js.Dict.get("origin") {
|
|
183
|
+
| Some(origin) if origin === Env.prodEnvioAppUrl || origin === Env.envioAppUrl =>
|
|
184
|
+
res->setHeader("Access-Control-Allow-Origin", origin)
|
|
185
|
+
| _ => ()
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
res->setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
|
189
|
+
res->setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
|
|
190
|
+
|
|
191
|
+
if req.method === Rest.Options {
|
|
192
|
+
res->sendStatus(200)
|
|
193
|
+
} else {
|
|
194
|
+
next()
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
app->useFor("/console", consoleCorsMiddleware)
|
|
198
|
+
app->useFor("/metrics", consoleCorsMiddleware)
|
|
199
|
+
app->useFor("/metrics/runtime", consoleCorsMiddleware)
|
|
200
|
+
|
|
201
|
+
app->get("/healthz", (_req, res) => {
|
|
202
|
+
// this is the machine readable port used in kubernetes to check the health of this service.
|
|
203
|
+
// aditional health information could be added in the future (info about errors, back-offs, etc).
|
|
204
|
+
res->sendStatus(200)
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
app->get("/console/state", (_req, res) => {
|
|
208
|
+
let state = if isDevelopmentMode {
|
|
209
|
+
getState()
|
|
210
|
+
} else {
|
|
211
|
+
Disabled({})
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
res->json(state->S.reverseConvertToJsonOrThrow(stateSchema))
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
app->post("/console/syncCache", (_req, res) => {
|
|
218
|
+
if isDevelopmentMode {
|
|
219
|
+
(ctx.persistence->Persistence.getInitializedStorageOrThrow).dumpEffectCache()
|
|
220
|
+
->Promise.thenResolve(_ => res->json(Boolean(true)))
|
|
221
|
+
->Promise.done
|
|
222
|
+
} else {
|
|
223
|
+
res->json(Boolean(false))
|
|
224
|
+
}
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
let runtimeRegistry = PromClient.makeRegistry()
|
|
228
|
+
PromClient.collectDefaultMetrics({"register": runtimeRegistry})
|
|
229
|
+
|
|
230
|
+
app->get("/metrics", (_req, res) => {
|
|
231
|
+
res->set("Content-Type", PromClient.defaultRegister->PromClient.getContentType)
|
|
232
|
+
let _ =
|
|
233
|
+
PromClient.defaultRegister
|
|
234
|
+
->PromClient.metrics
|
|
235
|
+
->Promise.thenResolve(metrics => res->endWithData(metrics))
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
app->get("/metrics/runtime", (_req, res) => {
|
|
239
|
+
res->set("Content-Type", runtimeRegistry->PromClient.getContentType)
|
|
240
|
+
let _ =
|
|
241
|
+
runtimeRegistry
|
|
242
|
+
->PromClient.metrics
|
|
243
|
+
->Promise.thenResolve(metrics => res->endWithData(metrics))
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
let server = app->listen(Env.serverPort)
|
|
247
|
+
server->Express.onError(err => {
|
|
248
|
+
let code = (err->(Utils.magic: Js.Exn.t => {..}))["code"]
|
|
249
|
+
if code === "EADDRINUSE" {
|
|
250
|
+
Logging.error(
|
|
251
|
+
`Port ${Env.serverPort->Int.toString} is already in use. To fix this either:` ++
|
|
252
|
+
`\n 1. Kill the process using the port: lsof -ti :${Env.serverPort->Int.toString} | xargs kill -9` ++ `\n 2. Use a different port by setting the ENVIO_INDEXER_PORT environment variable: ENVIO_INDEXER_PORT=9899 envio start`,
|
|
253
|
+
)
|
|
254
|
+
} else {
|
|
255
|
+
Logging.errorWithExn(err, "Failed to start indexer server")
|
|
256
|
+
}
|
|
257
|
+
NodeJs.process->NodeJs.exitWithCode(Failure)
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
type args = {@as("tui-off") tuiOff?: bool}
|
|
262
|
+
|
|
263
|
+
type process
|
|
264
|
+
@val external process: process = "process"
|
|
265
|
+
@get external argv: process => 'a = "argv"
|
|
266
|
+
|
|
267
|
+
type mainArgs = Yargs.parsedArgs<args>
|
|
268
|
+
|
|
269
|
+
let start = async (
|
|
270
|
+
~makeGeneratedConfig: unit => Config.t,
|
|
271
|
+
~persistence: Persistence.t,
|
|
272
|
+
~isTest=false,
|
|
273
|
+
) => {
|
|
274
|
+
let mainArgs: mainArgs = process->argv->Yargs.hideBin->Yargs.yargs->Yargs.argv
|
|
275
|
+
let shouldUseTui = !isTest && !(mainArgs.tuiOff->Belt.Option.getWithDefault(Env.tuiOffEnvVar))
|
|
276
|
+
// The most simple check to verify whether we are running in development mode
|
|
277
|
+
// and prevent exposing the console to public, when creating a real deployment.
|
|
278
|
+
// Note: isTest overrides isDevelopmentMode to ensure proper process exit in test mode.
|
|
279
|
+
let isDevelopmentMode = !isTest && Env.Db.password === "testing"
|
|
280
|
+
|
|
281
|
+
// Register all handlers first, then get the config with registrations
|
|
282
|
+
let configWithoutRegistrations = makeGeneratedConfig()
|
|
283
|
+
let registrations = await HandlerLoader.registerAllHandlers(~config=configWithoutRegistrations)
|
|
284
|
+
let config = makeGeneratedConfig()
|
|
285
|
+
let config = if isTest {
|
|
286
|
+
{...config, shouldRollbackOnReorg: false}
|
|
287
|
+
} else {
|
|
288
|
+
config
|
|
289
|
+
}
|
|
290
|
+
let ctx = {
|
|
291
|
+
Ctx.registrations,
|
|
292
|
+
config,
|
|
293
|
+
persistence,
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
let envioVersion = Utils.EnvioPackage.value.version
|
|
297
|
+
Prometheus.Info.set(~version=envioVersion)
|
|
298
|
+
Prometheus.ProcessStartTimeSeconds.set()
|
|
299
|
+
Prometheus.RollbackEnabled.set(~enabled=ctx.config.shouldRollbackOnReorg)
|
|
300
|
+
|
|
301
|
+
if !isTest {
|
|
302
|
+
startServer(~ctx, ~isDevelopmentMode, ~getState=() =>
|
|
303
|
+
switch globalGsManagerRef.contents {
|
|
304
|
+
| None => Initializing({})
|
|
305
|
+
| Some(gsManager) => {
|
|
306
|
+
let state = gsManager->GlobalStateManager.getState
|
|
307
|
+
let chains =
|
|
308
|
+
state.chainManager.chainFetchers
|
|
309
|
+
->ChainMap.values
|
|
310
|
+
->Array.map(cf => {
|
|
311
|
+
let {fetchState} = cf
|
|
312
|
+
let latestFetchedBlockNumber = Pervasives.max(
|
|
313
|
+
FetchState.bufferBlockNumber(fetchState),
|
|
314
|
+
0,
|
|
315
|
+
)
|
|
316
|
+
let knownHeight =
|
|
317
|
+
cf->ChainFetcher.hasProcessedToEndblock
|
|
318
|
+
? cf.fetchState.endBlock->Option.getWithDefault(cf.fetchState.knownHeight)
|
|
319
|
+
: cf.fetchState.knownHeight
|
|
320
|
+
|
|
321
|
+
{
|
|
322
|
+
chainId: cf.chainConfig.id->Js.Int.toFloat,
|
|
323
|
+
poweredByHyperSync: (
|
|
324
|
+
cf.sourceManager->SourceManager.getActiveSource
|
|
325
|
+
).poweredByHyperSync,
|
|
326
|
+
latestFetchedBlockNumber,
|
|
327
|
+
knownHeight,
|
|
328
|
+
numBatchesFetched: 0,
|
|
329
|
+
startBlock: cf.fetchState.startBlock,
|
|
330
|
+
endBlock: cf.fetchState.endBlock,
|
|
331
|
+
firstEventBlockNumber: cf.fetchState.firstEventBlock,
|
|
332
|
+
latestProcessedBlock: cf.committedProgressBlockNumber === -1
|
|
333
|
+
? None
|
|
334
|
+
: Some(cf.committedProgressBlockNumber),
|
|
335
|
+
timestampCaughtUpToHeadOrEndblock: cf.timestampCaughtUpToHeadOrEndblock,
|
|
336
|
+
numEventsProcessed: cf.numEventsProcessed,
|
|
337
|
+
numAddresses: cf.fetchState->FetchState.numAddresses,
|
|
338
|
+
}
|
|
339
|
+
})
|
|
340
|
+
Active({
|
|
341
|
+
envioVersion,
|
|
342
|
+
chains,
|
|
343
|
+
indexerStartTime: state.indexerStartTime,
|
|
344
|
+
isPreRegisteringDynamicContracts: false,
|
|
345
|
+
rollbackOnReorg: ctx.config.shouldRollbackOnReorg,
|
|
346
|
+
isUnorderedMultichainMode: switch ctx.config.multichain {
|
|
347
|
+
| Unordered => true
|
|
348
|
+
| Ordered => false
|
|
349
|
+
},
|
|
350
|
+
})
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
await ctx.persistence->Persistence.init(~chainConfigs=ctx.config.chainMap->ChainMap.values)
|
|
357
|
+
|
|
358
|
+
let chainManager = await ChainManager.makeFromDbState(
|
|
359
|
+
~initialState=ctx.persistence->Persistence.getInitializedState,
|
|
360
|
+
~config=ctx.config,
|
|
361
|
+
~registrations=ctx.registrations,
|
|
362
|
+
)
|
|
363
|
+
let globalState = GlobalState.make(~ctx, ~chainManager, ~isDevelopmentMode, ~shouldUseTui)
|
|
364
|
+
let gsManager = globalState->GlobalStateManager.make
|
|
365
|
+
if shouldUseTui {
|
|
366
|
+
let _rerender = Tui.start(~getState=() => gsManager->GlobalStateManager.getState)
|
|
367
|
+
}
|
|
368
|
+
globalGsManagerRef := Some(gsManager)
|
|
369
|
+
gsManager->GlobalStateManager.dispatchTask(NextQuery(CheckAllChains))
|
|
370
|
+
/*
|
|
371
|
+
NOTE:
|
|
372
|
+
This `ProcessEventBatch` dispatch shouldn't be necessary but we are adding for safety, it should immediately return doing
|
|
373
|
+
nothing since there is no events on the queues.
|
|
374
|
+
*/
|
|
375
|
+
|
|
376
|
+
gsManager->GlobalStateManager.dispatchTask(ProcessEventBatch)
|
|
377
|
+
}
|