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.
Files changed (55) hide show
  1. package/index.d.ts +329 -0
  2. package/index.js +3 -0
  3. package/package.json +13 -6
  4. package/rescript.json +4 -1
  5. package/src/ChainFetcher.res +25 -1
  6. package/src/ChainFetcher.res.mjs +19 -1
  7. package/src/Config.res +211 -18
  8. package/src/Config.res.mjs +226 -27
  9. package/src/{Indexer.res → Ctx.res} +1 -1
  10. package/src/EventProcessing.res +18 -18
  11. package/src/EventProcessing.res.mjs +14 -14
  12. package/src/GlobalState.res +29 -35
  13. package/src/GlobalState.res.mjs +47 -47
  14. package/src/GlobalStateManager.res +68 -0
  15. package/src/GlobalStateManager.res.mjs +75 -0
  16. package/src/GlobalStateManager.resi +7 -0
  17. package/src/Internal.res +0 -1
  18. package/src/LogSelection.res +33 -27
  19. package/src/LogSelection.res.mjs +6 -0
  20. package/src/Main.res +342 -0
  21. package/src/Main.res.mjs +289 -0
  22. package/src/PgStorage.gen.ts +10 -0
  23. package/src/PgStorage.res +24 -2
  24. package/src/PgStorage.res.d.mts +5 -0
  25. package/src/PgStorage.res.mjs +22 -1
  26. package/src/UserContext.res +0 -1
  27. package/src/UserContext.res.mjs +0 -2
  28. package/src/Utils.res +13 -0
  29. package/src/bindings/Ethers.res +0 -4
  30. package/src/bindings/Ethers.res.mjs +0 -5
  31. package/src/bindings/Postgres.gen.ts +8 -0
  32. package/src/bindings/Postgres.res +3 -0
  33. package/src/bindings/Postgres.res.d.mts +5 -0
  34. package/src/bindings/RescriptMocha.res +123 -0
  35. package/src/bindings/RescriptMocha.res.mjs +18 -0
  36. package/src/bindings/Yargs.res +8 -0
  37. package/src/bindings/Yargs.res.mjs +2 -0
  38. package/src/sources/FuelSDK.res +4 -3
  39. package/src/tui/Tui.res +266 -0
  40. package/src/tui/Tui.res.mjs +342 -0
  41. package/src/tui/bindings/Ink.res +376 -0
  42. package/src/tui/bindings/Ink.res.mjs +75 -0
  43. package/src/tui/bindings/Style.res +123 -0
  44. package/src/tui/bindings/Style.res.mjs +2 -0
  45. package/src/tui/components/BufferedProgressBar.res +40 -0
  46. package/src/tui/components/BufferedProgressBar.res.mjs +57 -0
  47. package/src/tui/components/CustomHooks.res +114 -0
  48. package/src/tui/components/CustomHooks.res.mjs +162 -0
  49. package/src/tui/components/Messages.res +41 -0
  50. package/src/tui/components/Messages.res.mjs +75 -0
  51. package/src/tui/components/SyncETA.res +193 -0
  52. package/src/tui/components/SyncETA.res.mjs +269 -0
  53. package/src/tui/components/TuiData.res +46 -0
  54. package/src/tui/components/TuiData.res.mjs +29 -0
  55. /package/src/{Indexer.res.mjs → Ctx.res.mjs} +0 -0
@@ -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("..", ".envio", "cache");
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 ,
@@ -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
@@ -148,8 +148,6 @@ var handlerTraps = {
148
148
  case "chain" :
149
149
  var chainId = Internal.getItemChainId(params.item);
150
150
  return params.chains[chainId];
151
- case "chains" :
152
- return params.chains;
153
151
  case "effect" :
154
152
  return initEffect(params);
155
153
  case "isPreload" :
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 = {
@@ -1,7 +1,3 @@
1
- type abi = EvmTypes.Abi.t
2
-
3
- let makeAbi = (abi: Js.Json.t): abi => abi->Utils.magic
4
-
5
1
  type txHash = string
6
2
 
7
3
  module Constants = {
@@ -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,8 @@
1
+ /* TypeScript file generated from Postgres.res by genType. */
2
+
3
+ /* eslint-disable */
4
+ /* tslint:disable */
5
+
6
+ import type {Sql as $$sql} from 'postgres';
7
+
8
+ export type sql = $$sql;
@@ -1,3 +1,6 @@
1
+ // Only needed for some old tests
2
+ // Remove @genType in the future
3
+ @genType.import(("postgres", "Sql"))
1
4
  type sql
2
5
 
3
6
  type undefinedTransform = | @as(undefined) Undefined | @as(null) Null
@@ -0,0 +1,5 @@
1
+ // This is to prevent tsc --noEmit from failing
2
+ // when importing code from .res.mjs files in genType .ts files
3
+ // After we upgrade GenType and it starts to include ts-ignore,
4
+ // the line can be removed.
5
+ export type sql = any;
@@ -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,18 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ var Assert = {};
5
+
6
+ var This = {};
7
+
8
+ var Async = {};
9
+
10
+ var DoneCallback = {};
11
+
12
+ export {
13
+ Assert ,
14
+ This ,
15
+ Async ,
16
+ DoneCallback ,
17
+ }
18
+ /* No side effect */
@@ -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"
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
@@ -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 => Ethers.abi = "transpileAbi"
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: Ethers.abi, ~logId: string) => string => unknown = "getLogDecoder"
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: Ethers.abi, ~logId: string) => {
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
  }
@@ -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
+ }