envio 3.0.0-alpha.4 → 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/index.d.ts +329 -0
- package/index.js +3 -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 +211 -18
- package/src/Config.res.mjs +226 -27
- package/src/{Indexer.res → Ctx.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 +0 -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/UserContext.res +0 -1
- package/src/UserContext.res.mjs +0 -2
- package/src/Utils.res +13 -0
- package/src/bindings/Ethers.res +0 -4
- package/src/bindings/Ethers.res.mjs +0 -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/Yargs.res +8 -0
- package/src/bindings/Yargs.res.mjs +2 -0
- package/src/sources/FuelSDK.res +4 -3
- 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/{Indexer.res.mjs → Ctx.res.mjs} +0 -0
package/src/PgStorage.res.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Fs from "fs";
|
|
4
|
+
import * as Env from "./Env.res.mjs";
|
|
4
5
|
import * as Path from "path";
|
|
5
6
|
import * as $$Array from "rescript/lib/es6/array.js";
|
|
6
7
|
import * as Table from "./db/Table.res.mjs";
|
|
@@ -13,6 +14,7 @@ import * as Js_dict from "rescript/lib/es6/js_dict.js";
|
|
|
13
14
|
import * as Logging from "./Logging.res.mjs";
|
|
14
15
|
import * as $$Promise from "./bindings/Promise.res.mjs";
|
|
15
16
|
import * as Internal from "./Internal.res.mjs";
|
|
17
|
+
import Postgres from "postgres";
|
|
16
18
|
import * as Belt_Array from "rescript/lib/es6/belt_Array.js";
|
|
17
19
|
import * as Prometheus from "./Prometheus.res.mjs";
|
|
18
20
|
import * as Caml_option from "rescript/lib/es6/caml_option.js";
|
|
@@ -26,6 +28,24 @@ import * as Caml_js_exceptions from "rescript/lib/es6/caml_js_exceptions.js";
|
|
|
26
28
|
|
|
27
29
|
var getCacheRowCountFnName = "get_cache_row_count";
|
|
28
30
|
|
|
31
|
+
function makeClient() {
|
|
32
|
+
return Postgres({
|
|
33
|
+
host: Env.Db.host,
|
|
34
|
+
port: Env.Db.port,
|
|
35
|
+
database: Env.Db.database,
|
|
36
|
+
username: Env.Db.user,
|
|
37
|
+
password: Env.Db.password,
|
|
38
|
+
ssl: Env.Db.ssl,
|
|
39
|
+
max: 2,
|
|
40
|
+
onnotice: Env.userLogLevel === "warn" || Env.userLogLevel === "error" ? undefined : (function (_str) {
|
|
41
|
+
|
|
42
|
+
}),
|
|
43
|
+
transform: {
|
|
44
|
+
undefined: null
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
29
49
|
function makeCreateIndexQuery(tableName, indexFields, pgSchema) {
|
|
30
50
|
var indexName = tableName + "_" + indexFields.join("_");
|
|
31
51
|
var index = Belt_Array.map(indexFields, (function (idx) {
|
|
@@ -697,7 +717,7 @@ function make(sql, pgHost, pgSchema, pgPort, pgUser, pgDatabase, pgPassword, isH
|
|
|
697
717
|
var psqlExecOptions = {
|
|
698
718
|
env: psqlExecOptions_env
|
|
699
719
|
};
|
|
700
|
-
var cacheDirPath = Path.resolve("
|
|
720
|
+
var cacheDirPath = Path.resolve(".envio", "cache");
|
|
701
721
|
var isInitialized = async function () {
|
|
702
722
|
var envioTables = await sql.unsafe("SELECT table_schema FROM information_schema.tables WHERE table_schema = '" + pgSchema + "' AND (table_name = 'event_sync_state' OR table_name = '" + InternalTable.Chains.table.tableName + "');");
|
|
703
723
|
return Utils.$$Array.notEmpty(envioTables);
|
|
@@ -1075,6 +1095,7 @@ var maxItemsPerQuery = 500;
|
|
|
1075
1095
|
|
|
1076
1096
|
export {
|
|
1077
1097
|
getCacheRowCountFnName ,
|
|
1098
|
+
makeClient ,
|
|
1078
1099
|
makeCreateIndexQuery ,
|
|
1079
1100
|
makeCreateTableIndicesQuery ,
|
|
1080
1101
|
makeCreateTableQuery ,
|
package/src/UserContext.res
CHANGED
|
@@ -261,7 +261,6 @@ let handlerTraps: Utils.Proxy.traps<contextParams> = {
|
|
|
261
261
|
)
|
|
262
262
|
|
|
263
263
|
| "isPreload" => params.isPreload->Utils.magic
|
|
264
|
-
| "chains" => params.chains->Utils.magic
|
|
265
264
|
| "chain" =>
|
|
266
265
|
let chainId = params.item->Internal.getItemChainId
|
|
267
266
|
params.chains->Utils.Dict.dangerouslyGetByIntNonOption(chainId)->Utils.magic
|
package/src/UserContext.res.mjs
CHANGED
package/src/Utils.res
CHANGED
|
@@ -32,6 +32,19 @@ module Object = {
|
|
|
32
32
|
|
|
33
33
|
@val @scope("Object")
|
|
34
34
|
external defineProperty: ('obj, string, propertyDescriptor<'a>) => 'obj = "defineProperty"
|
|
35
|
+
|
|
36
|
+
// Property descriptor with required value field (no boxing)
|
|
37
|
+
type enumerablePropertyDescriptor<'a> = {
|
|
38
|
+
enumerable: bool,
|
|
39
|
+
value: 'a,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@val @scope("Object")
|
|
43
|
+
external definePropertyWithValue: ('obj, string, enumerablePropertyDescriptor<'a>) => 'obj =
|
|
44
|
+
"defineProperty"
|
|
45
|
+
|
|
46
|
+
@val @scope("Object")
|
|
47
|
+
external createNullObject: (@as(json`null`) _, unit) => 'a = "create"
|
|
35
48
|
}
|
|
36
49
|
|
|
37
50
|
module Error = {
|
package/src/bindings/Ethers.res
CHANGED
|
@@ -4,10 +4,6 @@ import * as Ethers from "ethers";
|
|
|
4
4
|
import * as Address from "../Address.res.mjs";
|
|
5
5
|
import * as Caml_option from "rescript/lib/es6/caml_option.js";
|
|
6
6
|
|
|
7
|
-
function makeAbi(abi) {
|
|
8
|
-
return abi;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
7
|
var Constants = {};
|
|
12
8
|
|
|
13
9
|
var Filter = {};
|
|
@@ -72,7 +68,6 @@ var JsonRpcProvider = {
|
|
|
72
68
|
};
|
|
73
69
|
|
|
74
70
|
export {
|
|
75
|
-
makeAbi ,
|
|
76
71
|
Constants ,
|
|
77
72
|
Filter ,
|
|
78
73
|
CombinedFilter ,
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
module Assert = {
|
|
2
|
+
type assertion<'a> = ('a, 'a, ~message: string=?) => unit
|
|
3
|
+
|
|
4
|
+
@module("assert") external equal: assertion<'a> = "equal"
|
|
5
|
+
@module("assert") external notEqual: assertion<'a> = "notEqual"
|
|
6
|
+
|
|
7
|
+
@module("assert") external deepEqual: assertion<'a> = "deepEqual"
|
|
8
|
+
@module("assert")
|
|
9
|
+
external notDeepEqual: assertion<'a> = "notDeepEqual"
|
|
10
|
+
|
|
11
|
+
@module("assert") external strictEqual: assertion<'a> = "strictEqual"
|
|
12
|
+
@module("assert")
|
|
13
|
+
external notStrictEqual: assertion<'a> = "notStrictEqual"
|
|
14
|
+
|
|
15
|
+
@module("assert")
|
|
16
|
+
external deepStrictEqual: assertion<'a> = "deepStrictEqual"
|
|
17
|
+
@module("assert")
|
|
18
|
+
external notDeepStrictEqual: assertion<'a> = "notDeepStrictEqual"
|
|
19
|
+
|
|
20
|
+
@module("assert") external ifError: 'a => unit = "ifError"
|
|
21
|
+
|
|
22
|
+
@module("assert")
|
|
23
|
+
external throws: (unit => 'a, ~error: 'error=?, ~message: string=?) => unit = "throws"
|
|
24
|
+
@module("assert")
|
|
25
|
+
external doesNotThrow: (unit => 'a, ~error: 'error=?, ~message: string=?) => unit = "doesNotThrow"
|
|
26
|
+
|
|
27
|
+
@module("assert")
|
|
28
|
+
external rejects: (unit => promise<'a>, ~error: 'error=?, ~message: string=?) => promise<unit> =
|
|
29
|
+
"rejects"
|
|
30
|
+
|
|
31
|
+
@module("assert") external ok: (bool, ~message: string=?) => unit = "ok"
|
|
32
|
+
@module("assert") external fail: string => 'a = "fail"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* Mocha bindings on `this` for `describe` and `it` functions */
|
|
36
|
+
module This = {
|
|
37
|
+
@val external timeout: int => unit = "this.timeout"
|
|
38
|
+
@val external retries: int => unit = "this.retries"
|
|
39
|
+
@val external slow: int => unit = "this.slow"
|
|
40
|
+
@val external skip: unit => unit = "this.skip"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@val
|
|
44
|
+
external describe: (string, unit => unit) => unit = "describe"
|
|
45
|
+
@val
|
|
46
|
+
external describe_only: (string, unit => unit) => unit = "describe.only"
|
|
47
|
+
@val
|
|
48
|
+
external describe_skip: (string, unit => unit) => unit = "describe.skip"
|
|
49
|
+
|
|
50
|
+
@val
|
|
51
|
+
external it: (string, unit => unit) => unit = "it"
|
|
52
|
+
@val
|
|
53
|
+
external it_only: (string, unit => unit) => unit = "it.only"
|
|
54
|
+
@val
|
|
55
|
+
external it_skip: (string, unit => unit) => unit = "it.skip"
|
|
56
|
+
@val
|
|
57
|
+
external before: (unit => unit) => unit = "before"
|
|
58
|
+
@val
|
|
59
|
+
external after: (unit => unit) => unit = "after"
|
|
60
|
+
@val
|
|
61
|
+
external beforeEach: (unit => unit) => unit = "beforeEach"
|
|
62
|
+
@val
|
|
63
|
+
external afterEach: (unit => unit) => unit = "afterEach"
|
|
64
|
+
@val
|
|
65
|
+
external beforeWithTitle: (string, unit => unit) => unit = "before"
|
|
66
|
+
@val
|
|
67
|
+
external afterWithTitle: (string, unit => unit) => unit = "after"
|
|
68
|
+
@val
|
|
69
|
+
external beforeEachWithTitle: (string, unit => unit) => unit = "beforeEach"
|
|
70
|
+
@val
|
|
71
|
+
external afterEachWithTitle: (string, unit => unit) => unit = "afterEach"
|
|
72
|
+
|
|
73
|
+
module Async = {
|
|
74
|
+
@val
|
|
75
|
+
external it: (string, unit => promise<unit>) => unit = "it"
|
|
76
|
+
@val
|
|
77
|
+
external it_only: (string, unit => promise<unit>) => unit = "it.only"
|
|
78
|
+
@val
|
|
79
|
+
external it_skip: (string, unit => promise<unit>) => unit = "it.skip"
|
|
80
|
+
@val
|
|
81
|
+
external before: (unit => promise<unit>) => unit = "before"
|
|
82
|
+
@val
|
|
83
|
+
external after: (unit => promise<unit>) => unit = "after"
|
|
84
|
+
@val
|
|
85
|
+
external beforeEach: (unit => promise<unit>) => unit = "beforeEach"
|
|
86
|
+
@val
|
|
87
|
+
external afterEach: (unit => promise<unit>) => unit = "afterEach"
|
|
88
|
+
@val
|
|
89
|
+
external beforeWithTitle: (string, unit => promise<unit>) => unit = "before"
|
|
90
|
+
@val
|
|
91
|
+
external afterWithTitle: (string, unit => promise<unit>) => unit = "after"
|
|
92
|
+
@val
|
|
93
|
+
external beforeEachWithTitle: (string, unit => promise<unit>) => unit = "beforeEach"
|
|
94
|
+
@val
|
|
95
|
+
external afterEachWithTitle: (string, unit => promise<unit>) => unit = "afterEach"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
module DoneCallback = {
|
|
99
|
+
type doneCallback = Js.Nullable.t<Js.Exn.t> => unit
|
|
100
|
+
|
|
101
|
+
@val
|
|
102
|
+
external it: (string, doneCallback => unit) => unit = "it"
|
|
103
|
+
@val
|
|
104
|
+
external it_only: (string, doneCallback => unit) => unit = "it.only"
|
|
105
|
+
@val
|
|
106
|
+
external it_skip: (string, doneCallback => unit) => unit = "it.skip"
|
|
107
|
+
@val
|
|
108
|
+
external before: (doneCallback => unit) => unit = "before"
|
|
109
|
+
@val
|
|
110
|
+
external after: (doneCallback => unit) => unit = "after"
|
|
111
|
+
@val
|
|
112
|
+
external beforeEach: (doneCallback => unit) => unit = "beforeEach"
|
|
113
|
+
@val
|
|
114
|
+
external afterEach: (doneCallback => unit) => unit = "afterEach"
|
|
115
|
+
@val
|
|
116
|
+
external beforeWithTitle: (string, doneCallback => unit) => unit = "before"
|
|
117
|
+
@val
|
|
118
|
+
external afterWithTitle: (string, doneCallback => unit) => unit = "after"
|
|
119
|
+
@val
|
|
120
|
+
external beforeEachWithTitle: (string, doneCallback => unit) => unit = "beforeEach"
|
|
121
|
+
@val
|
|
122
|
+
external afterEachWithTitle: (string, doneCallback => unit) => unit = "afterEach"
|
|
123
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type arg = string
|
|
2
|
+
|
|
3
|
+
type parsedArgs<'a> = 'a
|
|
4
|
+
|
|
5
|
+
@module("yargs/yargs") external yargs: array<arg> => parsedArgs<'a> = "default"
|
|
6
|
+
@module("yargs/helpers") external hideBin: array<arg> => array<arg> = "hideBin"
|
|
7
|
+
|
|
8
|
+
@get external argv: parsedArgs<'a> => 'a = "argv"
|
package/src/sources/FuelSDK.res
CHANGED
|
@@ -15,10 +15,11 @@ type receiptType =
|
|
|
15
15
|
| @as(12) Burn
|
|
16
16
|
|
|
17
17
|
@module("./vendored-fuel-abi-coder.js")
|
|
18
|
-
external transpileAbi: Js.Json.t =>
|
|
18
|
+
external transpileAbi: Js.Json.t => EvmTypes.Abi.t = "transpileAbi"
|
|
19
19
|
|
|
20
20
|
@module("./vendored-fuel-abi-coder.js") @scope("AbiCoder")
|
|
21
|
-
external getLogDecoder: (~abi:
|
|
21
|
+
external getLogDecoder: (~abi: EvmTypes.Abi.t, ~logId: string) => string => unknown =
|
|
22
|
+
"getLogDecoder"
|
|
22
23
|
|
|
23
24
|
module Receipt = {
|
|
24
25
|
@tag("receiptType")
|
|
@@ -30,7 +31,7 @@ module Receipt = {
|
|
|
30
31
|
| @as(11) Mint({val: bigint, subId: string})
|
|
31
32
|
| @as(12) Burn({val: bigint, subId: string})
|
|
32
33
|
|
|
33
|
-
let getLogDataDecoder = (~abi:
|
|
34
|
+
let getLogDataDecoder = (~abi: EvmTypes.Abi.t, ~logId: string) => {
|
|
34
35
|
let decode = getLogDecoder(~abi, ~logId)
|
|
35
36
|
data => data->decode->Utils.magic
|
|
36
37
|
}
|
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
|
+
}
|