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