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/tui/Tui.res
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
open Ink
|
|
2
|
+
open Belt
|
|
3
|
+
|
|
4
|
+
module ChainLine = {
|
|
5
|
+
@react.component
|
|
6
|
+
let make = (
|
|
7
|
+
~chainId,
|
|
8
|
+
~maxChainIdLength,
|
|
9
|
+
~stdoutColumns: int,
|
|
10
|
+
~progressBlock,
|
|
11
|
+
~bufferBlock,
|
|
12
|
+
~sourceBlock,
|
|
13
|
+
~firstEventBlock,
|
|
14
|
+
~startBlock,
|
|
15
|
+
~endBlock,
|
|
16
|
+
~poweredByHyperSync,
|
|
17
|
+
~eventsProcessed,
|
|
18
|
+
) => {
|
|
19
|
+
let chainsWidth = Pervasives.min(stdoutColumns - 2, 60)
|
|
20
|
+
let headerWidth = maxChainIdLength + 10 // 10 for additional text
|
|
21
|
+
|
|
22
|
+
switch (progressBlock, bufferBlock, sourceBlock) {
|
|
23
|
+
| (Some(progressBlock), Some(bufferBlock), Some(sourceBlock)) =>
|
|
24
|
+
let toBlock = switch endBlock {
|
|
25
|
+
| Some(endBlock) => Pervasives.min(sourceBlock, endBlock)
|
|
26
|
+
| None => sourceBlock
|
|
27
|
+
}
|
|
28
|
+
let firstEventBlock = firstEventBlock->Option.getWithDefault(startBlock)
|
|
29
|
+
|
|
30
|
+
let progressBlockStr = progressBlock->TuiData.formatLocaleString
|
|
31
|
+
let toBlockStr = toBlock->TuiData.formatLocaleString
|
|
32
|
+
let eventsStr = eventsProcessed->TuiData.formatLocaleString
|
|
33
|
+
|
|
34
|
+
let blocksText =
|
|
35
|
+
`Blocks: ${progressBlockStr} / ${toBlockStr}` ++
|
|
36
|
+
(endBlock->Option.isSome ? " (End Block)" : "") ++ ` `
|
|
37
|
+
let eventsText = `Events: ${eventsStr}`
|
|
38
|
+
|
|
39
|
+
let fitsSameLine = blocksText->String.length + eventsText->String.length <= chainsWidth
|
|
40
|
+
|
|
41
|
+
<Box flexDirection={Column}>
|
|
42
|
+
<Box flexDirection=Row width=Num(chainsWidth)>
|
|
43
|
+
<Box width={Num(headerWidth)}>
|
|
44
|
+
<Text> {"Chain: "->React.string} </Text>
|
|
45
|
+
<Text bold=true> {chainId->React.string} </Text>
|
|
46
|
+
<Text> {" "->React.string} </Text>
|
|
47
|
+
{poweredByHyperSync ? <Text color=Secondary> {"⚡"->React.string} </Text> : React.null}
|
|
48
|
+
</Box>
|
|
49
|
+
<BufferedProgressBar
|
|
50
|
+
barWidth={chainsWidth - headerWidth}
|
|
51
|
+
loaded={progressBlock - firstEventBlock}
|
|
52
|
+
buffered={bufferBlock - firstEventBlock}
|
|
53
|
+
outOf={toBlock - firstEventBlock}
|
|
54
|
+
loadingColor={Secondary}
|
|
55
|
+
/>
|
|
56
|
+
</Box>
|
|
57
|
+
<Box flexDirection={Row}>
|
|
58
|
+
<Text color={Gray}> {blocksText->React.string} </Text>
|
|
59
|
+
{fitsSameLine ? <Text color={Gray}> {eventsText->React.string} </Text> : React.null}
|
|
60
|
+
</Box>
|
|
61
|
+
{fitsSameLine
|
|
62
|
+
? React.null
|
|
63
|
+
: <Box flexDirection={Row}>
|
|
64
|
+
<Text color={Gray}> {eventsText->String.trim->React.string} </Text>
|
|
65
|
+
</Box>}
|
|
66
|
+
<Newline />
|
|
67
|
+
</Box>
|
|
68
|
+
| (_, _, _) =>
|
|
69
|
+
<>
|
|
70
|
+
<Box flexDirection=Row width=Num(chainsWidth)>
|
|
71
|
+
<Box width={Num(headerWidth)}>
|
|
72
|
+
<Text> {"Chain: "->React.string} </Text>
|
|
73
|
+
<Text bold=true> {chainId->React.string} </Text>
|
|
74
|
+
<Text> {" "->React.string} </Text>
|
|
75
|
+
{poweredByHyperSync ? <Text color=Secondary> {"⚡"->React.string} </Text> : React.null}
|
|
76
|
+
</Box>
|
|
77
|
+
<Text> {"Loading progress..."->React.string} </Text>
|
|
78
|
+
</Box>
|
|
79
|
+
<Newline />
|
|
80
|
+
</>
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module TotalEventsProcessed = {
|
|
86
|
+
@react.component
|
|
87
|
+
let make = (~totalEventsProcessed) => {
|
|
88
|
+
let label = "Total Events: "
|
|
89
|
+
<Text>
|
|
90
|
+
<Text bold=true> {label->React.string} </Text>
|
|
91
|
+
<Text color={Secondary}>
|
|
92
|
+
{`${totalEventsProcessed->TuiData.formatLocaleString}`->React.string}
|
|
93
|
+
</Text>
|
|
94
|
+
</Text>
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
module App = {
|
|
99
|
+
@react.component
|
|
100
|
+
let make = (~getState) => {
|
|
101
|
+
let stdoutColumns = Hooks.useStdoutColumns()
|
|
102
|
+
let (state: GlobalState.t, setState) = React.useState(() => getState())
|
|
103
|
+
|
|
104
|
+
// useEffect to refresh state every 500ms
|
|
105
|
+
React.useEffect(() => {
|
|
106
|
+
let intervalId = Js.Global.setInterval(() => {
|
|
107
|
+
setState(_ => getState())
|
|
108
|
+
}, 500)
|
|
109
|
+
|
|
110
|
+
Some(
|
|
111
|
+
() => {
|
|
112
|
+
Js.Global.clearInterval(intervalId)
|
|
113
|
+
},
|
|
114
|
+
)
|
|
115
|
+
}, [getState])
|
|
116
|
+
|
|
117
|
+
let chains =
|
|
118
|
+
state.chainManager.chainFetchers
|
|
119
|
+
->ChainMap.values
|
|
120
|
+
->Array.map(cf => {
|
|
121
|
+
let {numEventsProcessed, fetchState, numBatchesFetched} = cf
|
|
122
|
+
let latestFetchedBlockNumber = Pervasives.max(fetchState->FetchState.bufferBlockNumber, 0)
|
|
123
|
+
let hasProcessedToEndblock = cf->ChainFetcher.hasProcessedToEndblock
|
|
124
|
+
let knownHeight =
|
|
125
|
+
cf->ChainFetcher.hasProcessedToEndblock
|
|
126
|
+
? cf.fetchState.endBlock->Option.getWithDefault(cf.fetchState.knownHeight)
|
|
127
|
+
: cf.fetchState.knownHeight
|
|
128
|
+
|
|
129
|
+
let progress: TuiData.progress = if hasProcessedToEndblock {
|
|
130
|
+
// If the endblock has been reached then set the progress to synced.
|
|
131
|
+
// if there's chains that have no events in the block range start->end,
|
|
132
|
+
// it's possible there are no events in that block range (ie firstEventBlockNumber = None)
|
|
133
|
+
// This ensures TUI still displays synced in this case
|
|
134
|
+
let {
|
|
135
|
+
committedProgressBlockNumber,
|
|
136
|
+
timestampCaughtUpToHeadOrEndblock,
|
|
137
|
+
numEventsProcessed,
|
|
138
|
+
firstEventBlockNumber,
|
|
139
|
+
} = cf
|
|
140
|
+
|
|
141
|
+
Synced({
|
|
142
|
+
firstEventBlockNumber: firstEventBlockNumber->Option.getWithDefault(0),
|
|
143
|
+
latestProcessedBlock: committedProgressBlockNumber,
|
|
144
|
+
timestampCaughtUpToHeadOrEndblock: timestampCaughtUpToHeadOrEndblock->Option.getWithDefault(
|
|
145
|
+
Js.Date.now()->Js.Date.fromFloat,
|
|
146
|
+
),
|
|
147
|
+
numEventsProcessed,
|
|
148
|
+
})
|
|
149
|
+
} else {
|
|
150
|
+
switch cf {
|
|
151
|
+
| {
|
|
152
|
+
committedProgressBlockNumber,
|
|
153
|
+
timestampCaughtUpToHeadOrEndblock: Some(timestampCaughtUpToHeadOrEndblock),
|
|
154
|
+
firstEventBlockNumber: Some(firstEventBlockNumber),
|
|
155
|
+
} =>
|
|
156
|
+
Synced({
|
|
157
|
+
firstEventBlockNumber,
|
|
158
|
+
latestProcessedBlock: committedProgressBlockNumber,
|
|
159
|
+
timestampCaughtUpToHeadOrEndblock,
|
|
160
|
+
numEventsProcessed,
|
|
161
|
+
})
|
|
162
|
+
| {
|
|
163
|
+
committedProgressBlockNumber,
|
|
164
|
+
timestampCaughtUpToHeadOrEndblock: None,
|
|
165
|
+
firstEventBlockNumber: Some(firstEventBlockNumber),
|
|
166
|
+
} =>
|
|
167
|
+
Syncing({
|
|
168
|
+
firstEventBlockNumber,
|
|
169
|
+
latestProcessedBlock: committedProgressBlockNumber,
|
|
170
|
+
numEventsProcessed,
|
|
171
|
+
})
|
|
172
|
+
| {firstEventBlockNumber: None} => SearchingForEvents
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
(
|
|
177
|
+
{
|
|
178
|
+
progress,
|
|
179
|
+
knownHeight,
|
|
180
|
+
latestFetchedBlockNumber,
|
|
181
|
+
numBatchesFetched,
|
|
182
|
+
eventsProcessed: numEventsProcessed,
|
|
183
|
+
chainId: cf.chainConfig.id->Int.toString,
|
|
184
|
+
progressBlock: cf.committedProgressBlockNumber === -1
|
|
185
|
+
? None
|
|
186
|
+
: Some(cf.committedProgressBlockNumber),
|
|
187
|
+
bufferBlock: Some(latestFetchedBlockNumber),
|
|
188
|
+
sourceBlock: Some(cf.fetchState.knownHeight),
|
|
189
|
+
firstEventBlockNumber: cf.firstEventBlockNumber,
|
|
190
|
+
startBlock: cf.fetchState.startBlock,
|
|
191
|
+
endBlock: cf.fetchState.endBlock,
|
|
192
|
+
poweredByHyperSync: (
|
|
193
|
+
cf.sourceManager->SourceManager.getActiveSource
|
|
194
|
+
).poweredByHyperSync,
|
|
195
|
+
}: TuiData.chain
|
|
196
|
+
)
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
let totalEventsProcessed = chains->Array.reduce(0, (acc, chain) => {
|
|
200
|
+
acc + chain.eventsProcessed
|
|
201
|
+
})
|
|
202
|
+
let maxChainIdLength = chains->Array.reduce(0, (acc, chain) => {
|
|
203
|
+
let chainIdLength = chain.chainId->String.length
|
|
204
|
+
if chainIdLength > acc {
|
|
205
|
+
chainIdLength
|
|
206
|
+
} else {
|
|
207
|
+
acc
|
|
208
|
+
}
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
<Box flexDirection={Column}>
|
|
212
|
+
<BigText
|
|
213
|
+
text="envio"
|
|
214
|
+
colors=[Secondary, Primary]
|
|
215
|
+
font={chains->Array.length > 5 ? Tiny : Block}
|
|
216
|
+
space=false
|
|
217
|
+
/>
|
|
218
|
+
<Newline />
|
|
219
|
+
{chains
|
|
220
|
+
->Array.mapWithIndex((i, chainData) => {
|
|
221
|
+
<ChainLine
|
|
222
|
+
key={i->Int.toString}
|
|
223
|
+
chainId={chainData.chainId}
|
|
224
|
+
maxChainIdLength={maxChainIdLength}
|
|
225
|
+
progressBlock={chainData.progressBlock}
|
|
226
|
+
bufferBlock={chainData.bufferBlock}
|
|
227
|
+
sourceBlock={chainData.sourceBlock}
|
|
228
|
+
startBlock={chainData.startBlock}
|
|
229
|
+
endBlock={chainData.endBlock}
|
|
230
|
+
stdoutColumns={stdoutColumns}
|
|
231
|
+
firstEventBlock={chainData.firstEventBlockNumber}
|
|
232
|
+
poweredByHyperSync={chainData.poweredByHyperSync}
|
|
233
|
+
eventsProcessed={chainData.eventsProcessed}
|
|
234
|
+
/>
|
|
235
|
+
})
|
|
236
|
+
->React.array}
|
|
237
|
+
<TotalEventsProcessed totalEventsProcessed />
|
|
238
|
+
<SyncETA chains indexerStartTime=state.indexerStartTime />
|
|
239
|
+
<Newline />
|
|
240
|
+
<Box flexDirection={Row}>
|
|
241
|
+
<Text> {"GraphQL: "->React.string} </Text>
|
|
242
|
+
<Text color={Info} underline=true> {Env.Hasura.url->React.string} </Text>
|
|
243
|
+
{
|
|
244
|
+
let defaultPassword = "testing"
|
|
245
|
+
if Env.Hasura.secret == defaultPassword {
|
|
246
|
+
<Text color={Gray}> {` (password: ${defaultPassword})`->React.string} </Text>
|
|
247
|
+
} else {
|
|
248
|
+
React.null
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
</Box>
|
|
252
|
+
<Box flexDirection={Row}>
|
|
253
|
+
<Text> {"Dev Console: "->React.string} </Text>
|
|
254
|
+
<Text color={Info} underline=true> {`${Env.envioAppUrl}/console`->React.string} </Text>
|
|
255
|
+
</Box>
|
|
256
|
+
<Messages config=state.ctx.config />
|
|
257
|
+
</Box>
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
let start = (~getState) => {
|
|
262
|
+
let {rerender} = render(<App getState />)
|
|
263
|
+
() => {
|
|
264
|
+
rerender(<App getState />)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Env from "../Env.res.mjs";
|
|
4
|
+
import * as $$Ink from "./bindings/Ink.res.mjs";
|
|
5
|
+
import * as $$Ink$1 from "ink";
|
|
6
|
+
import * as Caml from "rescript/lib/es6/caml.js";
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import * as $$String from "rescript/lib/es6/string.js";
|
|
9
|
+
import * as SyncETA from "./components/SyncETA.res.mjs";
|
|
10
|
+
import * as TuiData from "./components/TuiData.res.mjs";
|
|
11
|
+
import * as ChainMap from "../ChainMap.res.mjs";
|
|
12
|
+
import * as Messages from "./components/Messages.res.mjs";
|
|
13
|
+
import * as Belt_Array from "rescript/lib/es6/belt_Array.js";
|
|
14
|
+
import * as FetchState from "../FetchState.res.mjs";
|
|
15
|
+
import * as Belt_Option from "rescript/lib/es6/belt_Option.js";
|
|
16
|
+
import * as Caml_option from "rescript/lib/es6/caml_option.js";
|
|
17
|
+
import * as ChainFetcher from "../ChainFetcher.res.mjs";
|
|
18
|
+
import InkBigText from "ink-big-text";
|
|
19
|
+
import * as SourceManager from "../sources/SourceManager.res.mjs";
|
|
20
|
+
import * as JsxRuntime from "react/jsx-runtime";
|
|
21
|
+
import * as BufferedProgressBar from "./components/BufferedProgressBar.res.mjs";
|
|
22
|
+
|
|
23
|
+
function Tui$ChainLine(props) {
|
|
24
|
+
var poweredByHyperSync = props.poweredByHyperSync;
|
|
25
|
+
var endBlock = props.endBlock;
|
|
26
|
+
var sourceBlock = props.sourceBlock;
|
|
27
|
+
var bufferBlock = props.bufferBlock;
|
|
28
|
+
var progressBlock = props.progressBlock;
|
|
29
|
+
var chainId = props.chainId;
|
|
30
|
+
var chainsWidth = Caml.int_min(props.stdoutColumns - 2 | 0, 60);
|
|
31
|
+
var headerWidth = props.maxChainIdLength + 10 | 0;
|
|
32
|
+
if (progressBlock !== undefined && bufferBlock !== undefined && sourceBlock !== undefined) {
|
|
33
|
+
var toBlock = endBlock !== undefined && sourceBlock >= endBlock ? endBlock : sourceBlock;
|
|
34
|
+
var firstEventBlock = Belt_Option.getWithDefault(props.firstEventBlock, props.startBlock);
|
|
35
|
+
var progressBlockStr = TuiData.formatLocaleString(progressBlock);
|
|
36
|
+
var toBlockStr = TuiData.formatLocaleString(toBlock);
|
|
37
|
+
var eventsStr = TuiData.formatLocaleString(props.eventsProcessed);
|
|
38
|
+
var blocksText = "Blocks: " + progressBlockStr + " / " + toBlockStr + (
|
|
39
|
+
Belt_Option.isSome(endBlock) ? " (End Block)" : ""
|
|
40
|
+
) + " ";
|
|
41
|
+
var eventsText = "Events: " + eventsStr;
|
|
42
|
+
var fitsSameLine = (blocksText.length + eventsText.length | 0) <= chainsWidth;
|
|
43
|
+
return JsxRuntime.jsxs($$Ink$1.Box, {
|
|
44
|
+
children: [
|
|
45
|
+
JsxRuntime.jsxs($$Ink$1.Box, {
|
|
46
|
+
children: [
|
|
47
|
+
JsxRuntime.jsxs($$Ink$1.Box, {
|
|
48
|
+
children: [
|
|
49
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
50
|
+
children: "Chain: "
|
|
51
|
+
}),
|
|
52
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
53
|
+
children: chainId,
|
|
54
|
+
bold: true
|
|
55
|
+
}),
|
|
56
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
57
|
+
children: " "
|
|
58
|
+
}),
|
|
59
|
+
poweredByHyperSync ? JsxRuntime.jsx($$Ink$1.Text, {
|
|
60
|
+
children: "⚡",
|
|
61
|
+
color: "#FFBB2F"
|
|
62
|
+
}) : null
|
|
63
|
+
],
|
|
64
|
+
width: headerWidth
|
|
65
|
+
}),
|
|
66
|
+
JsxRuntime.jsx(BufferedProgressBar.make, {
|
|
67
|
+
loaded: progressBlock - firstEventBlock | 0,
|
|
68
|
+
buffered: bufferBlock - firstEventBlock | 0,
|
|
69
|
+
outOf: toBlock - firstEventBlock | 0,
|
|
70
|
+
barWidth: chainsWidth - headerWidth | 0,
|
|
71
|
+
loadingColor: "#FFBB2F"
|
|
72
|
+
})
|
|
73
|
+
],
|
|
74
|
+
width: chainsWidth,
|
|
75
|
+
flexDirection: "row"
|
|
76
|
+
}),
|
|
77
|
+
JsxRuntime.jsxs($$Ink$1.Box, {
|
|
78
|
+
children: [
|
|
79
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
80
|
+
children: blocksText,
|
|
81
|
+
color: "gray"
|
|
82
|
+
}),
|
|
83
|
+
fitsSameLine ? JsxRuntime.jsx($$Ink$1.Text, {
|
|
84
|
+
children: eventsText,
|
|
85
|
+
color: "gray"
|
|
86
|
+
}) : null
|
|
87
|
+
],
|
|
88
|
+
flexDirection: "row"
|
|
89
|
+
}),
|
|
90
|
+
fitsSameLine ? null : JsxRuntime.jsx($$Ink$1.Box, {
|
|
91
|
+
children: Caml_option.some(JsxRuntime.jsx($$Ink$1.Text, {
|
|
92
|
+
children: $$String.trim(eventsText),
|
|
93
|
+
color: "gray"
|
|
94
|
+
})),
|
|
95
|
+
flexDirection: "row"
|
|
96
|
+
}),
|
|
97
|
+
JsxRuntime.jsx($$Ink.Newline.make, {})
|
|
98
|
+
],
|
|
99
|
+
flexDirection: "column"
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return JsxRuntime.jsxs(JsxRuntime.Fragment, {
|
|
103
|
+
children: [
|
|
104
|
+
JsxRuntime.jsxs($$Ink$1.Box, {
|
|
105
|
+
children: [
|
|
106
|
+
JsxRuntime.jsxs($$Ink$1.Box, {
|
|
107
|
+
children: [
|
|
108
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
109
|
+
children: "Chain: "
|
|
110
|
+
}),
|
|
111
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
112
|
+
children: chainId,
|
|
113
|
+
bold: true
|
|
114
|
+
}),
|
|
115
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
116
|
+
children: " "
|
|
117
|
+
}),
|
|
118
|
+
poweredByHyperSync ? JsxRuntime.jsx($$Ink$1.Text, {
|
|
119
|
+
children: "⚡",
|
|
120
|
+
color: "#FFBB2F"
|
|
121
|
+
}) : null
|
|
122
|
+
],
|
|
123
|
+
width: headerWidth
|
|
124
|
+
}),
|
|
125
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
126
|
+
children: "Loading progress..."
|
|
127
|
+
})
|
|
128
|
+
],
|
|
129
|
+
width: chainsWidth,
|
|
130
|
+
flexDirection: "row"
|
|
131
|
+
}),
|
|
132
|
+
JsxRuntime.jsx($$Ink.Newline.make, {})
|
|
133
|
+
]
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
var ChainLine = {
|
|
138
|
+
make: Tui$ChainLine
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
function Tui$TotalEventsProcessed(props) {
|
|
142
|
+
return JsxRuntime.jsxs($$Ink$1.Text, {
|
|
143
|
+
children: [
|
|
144
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
145
|
+
children: "Total Events: ",
|
|
146
|
+
bold: true
|
|
147
|
+
}),
|
|
148
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
149
|
+
children: TuiData.formatLocaleString(props.totalEventsProcessed),
|
|
150
|
+
color: "#FFBB2F"
|
|
151
|
+
})
|
|
152
|
+
]
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
var TotalEventsProcessed = {
|
|
157
|
+
make: Tui$TotalEventsProcessed
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
function Tui$App(props) {
|
|
161
|
+
var getState = props.getState;
|
|
162
|
+
var stdoutColumns = $$Ink.Hooks.useStdoutColumns();
|
|
163
|
+
var match = React.useState(function () {
|
|
164
|
+
return getState();
|
|
165
|
+
});
|
|
166
|
+
var setState = match[1];
|
|
167
|
+
var state = match[0];
|
|
168
|
+
React.useEffect((function () {
|
|
169
|
+
var intervalId = setInterval((function () {
|
|
170
|
+
setState(function (param) {
|
|
171
|
+
return getState();
|
|
172
|
+
});
|
|
173
|
+
}), 500);
|
|
174
|
+
return (function () {
|
|
175
|
+
clearInterval(intervalId);
|
|
176
|
+
});
|
|
177
|
+
}), [getState]);
|
|
178
|
+
var chains = Belt_Array.map(ChainMap.values(state.chainManager.chainFetchers), (function (cf) {
|
|
179
|
+
var numEventsProcessed = cf.numEventsProcessed;
|
|
180
|
+
var latestFetchedBlockNumber = Caml.int_max(FetchState.bufferBlockNumber(cf.fetchState), 0);
|
|
181
|
+
var hasProcessedToEndblock = ChainFetcher.hasProcessedToEndblock(cf);
|
|
182
|
+
var knownHeight = ChainFetcher.hasProcessedToEndblock(cf) ? Belt_Option.getWithDefault(cf.fetchState.endBlock, cf.fetchState.knownHeight) : cf.fetchState.knownHeight;
|
|
183
|
+
var progress;
|
|
184
|
+
if (hasProcessedToEndblock) {
|
|
185
|
+
progress = {
|
|
186
|
+
TAG: "Synced",
|
|
187
|
+
_0: {
|
|
188
|
+
firstEventBlockNumber: Belt_Option.getWithDefault(cf.firstEventBlockNumber, 0),
|
|
189
|
+
latestProcessedBlock: cf.committedProgressBlockNumber,
|
|
190
|
+
numEventsProcessed: cf.numEventsProcessed,
|
|
191
|
+
timestampCaughtUpToHeadOrEndblock: Belt_Option.getWithDefault(cf.timestampCaughtUpToHeadOrEndblock, new Date(Date.now()))
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
} else {
|
|
195
|
+
var timestampCaughtUpToHeadOrEndblock = cf.timestampCaughtUpToHeadOrEndblock;
|
|
196
|
+
if (timestampCaughtUpToHeadOrEndblock !== undefined) {
|
|
197
|
+
var firstEventBlockNumber = cf.firstEventBlockNumber;
|
|
198
|
+
progress = firstEventBlockNumber !== undefined ? ({
|
|
199
|
+
TAG: "Synced",
|
|
200
|
+
_0: {
|
|
201
|
+
firstEventBlockNumber: firstEventBlockNumber,
|
|
202
|
+
latestProcessedBlock: cf.committedProgressBlockNumber,
|
|
203
|
+
numEventsProcessed: numEventsProcessed,
|
|
204
|
+
timestampCaughtUpToHeadOrEndblock: Caml_option.valFromOption(timestampCaughtUpToHeadOrEndblock)
|
|
205
|
+
}
|
|
206
|
+
}) : "SearchingForEvents";
|
|
207
|
+
} else {
|
|
208
|
+
var firstEventBlockNumber$1 = cf.firstEventBlockNumber;
|
|
209
|
+
progress = firstEventBlockNumber$1 !== undefined ? ({
|
|
210
|
+
TAG: "Syncing",
|
|
211
|
+
_0: {
|
|
212
|
+
firstEventBlockNumber: firstEventBlockNumber$1,
|
|
213
|
+
latestProcessedBlock: cf.committedProgressBlockNumber,
|
|
214
|
+
numEventsProcessed: numEventsProcessed
|
|
215
|
+
}
|
|
216
|
+
}) : "SearchingForEvents";
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
chainId: String(cf.chainConfig.id),
|
|
221
|
+
eventsProcessed: numEventsProcessed,
|
|
222
|
+
progressBlock: cf.committedProgressBlockNumber === -1 ? undefined : cf.committedProgressBlockNumber,
|
|
223
|
+
bufferBlock: latestFetchedBlockNumber,
|
|
224
|
+
sourceBlock: cf.fetchState.knownHeight,
|
|
225
|
+
startBlock: cf.fetchState.startBlock,
|
|
226
|
+
endBlock: cf.fetchState.endBlock,
|
|
227
|
+
firstEventBlockNumber: cf.firstEventBlockNumber,
|
|
228
|
+
poweredByHyperSync: SourceManager.getActiveSource(cf.sourceManager).poweredByHyperSync,
|
|
229
|
+
progress: progress,
|
|
230
|
+
latestFetchedBlockNumber: latestFetchedBlockNumber,
|
|
231
|
+
knownHeight: knownHeight,
|
|
232
|
+
numBatchesFetched: cf.numBatchesFetched
|
|
233
|
+
};
|
|
234
|
+
}));
|
|
235
|
+
var totalEventsProcessed = Belt_Array.reduce(chains, 0, (function (acc, chain) {
|
|
236
|
+
return acc + chain.eventsProcessed | 0;
|
|
237
|
+
}));
|
|
238
|
+
var maxChainIdLength = Belt_Array.reduce(chains, 0, (function (acc, chain) {
|
|
239
|
+
var chainIdLength = chain.chainId.length;
|
|
240
|
+
if (chainIdLength > acc) {
|
|
241
|
+
return chainIdLength;
|
|
242
|
+
} else {
|
|
243
|
+
return acc;
|
|
244
|
+
}
|
|
245
|
+
}));
|
|
246
|
+
var defaultPassword = "testing";
|
|
247
|
+
return JsxRuntime.jsxs($$Ink$1.Box, {
|
|
248
|
+
children: [
|
|
249
|
+
JsxRuntime.jsx(InkBigText, {
|
|
250
|
+
text: "envio",
|
|
251
|
+
font: chains.length > 5 ? "tiny" : "block",
|
|
252
|
+
colors: [
|
|
253
|
+
"#FFBB2F",
|
|
254
|
+
"#9860E5"
|
|
255
|
+
],
|
|
256
|
+
space: false
|
|
257
|
+
}),
|
|
258
|
+
JsxRuntime.jsx($$Ink.Newline.make, {}),
|
|
259
|
+
Belt_Array.mapWithIndex(chains, (function (i, chainData) {
|
|
260
|
+
return JsxRuntime.jsx(Tui$ChainLine, {
|
|
261
|
+
chainId: chainData.chainId,
|
|
262
|
+
maxChainIdLength: maxChainIdLength,
|
|
263
|
+
stdoutColumns: stdoutColumns,
|
|
264
|
+
progressBlock: chainData.progressBlock,
|
|
265
|
+
bufferBlock: chainData.bufferBlock,
|
|
266
|
+
sourceBlock: chainData.sourceBlock,
|
|
267
|
+
firstEventBlock: chainData.firstEventBlockNumber,
|
|
268
|
+
startBlock: chainData.startBlock,
|
|
269
|
+
endBlock: chainData.endBlock,
|
|
270
|
+
poweredByHyperSync: chainData.poweredByHyperSync,
|
|
271
|
+
eventsProcessed: chainData.eventsProcessed
|
|
272
|
+
}, String(i));
|
|
273
|
+
})),
|
|
274
|
+
JsxRuntime.jsx(Tui$TotalEventsProcessed, {
|
|
275
|
+
totalEventsProcessed: totalEventsProcessed
|
|
276
|
+
}),
|
|
277
|
+
JsxRuntime.jsx(SyncETA.make, {
|
|
278
|
+
chains: chains,
|
|
279
|
+
indexerStartTime: state.indexerStartTime
|
|
280
|
+
}),
|
|
281
|
+
JsxRuntime.jsx($$Ink.Newline.make, {}),
|
|
282
|
+
JsxRuntime.jsxs($$Ink$1.Box, {
|
|
283
|
+
children: [
|
|
284
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
285
|
+
children: "GraphQL: "
|
|
286
|
+
}),
|
|
287
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
288
|
+
children: Env.Hasura.url,
|
|
289
|
+
color: "#6CBFEE",
|
|
290
|
+
underline: true
|
|
291
|
+
}),
|
|
292
|
+
Env.Hasura.secret === defaultPassword ? JsxRuntime.jsx($$Ink$1.Text, {
|
|
293
|
+
children: " (password: " + defaultPassword + ")",
|
|
294
|
+
color: "gray"
|
|
295
|
+
}) : null
|
|
296
|
+
],
|
|
297
|
+
flexDirection: "row"
|
|
298
|
+
}),
|
|
299
|
+
JsxRuntime.jsxs($$Ink$1.Box, {
|
|
300
|
+
children: [
|
|
301
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
302
|
+
children: "Dev Console: "
|
|
303
|
+
}),
|
|
304
|
+
JsxRuntime.jsx($$Ink$1.Text, {
|
|
305
|
+
children: Env.envioAppUrl + "/console",
|
|
306
|
+
color: "#6CBFEE",
|
|
307
|
+
underline: true
|
|
308
|
+
})
|
|
309
|
+
],
|
|
310
|
+
flexDirection: "row"
|
|
311
|
+
}),
|
|
312
|
+
JsxRuntime.jsx(Messages.make, {
|
|
313
|
+
config: state.ctx.config
|
|
314
|
+
})
|
|
315
|
+
],
|
|
316
|
+
flexDirection: "column"
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
var App = {
|
|
321
|
+
make: Tui$App
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
function start(getState) {
|
|
325
|
+
var match = $$Ink.render(undefined, JsxRuntime.jsx(Tui$App, {
|
|
326
|
+
getState: getState
|
|
327
|
+
}));
|
|
328
|
+
var rerender = match.rerender;
|
|
329
|
+
return function () {
|
|
330
|
+
rerender(JsxRuntime.jsx(Tui$App, {
|
|
331
|
+
getState: getState
|
|
332
|
+
}));
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export {
|
|
337
|
+
ChainLine ,
|
|
338
|
+
TotalEventsProcessed ,
|
|
339
|
+
App ,
|
|
340
|
+
start ,
|
|
341
|
+
}
|
|
342
|
+
/* Env Not a pure module */
|