envio 3.0.2 → 3.1.0-rc.1

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 (101) hide show
  1. package/README.md +0 -1
  2. package/evm.schema.json +15 -8
  3. package/fuel.schema.json +19 -12
  4. package/index.d.ts +0 -2
  5. package/package.json +6 -7
  6. package/rescript.json +1 -1
  7. package/src/Batch.res +4 -214
  8. package/src/Batch.res.mjs +6 -165
  9. package/src/ChainFetcher.res +12 -28
  10. package/src/ChainFetcher.res.mjs +8 -17
  11. package/src/ChainManager.res +10 -9
  12. package/src/ChainManager.res.mjs +6 -10
  13. package/src/Config.res +9 -25
  14. package/src/Config.res.mjs +17 -27
  15. package/src/Core.res +7 -0
  16. package/src/Ctx.res +1 -0
  17. package/src/Env.res +0 -8
  18. package/src/Env.res.mjs +0 -6
  19. package/src/EventConfigBuilder.res +13 -123
  20. package/src/EventConfigBuilder.res.mjs +6 -73
  21. package/src/EventProcessing.res +5 -29
  22. package/src/EventProcessing.res.mjs +11 -20
  23. package/src/EventUtils.res +0 -27
  24. package/src/EventUtils.res.mjs +0 -24
  25. package/src/FetchState.res +2 -15
  26. package/src/FetchState.res.mjs +3 -18
  27. package/src/GlobalState.res +26 -39
  28. package/src/GlobalState.res.mjs +12 -40
  29. package/src/HandlerLoader.res +6 -5
  30. package/src/HandlerLoader.res.mjs +27 -9
  31. package/src/HandlerRegister.res +1 -12
  32. package/src/HandlerRegister.res.mjs +1 -6
  33. package/src/HandlerRegister.resi +1 -1
  34. package/src/Hasura.res +96 -32
  35. package/src/Hasura.res.mjs +93 -38
  36. package/src/InMemoryStore.res +205 -45
  37. package/src/InMemoryStore.res.mjs +157 -40
  38. package/src/InMemoryTable.res +165 -249
  39. package/src/InMemoryTable.res.mjs +156 -227
  40. package/src/Internal.res +10 -34
  41. package/src/Internal.res.mjs +9 -3
  42. package/src/LoadLayer.res +5 -5
  43. package/src/LoadLayer.res.mjs +5 -5
  44. package/src/LogSelection.res +15 -19
  45. package/src/LogSelection.res.mjs +5 -6
  46. package/src/Main.res +4 -6
  47. package/src/Main.res.mjs +26 -15
  48. package/src/Persistence.res +7 -132
  49. package/src/Persistence.res.mjs +1 -102
  50. package/src/PgStorage.res +57 -40
  51. package/src/PgStorage.res.mjs +60 -34
  52. package/src/ReorgDetection.res +35 -58
  53. package/src/ReorgDetection.res.mjs +21 -29
  54. package/src/SimulateItems.res.mjs +21 -3
  55. package/src/Sink.res +2 -2
  56. package/src/Sink.res.mjs +1 -1
  57. package/src/TableIndices.res +9 -2
  58. package/src/TableIndices.res.mjs +7 -1
  59. package/src/TestIndexer.res +53 -60
  60. package/src/TestIndexer.res.mjs +77 -63
  61. package/src/TestIndexerProxyStorage.res +4 -14
  62. package/src/TestIndexerProxyStorage.res.mjs +1 -5
  63. package/src/UserContext.res +2 -4
  64. package/src/UserContext.res.mjs +4 -5
  65. package/src/Utils.res +0 -2
  66. package/src/Utils.res.mjs +0 -3
  67. package/src/bindings/ClickHouse.res +45 -38
  68. package/src/bindings/ClickHouse.res.mjs +16 -17
  69. package/src/bindings/Vitest.res +3 -0
  70. package/src/db/InternalTable.res +59 -18
  71. package/src/db/InternalTable.res.mjs +82 -51
  72. package/src/db/Table.res +9 -2
  73. package/src/db/Table.res.mjs +10 -7
  74. package/src/sources/EnvioApiClient.res +15 -0
  75. package/src/sources/EnvioApiClient.res.mjs +24 -0
  76. package/src/sources/EvmChain.res +32 -10
  77. package/src/sources/EvmChain.res.mjs +31 -5
  78. package/src/sources/HyperFuelSource.res +15 -58
  79. package/src/sources/HyperFuelSource.res.mjs +20 -39
  80. package/src/sources/HyperSync.res +54 -100
  81. package/src/sources/HyperSync.res.mjs +67 -96
  82. package/src/sources/HyperSync.resi +4 -22
  83. package/src/sources/HyperSyncClient.res +70 -247
  84. package/src/sources/HyperSyncClient.res.mjs +47 -46
  85. package/src/sources/HyperSyncSource.res +94 -166
  86. package/src/sources/HyperSyncSource.res.mjs +100 -127
  87. package/src/sources/RpcSource.res +43 -22
  88. package/src/sources/RpcSource.res.mjs +50 -35
  89. package/src/sources/SimulateSource.res +1 -7
  90. package/src/sources/SimulateSource.res.mjs +1 -7
  91. package/src/sources/Source.res +10 -1
  92. package/src/sources/Source.res.mjs +3 -0
  93. package/src/sources/SourceManager.res +177 -8
  94. package/src/sources/SourceManager.res.mjs +141 -3
  95. package/src/sources/SourceManager.resi +19 -0
  96. package/src/tui/Tui.res +44 -6
  97. package/src/tui/Tui.res.mjs +56 -8
  98. package/src/tui/components/TuiData.res +3 -0
  99. package/svm.schema.json +11 -4
  100. package/src/sources/HyperSyncJsonApi.res +0 -390
  101. package/src/sources/HyperSyncJsonApi.res.mjs +0 -237
@@ -15,6 +15,7 @@ import InkBigText from "ink-big-text";
15
15
  import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
16
16
  import * as SourceManager from "../sources/SourceManager.res.mjs";
17
17
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
18
+ import * as Primitive_float from "@rescript/runtime/lib/es6/Primitive_float.js";
18
19
  import * as JsxRuntime from "react/jsx-runtime";
19
20
  import * as BufferedProgressBar from "./components/BufferedProgressBar.res.mjs";
20
21
 
@@ -145,7 +146,7 @@ function computeEps(samples) {
145
146
  }
146
147
  }
147
148
 
148
- function use(totalEventsProcessed) {
149
+ function use(totalEventsProcessed, tick) {
149
150
  let match = React.useState(() => []);
150
151
  let setSamples = match[1];
151
152
  React.useEffect(() => {
@@ -158,7 +159,7 @@ function use(totalEventsProcessed) {
158
159
  events: totalEventsProcessed
159
160
  }]);
160
161
  });
161
- }, [totalEventsProcessed]);
162
+ }, [tick]);
162
163
  return computeEps(match[0]);
163
164
  }
164
165
 
@@ -195,11 +196,11 @@ let TotalEventsProcessed = {
195
196
  function Tui$App(props) {
196
197
  let getState = props.getState;
197
198
  let stdoutColumns = Ink.Hooks.useStdoutColumns();
198
- let match = React.useState(() => getState());
199
- let setState = match[1];
200
- let state = match[0];
199
+ let match = React.useState(() => 0);
200
+ let setTick = match[1];
201
+ let state = getState();
201
202
  React.useEffect(() => {
202
- let intervalId = setInterval(() => setState(param => getState()), 500);
203
+ let intervalId = setInterval(() => setTick(t => t + 1 | 0), 500);
203
204
  return () => {
204
205
  clearInterval(intervalId);
205
206
  };
@@ -254,7 +255,10 @@ function Tui$App(props) {
254
255
  poweredByHyperSync: SourceManager.getActiveSource(cf.sourceManager).poweredByHyperSync,
255
256
  progress: progress,
256
257
  latestFetchedBlockNumber: latestFetchedBlockNumber,
257
- knownHeight: knownHeight
258
+ knownHeight: knownHeight,
259
+ rateLimitTimeMs: SourceManager.getRateLimitTimeMs(cf.sourceManager),
260
+ isRateLimited: SourceManager.isRateLimited(cf.sourceManager),
261
+ rateLimitResetInMs: SourceManager.getRateLimitResetInMs(cf.sourceManager)
258
262
  };
259
263
  });
260
264
  let totalEventsProcessed = Stdlib_Array.reduce(chains, 0, (acc, chain) => acc + chain.eventsProcessed);
@@ -266,7 +270,50 @@ function Tui$App(props) {
266
270
  return acc;
267
271
  }
268
272
  });
269
- let eventsPerSecond = use(totalEventsProcessed);
273
+ let eventsPerSecond = use(totalEventsProcessed, match[0]);
274
+ let maxRateLimitTimeMs = Stdlib_Array.reduce(chains, 0, (acc, chain) => Primitive_float.max(acc, chain.rateLimitTimeMs));
275
+ let maxResetInMs = Stdlib_Array.reduce(chains, 0.0, (acc, chain) => Primitive_float.max(acc, Stdlib_Option.getOr(chain.rateLimitResetInMs, 0.0)));
276
+ let tmp;
277
+ if (maxRateLimitTimeMs > 1000) {
278
+ let rateLimitSecs = Math.round(maxRateLimitTimeMs / 1000);
279
+ let activeSuffix;
280
+ if (maxResetInMs > 0.0) {
281
+ let resetSecs = Primitive_float.max(1.0, Math.ceil(maxResetInMs / 1000));
282
+ activeSuffix = ` (⏳ ` + TuiData.formatFloatLocaleString(resetSecs) + `s until reset)`;
283
+ } else {
284
+ activeSuffix = "";
285
+ }
286
+ tmp = JsxRuntime.jsxs(Ink$1.Box, {
287
+ children: [
288
+ JsxRuntime.jsx(Ink.Newline.make, {}),
289
+ JsxRuntime.jsx(Ink$1.Text, {
290
+ children: `Backfill ` + TuiData.formatFloatLocaleString(rateLimitSecs) + `s slower due to your plan's rate limit` + activeSuffix,
291
+ color: "#FF8269"
292
+ }),
293
+ JsxRuntime.jsxs(Ink$1.Text, {
294
+ children: [
295
+ JsxRuntime.jsx(Ink$1.Text, {
296
+ children: "Upgrade at ",
297
+ color: "#FF8269"
298
+ }),
299
+ JsxRuntime.jsx(Ink$1.Text, {
300
+ children: "https://envio.dev/app/api-tokens",
301
+ color: "#FF8269",
302
+ underline: true
303
+ }),
304
+ JsxRuntime.jsx(Ink$1.Text, {
305
+ children: " for higher rate limits.",
306
+ color: "#FF8269"
307
+ })
308
+ ],
309
+ color: "#FF8269"
310
+ })
311
+ ],
312
+ flexDirection: "column"
313
+ });
314
+ } else {
315
+ tmp = null;
316
+ }
270
317
  let defaultPassword = "testing";
271
318
  let match$1 = state.ctx.config.storage.clickhouse;
272
319
  let match$2 = Env.ClickHouse.host();
@@ -302,6 +349,7 @@ function Tui$App(props) {
302
349
  chains: chains,
303
350
  indexerStartTime: state.indexerStartTime
304
351
  }),
352
+ tmp,
305
353
  JsxRuntime.jsx(Ink.Newline.make, {}),
306
354
  JsxRuntime.jsxs(Ink$1.Box, {
307
355
  children: [
@@ -30,6 +30,9 @@ type chain = {
30
30
  progress: progress,
31
31
  latestFetchedBlockNumber: int,
32
32
  knownHeight: int,
33
+ rateLimitTimeMs: float,
34
+ isRateLimited: bool,
35
+ rateLimitResetInMs: option<float>,
33
36
  }
34
37
 
35
38
  let minOfOption: (int, option<int>) => int = (a: int, b: option<int>) => {
package/svm.schema.json CHANGED
@@ -4,6 +4,10 @@
4
4
  "description": "Schema for a YAML config for an envio Svm indexer",
5
5
  "type": "object",
6
6
  "properties": {
7
+ "name": {
8
+ "description": "Name of the project",
9
+ "type": "string"
10
+ },
7
11
  "description": {
8
12
  "description": "Description of the project",
9
13
  "type": [
@@ -11,10 +15,6 @@
11
15
  "null"
12
16
  ]
13
17
  },
14
- "name": {
15
- "description": "Name of the project",
16
- "type": "string"
17
- },
18
18
  "schema": {
19
19
  "description": "Custom path to schema.graphql file",
20
20
  "type": [
@@ -133,6 +133,13 @@
133
133
  "Chain": {
134
134
  "type": "object",
135
135
  "properties": {
136
+ "skip": {
137
+ "description": "Excludes the chain from indexing and migrations. Code generation is unaffected. For testing, prefer using a test framework instead.",
138
+ "type": [
139
+ "boolean",
140
+ "null"
141
+ ]
142
+ },
136
143
  "rpc": {
137
144
  "description": "RPC endpoint URL for connecting to the Svm cluster to fetch blockchain data.",
138
145
  "type": "string"
@@ -1,390 +0,0 @@
1
- type unchecksummedEthAddress = string
2
-
3
- module QueryTypes = {
4
- type blockFieldOptions =
5
- | @as("number") Number
6
- | @as("hash") Hash
7
- | @as("parent_hash") ParentHash
8
- | @as("nonce") Nonce
9
- | @as("sha3_uncles") Sha3Uncles
10
- | @as("logs_bloom") LogsBloom
11
- | @as("transactions_root") TransactionsRoot
12
- | @as("state_root") StateRoot
13
- | @as("receipts_root") ReceiptsRoot
14
- | @as("miner") Miner
15
- | @as("difficulty") Difficulty
16
- | @as("total_difficulty") TotalDifficulty
17
- | @as("extra_data") ExtraData
18
- | @as("size") Size
19
- | @as("gas_limit") GasLimit
20
- | @as("gas_used") GasUsed
21
- | @as("timestamp") Timestamp
22
- | @as("uncles") Uncles
23
- | @as("base_fee_per_gas") BaseFeePerGas
24
-
25
- let blockFieldOptionsSchema = S.enum([
26
- Number,
27
- Hash,
28
- ParentHash,
29
- Nonce,
30
- Sha3Uncles,
31
- LogsBloom,
32
- TransactionsRoot,
33
- StateRoot,
34
- ReceiptsRoot,
35
- Miner,
36
- Difficulty,
37
- TotalDifficulty,
38
- ExtraData,
39
- Size,
40
- GasLimit,
41
- GasUsed,
42
- Timestamp,
43
- Uncles,
44
- BaseFeePerGas,
45
- ])
46
-
47
- type blockFieldSelection = array<blockFieldOptions>
48
-
49
- let blockFieldSelectionSchema = S.array(blockFieldOptionsSchema)
50
-
51
- type transactionFieldOptions =
52
- | @as("block_hash") BlockHash
53
- | @as("block_number") BlockNumber
54
- | @as("from") From
55
- | @as("gas") Gas
56
- | @as("gas_price") GasPrice
57
- | @as("hash") Hash
58
- | @as("input") Input
59
- | @as("nonce") Nonce
60
- | @as("to") To
61
- | @as("transaction_index") TransactionIndex
62
- | @as("value") Value
63
- | @as("v") V
64
- | @as("r") R
65
- | @as("s") S
66
- | @as("max_priority_fee_per_gas") MaxPriorityFeePerGas
67
- | @as("max_fee_per_gas") MaxFeePerGas
68
- | @as("chain_id") ChainId
69
- | @as("cumulative_gas_used") CumulativeGasUsed
70
- | @as("effective_gas_price") EffectiveGasPrice
71
- | @as("gas_used") GasUsed
72
- | @as("contract_address") ContractAddress
73
- | @as("logs_bloom") LogsBloom
74
- | @as("type") Type
75
- | @as("root") Root
76
- | @as("status") Status
77
- | @as("sighash") Sighash
78
-
79
- let transactionFieldOptionsSchema = S.enum([
80
- BlockHash,
81
- BlockNumber,
82
- From,
83
- Gas,
84
- GasPrice,
85
- Hash,
86
- Input,
87
- Nonce,
88
- To,
89
- TransactionIndex,
90
- Value,
91
- V,
92
- R,
93
- S,
94
- MaxPriorityFeePerGas,
95
- MaxFeePerGas,
96
- ChainId,
97
- CumulativeGasUsed,
98
- EffectiveGasPrice,
99
- GasUsed,
100
- ContractAddress,
101
- LogsBloom,
102
- Type,
103
- Root,
104
- Status,
105
- Sighash,
106
- ])
107
-
108
- type transactionFieldSelection = array<transactionFieldOptions>
109
-
110
- let transactionFieldSelectionSchema = S.array(transactionFieldOptionsSchema)
111
-
112
- type logFieldOptions =
113
- | @as("removed") Removed
114
- | @as("log_index") LogIndex
115
- | @as("transaction_index") TransactionIndex
116
- | @as("transaction_hash") TransactionHash
117
- | @as("block_hash") BlockHash
118
- | @as("block_number") BlockNumber
119
- | @as("address") Address
120
- | @as("data") Data
121
- | @as("topic0") Topic0
122
- | @as("topic1") Topic1
123
- | @as("topic2") Topic2
124
- | @as("topic3") Topic3
125
-
126
- let logFieldOptionsSchema = S.enum([
127
- Removed,
128
- LogIndex,
129
- TransactionIndex,
130
- TransactionHash,
131
- BlockHash,
132
- BlockNumber,
133
- Address,
134
- Data,
135
- Topic0,
136
- Topic1,
137
- Topic2,
138
- Topic3,
139
- ])
140
-
141
- type logFieldSelection = array<logFieldOptions>
142
-
143
- let logFieldSelectionSchema = S.array(logFieldOptionsSchema)
144
-
145
- type fieldSelection = {
146
- block?: blockFieldSelection,
147
- transaction?: transactionFieldSelection,
148
- log?: logFieldSelection,
149
- }
150
-
151
- let fieldSelectionSchema = S.object(s => {
152
- block: ?s.field("block", S.option(blockFieldSelectionSchema)),
153
- transaction: ?s.field("transaction", S.option(transactionFieldSelectionSchema)),
154
- log: ?s.field("log", S.option(logFieldSelectionSchema)),
155
- })
156
-
157
- type logParams = {
158
- address?: array<Address.t>,
159
- topics: array<array<EvmTypes.Hex.t>>,
160
- }
161
-
162
- let logParamsSchema = S.object(s => {
163
- address: ?s.field("address", S.option(S.array(Address.schema))),
164
- topics: s.field("topics", S.array(S.array(EvmTypes.Hex.schema))),
165
- })
166
-
167
- type transactionParams = {
168
- from?: array<Address.t>,
169
- to?: array<Address.t>,
170
- sighash?: array<string>,
171
- }
172
-
173
- let transactionParamsSchema = S.object(s => {
174
- from: ?s.field("from", S.option(S.array(Address.schema))),
175
- to: ?s.field("to", S.option(S.array(Address.schema))),
176
- sighash: ?s.field("sighash", S.option(S.array(S.string))),
177
- })
178
-
179
- type postQueryBody = {
180
- fromBlock: int,
181
- toBlockExclusive?: int,
182
- logs?: array<logParams>,
183
- transactions?: array<transactionParams>,
184
- fieldSelection: fieldSelection,
185
- maxNumLogs?: int,
186
- includeAllBlocks?: bool,
187
- }
188
-
189
- let postQueryBodySchema = S.object(s => {
190
- fromBlock: s.field("from_block", S.int),
191
- toBlockExclusive: ?s.field("to_block", S.option(S.int)),
192
- logs: ?s.field("logs", S.option(S.array(logParamsSchema))),
193
- transactions: ?s.field("transactions", S.option(S.array(transactionParamsSchema))),
194
- fieldSelection: s.field("field_selection", fieldSelectionSchema),
195
- maxNumLogs: ?s.field("max_num_logs", S.option(S.int)),
196
- includeAllBlocks: ?s.field("include_all_blocks", S.option(S.bool)),
197
- })
198
- }
199
-
200
- module ResponseTypes = {
201
- type blockData = {
202
- number?: int,
203
- hash?: string,
204
- parentHash?: string,
205
- nonce?: option<int>,
206
- sha3Uncles?: string,
207
- logsBloom?: string,
208
- transactionsRoot?: string,
209
- stateRoot?: string,
210
- receiptsRoot?: string,
211
- miner?: unchecksummedEthAddress,
212
- difficulty?: option<bigint>,
213
- totalDifficulty?: option<bigint>,
214
- extraData?: string,
215
- size?: bigint,
216
- gasLimit?: bigint,
217
- gasUsed?: bigint,
218
- timestamp?: bigint,
219
- uncles?: option<string>,
220
- baseFeePerGas?: option<bigint>,
221
- }
222
-
223
- let blockDataSchema = S.object(s => {
224
- number: ?s.field("number", S.option(S.int)),
225
- hash: ?s.field("hash", S.option(S.string)),
226
- parentHash: ?s.field("parent_hash", S.option(S.string)),
227
- nonce: ?s.field("nonce", S.option(S.null(S.int))),
228
- sha3Uncles: ?s.field("sha3_uncles", S.option(S.string)),
229
- logsBloom: ?s.field("logs_bloom", S.option(S.string)),
230
- transactionsRoot: ?s.field("transactions_root", S.option(S.string)),
231
- stateRoot: ?s.field("state_root", S.option(S.string)),
232
- receiptsRoot: ?s.field("receipts_root", S.option(S.string)),
233
- miner: ?s.field("miner", S.option(S.string)),
234
- difficulty: ?s.field("difficulty", S.option(S.null(Utils.BigInt.schema))),
235
- totalDifficulty: ?s.field("total_difficulty", S.option(S.null(Utils.BigInt.schema))),
236
- extraData: ?s.field("extra_data", S.option(S.string)),
237
- size: ?s.field("size", S.option(Utils.BigInt.schema)),
238
- gasLimit: ?s.field("gas_limit", S.option(Utils.BigInt.schema)),
239
- gasUsed: ?s.field("gas_used", S.option(Utils.BigInt.schema)),
240
- timestamp: ?s.field("timestamp", S.option(Utils.BigInt.schema)),
241
- uncles: ?s.field("unclus", S.option(S.null(S.string))),
242
- baseFeePerGas: ?s.field("base_fee_per_gas", S.option(S.null(Utils.BigInt.schema))),
243
- })
244
-
245
- type transactionData = {
246
- blockHash?: string,
247
- blockNumber?: int,
248
- from?: option<unchecksummedEthAddress>,
249
- gas?: bigint,
250
- gasPrice?: option<bigint>,
251
- hash?: string,
252
- input?: string,
253
- nonce?: int,
254
- to?: option<unchecksummedEthAddress>,
255
- transactionIndex?: int,
256
- value?: bigint,
257
- v?: option<string>,
258
- r?: option<string>,
259
- s?: option<string>,
260
- maxPriorityFeePerGas?: option<bigint>,
261
- maxFeePerGas?: option<bigint>,
262
- chainId?: option<int>,
263
- cumulativeGasUsed?: bigint,
264
- effectiveGasPrice?: bigint,
265
- gasUsed?: bigint,
266
- contractAddress?: option<unchecksummedEthAddress>,
267
- logsBoom?: string,
268
- type_?: option<int>,
269
- root?: option<string>,
270
- status?: option<int>,
271
- sighash?: option<string>,
272
- }
273
-
274
- let transactionDataSchema = S.object(s => {
275
- blockHash: ?s.field("block_hash", S.option(S.string)),
276
- blockNumber: ?s.field("block_number", S.option(S.int)),
277
- from: ?s.field("from", S.option(S.null(S.string))),
278
- gas: ?s.field("gas", S.option(Utils.BigInt.schema)),
279
- gasPrice: ?s.field("gas_price", S.option(S.null(Utils.BigInt.schema))),
280
- hash: ?s.field("hash", S.option(S.string)),
281
- input: ?s.field("input", S.option(S.string)),
282
- nonce: ?s.field("nonce", S.option(S.int)),
283
- to: ?s.field("to", S.option(S.null(S.string))),
284
- transactionIndex: ?s.field("transaction_index", S.option(S.int)),
285
- value: ?s.field("value", S.option(Utils.BigInt.schema)),
286
- v: ?s.field("v", S.option(S.null(S.string))),
287
- r: ?s.field("r", S.option(S.null(S.string))),
288
- s: ?s.field("s", S.option(S.null(S.string))),
289
- maxPriorityFeePerGas: ?s.field(
290
- "max_priority_fee_per_gas",
291
- S.option(S.null(Utils.BigInt.schema)),
292
- ),
293
- maxFeePerGas: ?s.field("max_fee_per_gas", S.option(S.null(Utils.BigInt.schema))),
294
- chainId: ?s.field("chain_id", S.option(S.null(S.int))),
295
- cumulativeGasUsed: ?s.field("cumulative_gas_used", S.option(Utils.BigInt.schema)),
296
- effectiveGasPrice: ?s.field("effective_gas_price", S.option(Utils.BigInt.schema)),
297
- gasUsed: ?s.field("gas_used", S.option(Utils.BigInt.schema)),
298
- contractAddress: ?s.field("contract_address", S.option(S.null(S.string))),
299
- logsBoom: ?s.field("logs_bloom", S.option(S.string)),
300
- type_: ?s.field("type", S.option(S.null(S.int))),
301
- root: ?s.field("root", S.option(S.null(S.string))),
302
- status: ?s.field("status", S.option(S.null(S.int))),
303
- sighash: ?s.field("sighash", S.option(S.null(S.string))),
304
- })
305
-
306
- type logData = {
307
- removed?: option<bool>,
308
- index?: int,
309
- transactionIndex?: int,
310
- transactionHash?: string,
311
- blockHash?: string,
312
- blockNumber?: int,
313
- address?: unchecksummedEthAddress,
314
- data?: string,
315
- topic0?: option<EvmTypes.Hex.t>,
316
- topic1?: option<EvmTypes.Hex.t>,
317
- topic2?: option<EvmTypes.Hex.t>,
318
- topic3?: option<EvmTypes.Hex.t>,
319
- }
320
-
321
- let logDataSchema = S.object(s => {
322
- removed: ?s.field("removed", S.option(S.null(S.bool))),
323
- index: ?s.field("log_index", S.option(S.int)),
324
- transactionIndex: ?s.field("transaction_index", S.option(S.int)),
325
- transactionHash: ?s.field("transaction_hash", S.option(S.string)),
326
- blockHash: ?s.field("block_hash", S.option(S.string)),
327
- blockNumber: ?s.field("block_number", S.option(S.int)),
328
- address: ?s.field("address", S.option(S.string)),
329
- data: ?s.field("data", S.option(S.string)),
330
- topic0: ?s.field("topic0", S.option(S.null(EvmTypes.Hex.schema))),
331
- topic1: ?s.field("topic1", S.option(S.null(EvmTypes.Hex.schema))),
332
- topic2: ?s.field("topic2", S.option(S.null(EvmTypes.Hex.schema))),
333
- topic3: ?s.field("topic3", S.option(S.null(EvmTypes.Hex.schema))),
334
- })
335
-
336
- type data = {
337
- blocks?: array<blockData>,
338
- transactions?: array<transactionData>,
339
- logs?: array<logData>,
340
- }
341
-
342
- let dataSchema = S.object(s => {
343
- blocks: ?s.field("blocks", S.array(blockDataSchema)->S.option),
344
- transactions: ?s.field("transactions", S.array(transactionDataSchema)->S.option),
345
- logs: ?s.field("logs", S.array(logDataSchema)->S.option),
346
- })
347
-
348
- type queryResponse = {
349
- data: array<data>,
350
- archiveHeight: int,
351
- nextBlock: int,
352
- totalTime: int,
353
- }
354
-
355
- let queryResponseSchema = S.object(s => {
356
- data: s.field("data", S.array(dataSchema)),
357
- archiveHeight: s.field("archive_height", S.int),
358
- nextBlock: s.field("next_block", S.int),
359
- totalTime: s.field("total_execution_time", S.int),
360
- })
361
- }
362
-
363
- let queryRoute = Rest.route(() => {
364
- path: "/query",
365
- method: Post,
366
- input: s =>
367
- {
368
- "query": s.body(QueryTypes.postQueryBodySchema),
369
- "token": s.auth(Bearer),
370
- },
371
- responses: [s => s.data(ResponseTypes.queryResponseSchema)],
372
- })
373
-
374
- @unboxed
375
- type heightResult = Value(int) | ErrorMessage(string)
376
-
377
- let heightRoute = Rest.route(() => {
378
- path: "/height",
379
- method: Get,
380
- input: s => s.auth(Bearer),
381
- responses: [
382
- s =>
383
- s.data(
384
- S.union([
385
- S.object(s => Value(s.field("height", S.int))),
386
- S.string->S.shape(s => ErrorMessage(s)),
387
- ]),
388
- ),
389
- ],
390
- })