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