From 91639ffee68af98e0ba64e648a30e9edb9adb09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 11 Apr 2019 22:35:06 +0200 Subject: [PATCH] Update to latest ethereum-types and reformat with max-width 120 (#211) * Bump ethereum types. * Update ethereum-types and reformat. * Fix tests. --- Cargo.toml | 47 ++++---- examples/batch.rs | 4 +- examples/contract.rs | 13 +- examples/http.rs | 5 +- examples/simple_log_filter.rs | 62 ++++++---- examples/simple_log_sub.rs | 62 ++++++---- examples/simple_storage.rs | 10 +- rustfmt.toml | 2 +- src/api/eth.rs | 41 +++++-- src/api/eth_filter.rs | 59 ++++++++-- src/api/eth_subscribe.rs | 18 ++- src/api/mod.rs | 21 +++- src/api/parity_accounts.rs | 12 +- src/api/parity_set.rs | 28 +++-- src/api/personal.rs | 33 ++++-- src/api/traces.rs | 29 +++-- src/confirm.rs | 107 +++++++++++++---- src/contract/deploy.rs | 53 +++++++-- src/contract/error.rs | 2 + src/contract/mod.rs | 71 +++++++++-- src/contract/result.rs | 16 ++- src/contract/tokens.rs | 42 +++++-- src/error.rs | 5 +- src/helpers.rs | 14 ++- src/lib.rs | 20 +--- src/transports/batch.rs | 16 ++- src/transports/http.rs | 68 +++++++---- src/transports/ipc.rs | 74 ++++++++---- src/transports/shared.rs | 35 ++++-- src/transports/ws.rs | 196 ++++++++++++++++++------------- src/types/block.rs | 2 +- src/types/bytes.rs | 6 +- src/types/log.rs | 33 +++++- src/types/parity_peers.rs | 3 +- src/types/sync_state.rs | 33 +++++- src/types/trace_filtering.rs | 2 +- src/types/traces.rs | 5 +- src/types/transaction.rs | 1 + src/types/transaction_request.rs | 1 + src/types/uint.rs | 12 +- src/types/work.rs | 15 ++- 41 files changed, 899 insertions(+), 379 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 01fe9e3d..1ab95777 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "web3" -version = "0.6.0" +version = "0.7.0" description = "Ethereum JSON-RPC client." homepage = "https://github.com/tomusdrw/rust-web3" repository = "https://github.com/tomusdrw/rust-web3" @@ -12,34 +12,33 @@ readme = "README.md" edition = "2018" [dependencies] -arrayvec = "0.4" -ethabi = "6.0" -ethereum-types = "0.4" -futures = "0.1" -jsonrpc-core = "8.0.1" -log = "0.4" -parking_lot = "0.7" -rustc-hex = "1.0" -serde = "1.0" -serde_derive = "1.0" -serde_json = "1.0" +arrayvec = "0.4.10" +ethabi = "7.0.0" +ethereum-types = "0.5.2" +futures = "0.1.26" +jsonrpc-core = "11.0.0" +log = "0.4.6" +parking_lot = "0.7.1" +rustc-hex = "2.0.1" +serde = { version="1.0.90", features = ["derive"] } +serde_json = "1.0.39" tokio-timer = "0.1" -url = "1.7" -base64 = "0.10" -derive_more = "0.14" +url = "1.7.2" +base64 = "0.10.1" +derive_more = "0.14.0" # Optional deps -hyper = { version = "0.12", optional = true } -hyper-tls = { version = "0.3", optional = true } -native-tls = { version = "0.2", optional = true } -tokio-core = { version = "0.1", optional = true } -tokio-io = { version = "0.1", optional = true } -tokio-uds = { version = "0.1", optional = true } -websocket = { version = "0.21", optional = true } +hyper = { version = "0.12.25", optional = true } +hyper-tls = { version = "0.3.2", optional = true } +native-tls = { version = "0.2.2", optional = true } +tokio-core = { version = "0.1.17", optional = true } +tokio-io = { version = "0.1.12", optional = true } +tokio-uds = { version = "0.1.0", optional = true } +websocket = { version = "0.21.1", optional = true } [dev-dependencies] # For examples -tokio-core = "0.1" -rustc-hex = "1.0" +tokio-core = "0.1.17" +rustc-hex = "2.0.1" env_logger = "0.6.0" [features] diff --git a/examples/batch.rs b/examples/batch.rs index 01f193f6..63ac9163 100644 --- a/examples/batch.rs +++ b/examples/batch.rs @@ -9,7 +9,9 @@ fn main() { let mut event_loop = tokio_core::reactor::Core::new().unwrap(); let remote = event_loop.remote(); - let http = web3::transports::Http::with_event_loop("http://localhost:8545", &event_loop.handle(), MAX_PARALLEL_REQUESTS).unwrap(); + let http = + web3::transports::Http::with_event_loop("http://localhost:8545", &event_loop.handle(), MAX_PARALLEL_REQUESTS) + .unwrap(); let web3 = web3::Web3::new(web3::transports::Batch::new(http)); let _ = web3.eth().accounts(); diff --git a/examples/contract.rs b/examples/contract.rs index 4552bd5b..14ca1324 100644 --- a/examples/contract.rs +++ b/examples/contract.rs @@ -24,7 +24,11 @@ fn main() { opt.gas_price = Some(5.into()); opt.gas = Some(1_000_000.into()); })) - .execute(bytecode, (U256::from(1_000_000), "My Token".to_owned(), 3u64, "MT".to_owned()), my_account) + .execute( + bytecode, + (U256::from(1_000_000), "My Token".to_owned(), 3u64, "MT".to_owned()), + my_account, + ) .expect("Correct parameters are passed to the constructor.") .wait() .unwrap(); @@ -35,7 +39,12 @@ fn main() { // Accessing existing contract let contract_address = contract.address(); - let contract = Contract::from_json(web3.eth(), contract_address, include_bytes!("../src/contract/res/token.json")).unwrap(); + let contract = Contract::from_json( + web3.eth(), + contract_address, + include_bytes!("../src/contract/res/token.json"), + ) + .unwrap(); let result = contract.query("balanceOf", (my_account,), None, Options::default(), None); let balance_of: U256 = result.wait().unwrap(); diff --git a/examples/http.rs b/examples/http.rs index f445df79..efb7d861 100644 --- a/examples/http.rs +++ b/examples/http.rs @@ -8,7 +8,10 @@ const MAX_PARALLEL_REQUESTS: usize = 64; fn main() { let mut event_loop = tokio_core::reactor::Core::new().unwrap(); - let web3 = web3::Web3::new(web3::transports::Http::with_event_loop("http://localhost:8545", &event_loop.handle(), MAX_PARALLEL_REQUESTS).unwrap()); + let web3 = web3::Web3::new( + web3::transports::Http::with_event_loop("http://localhost:8545", &event_loop.handle(), MAX_PARALLEL_REQUESTS) + .unwrap(), + ); let accounts = web3.eth().accounts().map(|accounts| { println!("Accounts: {:?}", accounts); }); diff --git a/examples/simple_log_filter.rs b/examples/simple_log_filter.rs index dd32c4d7..d824d780 100644 --- a/examples/simple_log_filter.rs +++ b/examples/simple_log_filter.rs @@ -10,7 +10,8 @@ use web3::types::FilterBuilder; fn main() { let mut eloop = tokio_core::reactor::Core::new().unwrap(); - let web3 = web3::Web3::new(web3::transports::Http::with_event_loop("http://localhost:8545", &eloop.handle(), 1).unwrap()); + let web3 = + web3::Web3::new(web3::transports::Http::with_event_loop("http://localhost:8545", &eloop.handle(), 1).unwrap()); // Get the contract bytecode for instance from Solidity compiler let bytecode: Vec = include_str!("./build/SimpleEvent.bin").from_hex().unwrap(); @@ -20,31 +21,50 @@ fn main() { let accounts = accounts.unwrap(); println!("accounts: {:?}", &accounts); - Contract::deploy(web3.eth(), include_bytes!("./build/SimpleEvent.abi")).unwrap().confirmations(1).poll_interval(time::Duration::from_secs(10)).options(Options::with(|opt| opt.gas = Some(3_000_000.into()))).execute(bytecode, (), accounts[0]).unwrap().then(move |contract| { - let contract = contract.unwrap(); - println!("contract deployed at: {}", contract.address()); + Contract::deploy(web3.eth(), include_bytes!("./build/SimpleEvent.abi")) + .unwrap() + .confirmations(1) + .poll_interval(time::Duration::from_secs(10)) + .options(Options::with(|opt| opt.gas = Some(3_000_000.into()))) + .execute(bytecode, (), accounts[0]) + .unwrap() + .then(move |contract| { + let contract = contract.unwrap(); + println!("contract deployed at: {}", contract.address()); - // Filter for Hello event in our contract - let filter = FilterBuilder::default().address(vec![contract.address()]).topics(Some(vec!["0xd282f389399565f3671145f5916e51652b60eee8e5c759293a2f5771b8ddfd2e".into()]), None, None, None).build(); + // Filter for Hello event in our contract + let filter = FilterBuilder::default() + .address(vec![contract.address()]) + .topics( + Some(vec![ + "0xd282f389399565f3671145f5916e51652b60eee8e5c759293a2f5771b8ddfd2e" + .parse() + .unwrap(), + ]), + None, + None, + None, + ) + .build(); - let event_future = web3 - .eth_filter() - .create_logs_filter(filter) - .then(|filter| { - filter.unwrap().stream(time::Duration::from_secs(0)).for_each(|log| { - println!("got log: {:?}", log); - Ok(()) + let event_future = web3 + .eth_filter() + .create_logs_filter(filter) + .then(|filter| { + filter.unwrap().stream(time::Duration::from_secs(0)).for_each(|log| { + println!("got log: {:?}", log); + Ok(()) + }) }) - }) - .map_err(|_| ()); + .map_err(|_| ()); - let call_future = contract.call("hello", (), accounts[0], Options::default()).then(|tx| { - println!("got tx: {:?}", tx); - Ok(()) - }); + let call_future = contract.call("hello", (), accounts[0], Options::default()).then(|tx| { + println!("got tx: {:?}", tx); + Ok(()) + }); - event_future.join(call_future) - }) + event_future.join(call_future) + }) })) .unwrap(); } diff --git a/examples/simple_log_sub.rs b/examples/simple_log_sub.rs index 93e4cd1a..47cd3cf6 100644 --- a/examples/simple_log_sub.rs +++ b/examples/simple_log_sub.rs @@ -10,7 +10,8 @@ use web3::types::FilterBuilder; fn main() { let mut eloop = tokio_core::reactor::Core::new().unwrap(); - let web3 = web3::Web3::new(web3::transports::WebSocket::with_event_loop("ws://localhost:8546", &eloop.handle()).unwrap()); + let web3 = + web3::Web3::new(web3::transports::WebSocket::with_event_loop("ws://localhost:8546", &eloop.handle()).unwrap()); // Get the contract bytecode for instance from Solidity compiler let bytecode: Vec = include_str!("./build/SimpleEvent.bin").from_hex().unwrap(); @@ -20,31 +21,50 @@ fn main() { let accounts = accounts.unwrap(); println!("accounts: {:?}", &accounts); - Contract::deploy(web3.eth(), include_bytes!("./build/SimpleEvent.abi")).unwrap().confirmations(1).poll_interval(time::Duration::from_secs(10)).options(Options::with(|opt| opt.gas = Some(3_000_000.into()))).execute(bytecode, (), accounts[0]).unwrap().then(move |contract| { - let contract = contract.unwrap(); - println!("contract deployed at: {}", contract.address()); + Contract::deploy(web3.eth(), include_bytes!("./build/SimpleEvent.abi")) + .unwrap() + .confirmations(1) + .poll_interval(time::Duration::from_secs(10)) + .options(Options::with(|opt| opt.gas = Some(3_000_000.into()))) + .execute(bytecode, (), accounts[0]) + .unwrap() + .then(move |contract| { + let contract = contract.unwrap(); + println!("contract deployed at: {}", contract.address()); - // Filter for Hello event in our contract - let filter = FilterBuilder::default().address(vec![contract.address()]).topics(Some(vec!["0xd282f389399565f3671145f5916e51652b60eee8e5c759293a2f5771b8ddfd2e".into()]), None, None, None).build(); + // Filter for Hello event in our contract + let filter = FilterBuilder::default() + .address(vec![contract.address()]) + .topics( + Some(vec![ + "0xd282f389399565f3671145f5916e51652b60eee8e5c759293a2f5771b8ddfd2e" + .parse() + .unwrap(), + ]), + None, + None, + None, + ) + .build(); - let event_future = web3 - .eth_subscribe() - .subscribe_logs(filter) - .then(|sub| { - sub.unwrap().for_each(|log| { - println!("got log: {:?}", log); - Ok(()) + let event_future = web3 + .eth_subscribe() + .subscribe_logs(filter) + .then(|sub| { + sub.unwrap().for_each(|log| { + println!("got log: {:?}", log); + Ok(()) + }) }) - }) - .map_err(|_| ()); + .map_err(|_| ()); - let call_future = contract.call("hello", (), accounts[0], Options::default()).then(|tx| { - println!("got tx: {:?}", tx); - Ok(()) - }); + let call_future = contract.call("hello", (), accounts[0], Options::default()).then(|tx| { + println!("got tx: {:?}", tx); + Ok(()) + }); - event_future.join(call_future) - }) + event_future.join(call_future) + }) })) .unwrap(); } diff --git a/examples/simple_storage.rs b/examples/simple_storage.rs index bd0d3ff3..f8fd04a9 100644 --- a/examples/simple_storage.rs +++ b/examples/simple_storage.rs @@ -21,7 +21,15 @@ fn main() { // Get the contract bytecode for instance from Solidity compiler let bytecode: Vec = include_str!("./build/SimpleStorage.bin").from_hex().unwrap(); // Deploying a contract - let contract = Contract::deploy(web3.eth(), include_bytes!("./build/SimpleStorage.abi")).unwrap().confirmations(0).poll_interval(time::Duration::from_secs(10)).options(Options::with(|opt| opt.gas = Some(3_000_000.into()))).execute(bytecode, (), accounts[0]).unwrap().wait().unwrap(); + let contract = Contract::deploy(web3.eth(), include_bytes!("./build/SimpleStorage.abi")) + .unwrap() + .confirmations(0) + .poll_interval(time::Duration::from_secs(10)) + .options(Options::with(|opt| opt.gas = Some(3_000_000.into()))) + .execute(bytecode, (), accounts[0]) + .unwrap() + .wait() + .unwrap(); println!("{}", contract.address()); diff --git a/rustfmt.toml b/rustfmt.toml index a616011a..75306517 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1 +1 @@ -max_width = 600 +max_width = 120 diff --git a/src/api/eth.rs b/src/api/eth.rs index 60e26875..f5e5c4c9 100644 --- a/src/api/eth.rs +++ b/src/api/eth.rs @@ -2,7 +2,10 @@ use crate::api::Namespace; use crate::helpers::{self, CallFuture}; -use crate::types::{Address, Block, BlockId, BlockNumber, Bytes, CallRequest, Filter, Index, Log, SyncState, Transaction, TransactionId, TransactionReceipt, TransactionRequest, Work, H256, H520, H64, U256}; +use crate::types::{ + Address, Block, BlockId, BlockNumber, Bytes, CallRequest, Filter, Index, Log, SyncState, Transaction, + TransactionId, TransactionReceipt, TransactionRequest, Work, H256, H520, H64, U256, +}; use crate::Transport; /// `Eth` namespace @@ -138,7 +141,8 @@ impl Eth { } BlockId::Number(num) => { let num = helpers::serialize(&num); - self.transport.execute("eth_getBlockTransactionCountByNumber", vec![num]) + self.transport + .execute("eth_getBlockTransactionCountByNumber", vec![num]) } }; @@ -185,12 +189,14 @@ impl Eth { TransactionId::Block(BlockId::Hash(hash), index) => { let hash = helpers::serialize(&hash); let idx = helpers::serialize(&index); - self.transport.execute("eth_getTransactionByBlockHashAndIndex", vec![hash, idx]) + self.transport + .execute("eth_getTransactionByBlockHashAndIndex", vec![hash, idx]) } TransactionId::Block(BlockId::Number(number), index) => { let number = helpers::serialize(&number); let idx = helpers::serialize(&index); - self.transport.execute("eth_getTransactionByBlockNumberAndIndex", vec![number, idx]) + self.transport + .execute("eth_getTransactionByBlockNumberAndIndex", vec![number, idx]) } }; @@ -211,11 +217,13 @@ impl Eth { let result = match block { BlockId::Hash(hash) => { let hash = helpers::serialize(&hash); - self.transport.execute("eth_getUncleByBlockHashAndIndex", vec![hash, index]) + self.transport + .execute("eth_getUncleByBlockHashAndIndex", vec![hash, index]) } BlockId::Number(num) => { let num = helpers::serialize(&num); - self.transport.execute("eth_getUncleByBlockNumberAndIndex", vec![num, index]) + self.transport + .execute("eth_getUncleByBlockNumberAndIndex", vec![num, index]) } }; @@ -299,7 +307,10 @@ impl Eth { let nonce = helpers::serialize(&nonce); let pow_hash = helpers::serialize(&pow_hash); let mix_hash = helpers::serialize(&mix_hash); - CallFuture::new(self.transport.execute("eth_submitWork", vec![nonce, pow_hash, mix_hash])) + CallFuture::new( + self.transport + .execute("eth_submitWork", vec![nonce, pow_hash, mix_hash]), + ) } /// Get syncing status @@ -311,10 +322,14 @@ impl Eth { #[cfg(test)] mod tests { use futures::Future; + use serde_json::json; use crate::api::Namespace; use crate::rpc::Value; - use crate::types::{Block, BlockId, BlockNumber, Bytes, CallRequest, FilterBuilder, Log, SyncInfo, SyncState, Transaction, TransactionId, TransactionReceipt, TransactionRequest, Work, H256}; + use crate::types::{ + Address, Block, BlockId, BlockNumber, Bytes, CallRequest, FilterBuilder, Log, SyncInfo, SyncState, Transaction, + TransactionId, TransactionReceipt, TransactionRequest, Work, H256, H520, H64, + }; use super::Eth; @@ -519,7 +534,7 @@ mod tests { r#""0x456""#, r#""latest""# ]; - Value::String("0x0000000000000000000000000000000000000000000000000000000000000123".into()) => 0x123 + Value::String("0x0000000000000000000000000000000000000000000000000000000000000123".into()) => H256::from_low_u64_be(0x123) ); rpc_test! ( @@ -652,12 +667,12 @@ mod tests { Eth:send_raw_transaction, Bytes(vec![1, 2, 3, 4]) => "eth_sendRawTransaction", vec![r#""0x01020304""#]; - Value::String("0x0000000000000000000000000000000000000000000000000000000000000123".into()) => 0x123 + Value::String("0x0000000000000000000000000000000000000000000000000000000000000123".into()) => H256::from_low_u64_be(0x123) ); rpc_test! ( Eth:send_transaction, TransactionRequest { - from: 0x123.into(), to: Some(0x123.into()), + from: Address::from_low_u64_be(0x123), to: Some(Address::from_low_u64_be(0x123)), gas: None, gas_price: Some(0x1.into()), value: Some(0x1.into()), data: None, nonce: None, condition: None, @@ -671,7 +686,7 @@ mod tests { Eth:sign, 0x123, Bytes(vec![1, 2, 3, 4]) => "eth_sign", vec![r#""0x0000000000000000000000000000000000000123""#, r#""0x01020304""#]; - Value::String("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123".into()) => 0x123 + Value::String("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123".into()) => H520::from_low_u64_be(0x123) ); rpc_test! ( @@ -682,7 +697,7 @@ mod tests { ); rpc_test! ( - Eth:submit_work, 0x123, 0x456, 0x789 + Eth:submit_work, H64::from_low_u64_be(0x123), H256::from_low_u64_be(0x456), H256::from_low_u64_be(0x789) => "eth_submitWork", vec![r#""0x0000000000000123""#, r#""0x0000000000000000000000000000000000000000000000000000000000000456""#, r#""0x0000000000000000000000000000000000000000000000000000000000000789""#]; Value::Bool(true) => true diff --git a/src/api/eth_filter.rs b/src/api/eth_filter.rs index 29c7bf63..15cb8e1a 100644 --- a/src/api/eth_filter.rs +++ b/src/api/eth_filter.rs @@ -22,7 +22,11 @@ pub struct FilterStream { impl FilterStream { fn new(base: BaseFilter, poll_interval: Duration) -> Self { - FilterStream { base, interval: Timer::default().interval(poll_interval), state: FilterStreamState::WaitForInterval } + FilterStream { + base, + interval: Timer::default().interval(poll_interval), + state: FilterStreamState::WaitForInterval, + } } /// Borrow a transport from this filter. @@ -123,7 +127,11 @@ pub struct BaseFilter { impl Clone for BaseFilter { fn clone(&self) -> Self { - BaseFilter { id: self.id.clone(), transport: self.transport.clone(), item: PhantomData::default() } + BaseFilter { + id: self.id.clone(), + transport: self.transport.clone(), + item: PhantomData::default(), + } } } @@ -170,7 +178,11 @@ impl BaseFilter { /// Should be used to create new filter future fn create_filter(t: T, arg: Vec) -> CreateFilter { let future = CallFuture::new(t.execute(F::constructor(), arg)); - CreateFilter { transport: Some(t), item: PhantomData, future } + CreateFilter { + transport: Some(t), + item: PhantomData, + future, + } } /// Future which resolves with new filter @@ -190,7 +202,11 @@ where fn poll(&mut self) -> Poll { let id = try_ready!(self.future.poll()); - let result = BaseFilter { id, transport: self.transport.take().expect("future polled after ready; qed"), item: PhantomData }; + let result = BaseFilter { + id, + transport: self.transport.take().expect("future polled after ready; qed"), + item: PhantomData, + }; Ok(result.into()) } } @@ -288,7 +304,9 @@ mod tests { let eth = EthFilter::new(&transport); // when - let filter = FilterBuilder::default().topics(None, Some(vec![2.into()]), None, None).build(); + let filter = FilterBuilder::default() + .topics(None, Some(vec![2.into()]), None, None) + .build(); let filter = eth.create_logs_filter(filter).wait().unwrap(); assert_eq!(filter.id, "0x123".to_owned()); filter.logs().wait() @@ -296,7 +314,10 @@ mod tests { // then assert_eq!(result, Ok(vec![log])); - transport.assert_request("eth_newFilter", &[r#"{"topics":[null,"0x0000000000000000000000000000000000000000000000000000000000000002"]}"#.into()]); + transport.assert_request( + "eth_newFilter", + &[r#"{"topics":[null,"0x0000000000000000000000000000000000000000000000000000000000000002"]}"#.into()], + ); transport.assert_request("eth_getFilterLogs", &[r#""0x123""#.into()]); transport.assert_no_more_requests(); } @@ -333,7 +354,10 @@ mod tests { // then assert_eq!(result, Ok(Some(vec![log]))); - transport.assert_request("eth_newFilter", &[r#"{"address":"0x0000000000000000000000000000000000000002"}"#.into()]); + transport.assert_request( + "eth_newFilter", + &[r#"{"address":"0x0000000000000000000000000000000000000002"}"#.into()], + ); transport.assert_request("eth_getFilterChanges", &[r#""0x123""#.into()]); transport.assert_no_more_requests(); } @@ -361,7 +385,9 @@ mod tests { // given let mut transport = TestTransport::default(); transport.set_response(Value::String("0x123".into())); - transport.add_response(Value::Array(vec![Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000456"#.into())])); + transport.add_response(Value::Array(vec![Value::String( + r#"0x0000000000000000000000000000000000000000000000000000000000000456"#.into(), + )])); let result = { let eth = EthFilter::new(&transport); @@ -383,9 +409,16 @@ mod tests { // given let mut transport = TestTransport::default(); transport.set_response(Value::String("0x123".into())); - transport.add_response(Value::Array(vec![Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000456"#.into())])); - transport.add_response(Value::Array(vec![Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000457"#.into()), Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000458"#.into())])); - transport.add_response(Value::Array(vec![Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000459"#.into())])); + transport.add_response(Value::Array(vec![Value::String( + r#"0x0000000000000000000000000000000000000000000000000000000000000456"#.into(), + )])); + transport.add_response(Value::Array(vec![ + Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000457"#.into()), + Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000458"#.into()), + ])); + transport.add_response(Value::Array(vec![Value::String( + r#"0x0000000000000000000000000000000000000000000000000000000000000459"#.into(), + )])); let result = { let eth = EthFilter::new(&transport); @@ -425,7 +458,9 @@ mod tests { // given let mut transport = TestTransport::default(); transport.set_response(Value::String("0x123".into())); - transport.add_response(Value::Array(vec![Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000456"#.into())])); + transport.add_response(Value::Array(vec![Value::String( + r#"0x0000000000000000000000000000000000000000000000000000000000000456"#.into(), + )])); let result = { let eth = EthFilter::new(&transport); diff --git a/src/api/eth_subscribe.rs b/src/api/eth_subscribe.rs index 74e53bee..48ce639f 100644 --- a/src/api/eth_subscribe.rs +++ b/src/api/eth_subscribe.rs @@ -53,7 +53,12 @@ pub struct SubscriptionStream { impl SubscriptionStream { fn new(transport: T, id: SubscriptionId) -> Self { let rx = transport.subscribe(&id); - SubscriptionStream { transport, id, rx, _marker: PhantomData } + SubscriptionStream { + transport, + id, + rx, + _marker: PhantomData, + } } /// Return the ID of this subscription @@ -102,7 +107,11 @@ pub struct SubscriptionResult { impl SubscriptionResult { pub fn new(transport: T, id_future: CallFuture) -> Self { - SubscriptionResult { transport, inner: id_future, _marker: PhantomData } + SubscriptionResult { + transport, + inner: id_future, + _marker: PhantomData, + } } } @@ -116,7 +125,10 @@ where fn poll(&mut self) -> Poll { match self.inner.poll() { - Ok(Async::Ready(id)) => Ok(Async::Ready(SubscriptionStream::new(self.transport.clone(), SubscriptionId(id)))), + Ok(Async::Ready(id)) => Ok(Async::Ready(SubscriptionStream::new( + self.transport.clone(), + SubscriptionId(id), + ))), Ok(Async::NotReady) => Ok(Async::NotReady), Err(e) => Err(e), } diff --git a/src/api/mod.rs b/src/api/mod.rs index f22e0994..803b3de7 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -97,7 +97,12 @@ impl Web3 { } /// Should be used to wait for confirmations - pub fn wait_for_confirmations(&self, poll_interval: Duration, confirmations: usize, check: V) -> confirm::Confirmations + pub fn wait_for_confirmations( + &self, + poll_interval: Duration, + confirmations: usize, + check: V, + ) -> confirm::Confirmations where F: IntoFuture, Error = Error>, V: confirm::ConfirmationCheck, @@ -106,12 +111,22 @@ impl Web3 { } /// Sends transaction and returns future resolved after transaction is confirmed - pub fn send_transaction_with_confirmation(&self, tx: TransactionRequest, poll_interval: Duration, confirmations: usize) -> confirm::SendTransactionWithConfirmation { + pub fn send_transaction_with_confirmation( + &self, + tx: TransactionRequest, + poll_interval: Duration, + confirmations: usize, + ) -> confirm::SendTransactionWithConfirmation { confirm::send_transaction_with_confirmation(self.transport.clone(), tx, poll_interval, confirmations) } /// Sends raw transaction and returns future resolved after transaction is confirmed - pub fn send_raw_transaction_with_confirmation(&self, tx: Bytes, poll_interval: Duration, confirmations: usize) -> confirm::SendTransactionWithConfirmation { + pub fn send_raw_transaction_with_confirmation( + &self, + tx: Bytes, + poll_interval: Duration, + confirmations: usize, + ) -> confirm::SendTransactionWithConfirmation { confirm::send_raw_transaction_with_confirmation(self.transport.clone(), tx, poll_interval, confirmations) } } diff --git a/src/api/parity_accounts.rs b/src/api/parity_accounts.rs index a97a005e..6ab08502 100644 --- a/src/api/parity_accounts.rs +++ b/src/api/parity_accounts.rs @@ -69,7 +69,7 @@ mod tests { use super::ParityAccounts; rpc_test! ( - ParityAccounts : parity_kill_account, &Address::from("0x9b776baeaf3896657a9ba0db5564623b3e0173e0"), "123456789" + ParityAccounts : parity_kill_account, &"9b776baeaf3896657a9ba0db5564623b3e0173e0".parse::
().unwrap(), "123456789" => "parity_killAccount", vec![r#""0x9b776baeaf3896657a9ba0db5564623b3e0173e0""#, r#""123456789""#]; Value::Bool(true) => true ); @@ -77,23 +77,23 @@ mod tests { rpc_test! ( ParityAccounts : parity_new_account_from_phrase, "member funny cloth wrist ugly water tuition always fall recycle maze long", "123456789" => "parity_newAccountFromPhrase", vec![r#""member funny cloth wrist ugly water tuition always fall recycle maze long""#, r#""123456789""#]; - Value::String("0xE43eD16390bd419d48B09d6E2aa20203D1eF93E1".into()) => Address::from("0xE43eD16390bd419d48B09d6E2aa20203D1eF93E1") + Value::String("0xE43eD16390bd419d48B09d6E2aa20203D1eF93E1".into()) => "E43eD16390bd419d48B09d6E2aa20203D1eF93E1".parse::
().unwrap() ); rpc_test! ( - ParityAccounts : new_account_from_secret, &H256::from("c6592108cc3577f6a2d6178bc6947b43db39057195802caa0120f26e39af4945"), "123456789" + ParityAccounts : new_account_from_secret, &"c6592108cc3577f6a2d6178bc6947b43db39057195802caa0120f26e39af4945".parse::().unwrap(), "123456789" => "parity_newAccountFromSecret", vec![r#""0xc6592108cc3577f6a2d6178bc6947b43db39057195802caa0120f26e39af4945""#, r#""123456789""#]; - Value::String("0x9b776Baeaf3896657A9ba0db5564623B3E0173e0".into()) => Address::from("0x9b776Baeaf3896657A9ba0db5564623B3E0173e0") + Value::String("0x9b776Baeaf3896657A9ba0db5564623B3E0173e0".into()) => "9b776Baeaf3896657A9ba0db5564623B3E0173e0".parse::
().unwrap() ); rpc_test! ( ParityAccounts : parity_new_account_from_wallet, r#"{"version":3,"id":"3b330c3b-b0b3-4e39-b62e-c2041a98d673","address":"4c8ab9d3e938285776d6717d7319f6a9b1d809dd","Crypto":{"ciphertext":"bb3a6dbf21f0bf2b5eb0b43426590f16650acee9462ab710cca18781691a5739","cipherparams":{"iv":"6a533f77fc5cb8a752a16ec6a3200da1"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"a58609853dec53c81feb165e346c700e714285771825bb4cbf87c4ea1996b682","n":8192,"r":8,"p":1},"mac":"a71edeb659ed628db13579ce9f75c80c9d386c1239b280548d9a0e58ad20d6c7"}}"#, "123456789" => "parity_newAccountFromWallet", vec![r#""{\"version\":3,\"id\":\"3b330c3b-b0b3-4e39-b62e-c2041a98d673\",\"address\":\"4c8ab9d3e938285776d6717d7319f6a9b1d809dd\",\"Crypto\":{\"ciphertext\":\"bb3a6dbf21f0bf2b5eb0b43426590f16650acee9462ab710cca18781691a5739\",\"cipherparams\":{\"iv\":\"6a533f77fc5cb8a752a16ec6a3200da1\"},\"cipher\":\"aes-128-ctr\",\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"salt\":\"a58609853dec53c81feb165e346c700e714285771825bb4cbf87c4ea1996b682\",\"n\":8192,\"r\":8,\"p\":1},\"mac\":\"a71edeb659ed628db13579ce9f75c80c9d386c1239b280548d9a0e58ad20d6c7\"}}""#, r#""123456789""#]; - Value::String("0x4C8aB9d3e938285776d6717d7319F6a9B1d809DD".into()) => Address::from("0x4C8aB9d3e938285776d6717d7319F6a9B1d809DD") + Value::String("0x4C8aB9d3e938285776d6717d7319F6a9B1d809DD".into()) => "4C8aB9d3e938285776d6717d7319F6a9B1d809DD".parse::
().unwrap() ); rpc_test! ( - ParityAccounts : parity_remove_address, &Address::from("0x9b776baeaf3896657a9ba0db5564623b3e0173e0") + ParityAccounts : parity_remove_address, &"9b776baeaf3896657a9ba0db5564623b3e0173e0".parse::
().unwrap() => "parity_removeAddress", vec![r#""0x9b776baeaf3896657a9ba0db5564623b3e0173e0""#]; Value::Bool(true) => true ); diff --git a/src/api/parity_set.rs b/src/api/parity_set.rs index 87160a57..95edebfe 100644 --- a/src/api/parity_set.rs +++ b/src/api/parity_set.rs @@ -75,7 +75,10 @@ impl ParitySet { pub fn set_engine_signer(&self, address: &Address, password: &str) -> CallFuture { let address = helpers::serialize(&address); let password = helpers::serialize(&password); - CallFuture::new(self.transport().execute("parity_setEngineSigner", vec![address, password])) + CallFuture::new( + self.transport() + .execute("parity_setEngineSigner", vec![address, password]), + ) } /// Changes extra data for newly mined blocks @@ -182,9 +185,9 @@ mod tests { rpc_test! ( ParitySet:hash_content, - "https://raw.githubusercontent.com/paritytech/parity-ethereum/master/README.md" + "https://raw.githubusercontent.com/paritytech/parity-ethereum/master/README.md" => "parity_hashContent", vec![r#""https://raw.githubusercontent.com/paritytech/parity-ethereum/master/README.md""#]; - Value::String("0x5198e0fc1a9b90078c2e5bfbc6ab6595c470622d3c28f305d3433c300bba5a46".into()) => H256::from("0x5198e0fc1a9b90078c2e5bfbc6ab6595c470622d3c28f305d3433c300bba5a46") + Value::String("0x5198e0fc1a9b90078c2e5bfbc6ab6595c470622d3c28f305d3433c300bba5a46".into()) => "5198e0fc1a9b90078c2e5bfbc6ab6595c470622d3c28f305d3433c300bba5a46".parse::().unwrap() ); rpc_test! ( @@ -195,7 +198,7 @@ mod tests { ); rpc_test! ( - ParitySet:set_author, &Address::from("0x407d73d8a49eeb85d32cf465507dd71d507100c1") + ParitySet:set_author, &"407d73d8a49eeb85d32cf465507dd71d507100c1".parse::
().unwrap() => "parity_setAuthor", vec![r#""0x407d73d8a49eeb85d32cf465507dd71d507100c1""#]; Value::Bool(true) => true ); @@ -207,38 +210,40 @@ mod tests { ); rpc_test! ( - ParitySet:set_engine_signer, &Address::from("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "hunter2" + ParitySet:set_engine_signer, &"407d73d8a49eeb85d32cf465507dd71d507100c1".parse::
().unwrap(), "hunter2" => "parity_setEngineSigner", vec![r#""0x407d73d8a49eeb85d32cf465507dd71d507100c1""#, r#""hunter2""#]; Value::Bool(true) => true ); rpc_test! ( ParitySet:set_extra_data, - &H256::from("0x5198e0fc1a9b90078c2e5bfbc6ab6595c470622d3c28f305d3433c300bba5a46" ) + &"5198e0fc1a9b90078c2e5bfbc6ab6595c470622d3c28f305d3433c300bba5a46".parse::().unwrap() => "parity_setExtraData", vec![r#""0x5198e0fc1a9b90078c2e5bfbc6ab6595c470622d3c28f305d3433c300bba5a46""#]; Value::Bool(true) => true ); rpc_test! ( - ParitySet:set_gas_ceil_target, &H256::from("0x0000000000000000000000000000000000000000000000000000000000000123") + ParitySet:set_gas_ceil_target, &"0000000000000000000000000000000000000000000000000000000000000123".parse::().unwrap() => "parity_setGasCeilTarget", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#]; Value::Bool(true) => true ); rpc_test! ( - ParitySet:set_gas_floor_target, &H256::from("0x0000000000000000000000000000000000000000000000000000000000000123") + ParitySet:set_gas_floor_target, &"0000000000000000000000000000000000000000000000000000000000000123".parse::().unwrap() => "parity_setGasFloorTarget", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#]; Value::Bool(true) => true ); rpc_test! ( - ParitySet:set_max_transaction_gas, &H256::from("0x0000000000000000000000000000000000000000000000000000000000000123") + ParitySet:set_max_transaction_gas, + &"0000000000000000000000000000000000000000000000000000000000000123".parse::().unwrap() => "parity_setMaxTransactionGas", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#]; Value::Bool(true) => true ); rpc_test! ( - ParitySet:set_min_gas_price, &H256::from("0x0000000000000000000000000000000000000000000000000000000000000123") + ParitySet:set_min_gas_price, + &"0000000000000000000000000000000000000000000000000000000000000123".parse::().unwrap() => "parity_setMinGasPrice", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#]; Value::Bool(true) => true ); @@ -250,7 +255,8 @@ mod tests { ); rpc_test! ( - ParitySet:set_transactions_limit, &H256::from("0x0000000000000000000000000000000000000000000000000000000000000123") + ParitySet:set_transactions_limit, + &"0000000000000000000000000000000000000000000000000000000000000123".parse::().unwrap() => "parity_setTransactionsLimit", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#]; Value::Bool(true) => true ); diff --git a/src/api/personal.rs b/src/api/personal.rs index 1de85583..9b884a40 100644 --- a/src/api/personal.rs +++ b/src/api/personal.rs @@ -44,7 +44,10 @@ impl Personal { let address = helpers::serialize(&address); let password = helpers::serialize(&password); let duration = helpers::serialize(&duration); - CallFuture::new(self.transport.execute("personal_unlockAccount", vec![address, password, duration])) + CallFuture::new( + self.transport + .execute("personal_unlockAccount", vec![address, password, duration]), + ) } /// Sends a transaction from locked account. @@ -52,16 +55,26 @@ impl Personal { pub fn send_transaction(&self, transaction: TransactionRequest, password: &str) -> CallFuture { let transaction = helpers::serialize(&transaction); let password = helpers::serialize(&password); - CallFuture::new(self.transport.execute("personal_sendTransaction", vec![transaction, password])) + CallFuture::new( + self.transport + .execute("personal_sendTransaction", vec![transaction, password]), + ) } /// Signs a transaction without dispatching it to the network. /// The account does not need to be unlocked to make this call, and will not be left unlocked after. /// Returns a signed transaction in raw bytes along with it's details. - pub fn sign_transaction(&self, transaction: TransactionRequest, password: &str) -> CallFuture { + pub fn sign_transaction( + &self, + transaction: TransactionRequest, + password: &str, + ) -> CallFuture { let transaction = helpers::serialize(&transaction); let password = helpers::serialize(&password); - CallFuture::new(self.transport.execute("personal_signTransaction", vec![transaction, password])) + CallFuture::new( + self.transport + .execute("personal_signTransaction", vec![transaction, password]), + ) } } @@ -71,7 +84,7 @@ mod tests { use crate::api::Namespace; use crate::rpc::Value; - use crate::types::{RawTransaction, TransactionRequest}; + use crate::types::{Address, RawTransaction, TransactionRequest}; use rustc_hex::FromHex; use super::Personal; @@ -100,7 +113,7 @@ mod tests { rpc_test! ( Personal:new_account, "hunter2" => "personal_newAccount", vec![r#""hunter2""#]; - Value::String("0x0000000000000000000000000000000000000123".into()) => 0x123 + Value::String("0x0000000000000000000000000000000000000123".into()) => Address::from_low_u64_be(0x123) ); rpc_test! ( @@ -119,17 +132,17 @@ mod tests { }, "hunter2" => "personal_sendTransaction", vec![r#"{"from":"0x0000000000000000000000000000000000000123","gasPrice":"0x1","to":"0x0000000000000000000000000000000000000123","value":"0x1"}"#, r#""hunter2""#]; - Value::String("0x0000000000000000000000000000000000000000000000000000000000000123".into()) => 0x123 + Value::String("0x0000000000000000000000000000000000000000000000000000000000000123".into()) => Address::from_low_u64_be(0x123) ); rpc_test! ( Personal:sign_transaction, TransactionRequest { - from: "0x407d73d8a49eeb85d32cf465507dd71d507100c1".into(), - to: Some("0x853f43d8a49eeb85d32cf465507dd71d507100c1".into()), + from: "407d73d8a49eeb85d32cf465507dd71d507100c1".parse().unwrap(), + to: Some("853f43d8a49eeb85d32cf465507dd71d507100c1".parse().unwrap()), gas: Some(0x7f110.into()), gas_price: Some(0x09184e72a000u64.into()), value: Some(0x7f110.into()), - data: Some(FromHex::from_hex("603880600c6000396000f300603880600c6000396000f3603880600c6000396000f360").unwrap().into()), + data: Some(FromHex::from_hex::>("603880600c6000396000f300603880600c6000396000f3603880600c6000396000f360").unwrap().into()), nonce: Some(0x0.into()), condition: None, }, "hunter2" diff --git a/src/api/traces.rs b/src/api/traces.rs index ad9f1533..28b9a20d 100644 --- a/src/api/traces.rs +++ b/src/api/traces.rs @@ -23,7 +23,12 @@ impl Namespace for Traces { } impl Traces { /// Executes the given call and returns a number of possible traces for it - pub fn call(&self, req: CallRequest, trace_type: Vec, block: Option) -> CallFuture { + pub fn call( + &self, + req: CallRequest, + trace_type: Vec, + block: Option, + ) -> CallFuture { let req = helpers::serialize(&req); let block = helpers::serialize(&block.unwrap_or(BlockNumber::Latest)); let trace_type = helpers::serialize(&trace_type); @@ -41,14 +46,24 @@ impl Traces { pub fn replay_transaction(&self, hash: H256, trace_type: Vec) -> CallFuture { let hash = helpers::serialize(&hash); let trace_type = helpers::serialize(&trace_type); - CallFuture::new(self.transport.execute("trace_replayTransaction", vec![hash, trace_type])) + CallFuture::new( + self.transport + .execute("trace_replayTransaction", vec![hash, trace_type]), + ) } /// Replays all transactions in a block returning the requested traces for each transaction - pub fn replay_block_transactions(&self, block: BlockNumber, trace_type: Vec) -> CallFuture { + pub fn replay_block_transactions( + &self, + block: BlockNumber, + trace_type: Vec, + ) -> CallFuture { let block = helpers::serialize(&block); let trace_type = helpers::serialize(&trace_type); - CallFuture::new(self.transport.execute("trace_replayBlockTransaction", vec![block, trace_type])) + CallFuture::new( + self.transport + .execute("trace_replayBlockTransaction", vec![block, trace_type]), + ) } /// Returns traces created at given block @@ -186,7 +201,7 @@ mod tests { ); rpc_test!( - Traces:replay_transaction, H256::from("0x0000000000000000000000000000000000000000000000000000000000000123"), vec![TraceType::Trace] + Traces:replay_transaction, "0000000000000000000000000000000000000000000000000000000000000123".parse::().unwrap(), vec![TraceType::Trace] => "trace_replayTransaction", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#,r#"["trace"]"#]; ::serde_json::from_str(EXAMPLE_BLOCKTRACE).unwrap() @@ -216,7 +231,7 @@ mod tests { ); rpc_test!( - Traces:get, H256::from("0x0000000000000000000000000000000000000000000000000000000000000123"), vec![0.into()] + Traces:get, "0000000000000000000000000000000000000000000000000000000000000123".parse::().unwrap(), vec![0.into()] => "trace_get", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#, r#"["0x0"]"#]; ::serde_json::from_str(EXAMPLE_TRACE).unwrap() @@ -224,7 +239,7 @@ mod tests { ); rpc_test!( - Traces:transaction, H256::from("0x0000000000000000000000000000000000000000000000000000000000000123") + Traces:transaction, "0000000000000000000000000000000000000000000000000000000000000123".parse::().unwrap() => "trace_transaction", vec![r#""0x0000000000000000000000000000000000000000000000000000000000000123""#]; ::serde_json::from_str(EXAMPLE_TRACE_ARR).unwrap() diff --git a/src/confirm.rs b/src/confirm.rs index e6ad0847..10f57d42 100644 --- a/src/confirm.rs +++ b/src/confirm.rs @@ -70,7 +70,10 @@ where } None => WaitForConfirmationsState::WaitForNextBlock, }, - WaitForConfirmationsState::CompareConfirmations(confirmation_block_number, ref mut block_number_future) => { + WaitForConfirmationsState::CompareConfirmations( + confirmation_block_number, + ref mut block_number_future, + ) => { let block_number = try_ready!(block_number_future.poll()).low_u64(); if confirmation_block_number + self.confirmations as u64 <= block_number { return Ok(().into()); @@ -134,7 +137,10 @@ where eth: create.eth.take().expect("future polled after ready; qed"), state: WaitForConfirmationsState::WaitForNextBlock, filter_stream: filter.stream(create.poll_interval).skip(create.confirmations as u64), - confirmation_check: create.confirmation_check.take().expect("future polled after ready; qed"), + confirmation_check: create + .confirmation_check + .take() + .expect("future polled after ready; qed"), confirmations: create.confirmations, }; ConfirmationsState::Wait(future) @@ -147,7 +153,13 @@ where } /// Should be used to wait for confirmations -pub fn wait_for_confirmations(eth: Eth, eth_filter: EthFilter, poll_interval: Duration, confirmations: usize, check: V) -> Confirmations +pub fn wait_for_confirmations( + eth: Eth, + eth_filter: EthFilter, + poll_interval: Duration, + confirmations: usize, + check: V, +) -> Confirmations where T: Transport, V: ConfirmationCheck, @@ -185,14 +197,19 @@ impl ConfirmationCheck for TransactionReceiptBlockNumberCheck { type Check = TransactionReceiptBlockNumber; fn check(&self) -> Self::Check { - TransactionReceiptBlockNumber { future: self.eth.transaction_receipt(self.hash.clone()) } + TransactionReceiptBlockNumber { + future: self.eth.transaction_receipt(self.hash.clone()), + } } } enum SendTransactionWithConfirmationState { Error(Option), SendTransaction(CallFuture), - WaitForConfirmations(H256, Confirmations, TransactionReceiptBlockNumber>), + WaitForConfirmations( + H256, + Confirmations, TransactionReceiptBlockNumber>, + ), GetTransactionReceipt(CallFuture, T::Out>), } @@ -241,15 +258,24 @@ impl Future for SendTransactionWithConfirmation { loop { let next_state = match self.state { SendTransactionWithConfirmationState::Error(ref mut error) => { - return Err(error.take().expect("Error is initialized initially; future polled only once; qed")); + return Err(error + .take() + .expect("Error is initialized initially; future polled only once; qed")); } SendTransactionWithConfirmationState::SendTransaction(ref mut future) => { let hash = try_ready!(future.poll()); if self.confirmations > 0 { - let confirmation_check = TransactionReceiptBlockNumberCheck::new(Eth::new(self.transport.clone()), hash.clone()); + let confirmation_check = + TransactionReceiptBlockNumberCheck::new(Eth::new(self.transport.clone()), hash.clone()); let eth = Eth::new(self.transport.clone()); let eth_filter = EthFilter::new(self.transport.clone()); - let wait = wait_for_confirmations(eth, eth_filter, self.poll_interval, self.confirmations, confirmation_check); + let wait = wait_for_confirmations( + eth, + eth_filter, + self.poll_interval, + self.confirmations, + confirmation_check, + ); SendTransactionWithConfirmationState::WaitForConfirmations(hash, wait) } else { let receipt_future = Eth::new(&self.transport).transaction_receipt(hash); @@ -262,7 +288,8 @@ impl Future for SendTransactionWithConfirmation { SendTransactionWithConfirmationState::GetTransactionReceipt(receipt_future) } SendTransactionWithConfirmationState::GetTransactionReceipt(ref mut future) => { - let receipt = try_ready!(Future::poll(future)).expect("receipt can't be null after wait for confirmations; qed"); + let receipt = try_ready!(Future::poll(future)) + .expect("receipt can't be null after wait for confirmations; qed"); return Ok(receipt.into()); } }; @@ -272,7 +299,12 @@ impl Future for SendTransactionWithConfirmation { } /// Sends transaction and returns future resolved after transaction is confirmed -pub fn send_transaction_with_confirmation(transport: T, tx: TransactionRequest, poll_interval: Duration, confirmations: usize) -> SendTransactionWithConfirmation +pub fn send_transaction_with_confirmation( + transport: T, + tx: TransactionRequest, + poll_interval: Duration, + confirmations: usize, +) -> SendTransactionWithConfirmation where T: Transport, { @@ -280,7 +312,12 @@ where } /// Sends raw transaction and returns future resolved after transaction is confirmed -pub fn send_raw_transaction_with_confirmation(transport: T, tx: Bytes, poll_interval: Duration, confirmations: usize) -> SendTransactionWithConfirmation +pub fn send_raw_transaction_with_confirmation( + transport: T, + tx: Bytes, + poll_interval: Duration, + confirmations: usize, +) -> SendTransactionWithConfirmation where T: Transport, { @@ -294,6 +331,7 @@ mod tests { use crate::rpc::Value; use crate::types::{TransactionReceipt, TransactionRequest}; use futures::Future; + use serde_json::json; use std::time::Duration; #[test] @@ -321,17 +359,29 @@ mod tests { contract_address: None, logs: vec![], status: Some(1.into()), - logs_bloom: 0.into(), + logs_bloom: Default::default(), }; let poll_interval = Duration::from_secs(0); - transport.add_response(Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000111"#.into())); + transport.add_response(Value::String( + r#"0x0000000000000000000000000000000000000000000000000000000000000111"#.into(), + )); transport.add_response(Value::String("0x123".into())); - transport.add_response(Value::Array(vec![Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000456"#.into()), Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000457"#.into())])); - transport.add_response(Value::Array(vec![Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000458"#.into())])); - transport.add_response(Value::Array(vec![Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000459"#.into())])); + transport.add_response(Value::Array(vec![ + Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000456"#.into()), + Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000457"#.into()), + ])); + transport.add_response(Value::Array(vec![Value::String( + r#"0x0000000000000000000000000000000000000000000000000000000000000458"#.into(), + )])); + transport.add_response(Value::Array(vec![Value::String( + r#"0x0000000000000000000000000000000000000000000000000000000000000459"#.into(), + )])); transport.add_response(Value::Null); - transport.add_response(Value::Array(vec![Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000460"#.into()), Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000461"#.into())])); + transport.add_response(Value::Array(vec![ + Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000460"#.into()), + Value::String(r#"0x0000000000000000000000000000000000000000000000000000000000000461"#.into()), + ])); transport.add_response(Value::Null); transport.add_response(json!(transaction_receipt)); transport.add_response(Value::String("0x6".into())); @@ -339,7 +389,8 @@ mod tests { transport.add_response(Value::Bool(true)); let confirmation = { - let future = send_transaction_with_confirmation(&transport, transaction_request, poll_interval, confirmations); + let future = + send_transaction_with_confirmation(&transport, transaction_request, poll_interval, confirmations); future.wait() }; @@ -348,12 +399,24 @@ mod tests { transport.assert_request("eth_getFilterChanges", &[r#""0x123""#.into()]); transport.assert_request("eth_getFilterChanges", &[r#""0x123""#.into()]); transport.assert_request("eth_getFilterChanges", &[r#""0x123""#.into()]); - transport.assert_request("eth_getTransactionReceipt", &[r#""0x0000000000000000000000000000000000000000000000000000000000000111""#.into()]); + transport.assert_request( + "eth_getTransactionReceipt", + &[r#""0x0000000000000000000000000000000000000000000000000000000000000111""#.into()], + ); transport.assert_request("eth_getFilterChanges", &[r#""0x123""#.into()]); - transport.assert_request("eth_getTransactionReceipt", &[r#""0x0000000000000000000000000000000000000000000000000000000000000111""#.into()]); - transport.assert_request("eth_getTransactionReceipt", &[r#""0x0000000000000000000000000000000000000000000000000000000000000111""#.into()]); + transport.assert_request( + "eth_getTransactionReceipt", + &[r#""0x0000000000000000000000000000000000000000000000000000000000000111""#.into()], + ); + transport.assert_request( + "eth_getTransactionReceipt", + &[r#""0x0000000000000000000000000000000000000000000000000000000000000111""#.into()], + ); transport.assert_request("eth_blockNumber", &[]); - transport.assert_request("eth_getTransactionReceipt", &[r#""0x0000000000000000000000000000000000000000000000000000000000000111""#.into()]); + transport.assert_request( + "eth_getTransactionReceipt", + &[r#""0x0000000000000000000000000000000000000000000000000000000000000111""#.into()], + ); transport.assert_no_more_requests(); assert_eq!(confirmation, Ok(transaction_receipt)); } diff --git a/src/contract/deploy.rs b/src/contract/deploy.rs index c400aeaa..e764b876 100644 --- a/src/contract/deploy.rs +++ b/src/contract/deploy.rs @@ -54,7 +54,9 @@ impl Builder { let params = params.into_tokens(); let data = match (abi.constructor(), params.is_empty()) { - (None, false) => return Err(ethabi::ErrorKind::Msg(format!("Constructor is not defined in the ABI.")).into()), + (None, false) => { + return Err(ethabi::ErrorKind::Msg(format!("Constructor is not defined in the ABI.")).into()); + } (None, true) => code.into(), (Some(constructor), _) => constructor.encode_input(code.into(), ¶ms)?, }; @@ -70,9 +72,18 @@ impl Builder { condition: options.condition, }; - let waiting = confirm::send_transaction_with_confirmation(eth.transport().clone(), tx, self.poll_interval, self.confirmations); - - Ok(PendingContract { eth: Some(eth), abi: Some(abi), waiting }) + let waiting = confirm::send_transaction_with_confirmation( + eth.transport().clone(), + tx, + self.poll_interval, + self.confirmations, + ); + + Ok(PendingContract { + eth: Some(eth), + abi: Some(abi), + waiting, + }) } } @@ -113,12 +124,18 @@ mod tests { // given let mut transport = TestTransport::default(); // Transaction Hash - transport.add_response(rpc::Value::String("0x70ae45a5067fdf3356aa615ca08d925a38c7ff21b486a61e79d5af3969ebc1a1".into())); + transport.add_response(rpc::Value::String( + "0x70ae45a5067fdf3356aa615ca08d925a38c7ff21b486a61e79d5af3969ebc1a1".into(), + )); // BlockFilter transport.add_response(rpc::Value::String("0x0".into())); // getFilterChanges - transport.add_response(rpc::Value::Array(vec![rpc::Value::String("0xd5311584a9867d8e129113e1ec9db342771b94bd4533aeab820a5bcc2c54878f".into())])); - transport.add_response(rpc::Value::Array(vec![rpc::Value::String("0xd5311584a9867d8e129113e1ec9db342771b94bd4533aeab820a5bcc2c548790".into())])); + transport.add_response(rpc::Value::Array(vec![rpc::Value::String( + "0xd5311584a9867d8e129113e1ec9db342771b94bd4533aeab820a5bcc2c54878f".into(), + )])); + transport.add_response(rpc::Value::Array(vec![rpc::Value::String( + "0xd5311584a9867d8e129113e1ec9db342771b94bd4533aeab820a5bcc2c548790".into(), + )])); // receipt let receipt = ::serde_json::from_str::( "{\"blockHash\":\"0xd5311584a9867d8e129113e1ec9db342771b94bd4533aeab820a5bcc2c54878f\",\"blockNumber\":\"0x256\",\"contractAddress\":\"0x600515dfe465f600f0c9793fa27cd2794f3ec0e1\",\"cumulativeGasUsed\":\"0xe57e0\",\"gasUsed\":\"0xe57e0\",\"logs\":[],\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"root\":null,\"transactionHash\":\"0x70ae45a5067fdf3356aa615ca08d925a38c7ff21b486a61e79d5af3969ebc1a1\",\"transactionIndex\":\"0x0\"}" @@ -133,7 +150,17 @@ mod tests { let builder = Contract::deploy(api::Eth::new(&transport), include_bytes!("./res/token.json")).unwrap(); // when - builder.options(Options::with(|opt| opt.value = Some(5.into()))).confirmations(1).execute(vec![1, 2, 3, 4], (U256::from(1_000_000), "My Token".to_owned(), 3u64, "MT".to_owned()), 5.into()).unwrap().wait().unwrap(); + builder + .options(Options::with(|opt| opt.value = Some(5.into()))) + .confirmations(1) + .execute( + vec![1, 2, 3, 4], + (U256::from(1_000_000), "My Token".to_owned(), 3u64, "MT".to_owned()), + 5.into(), + ) + .unwrap() + .wait() + .unwrap(); }; // then @@ -143,9 +170,15 @@ mod tests { transport.assert_request("eth_newBlockFilter", &[]); transport.assert_request("eth_getFilterChanges", &["\"0x0\"".into()]); transport.assert_request("eth_getFilterChanges", &["\"0x0\"".into()]); - transport.assert_request("eth_getTransactionReceipt", &["\"0x70ae45a5067fdf3356aa615ca08d925a38c7ff21b486a61e79d5af3969ebc1a1\"".into()]); + transport.assert_request( + "eth_getTransactionReceipt", + &["\"0x70ae45a5067fdf3356aa615ca08d925a38c7ff21b486a61e79d5af3969ebc1a1\"".into()], + ); transport.assert_request("eth_blockNumber", &[]); - transport.assert_request("eth_getTransactionReceipt", &["\"0x70ae45a5067fdf3356aa615ca08d925a38c7ff21b486a61e79d5af3969ebc1a1\"".into()]); + transport.assert_request( + "eth_getTransactionReceipt", + &["\"0x70ae45a5067fdf3356aa615ca08d925a38c7ff21b486a61e79d5af3969ebc1a1\"".into()], + ); transport.assert_no_more_requests(); } } diff --git a/src/contract/error.rs b/src/contract/error.rs index 56123b63..aba390f4 100644 --- a/src/contract/error.rs +++ b/src/contract/error.rs @@ -3,6 +3,7 @@ use ethabi::Error as EthError; use crate::error::Error as ApiError; +use derive_more::Display; /// Contract error. #[derive(Debug, Display)] @@ -33,6 +34,7 @@ impl From for Error { pub mod deploy { use crate::error::Error as ApiError; use crate::types::H256; + use derive_more::Display; /// Contract deployment error. #[derive(Debug, Display)] diff --git a/src/contract/mod.rs b/src/contract/mod.rs index 0bb9c5d9..e37324bd 100644 --- a/src/contract/mod.rs +++ b/src/contract/mod.rs @@ -56,7 +56,13 @@ impl Contract { /// Creates deployment builder for a contract given it's ABI in JSON. pub fn deploy(eth: Eth, json: &[u8]) -> Result, ethabi::Error> { let abi = ethabi::Contract::load(json)?; - Ok(deploy::Builder { eth, abi, options: Options::default(), confirmations: 1, poll_interval: time::Duration::from_secs(7) }) + Ok(deploy::Builder { + eth, + abi, + options: Options::default(), + confirmations: 1, + poll_interval: time::Duration::from_secs(7), + }) } } @@ -103,7 +109,14 @@ impl Contract { } /// Execute a contract function and wait for confirmations - pub fn call_with_confirmations

(&self, func: &str, params: P, from: Address, options: Options, confirmations: usize) -> confirm::SendTransactionWithConfirmation + pub fn call_with_confirmations

( + &self, + func: &str, + params: P, + from: Address, + options: Options, + confirmations: usize, + ) -> confirm::SendTransactionWithConfirmation where P: Tokenize, { @@ -124,12 +137,20 @@ impl Contract { condition: options.condition, }; - confirm::send_transaction_with_confirmation(self.eth.transport().clone(), transaction_request, poll_interval, confirmations) + confirm::send_transaction_with_confirmation( + self.eth.transport().clone(), + transaction_request, + poll_interval, + confirmations, + ) }) .unwrap_or_else(|e| { // TODO [ToDr] SendTransactionWithConfirmation should support custom error type (so that we can return // `contract::Error` instead of more generic `Error`. - confirm::SendTransactionWithConfirmation::from_err(self.eth.transport().clone(), crate::error::Error::Decoder(format!("{:?}", e))) + confirm::SendTransactionWithConfirmation::from_err( + self.eth.transport().clone(), + crate::error::Error::Decoder(format!("{:?}", e)), + ) }) } @@ -160,7 +181,14 @@ impl Contract { } /// Call constant function - pub fn query(&self, func: &str, params: P, from: A, options: Options, block: B) -> QueryResult + pub fn query( + &self, + func: &str, + params: P, + from: A, + options: Options, + block: B, + ) -> QueryResult where R: Detokenize, A: Into>, @@ -169,7 +197,11 @@ impl Contract { { self.abi .function(func.into()) - .and_then(|function| function.encode_input(¶ms.into_tokens()).map(|call| (call, function))) + .and_then(|function| { + function + .encode_input(¶ms.into_tokens()) + .map(|call| (call, function)) + }) .map(|(call, function)| { let result = self.eth.call( CallRequest { @@ -213,11 +245,20 @@ mod tests { let token = contract(&transport); // when - token.query("name", (), None, Options::default(), BlockNumber::Number(1)).wait().unwrap() + token + .query("name", (), None, Options::default(), BlockNumber::Number(1)) + .wait() + .unwrap() }; // then - transport.assert_request("eth_call", &["{\"data\":\"0x06fdde03\",\"to\":\"0x0000000000000000000000000000000000000001\"}".into(), "\"0x1\"".into()]); + transport.assert_request( + "eth_call", + &[ + "{\"data\":\"0x06fdde03\",\"to\":\"0x0000000000000000000000000000000000000001\"}".into(), + "\"0x1\"".into(), + ], + ); transport.assert_no_more_requests(); assert_eq!(result, "Hello World!".to_owned()); } @@ -281,7 +322,10 @@ mod tests { let token = contract(&transport); // when - token.estimate_gas("name", (), 5.into(), Options::default()).wait().unwrap() + token + .estimate_gas("name", (), 5.into(), Options::default()) + .wait() + .unwrap() }; // then @@ -294,13 +338,18 @@ mod tests { fn should_query_single_parameter_function() { // given let mut transport = TestTransport::default(); - transport.set_response(rpc::Value::String("0x0000000000000000000000000000000000000000000000000000000000000020".into())); + transport.set_response(rpc::Value::String( + "0x0000000000000000000000000000000000000000000000000000000000000020".into(), + )); let result: U256 = { let token = contract(&transport); // when - token.query("balanceOf", Address::from(5), None, Options::default(), None).wait().unwrap() + token + .query("balanceOf", Address::from(5), None, Options::default(), None) + .wait() + .unwrap() }; // then diff --git a/src/contract/result.rs b/src/contract/result.rs index 6072cec8..edb30a8a 100644 --- a/src/contract/result.rs +++ b/src/contract/result.rs @@ -28,7 +28,9 @@ pub struct CallFuture { impl From> for CallFuture { fn from(inner: crate::helpers::CallFuture) -> Self { - CallFuture { inner: ResultType::Simple(inner) } + CallFuture { + inner: ResultType::Simple(inner), + } } } @@ -37,7 +39,9 @@ where E: Into, { fn from(e: E) -> Self { - CallFuture { inner: ResultType::Constant(Err(e.into())) } + CallFuture { + inner: ResultType::Constant(Err(e.into())), + } } } @@ -54,14 +58,18 @@ where E: Into, { fn from(e: E) -> Self { - QueryResult { inner: ResultType::Constant(Err(e.into())) } + QueryResult { + inner: ResultType::Constant(Err(e.into())), + } } } impl QueryResult { /// Create a new `QueryResult` wrapping the inner future. pub fn new(inner: helpers::CallFuture, function: ethabi::Function) -> Self { - QueryResult { inner: ResultType::Decodable(inner, function) } + QueryResult { + inner: ResultType::Decodable(inner, function), + } } } diff --git a/src/contract/tokens.rs b/src/contract/tokens.rs index 3530b676..97097a6e 100644 --- a/src/contract/tokens.rs +++ b/src/contract/tokens.rs @@ -16,7 +16,10 @@ pub trait Detokenize { impl Detokenize for T { fn from_tokens(mut tokens: Vec) -> Result { if tokens.len() != 1 { - Err(Error::InvalidOutputType(format!("Expected single element, got a list: {:?}", tokens))) + Err(Error::InvalidOutputType(format!( + "Expected single element, got a list: {:?}", + tokens + ))) } else { Self::from_token(tokens.drain(..).next().expect("At least one element in vector; qed")) } @@ -171,7 +174,7 @@ impl Tokenizable for H256 { } fn into_token(self) -> Token { - Token::FixedBytes(self.0.to_vec()) + Token::FixedBytes(self.as_ref().to_vec()) } } @@ -249,7 +252,9 @@ impl Tokenizable for Vec { impl Tokenizable for Vec { fn from_token(token: Token) -> Result { match token { - Token::FixedArray(tokens) | Token::Array(tokens) => tokens.into_iter().map(Tokenizable::from_token).collect(), + Token::FixedArray(tokens) | Token::Array(tokens) => { + tokens.into_iter().map(Tokenizable::from_token).collect() + } other => Err(Error::InvalidOutputType(format!("Expected `Array`, got {:?}", other)).into()), } } @@ -266,14 +271,20 @@ macro_rules! impl_fixed_types { match token { Token::FixedBytes(bytes) => { if bytes.len() != $num { - return Err(Error::InvalidOutputType(format!("Expected `FixedBytes({})`, got FixedBytes({})", $num, bytes.len()))); + return Err(Error::InvalidOutputType(format!( + "Expected `FixedBytes({})`, got FixedBytes({})", + $num, + bytes.len() + ))); } let mut arr = [0; $num]; arr.copy_from_slice(&bytes); Ok(arr) } - other => Err(Error::InvalidOutputType(format!("Expected `FixedBytes({})`, got {:?}", $num, other)).into()), + other => Err( + Error::InvalidOutputType(format!("Expected `FixedBytes({})`, got {:?}", $num, other)).into(), + ), } } @@ -287,7 +298,11 @@ macro_rules! impl_fixed_types { match token { Token::FixedArray(tokens) => { if tokens.len() != $num { - return Err(Error::InvalidOutputType(format!("Expected `FixedArray({})`, got FixedArray({})", $num, tokens.len()))); + return Err(Error::InvalidOutputType(format!( + "Expected `FixedArray({})`, got FixedArray({})", + $num, + tokens.len() + ))); } let mut arr = ArrayVec::<[T; $num]>::new(); @@ -301,7 +316,9 @@ macro_rules! impl_fixed_types { Err(_) => panic!("All elements inserted so the array is full; qed"), } } - other => Err(Error::InvalidOutputType(format!("Expected `FixedArray({})`, got {:?}", $num, other)).into()), + other => Err( + Error::InvalidOutputType(format!("Expected `FixedArray({})`, got {:?}", $num, other)).into(), + ), } } @@ -357,7 +374,16 @@ mod tests { #[test] fn should_decode_array_of_fixed_bytes() { // byte[8][] - let tokens = vec![Token::FixedArray(vec![Token::FixedBytes(vec![1]), Token::FixedBytes(vec![2]), Token::FixedBytes(vec![3]), Token::FixedBytes(vec![4]), Token::FixedBytes(vec![5]), Token::FixedBytes(vec![6]), Token::FixedBytes(vec![7]), Token::FixedBytes(vec![8])])]; + let tokens = vec![Token::FixedArray(vec![ + Token::FixedBytes(vec![1]), + Token::FixedBytes(vec![2]), + Token::FixedBytes(vec![3]), + Token::FixedBytes(vec![4]), + Token::FixedBytes(vec![5]), + Token::FixedBytes(vec![6]), + Token::FixedBytes(vec![7]), + Token::FixedBytes(vec![8]), + ])]; let data: [[u8; 1]; 8] = Detokenize::from_tokens(tokens).unwrap(); assert_eq!(data[0][0], 1); assert_eq!(data[1][0], 2); diff --git a/src/error.rs b/src/error.rs index 2831affa..474349cb 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,5 +1,6 @@ //! Web3 Error use crate::rpc::error::Error as RPCError; +use derive_more::Display; use serde_json::Error as SerdeError; use std::io::Error as IoError; @@ -67,7 +68,9 @@ impl PartialEq for Error { use self::Error::*; match (self, other) { (Unreachable, Unreachable) | (Internal, Internal) => true, - (Decoder(a), Decoder(b)) | (InvalidResponse(a), InvalidResponse(b)) | (Transport(a), Transport(b)) => a == b, + (Decoder(a), Decoder(b)) | (InvalidResponse(a), InvalidResponse(b)) | (Transport(a), Transport(b)) => { + a == b + } (Rpc(a), Rpc(b)) => a == b, (Io(a), Io(b)) => a.kind() == b.kind(), _ => false, diff --git a/src/helpers.rs b/src/helpers.rs index b3a88a80..f7ba5f7a 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -21,7 +21,10 @@ pub struct CallFuture { impl CallFuture { /// Create a new CallFuture wrapping the inner future. pub fn new(inner: F) -> Self { - CallFuture { inner, _marker: PhantomData } + CallFuture { + inner, + _marker: PhantomData, + } } } @@ -56,7 +59,7 @@ pub fn build_request(id: usize, method: &str, params: Vec) -> rpc::C rpc::Call::MethodCall(rpc::MethodCall { jsonrpc: Some(rpc::Version::V2), method: method.into(), - params: Some(rpc::Params::Array(params)), + params: rpc::Params::Array(params), id: rpc::Id::Num(id as u64), }) } @@ -144,7 +147,12 @@ pub mod tests { pub fn assert_no_more_requests(&mut self) { let requests = self.requests.borrow(); - assert_eq!(self.asserted, requests.len(), "Expected no more requests, got: {:?}", &requests[self.asserted..]); + assert_eq!( + self.asserted, + requests.len(), + "Expected no more requests, got: {:?}", + &requests[self.asserted..] + ); } } diff --git a/src/lib.rs b/src/lib.rs index d7b9e15b..49140d18 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,25 +2,7 @@ #![warn(missing_docs)] -extern crate arrayvec; -extern crate base64; -extern crate ethabi; -extern crate ethereum_types; -extern crate jsonrpc_core as rpc; -extern crate parking_lot; -extern crate rustc_hex; -extern crate serde; -extern crate tokio_timer; - -#[cfg_attr(test, macro_use)] -extern crate serde_json; - -#[macro_use] -extern crate derive_more; -#[macro_use] -extern crate log; -#[macro_use] -extern crate serde_derive; +use jsonrpc_core as rpc; /// Re-export of the `futures` crate. #[macro_use] diff --git a/src/transports/batch.rs b/src/transports/batch.rs index ccd45c9e..e83dcc43 100644 --- a/src/transports/batch.rs +++ b/src/transports/batch.rs @@ -27,7 +27,11 @@ where { /// Creates new Batch transport given existing transport supporing batch requests. pub fn new(transport: T) -> Self { - Batch { transport, pending: Default::default(), batch: Default::default() } + Batch { + transport, + pending: Default::default(), + batch: Default::default(), + } } /// Sends all requests as a batch. @@ -38,7 +42,10 @@ where let batch = self.transport.send_batch(batch); let pending = self.pending.clone(); - BatchFuture { state: BatchState::SendingBatch(batch, ids), pending } + BatchFuture { + state: BatchState::SendingBatch(batch, ids), + pending, + } } } @@ -63,7 +70,10 @@ where enum BatchState { SendingBatch(T, Vec), - Resolving(future::JoinAll>>>, Result>>), + Resolving( + future::JoinAll>>>, + Result>>, + ), Done, } diff --git a/src/transports/http.rs b/src/transports/http.rs index c99df0e6..6c7f7b13 100644 --- a/src/transports/http.rs +++ b/src/transports/http.rs @@ -99,20 +99,29 @@ impl Http { #[cfg(not(feature = "tls"))] let client = hyper::Client::new(); - handle.spawn(write_receiver.map(move |(request, tx): (_, Pending)| client.request(request).then(move |response| Ok((response, tx)))).buffer_unordered(max_parallel).for_each(|(response, tx)| { - use futures::future::Either::{A, B}; - let future = match response { - Ok(ref res) if !res.status().is_success() => A(future::err(Error::Transport(format!("Unexpected response status code: {}", res.status())).into())), - Ok(res) => B(res.into_body().concat2().map_err(Into::into)), - Err(err) => A(future::err(err.into())), - }; - future.then(move |result| { - if let Err(err) = tx.send(result) { - warn!("Error resuming asynchronous request: {:?}", err); - } - Ok(()) - }) - })); + handle.spawn( + write_receiver + .map(move |(request, tx): (_, Pending)| { + client.request(request).then(move |response| Ok((response, tx))) + }) + .buffer_unordered(max_parallel) + .for_each(|(response, tx)| { + use futures::future::Either::{A, B}; + let future = match response { + Ok(ref res) if !res.status().is_success() => A(future::err( + Error::Transport(format!("Unexpected response status code: {}", res.status())).into(), + )), + Ok(res) => B(res.into_body().concat2().map_err(Into::into)), + Err(err) => A(future::err(err.into())), + }; + future.then(move |result| { + if let Err(err) = tx.send(result) { + log::warn!("Error resuming asynchronous request: {:?}", err); + } + Ok(()) + }) + }), + ); let basic_auth = { let url = Url::parse(url)?; @@ -129,7 +138,12 @@ impl Http { } }; - Ok(Http { id: Default::default(), url: url.parse()?, basic_auth, write_sender }) + Ok(Http { + id: Default::default(), + url: url.parse()?, + basic_auth, + write_sender, + }) } fn send_request(&self, id: RequestId, request: rpc::Request, extract: F) -> FetchTask @@ -137,13 +151,17 @@ impl Http { F: Fn(hyper::Chunk) -> O, { let request = helpers::to_string(&request); - debug!("[{}] Sending: {} to {}", id, request, self.url); + log::debug!("[{}] Sending: {} to {}", id, request, self.url); let len = request.len(); let mut req = hyper::Request::new(hyper::Body::from(request)); *req.method_mut() = hyper::Method::POST; *req.uri_mut() = self.url.clone(); - req.headers_mut().insert(hyper::header::CONTENT_TYPE, HeaderValue::from_static("application/json")); - req.headers_mut().insert(hyper::header::USER_AGENT, HeaderValue::from_static("web3.rs")); + req.headers_mut().insert( + hyper::header::CONTENT_TYPE, + HeaderValue::from_static("application/json"), + ); + req.headers_mut() + .insert(hyper::header::USER_AGENT, HeaderValue::from_static("web3.rs")); // Don't send chunked request if len < MAX_SINGLE_CHUNK { @@ -151,10 +169,14 @@ impl Http { } // Send basic auth header if let Some(ref basic_auth) = self.basic_auth { - req.headers_mut().insert(hyper::header::AUTHORIZATION, basic_auth.clone()); + req.headers_mut() + .insert(hyper::header::AUTHORIZATION, basic_auth.clone()); } let (tx, rx) = futures::oneshot(); - let result = self.write_sender.unbounded_send((req, tx)).map_err(|_| Error::Io(::std::io::ErrorKind::BrokenPipe.into()).into()); + let result = self + .write_sender + .unbounded_send((req, tx)) + .map_err(|_| Error::Io(::std::io::ErrorKind::BrokenPipe.into()).into()); Response::new(id, result, rx, extract) } @@ -192,7 +214,8 @@ impl BatchTransport for Http { /// Parse bytes RPC response into `Result`. fn single_response>(response: T) -> Result { - let response = serde_json::from_slice(&*response).map_err(|e| Error::from(Error::InvalidResponse(format!("{:?}", e))))?; + let response = + serde_json::from_slice(&*response).map_err(|e| Error::from(Error::InvalidResponse(format!("{:?}", e))))?; match response { rpc::Response::Single(output) => helpers::to_result_from_output(output), @@ -202,7 +225,8 @@ fn single_response>(response: T) -> Result { /// Parse bytes RPC batch response into `Result`. fn batch_response>(response: T) -> Result>> { - let response = serde_json::from_slice(&*response).map_err(|e| Error::from(Error::InvalidResponse(format!("{:?}", e))))?; + let response = + serde_json::from_slice(&*response).map_err(|e| Error::from(Error::InvalidResponse(format!("{:?}", e))))?; match response { rpc::Response::Batch(outputs) => Ok(outputs.into_iter().map(helpers::to_result_from_output).collect()), diff --git a/src/transports/ipc.rs b/src/transports/ipc.rs index 35249334..563bb11a 100644 --- a/src/transports/ipc.rs +++ b/src/transports/ipc.rs @@ -30,7 +30,7 @@ macro_rules! try_nb { Ok(t) => t, Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => return Ok(futures::Async::NotReady), Err(e) => { - warn!("Unexpected IO error: {:?}", e); + log::warn!("Unexpected IO error: {:?}", e); return Err(()); } } @@ -74,7 +74,7 @@ impl Ipc { where P: AsRef, { - trace!("Connecting to: {:?}", path.as_ref()); + log::trace!("Connecting to: {:?}", path.as_ref()); let stream = UnixStream::connect(path, handle)?; Self::with_stream(stream, handle) } @@ -87,14 +87,29 @@ impl Ipc { let pending: Arc>> = Default::default(); let subscriptions: Arc>> = Default::default(); - let r = ReadStream { read, pending: pending.clone(), subscriptions: subscriptions.clone(), buffer: vec![], current_pos: 0 }; + let r = ReadStream { + read, + pending: pending.clone(), + subscriptions: subscriptions.clone(), + buffer: vec![], + current_pos: 0, + }; - let w = WriteStream { write, incoming: write_receiver, state: WriteState::WaitingForRequest }; + let w = WriteStream { + write, + incoming: write_receiver, + state: WriteState::WaitingForRequest, + }; handle.spawn(r); handle.spawn(w); - Ok(Ipc { id: Arc::new(atomic::AtomicUsize::new(1)), write_sender, pending, subscriptions }) + Ok(Ipc { + id: Arc::new(atomic::AtomicUsize::new(1)), + write_sender, + pending, + subscriptions, + }) } #[cfg(not(unix))] @@ -107,11 +122,14 @@ impl Ipc { F: Fn(Vec>) -> O, { let request = helpers::to_string(&request); - debug!("[{}] Calling: {}", id, request); + log::debug!("[{}] Calling: {}", id, request); let (tx, rx) = futures::oneshot(); self.pending.lock().insert(id, tx); - let result = self.write_sender.unbounded_send(request.into_bytes()).map_err(|_| Error::Io(io::ErrorKind::BrokenPipe.into()).into()); + let result = self + .write_sender + .unbounded_send(request.into_bytes()) + .map_err(|_| Error::Io(io::ErrorKind::BrokenPipe.into()).into()); Response::new(id, result, rx, extract) } @@ -159,7 +177,7 @@ impl DuplexTransport for Ipc { fn subscribe(&self, id: &SubscriptionId) -> Self::NotificationStream { let (tx, rx) = mpsc::unbounded(); if self.subscriptions.lock().insert(id.clone(), tx).is_some() { - warn!("Replacing already-registered subscription with id {:?}", id) + log::warn!("Replacing already-registered subscription with id {:?}", id) } Box::new(rx.map_err(|()| Error::Transport("No data available".into()).into())) } @@ -195,19 +213,25 @@ impl Future for WriteStream { // Ask for more to write let to_send = try_ready!(self.incoming.poll()); if let Some(to_send) = to_send { - trace!("Got new message to write: {:?}", String::from_utf8_lossy(&to_send)); - WriteState::Writing { buffer: to_send, current_pos: 0 } + log::trace!("Got new message to write: {:?}", String::from_utf8_lossy(&to_send)); + WriteState::Writing { + buffer: to_send, + current_pos: 0, + } } else { return Ok(futures::Async::NotReady); } } - WriteState::Writing { ref buffer, ref mut current_pos } => { + WriteState::Writing { + ref buffer, + ref mut current_pos, + } => { // Write everything in the buffer while *current_pos < buffer.len() { let n = try_nb!(self.write.write(&buffer[*current_pos..])); *current_pos += n; if n == 0 { - warn!("IO Error: Zero write."); + log::warn!("IO Error: Zero write."); return Err(()); // zero write? } } @@ -292,19 +316,19 @@ impl ReadStream { if let rpc::Id::Num(num) = id { if let Some(request) = self.pending.lock().remove(&(num as usize)) { - trace!("Responding to (id: {:?}) with {:?}", num, outputs); + log::trace!("Responding to (id: {:?}) with {:?}", num, outputs); if let Err(err) = request.send(helpers::to_results_from_outputs(outputs)) { - warn!("Sending a response to deallocated channel: {:?}", err); + log::warn!("Sending a response to deallocated channel: {:?}", err); } } else { - warn!("Got response for unknown request (id: {:?})", num); + log::warn!("Got response for unknown request (id: {:?})", num); } } else { - warn!("Got unsupported response (id: {:?})", id); + log::warn!("Got unsupported response (id: {:?})", id); } } Message::Notification(notification) => { - if let Some(rpc::Params::Map(params)) = notification.params { + if let rpc::Params::Map(params) = notification.params { let id = params.get("subscription"); let result = params.get("result"); @@ -312,13 +336,13 @@ impl ReadStream { let id: SubscriptionId = id.clone().into(); if let Some(stream) = self.subscriptions.lock().get(&id) { if let Err(e) = stream.unbounded_send(result.clone()) { - error!("Error sending notification (id: {:?}): {:?}", id, e); + log::error!("Error sending notification (id: {:?}): {:?}", id, e); } } else { - warn!("Got notification for unknown subscription (id: {:?})", id); + log::warn!("Got notification for unknown subscription (id: {:?})", id); } } else { - error!("Got unsupported notification (id: {:?})", id); + log::error!("Got unsupported notification (id: {:?})", id); } } } @@ -380,7 +404,10 @@ mod tests { // Read request let read = try_nb!(self.server.read(&mut data)); let request = String::from_utf8(data[0..read].to_vec()).unwrap(); - assert_eq!(&request, r#"{"jsonrpc":"2.0","method":"eth_accounts","params":["1"],"id":1}"#); + assert_eq!( + &request, + r#"{"jsonrpc":"2.0","method":"eth_accounts","params":["1"],"id":1}"# + ); // Write response let response = r#"{"jsonrpc":"2.0","id":1,"result":"x"}"#; @@ -441,6 +468,9 @@ mod tests { let res2 = ipc.execute("eth_accounts", vec![rpc::Value::String("1".into())]); // then - assert_eq!(eloop.run(res1.join(res2)), Ok((rpc::Value::String("x".into()), rpc::Value::String("x".into())))); + assert_eq!( + eloop.run(res1.join(res2)), + Ok((rpc::Value::String("x".into()), rpc::Value::String("x".into()))) + ); } } diff --git a/src/transports/shared.rs b/src/transports/shared.rs index 3369b3a3..52043684 100644 --- a/src/transports/shared.rs +++ b/src/transports/shared.rs @@ -51,7 +51,16 @@ impl EventLoopHandle { } }); - rx.recv().expect("Thread is always spawned.").map(|(http, remote)| (EventLoopHandle { thread: Some(eloop), remote, done }, http)) + rx.recv().expect("Thread is always spawned.").map(|(http, remote)| { + ( + EventLoopHandle { + thread: Some(eloop), + remote, + done, + }, + http, + ) + }) } /// Returns event loop remote. @@ -64,7 +73,11 @@ impl Drop for EventLoopHandle { fn drop(&mut self) { self.done.store(true, atomic::Ordering::Relaxed); self.remote.spawn(|_| Ok(())); - self.thread.take().expect("We never touch thread except for drop; drop happens only once; qed").join().expect("Thread should shut down cleanly."); + self.thread + .take() + .expect("We never touch thread except for drop; drop happens only once; qed") + .join() + .expect("Thread should shut down cleanly."); } } @@ -86,7 +99,11 @@ pub struct Response { impl Response { /// Creates a new `Response` pub fn new(id: RequestId, result: Result<()>, rx: PendingResult, extract: T) -> Self { - Response { id, extract, state: RequestState::Sending(Some(result), rx) } + Response { + id, + extract, + state: RequestState::Sending(Some(result), rx), + } } } @@ -103,15 +120,15 @@ where let extract = &self.extract; match self.state { RequestState::Sending(ref mut result, _) => { - trace!("[{}] Request pending.", self.id); + log::trace!("[{}] Request pending.", self.id); if let Some(Err(e)) = result.take() { return Err(e); } } RequestState::WaitingForResponse(ref mut rx) => { - trace!("[{}] Checking response.", self.id); + log::trace!("[{}] Checking response.", self.id); let result = try_ready!(rx.poll().map_err(|_| Error::Io(::std::io::ErrorKind::TimedOut.into()))); - trace!("[{}] Extracting result.", self.id); + log::trace!("[{}] Extracting result.", self.id); return result.and_then(|x| extract(x)).map(futures::Async::Ready); } RequestState::Done => { @@ -120,7 +137,11 @@ where } // Proceeed to the next state let state = mem::replace(&mut self.state, RequestState::Done); - self.state = if let RequestState::Sending(_, rx) = state { RequestState::WaitingForResponse(rx) } else { state } + self.state = if let RequestState::Sending(_, rx) = state { + RequestState::WaitingForResponse(rx) + } else { + state + } } } } diff --git a/src/transports/ws.rs b/src/transports/ws.rs index 05694d78..cba5523e 100644 --- a/src/transports/ws.rs +++ b/src/transports/ws.rs @@ -57,7 +57,7 @@ impl WebSocket { /// Create new WebSocket transport within existing Event Loop. pub fn with_event_loop(url: &str, handle: &reactor::Handle) -> Result { - trace!("Connecting to: {:?}", url); + log::trace!("Connecting to: {:?}", url); let url: Url = url.parse()?; let pending: Arc>> = Default::default(); @@ -69,77 +69,96 @@ impl WebSocket { let subscriptions_ = subscriptions.clone(); let write_sender_ = write_sender.clone(); - ClientBuilder::from_url(&url).async_connect(None, handle).from_err::().map(|(duplex, _)| duplex.split()).and_then(move |(sink, stream)| { - let reader = stream.from_err::().for_each(move |message| { - trace!("Message received: {:?}", message); - - match message { - OwnedMessage::Close(e) => write_sender_.unbounded_send(OwnedMessage::Close(e)).map_err(|_| Error::Transport("Error sending close message".into()).into()), - OwnedMessage::Ping(d) => write_sender_.unbounded_send(OwnedMessage::Pong(d)).map_err(|_| Error::Transport("Error sending pong message".into()).into()), - OwnedMessage::Text(t) => { - if let Ok(notification) = helpers::to_notification_from_slice(t.as_bytes()) { - if let Some(rpc::Params::Map(params)) = notification.params { - let id = params.get("subscription"); - let result = params.get("result"); - - if let (Some(&rpc::Value::String(ref id)), Some(result)) = (id, result) { - let id: SubscriptionId = id.clone().into(); - if let Some(stream) = subscriptions_.lock().get(&id) { - return stream.unbounded_send(result.clone()).map_err(|_| Error::Transport("Error sending notification".into()).into()); + ClientBuilder::from_url(&url) + .async_connect(None, handle) + .from_err::() + .map(|(duplex, _)| duplex.split()) + .and_then(move |(sink, stream)| { + let reader = stream.from_err::().for_each(move |message| { + log::trace!("Message received: {:?}", message); + + match message { + OwnedMessage::Close(e) => write_sender_ + .unbounded_send(OwnedMessage::Close(e)) + .map_err(|_| Error::Transport("Error sending close message".into()).into()), + OwnedMessage::Ping(d) => write_sender_ + .unbounded_send(OwnedMessage::Pong(d)) + .map_err(|_| Error::Transport("Error sending pong message".into()).into()), + OwnedMessage::Text(t) => { + if let Ok(notification) = helpers::to_notification_from_slice(t.as_bytes()) { + if let rpc::Params::Map(params) = notification.params { + let id = params.get("subscription"); + let result = params.get("result"); + + if let (Some(&rpc::Value::String(ref id)), Some(result)) = (id, result) { + let id: SubscriptionId = id.clone().into(); + if let Some(stream) = subscriptions_.lock().get(&id) { + return stream.unbounded_send(result.clone()).map_err(|_| { + Error::Transport("Error sending notification".into()).into() + }); + } else { + log::warn!("Got notification for unknown subscription (id: {:?})", id); + } } else { - warn!("Got notification for unknown subscription (id: {:?})", id); + log::error!("Got unsupported notification (id: {:?})", id); } - } else { - error!("Got unsupported notification (id: {:?})", id); } - } - return Ok(()); - } + return Ok(()); + } - let response = helpers::to_response_from_slice(t.as_bytes()); - let outputs = match response { - Ok(rpc::Response::Single(output)) => vec![output], - Ok(rpc::Response::Batch(outputs)) => outputs, - _ => vec![], - }; - - let id = match outputs.get(0) { - Some(&rpc::Output::Success(ref success)) => success.id.clone(), - Some(&rpc::Output::Failure(ref failure)) => failure.id.clone(), - None => rpc::Id::Num(0), - }; - - if let rpc::Id::Num(num) = id { - if let Some(request) = pending_.lock().remove(&(num as usize)) { - trace!("Responding to (id: {:?}) with {:?}", num, outputs); - if let Err(err) = request.send(helpers::to_results_from_outputs(outputs)) { - warn!("Sending a response to deallocated channel: {:?}", err); + let response = helpers::to_response_from_slice(t.as_bytes()); + let outputs = match response { + Ok(rpc::Response::Single(output)) => vec![output], + Ok(rpc::Response::Batch(outputs)) => outputs, + _ => vec![], + }; + + let id = match outputs.get(0) { + Some(&rpc::Output::Success(ref success)) => success.id.clone(), + Some(&rpc::Output::Failure(ref failure)) => failure.id.clone(), + None => rpc::Id::Num(0), + }; + + if let rpc::Id::Num(num) = id { + if let Some(request) = pending_.lock().remove(&(num as usize)) { + log::trace!("Responding to (id: {:?}) with {:?}", num, outputs); + if let Err(err) = request.send(helpers::to_results_from_outputs(outputs)) { + log::warn!("Sending a response to deallocated channel: {:?}", err); + } + } else { + log::warn!("Got response for unknown request (id: {:?})", num); } } else { - warn!("Got response for unknown request (id: {:?})", num); + log::warn!("Got unsupported response (id: {:?})", id); } - } else { - warn!("Got unsupported response (id: {:?})", id); - } - Ok(()) + Ok(()) + } + _ => Ok(()), } - _ => Ok(()), - } - }); + }); - let writer = sink.sink_from_err().send_all(write_receiver.map_err(|_| websocket::WebSocketError::NoDataAvailable)).map(|_| ()); + let writer = sink + .sink_from_err() + .send_all(write_receiver.map_err(|_| websocket::WebSocketError::NoDataAvailable)) + .map(|_| ()); - reader.join(writer) - }) + reader.join(writer) + }) }; handle.spawn(ws_future.map(|_| ()).map_err(|err| { - error!("WebSocketError: {:?}", err); + log::error!("WebSocketError: {:?}", err); })); - Ok(Self { id: Arc::new(atomic::AtomicUsize::new(1)), url: url, pending, subscriptions, write_sender }) + Ok(Self { + id: Arc::new(atomic::AtomicUsize::new(1)), + url: url, + pending, + subscriptions, + write_sender, + }) } fn send_request(&self, id: RequestId, request: rpc::Request, extract: F) -> WsTask @@ -147,11 +166,14 @@ impl WebSocket { F: Fn(Vec>) -> O, { let request = helpers::to_string(&request); - debug!("[{}] Calling: {}", id, request); + log::debug!("[{}] Calling: {}", id, request); let (tx, rx) = futures::oneshot(); self.pending.lock().insert(id, tx); - let result = self.write_sender.unbounded_send(OwnedMessage::Text(request)).map_err(|_| Error::Transport("Error sending request".into()).into()); + let result = self + .write_sender + .unbounded_send(OwnedMessage::Text(request)) + .map_err(|_| Error::Transport("Error sending request".into()).into()); Response::new(id, result, rx, extract) } @@ -168,9 +190,11 @@ impl Transport for WebSocket { } fn send(&self, id: RequestId, request: rpc::Call) -> Self::Out { - self.send_request(id, rpc::Request::Single(request), |response| match response.into_iter().next() { - Some(res) => res, - None => Err(Error::InvalidResponse("Expected single, got batch.".into()).into()), + self.send_request(id, rpc::Request::Single(request), |response| { + match response.into_iter().next() { + Some(res) => res, + None => Err(Error::InvalidResponse("Expected single, got batch.".into()).into()), + } }) } } @@ -195,7 +219,7 @@ impl DuplexTransport for WebSocket { fn subscribe(&self, id: &SubscriptionId) -> Self::NotificationStream { let (tx, rx) = mpsc::unbounded(); if self.subscriptions.lock().insert(id.clone(), tx).is_some() { - warn!("Replacing already-registered subscription with id {:?}", id) + log::warn!("Replacing already-registered subscription with id {:?}", id) } Box::new(rx.map_err(|()| Error::Transport("No data available".into()).into())) } @@ -226,30 +250,36 @@ mod tests { let server = Server::bind("localhost:3000", &handle).unwrap(); let f = { let handle_ = handle.clone(); - server.incoming().take(1).map_err(|InvalidConnection { error, .. }| error).for_each(move |(upgrade, addr)| { - trace!("Got a connection from {}", addr); - let f = upgrade.accept().and_then(|(s, _)| { - let (sink, stream) = s.split(); - - stream - .take_while(|m| Ok(!m.is_close())) - .filter_map(|m| match m { - OwnedMessage::Ping(p) => Some(OwnedMessage::Pong(p)), - OwnedMessage::Pong(_) => None, - OwnedMessage::Text(t) => { - assert_eq!(t, r#"{"jsonrpc":"2.0","method":"eth_accounts","params":["1"],"id":1}"#); - Some(OwnedMessage::Text(r#"{"jsonrpc":"2.0","id":1,"result":"x"}"#.to_owned())) - } - _ => None, - }) - .forward(sink) - .and_then(|(_, sink)| sink.send(OwnedMessage::Close(None))) - }); + server + .incoming() + .take(1) + .map_err(|InvalidConnection { error, .. }| error) + .for_each(move |(upgrade, addr)| { + log::trace!("Got a connection from {}", addr); + let f = upgrade.accept().and_then(|(s, _)| { + let (sink, stream) = s.split(); + + stream + .take_while(|m| Ok(!m.is_close())) + .filter_map(|m| match m { + OwnedMessage::Ping(p) => Some(OwnedMessage::Pong(p)), + OwnedMessage::Pong(_) => None, + OwnedMessage::Text(t) => { + assert_eq!(t, r#"{"jsonrpc":"2.0","method":"eth_accounts","params":["1"],"id":1}"#); + Some(OwnedMessage::Text( + r#"{"jsonrpc":"2.0","id":1,"result":"x"}"#.to_owned(), + )) + } + _ => None, + }) + .forward(sink) + .and_then(|(_, sink)| sink.send(OwnedMessage::Close(None))) + }); - handle_.spawn(f.map(|_| ()).map_err(|_| ())); + handle_.spawn(f.map(|_| ()).map_err(|_| ())); - Ok(()) - }) + Ok(()) + }) }; handle.spawn(f.map_err(|_| ())); diff --git a/src/types/block.rs b/src/types/block.rs index 18408d81..40c26b0c 100644 --- a/src/types/block.rs +++ b/src/types/block.rs @@ -1,5 +1,5 @@ use crate::types::{Bytes, H160, H2048, H256, H64, U128, U256}; -use serde::{Serialize, Serializer}; +use serde::{Deserialize, Serialize, Serializer}; /// The block header type returned from RPC calls. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] diff --git a/src/types/bytes.rs b/src/types/bytes.rs index 2800da48..3bba97eb 100644 --- a/src/types/bytes.rs +++ b/src/types/bytes.rs @@ -19,7 +19,7 @@ impl Serialize for Bytes { S: Serializer, { let mut serialized = "0x".to_owned(); - serialized.push_str(self.0.to_hex().as_ref()); + serialized.push_str(self.0.to_hex::().as_ref()); serializer.serialize_str(serialized.as_ref()) } } @@ -47,7 +47,9 @@ impl<'a> Visitor<'a> for BytesVisitor { E: Error, { if value.len() >= 2 && &value[0..2] == "0x" && value.len() & 1 == 0 { - Ok(Bytes(FromHex::from_hex(&value[2..]).map_err(|_| Error::custom("invalid hex"))?)) + Ok(Bytes( + FromHex::from_hex(&value[2..]).map_err(|_| Error::custom("invalid hex"))?, + )) } else { Err(Error::custom("invalid format")) } diff --git a/src/types/log.rs b/src/types/log.rs index 37ef5f6a..e82cb0f0 100644 --- a/src/types/log.rs +++ b/src/types/log.rs @@ -1,6 +1,6 @@ use crate::types::{BlockNumber, Bytes, H160, H256, U256}; use ethabi; -use serde::{Serialize, Serializer}; +use serde::{Deserialize, Serialize, Serializer}; /// A log produced by a transaction. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -120,8 +120,19 @@ impl FilterBuilder { } /// Topics - pub fn topics(mut self, topic1: Option>, topic2: Option>, topic3: Option>, topic4: Option>) -> Self { - let mut topics = vec![topic1, topic2, topic3, topic4].into_iter().rev().skip_while(Option::is_none).map(|option| option.map(ValueOrArray)).collect::>(); + pub fn topics( + mut self, + topic1: Option>, + topic2: Option>, + topic3: Option>, + topic4: Option>, + ) -> Self { + let mut topics = vec![topic1, topic2, topic3, topic4] + .into_iter() + .rev() + .skip_while(Option::is_none) + .map(|option| option.map(ValueOrArray)) + .collect::>(); topics.reverse(); self.filter.topics = Some(topics); @@ -130,7 +141,12 @@ impl FilterBuilder { /// Sets the topics according to the given `ethabi` topic filter pub fn topic_filter(self, topic_filter: ethabi::TopicFilter) -> Self { - self.topics(topic_to_option(topic_filter.topic0), topic_to_option(topic_filter.topic1), topic_to_option(topic_filter.topic2), topic_to_option(topic_filter.topic3)) + self.topics( + topic_to_option(topic_filter.topic0), + topic_to_option(topic_filter.topic1), + topic_to_option(topic_filter.topic2), + topic_to_option(topic_filter.topic3), + ) } /// Limit the result @@ -258,7 +274,14 @@ mod tests { topic3: ethabi::Topic::Any, }; let filter0 = FilterBuilder::default().topic_filter(topic_filter).build(); - let filter1 = FilterBuilder::default().topics(Some(vec![3.into()]), Some(vec![5.into(), 8.into()]), Some(vec![13.into()]), None).build(); + let filter1 = FilterBuilder::default() + .topics( + Some(vec![3.into()]), + Some(vec![5.into(), 8.into()]), + Some(vec![13.into()]), + None, + ) + .build(); assert_eq!(filter0, filter1); } } diff --git a/src/types/parity_peers.rs b/src/types/parity_peers.rs index 7087233e..0f561bab 100644 --- a/src/types/parity_peers.rs +++ b/src/types/parity_peers.rs @@ -1,7 +1,6 @@ //! Types for getting peer information use ethereum_types::U256; - -use serde_derive::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; /// Stores active peer count, connected count, max connected peers /// and a list of peers for parity node diff --git a/src/types/sync_state.rs b/src/types/sync_state.rs index 26fc8812..94e9b70f 100644 --- a/src/types/sync_state.rs +++ b/src/types/sync_state.rs @@ -1,6 +1,7 @@ use crate::types::U256; -use serde::de::{Deserialize, Deserializer, Error}; -use serde::ser::{Serialize, Serializer}; +use serde::de::{Deserializer, Error}; +use serde::ser::Serializer; +use serde::{Deserialize, Serialize}; /// Information about current blockchain syncing operations. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -42,7 +43,11 @@ struct SubscriptionSyncInfo { impl From for SyncInfo { fn from(s: SubscriptionSyncInfo) -> Self { - Self { starting_block: s.starting_block, current_block: s.current_block, highest_block: s.highest_block } + Self { + starting_block: s.starting_block, + current_block: s.current_block, + highest_block: s.highest_block, + } } } @@ -74,7 +79,9 @@ impl<'de> Deserialize<'de> for SyncState { SyncStateVariants::Subscription(state) => match state.status { None if !state.syncing => Ok(SyncState::NotSyncing), Some(ref info) if state.syncing => Ok(SyncState::Syncing(info.clone().into())), - _ => Err(D::Error::custom("expected object or `syncing = false`, got `syncing = true`")), + _ => Err(D::Error::custom( + "expected object or `syncing = false`, got `syncing = true`", + )), }, SyncStateVariants::Boolean(boolean) => { if !boolean { @@ -117,7 +124,14 @@ mod tests { let value: SyncState = serde_json::from_str(sync_state).unwrap(); - assert_eq!(value, SyncState::Syncing(SyncInfo { starting_block: 0x0.into(), current_block: 0x42.into(), highest_block: 0x9001.into() })); + assert_eq!( + value, + SyncState::Syncing(SyncInfo { + starting_block: 0x0.into(), + current_block: 0x42.into(), + highest_block: 0x9001.into() + }) + ); } #[test] @@ -135,7 +149,14 @@ mod tests { let value: SyncState = serde_json::from_str(sync_state).unwrap(); - assert_eq!(value, SyncState::Syncing(SyncInfo { starting_block: 0x0.into(), current_block: 0x42.into(), highest_block: 0x9001.into() })); + assert_eq!( + value, + SyncState::Syncing(SyncInfo { + starting_block: 0x0.into(), + current_block: 0x42.into(), + highest_block: 0x9001.into() + }) + ); } #[test] diff --git a/src/types/trace_filtering.rs b/src/types/trace_filtering.rs index 40f83795..48423f7a 100644 --- a/src/types/trace_filtering.rs +++ b/src/types/trace_filtering.rs @@ -1,6 +1,6 @@ //! Types for the Parity Transaction-Trace Filtering API use crate::types::{Address, BlockNumber, Bytes, H160, H256, U256}; -use serde_derive::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; /// Trace filter #[derive(Debug, Default, Clone, PartialEq, Serialize)] diff --git a/src/types/traces.rs b/src/types/traces.rs index 42011d82..5792c6f9 100644 --- a/src/types/traces.rs +++ b/src/types/traces.rs @@ -1,8 +1,9 @@ //! Types for the Parity Ad-Hoc Trace API -use crate::types::{Action, Bytes, Res, H160, H256, U256}; -use serde_derive::{Deserialize, Serialize}; use std::collections::BTreeMap; +use crate::types::{Action, Bytes, Res, H160, H256, U256}; +use serde::{Deserialize, Serialize}; + #[derive(Debug, Clone, Serialize)] /// Description of the type of trace to make pub enum TraceType { diff --git a/src/types/transaction.rs b/src/types/transaction.rs index 8066469a..6bdf5379 100644 --- a/src/types/transaction.rs +++ b/src/types/transaction.rs @@ -1,4 +1,5 @@ use crate::types::{Bytes, Index, Log, H160, H2048, H256, U256, U64}; +use serde::{Deserialize, Serialize}; /// Description of a Transaction, pending or in the chain. #[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)] diff --git a/src/types/transaction_request.rs b/src/types/transaction_request.rs index d370a7c2..8e09dae1 100644 --- a/src/types/transaction_request.rs +++ b/src/types/transaction_request.rs @@ -1,4 +1,5 @@ use crate::types::{Address, Bytes, U256}; +use serde::{Deserialize, Serialize}; /// Call contract request (eth_call / eth_estimateGas) #[derive(Clone, Debug, PartialEq, Serialize)] diff --git a/src/types/uint.rs b/src/types/uint.rs index 22190ccd..0959cb83 100644 --- a/src/types/uint.rs +++ b/src/types/uint.rs @@ -2,7 +2,7 @@ pub use ethereum_types::{Bloom as H2048, H128, H160, H256, H512, H520, H64, U128 #[cfg(test)] mod tests { - use super::{H128, U256}; + use super::{H128, U128, U256}; use serde_json; type Res = Result; @@ -75,10 +75,10 @@ mod tests { arr[13] = 1; arr[12] = 0; arr[11] = 10; - let a = H128::from(arr); - let b = H128::from(1023); - let c = H128::from(0); - let d = H128::from(10000); + let a: H128 = U128::from(arr).into(); + let b: H128 = U128::from(1023).into(); + let c: H128 = U128::from(0).into(); + let d: H128 = U128::from(10000).into(); // Debug assert_eq!(&format!("{:?}", a), "0x00000000000000000000000a00010f00"); @@ -103,7 +103,7 @@ mod tests { fn should_deserialize_hash_correctly() { let deserialized1: H128 = serde_json::from_str(r#""0x00000000000000000000000a00010f00""#).unwrap(); - assert_eq!(deserialized1, 0xa00010f00.into()); + assert_eq!(deserialized1, H128::from_low_u64_be(0xa00010f00)); } #[test] diff --git a/src/types/work.rs b/src/types/work.rs index 1f76f96c..71e4f89f 100644 --- a/src/types/work.rs +++ b/src/types/work.rs @@ -23,9 +23,20 @@ impl<'a> Deserialize<'a> for Work { { let v: Value = Deserialize::deserialize(deserializer)?; - let (pow_hash, seed_hash, target, number) = serde_json::from_value::<(H256, H256, H256, u64)>(v.clone()).map(|(pow_hash, seed_hash, target, number)| (pow_hash, seed_hash, target, Some(number))).or_else(|_| serde_json::from_value::<(H256, H256, H256)>(v).map(|(pow_hash, seed_hash, target)| (pow_hash, seed_hash, target, None))).map_err(|e| D::Error::custom(format!("Cannot deserialize Work: {:?}", e)))?; + let (pow_hash, seed_hash, target, number) = serde_json::from_value::<(H256, H256, H256, u64)>(v.clone()) + .map(|(pow_hash, seed_hash, target, number)| (pow_hash, seed_hash, target, Some(number))) + .or_else(|_| { + serde_json::from_value::<(H256, H256, H256)>(v) + .map(|(pow_hash, seed_hash, target)| (pow_hash, seed_hash, target, None)) + }) + .map_err(|e| D::Error::custom(format!("Cannot deserialize Work: {:?}", e)))?; - Ok(Work { pow_hash: pow_hash, seed_hash: seed_hash, target: target, number: number }) + Ok(Work { + pow_hash: pow_hash, + seed_hash: seed_hash, + target: target, + number: number, + }) } }