envio 3.0.0-alpha.21 → 3.0.0-alpha.22

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 (219) hide show
  1. package/bin.mjs +2 -48
  2. package/evm.schema.json +67 -0
  3. package/fuel.schema.json +67 -0
  4. package/index.d.ts +822 -38
  5. package/index.js +5 -3
  6. package/package.json +10 -8
  7. package/rescript.json +5 -9
  8. package/src/Address.res +4 -5
  9. package/src/Address.res.mjs +9 -12
  10. package/src/Api.res +15 -0
  11. package/src/Api.res.mjs +20 -0
  12. package/src/Batch.res +32 -34
  13. package/src/Batch.res.mjs +172 -187
  14. package/src/Bin.res +89 -0
  15. package/src/Bin.res.mjs +97 -0
  16. package/src/ChainFetcher.res +33 -57
  17. package/src/ChainFetcher.res.mjs +197 -227
  18. package/src/ChainManager.res +6 -14
  19. package/src/ChainManager.res.mjs +74 -85
  20. package/src/ChainMap.res +14 -16
  21. package/src/ChainMap.res.mjs +38 -38
  22. package/src/Config.res +193 -135
  23. package/src/Config.res.mjs +566 -592
  24. package/src/Core.res +182 -0
  25. package/src/Core.res.mjs +207 -0
  26. package/src/Ecosystem.res +25 -4
  27. package/src/Ecosystem.res.mjs +12 -13
  28. package/src/Env.res +20 -13
  29. package/src/Env.res.mjs +124 -113
  30. package/src/EnvSafe.res +269 -0
  31. package/src/EnvSafe.res.mjs +296 -0
  32. package/src/EnvSafe.resi +18 -0
  33. package/src/Envio.res +37 -26
  34. package/src/Envio.res.mjs +59 -60
  35. package/src/ErrorHandling.res +2 -2
  36. package/src/ErrorHandling.res.mjs +15 -15
  37. package/src/EventConfigBuilder.res +219 -81
  38. package/src/EventConfigBuilder.res.mjs +259 -202
  39. package/src/EventProcessing.res +27 -38
  40. package/src/EventProcessing.res.mjs +165 -183
  41. package/src/EventUtils.res +11 -11
  42. package/src/EventUtils.res.mjs +21 -22
  43. package/src/EvmTypes.res +0 -1
  44. package/src/EvmTypes.res.mjs +5 -5
  45. package/src/FetchState.res +360 -256
  46. package/src/FetchState.res.mjs +958 -914
  47. package/src/GlobalState.res +365 -351
  48. package/src/GlobalState.res.mjs +958 -992
  49. package/src/GlobalStateManager.res +1 -2
  50. package/src/GlobalStateManager.res.mjs +36 -44
  51. package/src/HandlerLoader.res +107 -23
  52. package/src/HandlerLoader.res.mjs +128 -38
  53. package/src/HandlerRegister.res +127 -103
  54. package/src/HandlerRegister.res.mjs +164 -164
  55. package/src/HandlerRegister.resi +12 -4
  56. package/src/Hasura.res +35 -22
  57. package/src/Hasura.res.mjs +158 -167
  58. package/src/InMemoryStore.res +20 -27
  59. package/src/InMemoryStore.res.mjs +64 -80
  60. package/src/InMemoryTable.res +34 -39
  61. package/src/InMemoryTable.res.mjs +165 -170
  62. package/src/Internal.res +52 -33
  63. package/src/Internal.res.mjs +84 -81
  64. package/src/LazyLoader.res.mjs +55 -61
  65. package/src/LoadLayer.res +77 -78
  66. package/src/LoadLayer.res.mjs +160 -189
  67. package/src/LoadManager.res +16 -21
  68. package/src/LoadManager.res.mjs +79 -84
  69. package/src/LogSelection.res +236 -68
  70. package/src/LogSelection.res.mjs +211 -141
  71. package/src/Logging.res +13 -9
  72. package/src/Logging.res.mjs +130 -143
  73. package/src/Main.res +428 -51
  74. package/src/Main.res.mjs +528 -271
  75. package/src/Persistence.res +77 -84
  76. package/src/Persistence.res.mjs +131 -132
  77. package/src/PgStorage.res +291 -167
  78. package/src/PgStorage.res.mjs +797 -817
  79. package/src/Prometheus.res +50 -58
  80. package/src/Prometheus.res.mjs +345 -373
  81. package/src/ReorgDetection.res +22 -24
  82. package/src/ReorgDetection.res.mjs +100 -106
  83. package/src/SafeCheckpointTracking.res +7 -7
  84. package/src/SafeCheckpointTracking.res.mjs +40 -43
  85. package/src/SimulateItems.res +41 -49
  86. package/src/SimulateItems.res.mjs +257 -272
  87. package/src/Sink.res +2 -2
  88. package/src/Sink.res.mjs +22 -26
  89. package/src/TableIndices.res +1 -2
  90. package/src/TableIndices.res.mjs +42 -48
  91. package/src/TestIndexer.res +196 -189
  92. package/src/TestIndexer.res.mjs +536 -536
  93. package/src/TestIndexerProxyStorage.res +15 -16
  94. package/src/TestIndexerProxyStorage.res.mjs +98 -122
  95. package/src/TestIndexerWorker.res +4 -0
  96. package/src/TestIndexerWorker.res.mjs +7 -0
  97. package/src/Throttler.res +3 -3
  98. package/src/Throttler.res.mjs +23 -24
  99. package/src/Time.res +1 -1
  100. package/src/Time.res.mjs +18 -21
  101. package/src/TopicFilter.res +3 -3
  102. package/src/TopicFilter.res.mjs +29 -30
  103. package/src/UserContext.res +93 -54
  104. package/src/UserContext.res.mjs +197 -182
  105. package/src/Utils.res +141 -86
  106. package/src/Utils.res.mjs +334 -295
  107. package/src/bindings/BigDecimal.res +0 -2
  108. package/src/bindings/BigDecimal.res.mjs +19 -23
  109. package/src/bindings/ClickHouse.res +28 -27
  110. package/src/bindings/ClickHouse.res.mjs +243 -240
  111. package/src/bindings/DateFns.res +11 -11
  112. package/src/bindings/DateFns.res.mjs +7 -7
  113. package/src/bindings/EventSource.res.mjs +2 -2
  114. package/src/bindings/Express.res +2 -5
  115. package/src/bindings/Hrtime.res +2 -2
  116. package/src/bindings/Hrtime.res.mjs +30 -32
  117. package/src/bindings/Lodash.res.mjs +1 -1
  118. package/src/bindings/NodeJs.res +14 -9
  119. package/src/bindings/NodeJs.res.mjs +20 -20
  120. package/src/bindings/Pino.res +8 -10
  121. package/src/bindings/Pino.res.mjs +40 -43
  122. package/src/bindings/Postgres.res +2 -5
  123. package/src/bindings/Postgres.res.mjs +9 -9
  124. package/src/bindings/PromClient.res +17 -2
  125. package/src/bindings/PromClient.res.mjs +30 -7
  126. package/src/bindings/SDSL.res.mjs +2 -2
  127. package/src/bindings/Viem.res +4 -4
  128. package/src/bindings/Viem.res.mjs +20 -22
  129. package/src/bindings/Vitest.res +1 -1
  130. package/src/bindings/Vitest.res.mjs +2 -2
  131. package/src/bindings/WebSocket.res +1 -1
  132. package/src/db/EntityHistory.res +9 -3
  133. package/src/db/EntityHistory.res.mjs +84 -59
  134. package/src/db/InternalTable.res +62 -60
  135. package/src/db/InternalTable.res.mjs +271 -203
  136. package/src/db/Schema.res +1 -2
  137. package/src/db/Schema.res.mjs +28 -32
  138. package/src/db/Table.res +28 -27
  139. package/src/db/Table.res.mjs +276 -292
  140. package/src/sources/EventRouter.res +21 -16
  141. package/src/sources/EventRouter.res.mjs +55 -57
  142. package/src/sources/Evm.res +17 -1
  143. package/src/sources/Evm.res.mjs +16 -8
  144. package/src/sources/EvmChain.res +15 -17
  145. package/src/sources/EvmChain.res.mjs +40 -42
  146. package/src/sources/Fuel.res +14 -1
  147. package/src/sources/Fuel.res.mjs +16 -8
  148. package/src/sources/FuelSDK.res +1 -1
  149. package/src/sources/FuelSDK.res.mjs +6 -8
  150. package/src/sources/HyperFuel.res +8 -10
  151. package/src/sources/HyperFuel.res.mjs +113 -123
  152. package/src/sources/HyperFuelClient.res.mjs +6 -7
  153. package/src/sources/HyperFuelSource.res +19 -20
  154. package/src/sources/HyperFuelSource.res.mjs +339 -356
  155. package/src/sources/HyperSync.res +11 -13
  156. package/src/sources/HyperSync.res.mjs +206 -220
  157. package/src/sources/HyperSyncClient.res +5 -7
  158. package/src/sources/HyperSyncClient.res.mjs +70 -75
  159. package/src/sources/HyperSyncHeightStream.res +8 -9
  160. package/src/sources/HyperSyncHeightStream.res.mjs +78 -86
  161. package/src/sources/HyperSyncJsonApi.res +18 -15
  162. package/src/sources/HyperSyncJsonApi.res.mjs +201 -231
  163. package/src/sources/HyperSyncSource.res +17 -21
  164. package/src/sources/HyperSyncSource.res.mjs +268 -290
  165. package/src/sources/Rpc.res +5 -5
  166. package/src/sources/Rpc.res.mjs +168 -192
  167. package/src/sources/RpcSource.res +166 -167
  168. package/src/sources/RpcSource.res.mjs +972 -1046
  169. package/src/sources/RpcWebSocketHeightStream.res +10 -11
  170. package/src/sources/RpcWebSocketHeightStream.res.mjs +131 -145
  171. package/src/sources/SimulateSource.res +1 -1
  172. package/src/sources/SimulateSource.res.mjs +35 -38
  173. package/src/sources/Source.res +1 -1
  174. package/src/sources/Source.res.mjs +3 -3
  175. package/src/sources/SourceManager.res +39 -20
  176. package/src/sources/SourceManager.res.mjs +340 -371
  177. package/src/sources/SourceManager.resi +2 -1
  178. package/src/sources/Svm.res +12 -5
  179. package/src/sources/Svm.res.mjs +44 -41
  180. package/src/tui/Tui.res +23 -12
  181. package/src/tui/Tui.res.mjs +292 -290
  182. package/src/tui/bindings/Ink.res +2 -4
  183. package/src/tui/bindings/Ink.res.mjs +35 -41
  184. package/src/tui/components/BufferedProgressBar.res +7 -7
  185. package/src/tui/components/BufferedProgressBar.res.mjs +46 -46
  186. package/src/tui/components/CustomHooks.res +1 -2
  187. package/src/tui/components/CustomHooks.res.mjs +102 -122
  188. package/src/tui/components/Messages.res +1 -2
  189. package/src/tui/components/Messages.res.mjs +38 -42
  190. package/src/tui/components/SyncETA.res +10 -11
  191. package/src/tui/components/SyncETA.res.mjs +178 -196
  192. package/src/tui/components/TuiData.res +1 -1
  193. package/src/tui/components/TuiData.res.mjs +7 -6
  194. package/src/vendored/Rest.res +52 -66
  195. package/src/vendored/Rest.res.mjs +324 -364
  196. package/svm.schema.json +67 -0
  197. package/src/Address.gen.ts +0 -8
  198. package/src/Config.gen.ts +0 -19
  199. package/src/Envio.gen.ts +0 -55
  200. package/src/EvmTypes.gen.ts +0 -6
  201. package/src/InMemoryStore.gen.ts +0 -6
  202. package/src/Internal.gen.ts +0 -64
  203. package/src/PgStorage.gen.ts +0 -10
  204. package/src/PgStorage.res.d.mts +0 -5
  205. package/src/Types.ts +0 -56
  206. package/src/bindings/BigDecimal.gen.ts +0 -14
  207. package/src/bindings/BigDecimal.res.d.mts +0 -5
  208. package/src/bindings/BigInt.gen.ts +0 -10
  209. package/src/bindings/BigInt.res +0 -70
  210. package/src/bindings/BigInt.res.d.mts +0 -5
  211. package/src/bindings/BigInt.res.mjs +0 -154
  212. package/src/bindings/Ethers.res.d.mts +0 -5
  213. package/src/bindings/Pino.gen.ts +0 -17
  214. package/src/bindings/Postgres.gen.ts +0 -8
  215. package/src/bindings/Postgres.res.d.mts +0 -5
  216. package/src/bindings/Promise.res +0 -67
  217. package/src/bindings/Promise.res.mjs +0 -26
  218. package/src/db/InternalTable.gen.ts +0 -36
  219. package/src/sources/HyperSyncClient.gen.ts +0 -19
@@ -15,6 +15,7 @@ let make: (
15
15
  ~newBlockStallTimeout: int=?,
16
16
  ~newBlockStallTimeoutLive: int=?,
17
17
  ~stalledPollingInterval: int=?,
18
+ ~reducedPollingInterval: int=?,
18
19
  ~recoveryTimeout: float=?,
19
20
  ~getHeightRetryInterval: (~retry: int) => int=?,
20
21
  ) => t
@@ -30,7 +31,7 @@ let fetchNext: (
30
31
  ~stateId: int,
31
32
  ) => promise<unit>
32
33
 
33
- let waitForNewBlock: (t, ~knownHeight: int, ~isLive: bool) => promise<int>
34
+ let waitForNewBlock: (t, ~knownHeight: int, ~isLive: bool, ~reducedPolling: bool) => promise<int>
34
35
 
35
36
  let executeQuery: (
36
37
  t,
@@ -2,7 +2,7 @@
2
2
  @get external getTimestamp: Internal.eventBlock => int = "time"
3
3
  @get external getId: Internal.eventBlock => string = "hash"
4
4
 
5
- let cleanUpRawEventFieldsInPlace: Js.Json.t => unit = %raw(`fields => {
5
+ let cleanUpRawEventFieldsInPlace: JSON.t => unit = %raw(`fields => {
6
6
  delete fields.hash
7
7
  delete fields.height
8
8
  delete fields.time
@@ -19,6 +19,13 @@ let ecosystem: Ecosystem.t = {
19
19
  getTimestamp,
20
20
  getId,
21
21
  cleanUpRawEventFieldsInPlace,
22
+ onBlockMethodName: "onSlot",
23
+ // SVM filter shape: `{slot: {_gte?, _lte?, _every?}}`.
24
+ // Inner range chunk parsed by `blockRangeSchema` in `Main.res`.
25
+ onBlockFilterSchema: S.object(s => s.field("slot", S.option(S.unknown))),
26
+ // SVM has no event handlers, so there is no `onEvent` `where` value to
27
+ // parse. The schema is a no-op object that always surfaces `None`.
28
+ onEventBlockFilterSchema: S.object(_ => None),
22
29
  }
23
30
 
24
31
  module GetFinalizedSlot = {
@@ -38,7 +45,7 @@ let makeRPCSource = (~chain, ~rpc: string): Source.t => {
38
45
 
39
46
  let urlHost = switch Utils.Url.getHostFromUrl(rpc) {
40
47
  | None =>
41
- Js.Exn.raiseError(
48
+ JsError.throwWithMessage(
42
49
  `The RPC url for chain ${chainId->Belt.Int.toString} is in incorrect format. The RPC url needs to start with either http:// or https://`,
43
50
  )
44
51
  | Some(host) => host
@@ -52,7 +59,7 @@ let makeRPCSource = (~chain, ~rpc: string): Source.t => {
52
59
  poweredByHyperSync: false,
53
60
  pollingInterval: 10_000,
54
61
  getBlockHashes: (~blockNumbers as _, ~logger as _) =>
55
- Js.Exn.raiseError("Svm does not support getting block hashes"),
62
+ JsError.throwWithMessage("Svm does not support getting block hashes"),
56
63
  getHeightOrThrow: async () => {
57
64
  let timerRef = Hrtime.makeTimer()
58
65
  let height = await GetFinalizedSlot.route->Rest.fetch((), ~client)
@@ -70,12 +77,12 @@ let makeRPCSource = (~chain, ~rpc: string): Source.t => {
70
77
  ~fromBlock as _,
71
78
  ~toBlock as _,
72
79
  ~addressesByContractName as _,
73
- ~indexingContracts as _,
80
+ ~indexingAddresses as _,
74
81
  ~knownHeight as _,
75
82
  ~partitionId as _,
76
83
  ~selection as _,
77
84
  ~retry as _,
78
85
  ~logger as _,
79
- ) => Js.Exn.raiseError("Svm does not support getting items"),
86
+ ) => JsError.throwWithMessage("Svm does not support getting items"),
80
87
  }
81
88
  }
@@ -4,19 +4,19 @@ import * as Rpc from "./Rpc.res.mjs";
4
4
  import * as Rest from "../vendored/Rest.res.mjs";
5
5
  import * as Utils from "../Utils.res.mjs";
6
6
  import * as Hrtime from "../bindings/Hrtime.res.mjs";
7
- import * as Js_exn from "rescript/lib/es6/js_exn.js";
8
7
  import * as Prometheus from "../Prometheus.res.mjs";
8
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
9
9
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
10
10
 
11
- var cleanUpRawEventFieldsInPlace = (fields => {
11
+ let cleanUpRawEventFieldsInPlace = (fields => {
12
12
  delete fields.hash
13
13
  delete fields.height
14
14
  delete fields.time
15
15
  });
16
16
 
17
- var ecosystem_blockFields = ["slot"];
17
+ let ecosystem_blockFields = ["slot"];
18
18
 
19
- var ecosystem_transactionFields = [];
19
+ let ecosystem_transactionFields = [];
20
20
 
21
21
  function ecosystem_getNumber(prim) {
22
22
  return prim.height;
@@ -30,7 +30,11 @@ function ecosystem_getId(prim) {
30
30
  return prim.hash;
31
31
  }
32
32
 
33
- var ecosystem = {
33
+ let ecosystem_onBlockFilterSchema = S$RescriptSchema.object(s => s.f("slot", S$RescriptSchema.option(S$RescriptSchema.unknown)));
34
+
35
+ let ecosystem_onEventBlockFilterSchema = S$RescriptSchema.object(param => {});
36
+
37
+ let ecosystem = {
34
38
  name: "svm",
35
39
  blockFields: ecosystem_blockFields,
36
40
  transactionFields: ecosystem_transactionFields,
@@ -40,51 +44,50 @@ var ecosystem = {
40
44
  getNumber: ecosystem_getNumber,
41
45
  getTimestamp: ecosystem_getTimestamp,
42
46
  getId: ecosystem_getId,
43
- cleanUpRawEventFieldsInPlace: cleanUpRawEventFieldsInPlace
47
+ cleanUpRawEventFieldsInPlace: cleanUpRawEventFieldsInPlace,
48
+ onBlockMethodName: "onSlot",
49
+ onBlockFilterSchema: ecosystem_onBlockFilterSchema,
50
+ onEventBlockFilterSchema: ecosystem_onEventBlockFilterSchema
44
51
  };
45
52
 
46
- var route = Rpc.makeRpcRoute("getSlot", S$RescriptSchema.tuple(function (s) {
47
- s.tag(0, {
48
- commitment: "finalized"
49
- });
50
- }), S$RescriptSchema.$$int);
53
+ let route = Rpc.makeRpcRoute("getSlot", S$RescriptSchema.tuple(s => {
54
+ s.tag(0, {
55
+ commitment: "finalized"
56
+ });
57
+ }), S$RescriptSchema.int);
51
58
 
52
- var GetFinalizedSlot = {
59
+ let GetFinalizedSlot = {
53
60
  route: route
54
61
  };
55
62
 
56
63
  function makeRPCSource(chain, rpc) {
57
- var client = Rest.client(rpc, undefined);
58
- var host = Utils.Url.getHostFromUrl(rpc);
59
- var urlHost = host !== undefined ? host : Js_exn.raiseError("The RPC url for chain " + String(chain) + " is in incorrect format. The RPC url needs to start with either http:// or https://");
60
- var name = "RPC (" + urlHost + ")";
64
+ let client = Rest.client(rpc, undefined);
65
+ let host = Utils.Url.getHostFromUrl(rpc);
66
+ let urlHost = host !== undefined ? host : Stdlib_JsError.throwWithMessage(`The RPC url for chain ` + String(chain) + ` is in incorrect format. The RPC url needs to start with either http:// or https://`);
67
+ let name = `RPC (` + urlHost + `)`;
61
68
  return {
62
- name: name,
63
- sourceFor: "Sync",
64
- chain: chain,
65
- poweredByHyperSync: false,
66
- pollingInterval: 10000,
67
- getBlockHashes: (function (param, param$1) {
68
- return Js_exn.raiseError("Svm does not support getting block hashes");
69
- }),
70
- getHeightOrThrow: (async function () {
71
- var timerRef = Hrtime.makeTimer();
72
- var height = await Rest.$$fetch(route, undefined, client);
73
- var seconds = Hrtime.toSecondsFloat(Hrtime.timeSince(timerRef));
74
- Prometheus.SourceRequestCount.increment(name, chain, "getSlot");
75
- Prometheus.SourceRequestCount.addSeconds(name, chain, "getSlot", seconds);
76
- return height;
77
- }),
78
- getItemsOrThrow: (function (param, param$1, param$2, param$3, param$4, param$5, param$6, param$7, param$8) {
79
- return Js_exn.raiseError("Svm does not support getting items");
80
- })
81
- };
69
+ name: name,
70
+ sourceFor: "Sync",
71
+ chain: chain,
72
+ poweredByHyperSync: false,
73
+ pollingInterval: 10000,
74
+ getBlockHashes: (param, param$1) => Stdlib_JsError.throwWithMessage("Svm does not support getting block hashes"),
75
+ getHeightOrThrow: async () => {
76
+ let timerRef = Hrtime.makeTimer();
77
+ let height = await Rest.fetch(route, undefined, client);
78
+ let seconds = Hrtime.toSecondsFloat(Hrtime.timeSince(timerRef));
79
+ Prometheus.SourceRequestCount.increment(name, chain, "getSlot");
80
+ Prometheus.SourceRequestCount.addSeconds(name, chain, "getSlot", seconds);
81
+ return height;
82
+ },
83
+ getItemsOrThrow: (param, param$1, param$2, param$3, param$4, param$5, param$6, param$7, param$8) => Stdlib_JsError.throwWithMessage("Svm does not support getting items")
84
+ };
82
85
  }
83
86
 
84
87
  export {
85
- cleanUpRawEventFieldsInPlace ,
86
- ecosystem ,
87
- GetFinalizedSlot ,
88
- makeRPCSource ,
88
+ cleanUpRawEventFieldsInPlace,
89
+ ecosystem,
90
+ GetFinalizedSlot,
91
+ makeRPCSource,
89
92
  }
90
- /* route Not a pure module */
93
+ /* ecosystem Not a pure module */
package/src/tui/Tui.res CHANGED
@@ -1,5 +1,4 @@
1
1
  open Ink
2
- open Belt
3
2
 
4
3
  module ChainLine = {
5
4
  @react.component
@@ -100,13 +99,13 @@ module App = {
100
99
 
101
100
  // useEffect to refresh state every 500ms
102
101
  React.useEffect(() => {
103
- let intervalId = Js.Global.setInterval(() => {
102
+ let intervalId = setInterval(() => {
104
103
  setState(_ => getState())
105
104
  }, 500)
106
105
 
107
106
  Some(
108
107
  () => {
109
- Js.Global.clearInterval(intervalId)
108
+ clearInterval(intervalId)
110
109
  },
111
110
  )
112
111
  }, [getState])
@@ -120,7 +119,7 @@ module App = {
120
119
  let hasProcessedToEndblock = cf->ChainFetcher.hasProcessedToEndblock
121
120
  let knownHeight =
122
121
  cf->ChainFetcher.hasProcessedToEndblock
123
- ? cf.fetchState.endBlock->Option.getWithDefault(cf.fetchState.knownHeight)
122
+ ? cf.fetchState.endBlock->Option.getOr(cf.fetchState.knownHeight)
124
123
  : cf.fetchState.knownHeight
125
124
 
126
125
  let firstEventBlock = cf.fetchState.firstEventBlock
@@ -130,10 +129,10 @@ module App = {
130
129
  // it's possible there are no events in that block range (ie firstEventBlock = None)
131
130
  // This ensures TUI still displays synced in this case
132
131
  Synced({
133
- firstEventBlockNumber: firstEventBlock->Option.getWithDefault(0),
132
+ firstEventBlockNumber: firstEventBlock->Option.getOr(0),
134
133
  latestProcessedBlock: cf.committedProgressBlockNumber,
135
- timestampCaughtUpToHeadOrEndblock: cf.timestampCaughtUpToHeadOrEndblock->Option.getWithDefault(
136
- Js.Date.now()->Js.Date.fromFloat,
134
+ timestampCaughtUpToHeadOrEndblock: cf.timestampCaughtUpToHeadOrEndblock->Option.getOr(
135
+ Date.now()->Date.fromTime,
137
136
  ),
138
137
  numEventsProcessed,
139
138
  })
@@ -199,7 +198,7 @@ module App = {
199
198
  />
200
199
  <Newline />
201
200
  {chains
202
- ->Array.mapWithIndex((i, chainData) => {
201
+ ->Array.mapWithIndex((chainData, i) => {
203
202
  <ChainLine
204
203
  key={i->Int.toString}
205
204
  chainId={chainData.chainId}
@@ -230,10 +229,22 @@ module App = {
230
229
  }
231
230
  }
232
231
  </Box>
233
- <Box flexDirection={Row}>
234
- <Text> {"Dev Console: "->React.string} </Text>
235
- <Text color={Info} underline=true> {`${Env.envioAppUrl}/console`->React.string} </Text>
236
- </Box>
232
+ {if Envio.isDevMode() {
233
+ <Box flexDirection={Row}>
234
+ <Text> {"Dev Console: "->React.string} </Text>
235
+ <Text color={Info} underline=true> {`${Env.envioAppUrl}/console`->React.string} </Text>
236
+ </Box>
237
+ } else {
238
+ React.null
239
+ }}
240
+ {switch (state.ctx.config.storage.clickhouse, Env.ClickHouse.host()) {
241
+ | (true, Some(host)) =>
242
+ <Box flexDirection={Row}>
243
+ <Text> {"ClickHouse: "->React.string} </Text>
244
+ <Text color={Info} underline=true> {`${host}/play`->React.string} </Text>
245
+ </Box>
246
+ | _ => React.null
247
+ }}
237
248
  <Messages config=state.ctx.config />
238
249
  </Box>
239
250
  }