1use crate::{
4 api::Namespace,
5 helpers::{self, CallFuture},
6 transports::ic_http_client::CallOptions,
7 types::{
8 Address, Block, BlockHeader, BlockId, BlockNumber, Bytes, CallRequest, FeeHistory, Filter, Index, Log, Proof,
9 SyncState, Transaction, TransactionId, TransactionReceipt, TransactionRequest, Work, H256, H520, H64, U256,
10 U64,
11 },
12 Transport,
13};
14
15#[derive(Debug, Clone)]
17pub struct Eth<T> {
18 transport: T,
19}
20
21impl<T: Transport> Namespace<T> for Eth<T> {
22 fn new(transport: T) -> Self
23 where
24 Self: Sized,
25 {
26 Eth { transport }
27 }
28
29 fn transport(&self) -> &T {
30 &self.transport
31 }
32}
33
34impl<T: Transport> Eth<T> {
35 pub fn accounts(&self, options: CallOptions) -> CallFuture<Vec<Address>, T::Out> {
37 CallFuture::new(self.transport.execute("eth_accounts", vec![], options))
38 }
39
40 pub fn block_number(&self, options: CallOptions) -> CallFuture<U64, T::Out> {
42 CallFuture::new(self.transport.execute("eth_blockNumber", vec![], options))
43 }
44
45 pub fn call(&self, req: CallRequest, block: Option<BlockId>, options: CallOptions) -> CallFuture<Bytes, T::Out> {
47 let req = helpers::serialize(&req);
48 let block = helpers::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
49
50 CallFuture::new(self.transport.execute("eth_call", vec![req, block], options))
51 }
52
53 pub fn coinbase(&self, options: CallOptions) -> CallFuture<Address, T::Out> {
55 CallFuture::new(self.transport.execute("eth_coinbase", vec![], options))
56 }
57
58 pub fn compile_lll(&self, code: String, options: CallOptions) -> CallFuture<Bytes, T::Out> {
60 let code = helpers::serialize(&code);
61 CallFuture::new(self.transport.execute("eth_compileLLL", vec![code], options))
62 }
63
64 pub fn compile_solidity(&self, code: String, options: CallOptions) -> CallFuture<Bytes, T::Out> {
66 let code = helpers::serialize(&code);
67 CallFuture::new(self.transport.execute("eth_compileSolidity", vec![code], options))
68 }
69
70 pub fn compile_serpent(&self, code: String, options: CallOptions) -> CallFuture<Bytes, T::Out> {
72 let code = helpers::serialize(&code);
73 CallFuture::new(self.transport.execute("eth_compileSerpent", vec![code], options))
74 }
75
76 pub fn estimate_gas(
78 &self,
79 req: CallRequest,
80 block: Option<BlockNumber>,
81 options: CallOptions,
82 ) -> CallFuture<U256, T::Out> {
83 let req = helpers::serialize(&req);
84
85 let args = match block {
86 Some(block) => vec![req, helpers::serialize(&block)],
87 None => vec![req],
88 };
89
90 CallFuture::new(self.transport.execute("eth_estimateGas", args, options))
91 }
92
93 pub fn max_priority_fee_per_gas(&self, options: CallOptions) -> CallFuture<U256, T::Out> {
95 CallFuture::new(self.transport.execute("eth_maxPriorityFeePerGas", vec![], options))
96 }
97
98 pub fn gas_price(&self, options: CallOptions) -> CallFuture<U256, T::Out> {
100 CallFuture::new(self.transport.execute("eth_gasPrice", vec![], options))
101 }
102
103 pub fn fee_history(
106 &self,
107 block_count: U256,
108 newest_block: BlockNumber,
109 reward_percentiles: Option<Vec<f64>>,
110 options: CallOptions,
111 ) -> CallFuture<FeeHistory, T::Out> {
112 let block_count = helpers::serialize(&block_count);
113 let newest_block = helpers::serialize(&newest_block);
114 let reward_percentiles = helpers::serialize(&reward_percentiles);
115
116 CallFuture::new(self.transport.execute(
117 "eth_feeHistory",
118 vec![block_count, newest_block, reward_percentiles],
119 options,
120 ))
121 }
122
123 pub fn balance(
125 &self,
126 address: Address,
127 block: Option<BlockNumber>,
128 options: CallOptions,
129 ) -> CallFuture<U256, T::Out> {
130 let address = helpers::serialize(&address);
131 let block = helpers::serialize(&block.unwrap_or(BlockNumber::Latest));
132
133 CallFuture::new(self.transport.execute("eth_getBalance", vec![address, block], options))
134 }
135
136 pub fn logs(&self, filter: Filter, options: CallOptions) -> CallFuture<Vec<Log>, T::Out> {
138 let filter = helpers::serialize(&filter);
139 CallFuture::new(self.transport.execute("eth_getLogs", vec![filter], options))
140 }
141
142 pub fn block(&self, block: BlockId, options: CallOptions) -> CallFuture<Option<Block<H256>>, T::Out> {
144 let include_txs = helpers::serialize(&false);
145
146 let result = match block {
147 BlockId::Hash(hash) => {
148 let hash = helpers::serialize(&hash);
149 self.transport
150 .execute("eth_getBlockByHash", vec![hash, include_txs], options)
151 }
152 BlockId::Number(num) => {
153 let num = helpers::serialize(&num);
154 self.transport
155 .execute("eth_getBlockByNumber", vec![num, include_txs], options)
156 }
157 };
158
159 CallFuture::new(result)
160 }
161
162 pub fn block_with_txs(
164 &self,
165 block: BlockId,
166 options: CallOptions,
167 ) -> CallFuture<Option<Block<Transaction>>, T::Out> {
168 let include_txs = helpers::serialize(&true);
169
170 let result = match block {
171 BlockId::Hash(hash) => {
172 let hash = helpers::serialize(&hash);
173 self.transport
174 .execute("eth_getBlockByHash", vec![hash, include_txs], options)
175 }
176 BlockId::Number(num) => {
177 let num = helpers::serialize(&num);
178 self.transport
179 .execute("eth_getBlockByNumber", vec![num, include_txs], options)
180 }
181 };
182
183 CallFuture::new(result)
184 }
185
186 pub fn block_transaction_count(&self, block: BlockId, options: CallOptions) -> CallFuture<Option<U256>, T::Out> {
188 let result = match block {
189 BlockId::Hash(hash) => {
190 let hash = helpers::serialize(&hash);
191 self.transport
192 .execute("eth_getBlockTransactionCountByHash", vec![hash], options)
193 }
194 BlockId::Number(num) => {
195 let num = helpers::serialize(&num);
196 self.transport
197 .execute("eth_getBlockTransactionCountByNumber", vec![num], options)
198 }
199 };
200
201 CallFuture::new(result)
202 }
203
204 pub fn code(
206 &self,
207 address: Address,
208 block: Option<BlockNumber>,
209 options: CallOptions,
210 ) -> CallFuture<Bytes, T::Out> {
211 let address = helpers::serialize(&address);
212 let block = helpers::serialize(&block.unwrap_or(BlockNumber::Latest));
213
214 CallFuture::new(self.transport.execute("eth_getCode", vec![address, block], options))
215 }
216
217 pub fn compilers(&self, options: CallOptions) -> CallFuture<Vec<String>, T::Out> {
219 CallFuture::new(self.transport.execute("eth_getCompilers", vec![], options))
220 }
221
222 pub fn chain_id(&self, options: CallOptions) -> CallFuture<U256, T::Out> {
224 CallFuture::new(self.transport.execute("eth_chainId", vec![], options))
225 }
226
227 pub fn request_accounts(&self, options: CallOptions) -> CallFuture<Vec<Address>, T::Out> {
231 CallFuture::new(self.transport.execute("eth_requestAccounts", vec![], options))
232 }
233
234 pub fn storage(
236 &self,
237 address: Address,
238 idx: U256,
239 block: Option<BlockNumber>,
240 options: CallOptions,
241 ) -> CallFuture<H256, T::Out> {
242 let address = helpers::serialize(&address);
243 let idx = helpers::serialize(&idx);
244 let block = helpers::serialize(&block.unwrap_or(BlockNumber::Latest));
245
246 CallFuture::new(
247 self.transport
248 .execute("eth_getStorageAt", vec![address, idx, block], options),
249 )
250 }
251
252 pub fn transaction_count(
254 &self,
255 address: Address,
256 block: Option<BlockNumber>,
257 options: CallOptions,
258 ) -> CallFuture<U256, T::Out> {
259 let address = helpers::serialize(&address);
260 let block = helpers::serialize(&block.unwrap_or(BlockNumber::Latest));
261
262 CallFuture::new(
263 self.transport
264 .execute("eth_getTransactionCount", vec![address, block], options),
265 )
266 }
267
268 pub fn transaction(&self, id: TransactionId, options: CallOptions) -> CallFuture<Option<Transaction>, T::Out> {
270 let result = match id {
271 TransactionId::Hash(hash) => {
272 let hash = helpers::serialize(&hash);
273 self.transport.execute("eth_getTransactionByHash", vec![hash], options)
274 }
275 TransactionId::Block(BlockId::Hash(hash), index) => {
276 let hash = helpers::serialize(&hash);
277 let idx = helpers::serialize(&index);
278 self.transport
279 .execute("eth_getTransactionByBlockHashAndIndex", vec![hash, idx], options)
280 }
281 TransactionId::Block(BlockId::Number(number), index) => {
282 let number = helpers::serialize(&number);
283 let idx = helpers::serialize(&index);
284 self.transport
285 .execute("eth_getTransactionByBlockNumberAndIndex", vec![number, idx], options)
286 }
287 };
288
289 CallFuture::new(result)
290 }
291
292 pub fn transaction_receipt(
294 &self,
295 hash: H256,
296 options: CallOptions,
297 ) -> CallFuture<Option<TransactionReceipt>, T::Out> {
298 let hash = helpers::serialize(&hash);
299
300 CallFuture::new(self.transport.execute("eth_getTransactionReceipt", vec![hash], options))
301 }
302
303 pub fn uncle_header(
308 &self,
309 block: BlockId,
310 index: Index,
311 options: CallOptions,
312 ) -> CallFuture<Option<BlockHeader>, T::Out> {
313 self.fetch_uncle(block, index, options)
314 }
315
316 pub fn uncle(&self, block: BlockId, index: Index, options: CallOptions) -> CallFuture<Option<Block<H256>>, T::Out> {
318 self.fetch_uncle(block, index, options)
319 }
320
321 fn fetch_uncle<X>(&self, block: BlockId, index: Index, options: CallOptions) -> CallFuture<Option<X>, T::Out> {
322 let index = helpers::serialize(&index);
323
324 let result = match block {
325 BlockId::Hash(hash) => {
326 let hash = helpers::serialize(&hash);
327 self.transport
328 .execute("eth_getUncleByBlockHashAndIndex", vec![hash, index], options)
329 }
330 BlockId::Number(num) => {
331 let num = helpers::serialize(&num);
332 self.transport
333 .execute("eth_getUncleByBlockNumberAndIndex", vec![num, index], options)
334 }
335 };
336
337 CallFuture::new(result)
338 }
339
340 pub fn uncle_count(&self, block: BlockId, options: CallOptions) -> CallFuture<Option<U256>, T::Out> {
342 let result = match block {
343 BlockId::Hash(hash) => {
344 let hash = helpers::serialize(&hash);
345 self.transport
346 .execute("eth_getUncleCountByBlockHash", vec![hash], options)
347 }
348 BlockId::Number(num) => {
349 let num = helpers::serialize(&num);
350 self.transport
351 .execute("eth_getUncleCountByBlockNumber", vec![num], options)
352 }
353 };
354
355 CallFuture::new(result)
356 }
357
358 pub fn work(&self, options: CallOptions) -> CallFuture<Work, T::Out> {
360 CallFuture::new(self.transport.execute("eth_getWork", vec![], options))
361 }
362
363 pub fn hashrate(&self, options: CallOptions) -> CallFuture<U256, T::Out> {
365 CallFuture::new(self.transport.execute("eth_hashrate", vec![], options))
366 }
367
368 pub fn mining(&self, options: CallOptions) -> CallFuture<bool, T::Out> {
370 CallFuture::new(self.transport.execute("eth_mining", vec![], options))
371 }
372
373 pub fn new_block_filter(&self, options: CallOptions) -> CallFuture<U256, T::Out> {
375 CallFuture::new(self.transport.execute("eth_newBlockFilter", vec![], options))
376 }
377
378 pub fn new_pending_transaction_filter(&self, options: CallOptions) -> CallFuture<U256, T::Out> {
380 CallFuture::new(
381 self.transport
382 .execute("eth_newPendingTransactionFilter", vec![], options),
383 )
384 }
385
386 pub fn protocol_version(&self, options: CallOptions) -> CallFuture<String, T::Out> {
388 CallFuture::new(self.transport.execute("eth_protocolVersion", vec![], options))
389 }
390
391 pub fn send_raw_transaction(&self, rlp: Bytes, options: CallOptions) -> CallFuture<H256, T::Out> {
393 let rlp = helpers::serialize(&rlp);
394 CallFuture::new(self.transport.execute("eth_sendRawTransaction", vec![rlp], options))
395 }
396
397 pub fn send_transaction(&self, tx: TransactionRequest, options: CallOptions) -> CallFuture<H256, T::Out> {
399 let tx = helpers::serialize(&tx);
400 CallFuture::new(self.transport.execute("eth_sendTransaction", vec![tx], options))
401 }
402
403 pub fn sign(&self, address: Address, data: Bytes, options: CallOptions) -> CallFuture<H520, T::Out> {
405 let address = helpers::serialize(&address);
406 let data = helpers::serialize(&data);
407 CallFuture::new(self.transport.execute("eth_sign", vec![address, data], options))
408 }
409
410 pub fn submit_hashrate(&self, rate: U256, id: H256, options: CallOptions) -> CallFuture<bool, T::Out> {
412 let rate = helpers::serialize(&rate);
413 let id = helpers::serialize(&id);
414 CallFuture::new(self.transport.execute("eth_submitHashrate", vec![rate, id], options))
415 }
416
417 pub fn submit_work(
419 &self,
420 nonce: H64,
421 pow_hash: H256,
422 mix_hash: H256,
423 options: CallOptions,
424 ) -> CallFuture<bool, T::Out> {
425 let nonce = helpers::serialize(&nonce);
426 let pow_hash = helpers::serialize(&pow_hash);
427 let mix_hash = helpers::serialize(&mix_hash);
428 CallFuture::new(
429 self.transport
430 .execute("eth_submitWork", vec![nonce, pow_hash, mix_hash], options),
431 )
432 }
433
434 pub fn syncing(&self, options: CallOptions) -> CallFuture<SyncState, T::Out> {
436 CallFuture::new(self.transport.execute("eth_syncing", vec![], options))
437 }
438
439 pub fn proof(
441 &self,
442 address: Address,
443 keys: Vec<U256>,
444 block: Option<BlockNumber>,
445 options: CallOptions,
446 ) -> CallFuture<Option<Proof>, T::Out> {
447 let add = helpers::serialize(&address);
448 let ks = helpers::serialize(&keys);
449 let blk = helpers::serialize(&block.unwrap_or(BlockNumber::Latest));
450 CallFuture::new(self.transport.execute("eth_getProof", vec![add, ks, blk], options))
451 }
452}
453
454#[cfg(test)]
455mod tests {
456 use super::Eth;
457 use crate::{
458 api::Namespace,
459 rpc::Value,
460 transports::ic_http_client::CallOptions,
461 types::{
462 Address, Block, BlockHeader, BlockId, BlockNumber, CallRequest, FeeHistory, FilterBuilder, Log, Proof,
463 SyncInfo, SyncState, Transaction, TransactionId, TransactionReceipt, TransactionRequest, Work, H256, H520,
464 H64, U256,
465 },
466 };
467 use hex_literal::hex;
468 use serde_json::json;
469
470 const EXAMPLE_BLOCK: &str = r#"{
472 "number": "0x1b4",
473 "hash": "0x0e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331",
474 "parentHash": "0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5",
475 "mixHash": "0x1010101010101010101010101010101010101010101010101010101010101010",
476 "nonce": "0x0000000000000000",
477 "sealFields": [
478 "0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2",
479 "0x0000000000000042"
480 ],
481 "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
482 "logsBloom": "0x0e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331",
483 "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
484 "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
485 "stateRoot": "0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff",
486 "miner": "0x4e65fda2159562a496f9f3522f89122a3088497a",
487 "difficulty": "0x27f07",
488 "totalDifficulty": "0x27f07",
489 "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
490 "size": "0x27f07",
491 "gasLimit": "0x9f759",
492 "minGasPrice": "0x9f759",
493 "gasUsed": "0x9f759",
494 "timestamp": "0x54e34e8e",
495 "transactions": [],
496 "uncles": []
497 }"#;
498
499 const EXAMPLE_PENDING_BLOCK: &str = r#"{
501 "author": "0x0000000000000000000000000000000000000000",
502 "difficulty": "0x7eac2e8c440b2",
503 "extraData": "0xde830207028f5061726974792d457468657265756d86312e34312e30826c69",
504 "gasLimit": "0x974a0a",
505 "gasUsed": "0x44dd8",
506 "hash": null,
507 "logsBloom": null,
508 "miner": "0x0000000000000000000000000000000000000000",
509 "number": null,
510 "parentHash": "0xb4bb0904f19fd05ed527191f21ea27bd4f2d81903f77bfa2626631617001327c",
511 "receiptsRoot": "0x855c8c3b1c985b6bc5fd975a37b764095542b98a177588b887e197fcc5e0a0cd",
512 "sealFields": [],
513 "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
514 "size": "0x8b6",
515 "stateRoot": "0xfa035b07c349fb33768aebeb988639bd2ca7d5284170f29808ead43482a432c5",
516 "timestamp": "0x5ea09b90",
517 "totalDifficulty": "0x332b576efbc4023b848",
518 "transactions": [
519 "0x8e0d2bdfd47d7e68d5c86c30cbe4967ffcf920745a4b8177e1911fafd48e851a",
520 "0x2ac5f94e2d653d64fe89f7af2140600e4b7a59b3345700b5424bd4fae08212af",
521 "0x75d3e2d2ab548f4ca6e9f0c27306cedf28074ce60f39a6e78f56ea3f4a22e2d5",
522 "0xbcdb4f0829c7191a14e03dba0783fb015fa921d06b683e0ce8afb938745f89f7",
523 "0x75cede4d4cdb8402b242a1b1b39a23d537b2fee6a14783eaab67aa1e79bd71cd",
524 "0x50e406de9432a3589681b1eb3093ab6aba0895b5dc755588ca64735386591425",
525 "0x101e8b02d478dfab2266688b53668039107e98feacf085dcf9bfd24f390ec17d",
526 "0x22c75911be879047f4b0480fa07b2c2a77518571fb358d92b47c456d7065a76f",
527 "0x7715b514ba8ead48117b581f9ebcc61696a5b91f9111c55a7087e91474a58ec7",
528 "0x95dd913782cd4bfe5550a8f9102ba821f9a76691780c833d5130e311d62eb638"
529 ],
530 "transactionsRoot": "0x3acac83d7cc227b0c9a9ab1702964e70d7c8d1bfbf0f587b40e2a0aa0048aa44",
531 "uncles": []
532 }"#;
533
534 const EXAMPLE_LOG: &str = r#"{
538 "logIndex": "0x1",
539 "blockNumber":"0x1b4",
540 "blockHash": "0x008216c5785ac562ff41e2dcfdf5785ac562ff41e2dcfdf829c5a142f1fccd7d",
541 "transactionHash": "0x00df829c5a142f1fccd7d8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcf",
542 "transactionIndex": "0x0",
543 "address": "0x16c5785ac562ff41e2dcfdf829c5a142f1fccd7d",
544 "data":"0x0000000000000000000000000000000000000000000000000000000000000000",
545 "topics": ["0x59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a5"]
546 }"#;
547
548 const EXAMPLE_TX: &str = r#"{
550 "hash": "0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b",
551 "nonce": "0x0",
552 "blockHash": "0xbeab0aa2411b7ab17f30a99d3cb9c6ef2fc5426d6ad6fd9e2a26a6aed1d1055b",
553 "blockNumber": "0x15df",
554 "transactionIndex": "0x1",
555 "from": "0x407d73d8a49eeb85d32cf465507dd71d507100c1",
556 "to": "0x85dd43d8a49eeb85d32cf465507dd71d507100c1",
557 "value": "0x7f110",
558 "gas": "0x7f110",
559 "gasPrice": "0x09184e72a000",
560 "input": "0x603880600c6000396000f300603880600c6000396000f3603880600c6000396000f360"
561 }"#;
562
563 const EXAMPLE_RECEIPT: &str = r#"{
566 "transactionHash": "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238",
567 "transactionIndex": "0x1",
568 "from": "0xa7d9ddbe1f17865597fbd27ec712455208b6b76d",
569 "blockNumber": "0xb",
570 "blockHash": "0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b",
571 "cumulativeGasUsed": "0x33bc",
572 "gasUsed": "0x4dc",
573 "contractAddress": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
574 "logsBloom": "0x0e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d15273310e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331",
575 "logs": [],
576 "status": "0x1",
577 "effectiveGasPrice": "0x100"
578 }"#;
579
580 const EXAMPLE_FEE_HISTORY: &str = r#"{
581 "baseFeePerGas": [
582 "0x15f794d04b",
583 "0x1730fe199f",
584 "0x176212b802",
585 "0x165bce08cb",
586 "0x16c6235c9d",
587 "0x1539ff7ccd"
588 ],
589 "gasUsedRatio": [
590 0.722926465013414,
591 0.53306761204479,
592 0.32474768127264964,
593 0.574309529134573,
594 0.2282121795900929
595 ],
596 "oldestBlock": "0xcd1df9"
597 }"#;
598
599 const EXAMPLE_PROOF: &str = r#"{
602 "address": "0x1234567890123456789012345678901234567890",
603 "accountProof": [
604 "0xf90211a0c3b7e484f7e3258823aee7fada1378f1667757c4a1c3bde259adb4857b481726a0d0f709bf8bd61dd176b876f250638b03e65d367aa0e13f01a122e328e6215603a0d3ca85d7f5f63a6b01d818369c656639087aed983f63906b2eba99bf71255ef3a0d168cf7cc0253337d59fa3ed11bde10744a152fcb644c77bd8babbddf878714da02d4e42471dbdbd96eb3b115877d6b6202450cebee0d96d346d650ebd73eaa96ea07c2a9fbbec5c243327961f1a5ed3ce410dd0b255e4db934e68c2df424ede2a67a00a4ae2f21873ad931752edd3b3cfeffcedf15bb070525450bde50bdce6a78faca023e61f772deb072c430adb4316b65a66d8d3cef73dae7d515938e37c0db5c2f0a0d078fc1c446572cfb172888172287dd243ec085eb54594034926c99a3051230da04182e559c0f1bd6533e52fd995760da41701d37e8e21eab59e63db07e836a80fa0968213088b84869050884d5788ae5669d7d35ac0ddbdab71cfbd241da72df9e0a0bdc9921220e3bb9b4744c1764be9a9d7c22e5007387367285dc8f7495ebc0f21a01bf9c2458bb0c5c8f477734e347fb1f940a493ff0b533fef3c0bce20a5a69628a0626a993a9f6cb9febf4ca826b5731cc2ed85066c253cea94511d28a139445699a032a58d4abc48ee971d839915b0848d26af588b23138df7b072575d2dce3cb829a01b8af404f9cc8dc1590fa6f4ed79ea93a65d1aa152854f510efaceba183c8abb80",
605 "0xf90211a0e1557a91967828ea9eaf9b4c25bb0f079857340c54fa01acf24977f5d4d12ad4a0805a5d2f0d1b8c33c6415d2df4f4d812f4abe6b2d0f9f12196d31bbe5d76e47da0882d8a3a3493a0d76c907b0c2a4c6e3f26ca67a6a37aba6105c428d98ec2f67ea0b8bb9bd971ca68a49135390b03c11e2f7c352c146be2e3f8fff2a311dda5ddf1a01ae7bbab4493b34935640f40c74d7d72079742157ad5040a23f70c64f5153ca7a0574403fc7faa3a262eae412a707a74785a1159027e5b8de9990e1e82278e9691a01edc831a2e842b4d55b009c9831774fd6f17acfdee99f097c4fb20be583911f6a044569f910709fedb1ef83ef29b508e24def8eb9cc876dac0f6fa4f5f791cd719a0ebfdbfe9538bd72dbbeb56024982502950c69d9beb5d0d6d985917120e77e0d5a02c6fdf33ef98ca85a94ac9ed1319832ca5e2b344c1b8d921e77eda35480ba9d0a0c6b20bfc93fa2167bd43fe14cb648eb53c66fd56a3c95d0bd4c0442e86f7e686a01bed6e7e4a83c9aed9b39c49bb29782d63064d5ac425734dbfe4f0367eb29d07a0dede0f30aa107e1383be0a3ac31e0083213c27e1b11912e45e974257fa1d9915a089673bee5c46e4ee86b7e68115bc34b6eb9387e7c0d7300af1c502a8ef14fdf8a07e8e4d1729077f052c82cbd6de80966666514c53072945b53afd55c40b4f3a47a024caac94dd8acbf9c88a149b728115651faebd379f92e0ecc126fb136d5289df80",
606 "0xf89180a057d3fa3f15f8c0e639b1c3ac64e623348f39c5663587003279dcd5cf261489a58080a0b65511b496c46cca3eff9484a1a1961bcf7ae59237da1ead3675eea9b3f8469fa05114cfcd51e3a3735c556d68ac28f83dd28aa1a833425090521f0b9217c2114e8080a0adaeaae85d671adf3b559aaee605156f0c4511f9aa474cbcf6a594b219d216a88080808080808080"
607 ],
608 "balance": "0x2166f8062324c623840",
609 "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
610 "nonce": "0x6c",
611 "storageHash": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
612 "storageProof": [
613 {
614 "key": "0x0000000000000000000000000000000000000000000000000000000000000000",
615 "value": "0x0",
616 "proof": []
617 },
618 {
619 "key": "0x0000000000000000000000000000000000000000000000000000000000000001",
620 "value": "0x0",
621 "proof": []
622 }
623 ]
624 }"#;
625
626 rpc_test! (
627 Eth:accounts,CallOptions::default()=> "eth_accounts", Vec::<String>::new();
628 Value::Array(vec![Value::String("0x0000000000000000000000000000000000000123".into())]) => vec![Address::from_low_u64_be(0x123)]
629 );
630
631 rpc_test! (
632 Eth:block_number,CallOptions::default() => "eth_blockNumber", Vec::<String>::new();
633 Value::String("0x123".into()) => 0x123
634 );
635
636 rpc_test! (
637 Eth:call, CallRequest {
638 from: None, to: Some(Address::from_low_u64_be(0x123)),
639 gas: None, gas_price: None,
640 value: Some(0x1.into()), data: None,
641 transaction_type: None, access_list: None,
642 max_fee_per_gas: None, max_priority_fee_per_gas: None,
643 }, None,CallOptions::default()
644 =>
645 "eth_call", vec![r#"{"to":"0x0000000000000000000000000000000000000123","value":"0x1"}"#, r#""latest""#];
646 Value::String("0x010203".into()) => hex!("010203")
647 );
648
649 rpc_test! (
650 Eth:coinbase, CallOptions::default() => "eth_coinbase", Vec::<String>::new();
651 Value::String("0x0000000000000000000000000000000000000123".into()) => Address::from_low_u64_be(0x123)
652 );
653
654 rpc_test! (
655 Eth:compile_lll, "code",CallOptions::default() => "eth_compileLLL", vec![r#""code""#];
656 Value::String("0x0123".into()) => hex!("0123")
657 );
658
659 rpc_test! (
660 Eth:compile_solidity, "code",CallOptions::default() => "eth_compileSolidity", vec![r#""code""#];
661 Value::String("0x0123".into()) => hex!("0123")
662 );
663
664 rpc_test! (
665 Eth:compile_serpent, "code",CallOptions::default() => "eth_compileSerpent", vec![r#""code""#];
666 Value::String("0x0123".into()) => hex!("0123")
667 );
668
669 rpc_test! (
670 Eth:estimate_gas, CallRequest {
671 from: None, to: Some(Address::from_low_u64_be(0x123)),
672 gas: None, gas_price: None,
673 value: Some(0x1.into()), data: None,
674 transaction_type: None, access_list: None,
675 max_fee_per_gas: None, max_priority_fee_per_gas: None,
676 }, None,CallOptions::default()=>
677 "eth_estimateGas", vec![r#"{"to":"0x0000000000000000000000000000000000000123","value":"0x1"}"#];
678 Value::String("0x123".into()) => 0x123
679 );
680
681 rpc_test! (
682 Eth:estimate_gas:optional_to_addr, CallRequest {
683 from: None, to: None,
684 gas: None, gas_price: None,
685 value: Some(0x1.into()), data: None,
686 transaction_type: None, access_list: None,
687 max_fee_per_gas: None, max_priority_fee_per_gas: None,
688 }, None,CallOptions::default()
689 =>
690 "eth_estimateGas", vec![r#"{"value":"0x1"}"#];
691 Value::String("0x5555".into()) => 0x5555
692 );
693
694 rpc_test! (
695 Eth:estimate_gas:for_block, CallRequest {
696 from: None, to: Some(Address::from_low_u64_be(0x123)),
697 gas: None, gas_price: None,
698 value: Some(0x1.into()), data: None,
699 transaction_type: None, access_list: None,
700 max_fee_per_gas: None, max_priority_fee_per_gas: None,
701 }, Some(0x123.into()),CallOptions::default()
702 =>
703 "eth_estimateGas", vec![r#"{"to":"0x0000000000000000000000000000000000000123","value":"0x1"}"#, r#""0x123""#];
704 Value::String("0x123".into()) => 0x123
705 );
706
707 rpc_test! (
708 Eth:gas_price, CallOptions::default() => "eth_gasPrice", Vec::<String>::new();
709 Value::String("0x123".into()) => 0x123
710 );
711
712 rpc_test! {
713 Eth:max_priority_fee_per_gas, CallOptions::default() => "eth_maxPriorityFeePerGas", Vec::<String>::new();
714 Value::String("0x123".into()) => 0x123
715 }
716
717 rpc_test! (
718 Eth:fee_history, 0x3, BlockNumber::Latest, None,CallOptions::default() => "eth_feeHistory", vec![r#""0x3""#, r#""latest""#, r#"null"#];
719 ::serde_json::from_str(EXAMPLE_FEE_HISTORY).unwrap()
720 => ::serde_json::from_str::<FeeHistory>(EXAMPLE_FEE_HISTORY).unwrap()
721 );
722
723 rpc_test! (
724 Eth:balance, Address::from_low_u64_be(0x123), None, CallOptions::default()
725 =>
726 "eth_getBalance", vec![r#""0x0000000000000000000000000000000000000123""#, r#""latest""#];
727 Value::String("0x123".into()) => 0x123
728 );
729 rpc_test! (
730 Eth:logs, FilterBuilder::default().build(), CallOptions::default() => "eth_getLogs", vec!["{}"];
731 Value::Array(vec![::serde_json::from_str(EXAMPLE_LOG).unwrap()])
732 => vec![::serde_json::from_str::<Log>(EXAMPLE_LOG).unwrap()]
733 );
734
735 rpc_test! (
736 Eth:block:block_by_hash, BlockId::Hash(H256::from_low_u64_be(0x123)), CallOptions::default()
737 =>
738 "eth_getBlockByHash", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#, r#"false"#];
739 ::serde_json::from_str(EXAMPLE_BLOCK).unwrap()
740 => Some(::serde_json::from_str::<Block<H256>>(EXAMPLE_BLOCK).unwrap())
741 );
742
743 rpc_test! (
744 Eth:block, BlockNumber::Pending, CallOptions::default()
745 =>
746 "eth_getBlockByNumber", vec![r#""pending""#, r#"false"#];
747 ::serde_json::from_str(EXAMPLE_PENDING_BLOCK).unwrap()
748 => Some(::serde_json::from_str::<Block<H256>>(EXAMPLE_PENDING_BLOCK).unwrap())
749 );
750
751 rpc_test! (
752 Eth:block_with_txs, BlockNumber::Pending, CallOptions::default()
753 =>
754 "eth_getBlockByNumber", vec![r#""pending""#, r#"true"#];
755 ::serde_json::from_str(EXAMPLE_BLOCK).unwrap()
756 => Some(::serde_json::from_str::<Block<Transaction>>(EXAMPLE_BLOCK).unwrap())
757 );
758
759 rpc_test! (
760 Eth:block_transaction_count:block_tx_count_by_hash, BlockId::Hash(H256::from_low_u64_be(0x123)), CallOptions::default()
761 =>
762 "eth_getBlockTransactionCountByHash", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#];
763 Value::String("0x123".into()) => Some(0x123.into())
764 );
765
766 rpc_test! (
767 Eth:block_transaction_count, BlockNumber::Pending, CallOptions::default()
768 =>
769 "eth_getBlockTransactionCountByNumber", vec![r#""pending""#];
770 Value::Null => None
771 );
772
773 rpc_test! (
774 Eth:code, H256::from_low_u64_be(0x123), Some(BlockNumber::Pending), CallOptions::default()
775 =>
776 "eth_getCode", vec![r#""0x0000000000000000000000000000000000000123""#, r#""pending""#];
777 Value::String("0x0123".into()) => hex!("0123")
778 );
779
780 rpc_test! (
781 Eth:compilers, CallOptions::default() => "eth_getCompilers", Vec::<String>::new();
782 Value::Array(vec![]) => vec![]
783 );
784
785 rpc_test! (
786 Eth:chain_id, CallOptions::default()=> "eth_chainId", Vec::<String>::new();
787 Value::String("0x123".into()) => 0x123
788 );
789
790 rpc_test! (
791 Eth:storage, Address::from_low_u64_be(0x123), 0x456, None, CallOptions::default()
792 =>
793 "eth_getStorageAt", vec![
794 r#""0x0000000000000000000000000000000000000123""#,
795 r#""0x456""#,
796 r#""latest""#
797 ];
798 Value::String("0x0000000000000000000000000000000000000000000000000000000000000123".into()) => H256::from_low_u64_be(0x123)
799 );
800
801 rpc_test! (
802 Eth:transaction_count, Address::from_low_u64_be(0x123), None, CallOptions::default()
803 =>
804 "eth_getTransactionCount", vec![r#""0x0000000000000000000000000000000000000123""#, r#""latest""#];
805 Value::String("0x123".into()) => 0x123
806 );
807
808 rpc_test! (
809 Eth:transaction:tx_by_hash, TransactionId::Hash(H256::from_low_u64_be(0x123)), CallOptions::default()
810 =>
811 "eth_getTransactionByHash", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#];
812 ::serde_json::from_str(EXAMPLE_TX).unwrap()
813 => Some(::serde_json::from_str::<Transaction>(EXAMPLE_TX).unwrap())
814 );
815
816 rpc_test! (
817 Eth:transaction:tx_by_block_hash_and_index, TransactionId::Block(
818 BlockId::Hash(H256::from_low_u64_be(0x123)),
819 5.into()
820 ), CallOptions::default() =>
821 "eth_getTransactionByBlockHashAndIndex", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#, r#""0x5""#];
822 Value::Null => None
823 );
824
825 rpc_test! (
826 Eth:transaction:tx_by_block_no_and_index, TransactionId::Block(
827 BlockNumber::Pending.into(),
828 5.into()
829 ), CallOptions::default()
830 =>
831 "eth_getTransactionByBlockNumberAndIndex", vec![r#""pending""#, r#""0x5""#];
832 ::serde_json::from_str(EXAMPLE_TX).unwrap()
833 => Some(::serde_json::from_str::<Transaction>(EXAMPLE_TX).unwrap())
834 );
835
836 rpc_test! (
837 Eth:transaction_receipt, H256::from_low_u64_be(0x123), CallOptions::default()
838 =>
839 "eth_getTransactionReceipt", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#];
840 ::serde_json::from_str(EXAMPLE_RECEIPT).unwrap()
841 => Some(::serde_json::from_str::<TransactionReceipt>(EXAMPLE_RECEIPT).unwrap())
842 );
843
844 rpc_test! (
845 Eth:uncle:uncle_by_hash, BlockId::Hash(H256::from_low_u64_be(0x123)), 5, CallOptions::default()
846 =>
847 "eth_getUncleByBlockHashAndIndex", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#, r#""0x5""#];
848 ::serde_json::from_str(EXAMPLE_BLOCK).unwrap()
849 => Some(::serde_json::from_str::<Block<H256>>(EXAMPLE_BLOCK).unwrap())
850 );
851
852 rpc_test! (
853 Eth:uncle_header:uncle_header_by_hash, BlockId::Hash(H256::from_low_u64_be(0x123)), 5, CallOptions::default()
854 =>
855 "eth_getUncleByBlockHashAndIndex", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#, r#""0x5""#];
856 ::serde_json::from_str(EXAMPLE_BLOCK).unwrap()
857 => Some(::serde_json::from_str::<BlockHeader>(EXAMPLE_BLOCK).unwrap())
858 );
859
860 rpc_test! (
861 Eth:uncle:uncle_by_no, BlockNumber::Earliest, 5, CallOptions::default()
862 =>
863 "eth_getUncleByBlockNumberAndIndex", vec![r#""earliest""#, r#""0x5""#];
864 Value::Null => None
865 );
866
867 rpc_test! (
868 Eth:uncle_count:uncle_count_by_hash, BlockId::Hash(H256::from_low_u64_be(0x123)), CallOptions::default()
869 =>
870 "eth_getUncleCountByBlockHash", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#];
871 Value::String("0x123".into())=> Some(0x123.into())
872 );
873
874 rpc_test! (
875 Eth:uncle_count:uncle_count_by_no, BlockNumber::Earliest, CallOptions::default()
876 =>
877 "eth_getUncleCountByBlockNumber", vec![r#""earliest""#];
878 Value::Null => None
879 );
880
881 rpc_test! (
882 Eth:work:work_3, CallOptions::default() => "eth_getWork", Vec::<String>::new();
883 Value::Array(vec![
884 Value::String("0x0000000000000000000000000000000000000000000000000000000000000123".into()),
885 Value::String("0x0000000000000000000000000000000000000000000000000000000000000456".into()),
886 Value::String("0x0000000000000000000000000000000000000000000000000000000000000789".into()),
887 ]) => Work {
888 pow_hash: H256::from_low_u64_be(0x123),
889 seed_hash: H256::from_low_u64_be(0x456),
890 target: H256::from_low_u64_be(0x789),
891 number: None,
892 }
893 );
894
895 rpc_test! (
896 Eth:work:work_4, CallOptions::default() => "eth_getWork", Vec::<String>::new();
897 Value::Array(vec![
898 Value::String("0x0000000000000000000000000000000000000000000000000000000000000123".into()),
899 Value::String("0x0000000000000000000000000000000000000000000000000000000000000456".into()),
900 Value::String("0x0000000000000000000000000000000000000000000000000000000000000789".into()),
901 Value::Number(5.into()),
902 ]) => Work {
903 pow_hash: H256::from_low_u64_be(0x123),
904 seed_hash: H256::from_low_u64_be(0x456),
905 target: H256::from_low_u64_be(0x789),
906 number: Some(5),
907 }
908 );
909
910 rpc_test! (
911 Eth:hashrate, CallOptions::default() => "eth_hashrate", Vec::<String>::new();
912 Value::String("0x123".into()) => 0x123
913 );
914
915 rpc_test! (
916 Eth:mining, CallOptions::default() => "eth_mining", Vec::<String>::new();
917 Value::Bool(true) => true
918 );
919
920 rpc_test! (
921 Eth:new_block_filter, CallOptions::default() => "eth_newBlockFilter", Vec::<String>::new();
922 Value::String("0x123".into()) => 0x123
923 );
924 rpc_test! (
925 Eth:new_pending_transaction_filter, CallOptions::default() => "eth_newPendingTransactionFilter", Vec::<String>::new();
926 Value::String("0x123".into()) => 0x123
927 );
928
929 rpc_test! (
930 Eth:protocol_version, CallOptions::default() => "eth_protocolVersion", Vec::<String>::new();
931 Value::String("0x123".into()) => "0x123"
932 );
933
934 rpc_test! (
935 Eth:send_raw_transaction, hex!("01020304"), CallOptions::default()
936 =>
937 "eth_sendRawTransaction", vec![r#""0x01020304""#];
938 Value::String("0x0000000000000000000000000000000000000000000000000000000000000123".into()) => H256::from_low_u64_be(0x123)
939 );
940
941 rpc_test! (
942 Eth:send_transaction, TransactionRequest {
943 from: Address::from_low_u64_be(0x123), to: Some(Address::from_low_u64_be(0x123)),
944 gas: None, gas_price: Some(0x1.into()),
945 value: Some(0x1.into()), data: None,
946 nonce: None, condition: None,
947 transaction_type: None, access_list: None,
948 max_fee_per_gas: None, max_priority_fee_per_gas: None,
949 }, CallOptions::default()
950 =>
951 "eth_sendTransaction", vec![r#"{"from":"0x0000000000000000000000000000000000000123","gasPrice":"0x1","to":"0x0000000000000000000000000000000000000123","value":"0x1"}"#];
952 Value::String("0x0000000000000000000000000000000000000000000000000000000000000123".into()) => H256::from_low_u64_be(0x123)
953 );
954
955 rpc_test! (
956 Eth:sign, H256::from_low_u64_be(0x123), hex!("01020304"),CallOptions::default()
957 =>
958 "eth_sign", vec![r#""0x0000000000000000000000000000000000000123""#, r#""0x01020304""#];
959 Value::String("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123".into()) => H520::from_low_u64_be(0x123)
960 );
961
962 rpc_test! (
963 Eth:submit_hashrate, 0x123, H256::from_low_u64_be(0x456), CallOptions::default()
964 =>
965 "eth_submitHashrate", vec![r#""0x123""#, r#""0x0000000000000000000000000000000000000000000000000000000000000456""#];
966 Value::Bool(true) => true
967 );
968
969 rpc_test! (
970 Eth:submit_work, H64::from_low_u64_be(0x123), H256::from_low_u64_be(0x456), H256::from_low_u64_be(0x789),CallOptions::default()
971 =>
972 "eth_submitWork", vec![r#""0x0000000000000123""#, r#""0x0000000000000000000000000000000000000000000000000000000000000456""#, r#""0x0000000000000000000000000000000000000000000000000000000000000789""#];
973 Value::Bool(true) => true
974 );
975
976 rpc_test! (
977 Eth:syncing:syncing, CallOptions::default() => "eth_syncing", Vec::<String>::new();
978 json!({"startingBlock": "0x384","currentBlock": "0x386","highestBlock": "0x454"}) => SyncState::Syncing(SyncInfo { starting_block: 0x384.into(), current_block: 0x386.into(), highest_block: 0x454.into()})
979 );
980
981 rpc_test! {
982 Eth:syncing:not_syncing, CallOptions::default() => "eth_syncing", Vec::<String>::new();
983 Value::Bool(false) => SyncState::NotSyncing
984 }
985
986 rpc_test! {
987 Eth:proof, Address::from_low_u64_be(0x123), [U256::from(0x123)], BlockNumber::Latest, CallOptions::default()
988 =>
989 "eth_getProof", vec![r#""0x0000000000000000000000000000000000000123""#, r#"["0x123"]"#, r#""latest""#];
990 ::serde_json::from_str(EXAMPLE_PROOF).unwrap()
991 => Some(::serde_json::from_str::<Proof>(EXAMPLE_PROOF).unwrap())
992 }
993}