diff --git a/src/api/eth.rs b/src/api/eth.rs index cdcbd616..cabea4aa 100644 --- a/src/api/eth.rs +++ b/src/api/eth.rs @@ -1,10 +1,13 @@ //! `Eth` namespace +use serde::de::DeserializeOwned; + use crate::prelude::*; use crate::types::SyncState; use crate::{ api::Namespace, - helpers::{self, CallFuture}, + error::Result, + helpers, types::{ Address, Block, BlockHeader, BlockId, BlockNumber, Bytes, CallRequest, FeeHistory, Filter, Index, Log, Proof, Transaction, TransactionId, TransactionReceipt, TransactionRequest, Work, H256, H520, H64, U256, U64, @@ -19,9 +22,10 @@ use crate::{ /// fn get_gas_price() { /// use pink_web3::api::{Eth, Namespace}; /// use pink_web3::transports::pink_http::PinkHttp; +/// use pink_web3::ExpectReady; /// let phttp = PinkHttp::new("http://localhost:3333"); /// let eth = Eth::new(phttp); -/// let result = eth.gas_price().resolve(); +/// let result = eth.gas_price().expect_ready(); /// assert!(result.is_ok()); /// } #[derive(Debug, Clone)] @@ -44,49 +48,49 @@ impl Namespace for Eth { impl Eth { /// Get list of available accounts. - pub fn accounts(&self) -> CallFuture, T::Out> { - CallFuture::new(self.transport.execute("eth_accounts", vec![])) + pub async fn accounts(&self) -> Result> { + self.transport.execute("eth_accounts", vec![]).await } /// Get current block number - pub fn block_number(&self) -> CallFuture { - CallFuture::new(self.transport.execute("eth_blockNumber", vec![])) + pub async fn block_number(&self) -> Result { + self.transport.execute("eth_blockNumber", vec![]).await } /// Call a constant method of contract without changing the state of the blockchain. - pub fn call(&self, req: CallRequest, block: Option) -> CallFuture { + pub async fn call(&self, req: CallRequest, block: Option) -> Result { let req = helpers::serialize(&req); let block = block.unwrap_or_else(|| BlockNumber::Latest.into()); let block = helpers::serialize(&block); - CallFuture::new(self.transport.execute("eth_call", vec![req, block])) + self.transport.execute("eth_call", vec![req, block]).await } /// Get coinbase address - pub fn coinbase(&self) -> CallFuture { - CallFuture::new(self.transport.execute("eth_coinbase", vec![])) + pub async fn coinbase(&self) -> Result
{ + self.transport.execute("eth_coinbase", vec![]).await } /// Compile LLL - pub fn compile_lll(&self, code: String) -> CallFuture { + pub async fn compile_lll(&self, code: String) -> Result { let code = helpers::serialize(&code); - CallFuture::new(self.transport.execute("eth_compileLLL", vec![code])) + self.transport.execute("eth_compileLLL", vec![code]).await } /// Compile Solidity - pub fn compile_solidity(&self, code: String) -> CallFuture { + pub async fn compile_solidity(&self, code: String) -> Result { let code = helpers::serialize(&code); - CallFuture::new(self.transport.execute("eth_compileSolidity", vec![code])) + self.transport.execute("eth_compileSolidity", vec![code]).await } /// Compile Serpent - pub fn compile_serpent(&self, code: String) -> CallFuture { + pub async fn compile_serpent(&self, code: String) -> Result { let code = helpers::serialize(&code); - CallFuture::new(self.transport.execute("eth_compileSerpent", vec![code])) + self.transport.execute("eth_compileSerpent", vec![code]).await } /// Call a contract without changing the state of the blockchain to estimate gas usage. - pub fn estimate_gas(&self, req: CallRequest, block: Option) -> CallFuture { + pub async fn estimate_gas(&self, req: CallRequest, block: Option) -> Result { let req = helpers::serialize(&req); let args = match block.as_ref() { @@ -94,308 +98,310 @@ impl Eth { None => vec![req], }; - CallFuture::new(self.transport.execute("eth_estimateGas", args)) + self.transport.execute("eth_estimateGas", args).await } /// Get current recommended gas price - pub fn gas_price(&self) -> CallFuture { - CallFuture::new(self.transport.execute("eth_gasPrice", vec![])) + pub async fn gas_price(&self) -> Result { + self.transport.execute("eth_gasPrice", vec![]).await } /// Returns a collection of historical gas information. This can be used for evaluating the max_fee_per_gas /// and max_priority_fee_per_gas to send the future transactions. - pub fn fee_history( + pub async fn fee_history( &self, block_count: U256, newest_block: BlockNumber, reward_percentiles: Option>, - ) -> CallFuture { + ) -> Result { let block_count = helpers::serialize(&block_count); let newest_block = helpers::serialize(&newest_block); let reward_percentiles = helpers::serialize(&reward_percentiles); - CallFuture::new( - self.transport - .execute("eth_feeHistory", vec![block_count, newest_block, reward_percentiles]), - ) + self.transport + .execute("eth_feeHistory", vec![block_count, newest_block, reward_percentiles]) + .await } /// Get balance of given address - pub fn balance(&self, address: Address, block: Option) -> CallFuture { + pub async fn balance(&self, address: Address, block: Option) -> Result { let address = helpers::serialize(&address); let block = block.unwrap_or(BlockNumber::Latest); let block = helpers::serialize(&block); - CallFuture::new(self.transport.execute("eth_getBalance", vec![address, block])) + self.transport.execute("eth_getBalance", vec![address, block]).await } /// Get all logs matching a given filter object - pub fn logs(&self, filter: Filter) -> CallFuture, T::Out> { + pub async fn logs(&self, filter: Filter) -> Result> { let filter = helpers::serialize(&filter); - CallFuture::new(self.transport.execute("eth_getLogs", vec![filter])) + self.transport.execute("eth_getLogs", vec![filter]).await } /// Get block details with transaction hashes. - pub fn block(&self, block: BlockId) -> CallFuture>, T::Out> { + pub async fn block(&self, block: BlockId) -> Result>> { let include_txs = helpers::serialize(&false); - let result = match block { + match block { BlockId::Hash(hash) => { let hash = helpers::serialize(&hash); - self.transport.execute("eth_getBlockByHash", vec![hash, include_txs]) + self.transport + .execute("eth_getBlockByHash", vec![hash, include_txs]) + .await } BlockId::Number(num) => { let num = helpers::serialize(&num); - self.transport.execute("eth_getBlockByNumber", vec![num, include_txs]) + self.transport + .execute("eth_getBlockByNumber", vec![num, include_txs]) + .await } - }; - - CallFuture::new(result) + } } /// Get block details with full transaction objects. - pub fn block_with_txs(&self, block: BlockId) -> CallFuture>, T::Out> { + pub async fn block_with_txs(&self, block: BlockId) -> Result>> { let include_txs = helpers::serialize(&true); - let result = match block { + match block { BlockId::Hash(hash) => { let hash = helpers::serialize(&hash); - self.transport.execute("eth_getBlockByHash", vec![hash, include_txs]) + self.transport + .execute("eth_getBlockByHash", vec![hash, include_txs]) + .await } BlockId::Number(num) => { let num = helpers::serialize(&num); - self.transport.execute("eth_getBlockByNumber", vec![num, include_txs]) + self.transport + .execute("eth_getBlockByNumber", vec![num, include_txs]) + .await } - }; - - CallFuture::new(result) + } } /// Get number of transactions in block - pub fn block_transaction_count(&self, block: BlockId) -> CallFuture, T::Out> { - let result = match block { + pub async fn block_transaction_count(&self, block: BlockId) -> Result> { + match block { BlockId::Hash(hash) => { let hash = helpers::serialize(&hash); - self.transport.execute("eth_getBlockTransactionCountByHash", vec![hash]) + self.transport + .execute("eth_getBlockTransactionCountByHash", vec![hash]) + .await } BlockId::Number(num) => { let num = helpers::serialize(&num); self.transport .execute("eth_getBlockTransactionCountByNumber", vec![num]) + .await } - }; - - CallFuture::new(result) + } } /// Get code under given address - pub fn code(&self, address: Address, block: Option) -> CallFuture { + pub async fn code(&self, address: Address, block: Option) -> Result { let address = helpers::serialize(&address); let block = block.unwrap_or(BlockNumber::Latest); let block = helpers::serialize(&block); - CallFuture::new(self.transport.execute("eth_getCode", vec![address, block])) + self.transport.execute("eth_getCode", vec![address, block]).await } /// Get supported compilers - pub fn compilers(&self) -> CallFuture, T::Out> { - CallFuture::new(self.transport.execute("eth_getCompilers", vec![])) + pub async fn compilers(&self) -> Result> { + self.transport.execute("eth_getCompilers", vec![]).await } /// Get chain id - pub fn chain_id(&self) -> CallFuture { - CallFuture::new(self.transport.execute("eth_chainId", vec![])) + pub async fn chain_id(&self) -> Result { + self.transport.execute("eth_chainId", vec![]).await } /// Get available user accounts. This method is only available in the browser. With MetaMask, /// this will cause the popup that prompts the user to allow or deny access to their accounts /// to your app. - pub fn request_accounts(&self) -> CallFuture, T::Out> { - CallFuture::new(self.transport.execute("eth_requestAccounts", vec![])) + pub async fn request_accounts(&self) -> Result> { + self.transport.execute("eth_requestAccounts", vec![]).await } /// Get storage entry - pub fn storage(&self, address: Address, idx: U256, block: Option) -> CallFuture { + pub async fn storage(&self, address: Address, idx: U256, block: Option) -> Result { let address = helpers::serialize(&address); let idx = helpers::serialize(&idx); let block = block.unwrap_or(BlockNumber::Latest); let block = helpers::serialize(&block); - CallFuture::new(self.transport.execute("eth_getStorageAt", vec![address, idx, block])) + self.transport + .execute("eth_getStorageAt", vec![address, idx, block]) + .await } /// Get nonce - pub fn transaction_count(&self, address: Address, block: Option) -> CallFuture { + pub async fn transaction_count(&self, address: Address, block: Option) -> Result { let address = helpers::serialize(&address); let block = block.unwrap_or(BlockNumber::Latest); let block = helpers::serialize(&block); - CallFuture::new(self.transport.execute("eth_getTransactionCount", vec![address, block])) + self.transport + .execute("eth_getTransactionCount", vec![address, block]) + .await } /// Get transaction - pub fn transaction(&self, id: TransactionId) -> CallFuture, T::Out> { - let result = match id { + pub async fn transaction(&self, id: TransactionId) -> Result> { + match id { TransactionId::Hash(hash) => { let hash = helpers::serialize(&hash); - self.transport.execute("eth_getTransactionByHash", vec![hash]) + self.transport.execute("eth_getTransactionByHash", vec![hash]).await } TransactionId::Block(BlockId::Hash(hash), index) => { let hash = helpers::serialize(&hash); let idx = helpers::serialize(&index); self.transport .execute("eth_getTransactionByBlockHashAndIndex", vec![hash, idx]) + .await } TransactionId::Block(BlockId::Number(number), index) => { let number = helpers::serialize(&number); let idx = helpers::serialize(&index); self.transport .execute("eth_getTransactionByBlockNumberAndIndex", vec![number, idx]) + .await } - }; - - CallFuture::new(result) + } } /// Get transaction receipt - pub fn transaction_receipt(&self, hash: H256) -> CallFuture, T::Out> { + pub async fn transaction_receipt(&self, hash: H256) -> Result> { let hash = helpers::serialize(&hash); - CallFuture::new(self.transport.execute("eth_getTransactionReceipt", vec![hash])) + self.transport.execute("eth_getTransactionReceipt", vec![hash]).await } /// Get uncle header by block ID and uncle index. /// /// This method is meant for TurboGeth compatiblity, /// which is missing transaction hashes in the response. - pub fn uncle_header(&self, block: BlockId, index: Index) -> CallFuture, T::Out> { - self.fetch_uncle(block, index) + pub async fn uncle_header(&self, block: BlockId, index: Index) -> Result> { + self.fetch_uncle(block, index).await } /// Get uncle by block ID and uncle index -- transactions only has hashes. - pub fn uncle(&self, block: BlockId, index: Index) -> CallFuture>, T::Out> { - self.fetch_uncle(block, index) + pub async fn uncle(&self, block: BlockId, index: Index) -> Result>> { + self.fetch_uncle(block, index).await } - fn fetch_uncle(&self, block: BlockId, index: Index) -> CallFuture, T::Out> { + async fn fetch_uncle(&self, block: BlockId, index: Index) -> Result> { let index = helpers::serialize(&index); - let result = match block { + match block { BlockId::Hash(hash) => { let hash = helpers::serialize(&hash); self.transport .execute("eth_getUncleByBlockHashAndIndex", vec![hash, index]) + .await } BlockId::Number(num) => { let num = helpers::serialize(&num); self.transport .execute("eth_getUncleByBlockNumberAndIndex", vec![num, index]) + .await } - }; - - CallFuture::new(result) + } } /// Get uncle count in block - pub fn uncle_count(&self, block: BlockId) -> CallFuture, T::Out> { - let result = match block { + pub async fn uncle_count(&self, block: BlockId) -> Result> { + match block { BlockId::Hash(hash) => { let hash = helpers::serialize(&hash); - self.transport.execute("eth_getUncleCountByBlockHash", vec![hash]) + self.transport.execute("eth_getUncleCountByBlockHash", vec![hash]).await } BlockId::Number(num) => { let num = helpers::serialize(&num); - self.transport.execute("eth_getUncleCountByBlockNumber", vec![num]) + self.transport + .execute("eth_getUncleCountByBlockNumber", vec![num]) + .await } - }; - - CallFuture::new(result) + } } /// Get work package - pub fn work(&self) -> CallFuture { - CallFuture::new(self.transport.execute("eth_getWork", vec![])) + pub async fn work(&self) -> Result { + self.transport.execute("eth_getWork", vec![]).await } /// Get hash rate - pub fn hashrate(&self) -> CallFuture { - CallFuture::new(self.transport.execute("eth_hashrate", vec![])) + pub async fn hashrate(&self) -> Result { + self.transport.execute("eth_hashrate", vec![]).await } /// Get mining status - pub fn mining(&self) -> CallFuture { - CallFuture::new(self.transport.execute("eth_mining", vec![])) + pub async fn mining(&self) -> Result { + self.transport.execute("eth_mining", vec![]).await } /// Start new block filter - pub fn new_block_filter(&self) -> CallFuture { - CallFuture::new(self.transport.execute("eth_newBlockFilter", vec![])) + pub async fn new_block_filter(&self) -> Result { + self.transport.execute("eth_newBlockFilter", vec![]).await } /// Start new pending transaction filter - pub fn new_pending_transaction_filter(&self) -> CallFuture { - CallFuture::new(self.transport.execute("eth_newPendingTransactionFilter", vec![])) + pub async fn new_pending_transaction_filter(&self) -> Result { + self.transport.execute("eth_newPendingTransactionFilter", vec![]).await } /// Start new pending transaction filter - pub fn protocol_version(&self) -> CallFuture { - CallFuture::new(self.transport.execute("eth_protocolVersion", vec![])) + pub async fn protocol_version(&self) -> Result { + self.transport.execute("eth_protocolVersion", vec![]).await } /// Sends a rlp-encoded signed transaction - pub fn send_raw_transaction(&self, rlp: Bytes) -> CallFuture { + pub async fn send_raw_transaction(&self, rlp: Bytes) -> Result { let rlp = helpers::serialize(&rlp); - CallFuture::new(self.transport.execute("eth_sendRawTransaction", vec![rlp])) + self.transport.execute("eth_sendRawTransaction", vec![rlp]).await } /// Sends a transaction transaction - pub fn send_transaction(&self, tx: TransactionRequest) -> CallFuture { + pub async fn send_transaction(&self, tx: TransactionRequest) -> Result { let tx = helpers::serialize(&tx); - CallFuture::new(self.transport.execute("eth_sendTransaction", vec![tx])) + self.transport.execute("eth_sendTransaction", vec![tx]).await } /// Signs a hash of given data - pub fn sign(&self, address: Address, data: Bytes) -> CallFuture { + pub async fn sign(&self, address: Address, data: Bytes) -> Result { let address = helpers::serialize(&address); let data = helpers::serialize(&data); - CallFuture::new(self.transport.execute("eth_sign", vec![address, data])) + self.transport.execute("eth_sign", vec![address, data]).await } /// Submit hashrate of external miner - pub fn submit_hashrate(&self, rate: U256, id: H256) -> CallFuture { + pub async fn submit_hashrate(&self, rate: U256, id: H256) -> Result { let rate = helpers::serialize(&rate); let id = helpers::serialize(&id); - CallFuture::new(self.transport.execute("eth_submitHashrate", vec![rate, id])) + self.transport.execute("eth_submitHashrate", vec![rate, id]).await } /// Submit work of external miner - pub fn submit_work(&self, nonce: H64, pow_hash: H256, mix_hash: H256) -> CallFuture { + pub async fn submit_work(&self, nonce: H64, pow_hash: H256, mix_hash: H256) -> Result { 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]), - ) + self.transport + .execute("eth_submitWork", vec![nonce, pow_hash, mix_hash]) + .await } /// Get syncing status - pub fn syncing(&self) -> CallFuture { - CallFuture::new(self.transport.execute("eth_syncing", vec![])) + pub async fn syncing(&self) -> Result { + self.transport.execute("eth_syncing", vec![]).await } /// Returns the account- and storage-values of the specified account including the Merkle-proof. - pub fn proof( - &self, - address: Address, - keys: Vec, - block: Option, - ) -> CallFuture, T::Out> { + pub async fn proof(&self, address: Address, keys: Vec, block: Option) -> Result> { let add = helpers::serialize(&address); let ks = helpers::serialize(&keys); let block = block.unwrap_or(BlockNumber::Latest); let blk = helpers::serialize(&block); - CallFuture::new(self.transport.execute("eth_getProof", vec![add, ks, blk])) + self.transport.execute("eth_getProof", vec![add, ks, blk]).await } } diff --git a/src/api/eth_filter.rs b/src/api/eth_filter.rs index 9bd015bc..c16e188d 100644 --- a/src/api/eth_filter.rs +++ b/src/api/eth_filter.rs @@ -1,5 +1,4 @@ //! `Eth` namespace, filters. -use crate::helpers::CallFuture; use crate::prelude::*; use crate::{ api::Namespace, @@ -111,7 +110,7 @@ impl BaseFilter { Self: Sized, { let id = helpers::serialize(&self.id); - Ok(CallFuture::new(self.transport.execute("eth_uninstallFilter", vec![id])).await?) + self.transport.execute("eth_uninstallFilter", vec![id]).await } /// Borrows the transport. @@ -125,7 +124,7 @@ impl BaseFilter { /// Will return logs that happened after previous poll. pub async fn poll(&self) -> error::Result>> { let id = helpers::serialize(&self.id); - Ok(CallFuture::new(self.transport.execute("eth_getFilterChanges", vec![id])).await?) + self.transport.execute("eth_getFilterChanges", vec![id]).await } /// Returns the stream of items which automatically polls the server @@ -138,7 +137,7 @@ impl BaseFilter { /// Returns future with all logs matching given filter pub async fn logs(&self) -> error::Result> { let id = helpers::serialize(&self.id); - Ok(CallFuture::new(self.transport.execute("eth_getFilterLogs", vec![id])).await?) + self.transport.execute("eth_getFilterLogs", vec![id]).await } } @@ -147,7 +146,7 @@ async fn create_filter<'a, T: Transport, F: FilterInterface>( transport: T, arg: Vec>, ) -> error::Result> { - let id = CallFuture::new(transport.execute(F::constructor(), arg)).await?; + let id = transport.execute(F::constructor(), arg).await?; Ok(BaseFilter { id, transport, diff --git a/src/api/eth_subscribe.rs b/src/api/eth_subscribe.rs index dfa3436c..16588b6c 100644 --- a/src/api/eth_subscribe.rs +++ b/src/api/eth_subscribe.rs @@ -75,7 +75,7 @@ impl SubscriptionStream { pub async fn unsubscribe(self) -> error::Result { let &SubscriptionId(ref id) = &self.id; let id = helpers::serialize(&id); - Ok(CallFuture::new(self.transport.execute("eth_unsubscribe", vec![id])).await?) + self.transport.execute("eth_unsubscribe", vec![id]).await } } @@ -107,7 +107,7 @@ impl EthSubscribe { /// Create a new heads subscription pub async fn subscribe_new_heads(&self) -> error::Result> { let subscription = helpers::serialize(&&"newHeads"); - let id = CallFuture::new(self.transport.execute("eth_subscribe", vec![subscription]).await?; + let id = self.transport.execute("eth_subscribe", vec![subscription]).await?; SubscriptionStream::new(self.transport.clone(), SubscriptionId(id)) } @@ -126,14 +126,14 @@ impl EthSubscribe { /// Create a pending transactions subscription pub async fn subscribe_new_pending_transactions(&self) -> error::Result> { let subscription = helpers::serialize(&&"newPendingTransactions"); - let id = CallFuture::new(self.transport.execute("eth_subscribe", vec![subscription])).await?; + let id = self.transport.execute("eth_subscribe", vec![subscription]).await?; SubscriptionStream::new(self.transport.clone(), SubscriptionId(id)) } /// Create a sync status subscription pub async fn subscribe_syncing(&self) -> error::Result> { let subscription = helpers::serialize(&&"syncing"); - let id = CallFuture::new(self.transport.execute("eth_subscribe", vec![subscription])).await?; + let id = self.transport.execute("eth_subscribe", vec![subscription]).await?; SubscriptionStream::new(self.transport.clone(), SubscriptionId(id)) } } diff --git a/src/api/mod.rs b/src/api/mod.rs index 9110061c..16b3709d 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -31,8 +31,8 @@ use crate::{ types::{Bytes, TransactionReceipt, TransactionRequest, U64}, Transport, }; -use futures::Future; use core::time::Duration; +use futures::Future; /// Common API for all namespaces pub trait Namespace: Clone { diff --git a/src/api/net.rs b/src/api/net.rs index f69da135..3f19a493 100644 --- a/src/api/net.rs +++ b/src/api/net.rs @@ -1,6 +1,6 @@ //! `Net` namespace use crate::prelude::*; -use crate::{api::Namespace, helpers::CallFuture, types::U256, Transport}; +use crate::{api::Namespace, error::Result, types::U256, Transport}; /// `Net` namespace #[derive(Debug, Clone)] @@ -23,18 +23,18 @@ impl Namespace for Net { impl Net { /// Returns the network id. - pub fn version(&self) -> CallFuture { - CallFuture::new(self.transport.execute("net_version", vec![])) + pub async fn version(&self) -> Result { + self.transport.execute("net_version", vec![]).await } /// Returns number of peers connected to node. - pub fn peer_count(&self) -> CallFuture { - CallFuture::new(self.transport.execute("net_peerCount", vec![])) + pub async fn peer_count(&self) -> Result { + self.transport.execute("net_peerCount", vec![]).await } /// Whether the node is listening for network connections - pub fn is_listening(&self) -> CallFuture { - CallFuture::new(self.transport.execute("net_listening", vec![])) + pub async fn is_listening(&self) -> Result { + self.transport.execute("net_listening", vec![]).await } } diff --git a/src/api/parity.rs b/src/api/parity.rs index 4b7a778c..9338a48b 100644 --- a/src/api/parity.rs +++ b/src/api/parity.rs @@ -1,7 +1,8 @@ use crate::prelude::*; use crate::{ api::Namespace, - helpers::{self, CallFuture}, + error::Result, + helpers, types::{Bytes, CallRequest, ParityPendingTransactionFilter, Transaction}, Transport, }; @@ -27,19 +28,19 @@ impl Namespace for Parity { impl Parity { /// Sequentially call multiple contract methods in one request without changing the state of the blockchain. - pub fn call(&self, reqs: Vec) -> CallFuture, T::Out> { + pub async fn call(&self, reqs: Vec) -> Result> { let reqs = helpers::serialize(&reqs); - CallFuture::new(self.transport.execute("parity_call", vec![reqs])) + self.transport.execute("parity_call", vec![reqs]).await } /// Get pending transactions /// Blocked by https://github.com/openethereum/openethereum/issues/159 - pub fn pending_transactions( + pub async fn pending_transactions( &self, limit: Option, filter: Option, - ) -> CallFuture, T::Out> { + ) -> Result> { let limit = helpers::serialize(&limit); let filter = filter.as_ref().map(helpers::serialize); let params = match (limit, filter) { @@ -47,7 +48,7 @@ impl Parity { (l, None) => vec![l], }; - CallFuture::new(self.transport.execute("parity_pendingTransactions", params)) + self.transport.execute("parity_pendingTransactions", params).await } } diff --git a/src/api/parity_accounts.rs b/src/api/parity_accounts.rs index dc04556c..d885e0f3 100644 --- a/src/api/parity_accounts.rs +++ b/src/api/parity_accounts.rs @@ -1,6 +1,7 @@ use crate::{ api::Namespace, - helpers::{self, CallFuture}, + error::Result, + helpers, types::{Address, H256}, Transport, }; @@ -26,37 +27,43 @@ impl Namespace for ParityAccounts { impl ParityAccounts { /// Given an address of an account and its password deletes the account from the parity node - pub fn parity_kill_account(&self, address: &Address, pwd: &str) -> CallFuture { + pub async fn parity_kill_account(&self, address: &Address, pwd: &str) -> Result { let address = helpers::serialize(&address); let pwd = helpers::serialize(&pwd); - CallFuture::new(self.transport.execute("parity_killAccount", vec![address, pwd])) + self.transport.execute("parity_killAccount", vec![address, pwd]).await } /// Imports an account from a given seed/phrase /// Retunrs the address of the corresponding seed vinculated account - pub fn parity_new_account_from_phrase(&self, seed: &str, pwd: &str) -> CallFuture { + pub async fn parity_new_account_from_phrase(&self, seed: &str, pwd: &str) -> Result
{ let seed = helpers::serialize(&seed); let pwd = helpers::serialize(&pwd); - CallFuture::new(self.transport.execute("parity_newAccountFromPhrase", vec![seed, pwd])) + self.transport + .execute("parity_newAccountFromPhrase", vec![seed, pwd]) + .await } /// Imports an account from a given secret key. /// Returns the address of the corresponding Sk vinculated account. - pub fn new_account_from_secret(&self, secret: &H256, pwd: &str) -> CallFuture { + pub async fn new_account_from_secret(&self, secret: &H256, pwd: &str) -> Result
{ let secret = helpers::serialize(&secret); let pwd = helpers::serialize(&pwd); - CallFuture::new(self.transport.execute("parity_newAccountFromSecret", vec![secret, pwd])) + self.transport + .execute("parity_newAccountFromSecret", vec![secret, pwd]) + .await } /// Imports an account from a JSON encoded Wallet file. /// Returns the address of the corresponding wallet. - pub fn parity_new_account_from_wallet(&self, wallet: &str, pwd: &str) -> CallFuture { + pub async fn parity_new_account_from_wallet(&self, wallet: &str, pwd: &str) -> Result
{ let wallet = helpers::serialize(&wallet); let pwd = helpers::serialize(&pwd); - CallFuture::new(self.transport.execute("parity_newAccountFromWallet", vec![wallet, pwd])) + self.transport + .execute("parity_newAccountFromWallet", vec![wallet, pwd]) + .await } /// Removes the address of the Parity node addressbook. /// Returns true if the operation suceeded. - pub fn parity_remove_address(&self, address: &Address) -> CallFuture { + pub async fn parity_remove_address(&self, address: &Address) -> Result { let address = helpers::serialize(&address); - CallFuture::new(self.transport.execute("parity_removeAddress", vec![address])) + self.transport.execute("parity_removeAddress", vec![address]).await } } diff --git a/src/api/parity_set.rs b/src/api/parity_set.rs index 72540bd9..5d961831 100644 --- a/src/api/parity_set.rs +++ b/src/api/parity_set.rs @@ -1,7 +1,8 @@ use crate::prelude::*; use crate::{ api::Namespace, - helpers::{self, CallFuture}, + error::Result, + helpers, types::{Address, ParityPeerType, H256}, Transport, }; @@ -24,110 +25,118 @@ impl Namespace for ParitySet { impl ParitySet { /// Set Parity to accept non-reserved peers (default behavior) - pub fn accept_non_reserved_peers(&self) -> CallFuture { - CallFuture::new(self.transport().execute("parity_acceptNonReservedPeers", vec![])) + pub async fn accept_non_reserved_peers(&self) -> Result { + self.transport().execute("parity_acceptNonReservedPeers", vec![]).await } /// Add a reserved peer - pub fn add_reserved_peer(&self, enode: &str) -> CallFuture { + pub async fn add_reserved_peer(&self, enode: &str) -> Result { let enode = helpers::serialize(&enode); - CallFuture::new(self.transport().execute("parity_addReservedPeer", vec![enode])) + self.transport().execute("parity_addReservedPeer", vec![enode]).await } /// Set Parity to drop all non-reserved peers. To restore default behavior call parity_acceptNonReservedPeers - pub fn drop_non_reserved_peers(&self) -> CallFuture { - CallFuture::new(self.transport().execute("parity_dropNonReservedPeers", vec![])) + pub async fn drop_non_reserved_peers(&self) -> Result { + self.transport().execute("parity_dropNonReservedPeers", vec![]).await } /// Get list of connected/connecting peers. - pub fn parity_net_peers(&self) -> CallFuture { - CallFuture::new(self.transport.execute("parity_netPeers", vec![])) + pub async fn parity_net_peers(&self) -> Result { + self.transport.execute("parity_netPeers", vec![]).await } /// Attempts to upgrade Parity to the version specified in parity_upgradeReady - pub fn execute_upgrade(&self) -> CallFuture { - CallFuture::new(self.transport().execute("parity_executeUpgrade", vec![])) + pub async fn execute_upgrade(&self) -> Result { + self.transport().execute("parity_executeUpgrade", vec![]).await } /// Creates a hash of a file at a given URL - pub fn hash_content(&self, url: &str) -> CallFuture { + pub async fn hash_content(&self, url: &str) -> Result { let url = helpers::serialize(&url); - CallFuture::new(self.transport().execute("parity_hashContent", vec![url])) + self.transport().execute("parity_hashContent", vec![url]).await } /// Remove a reserved peer - pub fn remove_reserved_peer(&self, enode: &str) -> CallFuture { + pub async fn remove_reserved_peer(&self, enode: &str) -> Result { let enode = helpers::serialize(&enode); - CallFuture::new(self.transport().execute("parity_removeReservedPeer", vec![enode])) + self.transport().execute("parity_removeReservedPeer", vec![enode]).await } /// Changes author (coinbase) for mined blocks - pub fn set_author(&self, author: &Address) -> CallFuture { + pub async fn set_author(&self, author: &Address) -> Result { let address = helpers::serialize(&author); - CallFuture::new(self.transport().execute("parity_setAuthor", vec![address])) + self.transport().execute("parity_setAuthor", vec![address]).await } /// Sets the network spec file Parity is using - pub fn set_chain(&self, chain: &str) -> CallFuture { + pub async fn set_chain(&self, chain: &str) -> Result { let chain = helpers::serialize(&chain); - CallFuture::new(self.transport().execute("parity_setChain", vec![chain])) + self.transport().execute("parity_setChain", vec![chain]).await } /// Sets an authority account for signing consensus messages - pub fn set_engine_signer(&self, address: &Address, password: &str) -> CallFuture { + pub async fn set_engine_signer(&self, address: &Address, password: &str) -> Result { let address = helpers::serialize(&address); let password = helpers::serialize(&password); - CallFuture::new( - self.transport() - .execute("parity_setEngineSigner", vec![address, password]), - ) + + self.transport() + .execute("parity_setEngineSigner", vec![address, password]) + .await } /// Changes extra data for newly mined blocks - pub fn set_extra_data(&self, data: &H256) -> CallFuture { + pub async fn set_extra_data(&self, data: &H256) -> Result { let data = helpers::serialize(&data); - CallFuture::new(self.transport().execute("parity_setExtraData", vec![data])) + self.transport().execute("parity_setExtraData", vec![data]).await } /// Sets new gas ceiling target for mined blocks - pub fn set_gas_ceil_target(&self, quantity: &H256) -> CallFuture { + pub async fn set_gas_ceil_target(&self, quantity: &H256) -> Result { let quantity = helpers::serialize(&quantity); - CallFuture::new(self.transport().execute("parity_setGasCeilTarget", vec![quantity])) + self.transport() + .execute("parity_setGasCeilTarget", vec![quantity]) + .await } /// Sets a new gas floor target for mined blocks - pub fn set_gas_floor_target(&self, quantity: &H256) -> CallFuture { + pub async fn set_gas_floor_target(&self, quantity: &H256) -> Result { let quantity = helpers::serialize(&quantity); - CallFuture::new(self.transport().execute("parity_setGasFloorTarget", vec![quantity])) + self.transport() + .execute("parity_setGasFloorTarget", vec![quantity]) + .await } /// Sets the maximum amount of gas a single transaction may consume - pub fn set_max_transaction_gas(&self, quantity: &H256) -> CallFuture { + pub async fn set_max_transaction_gas(&self, quantity: &H256) -> Result { let quantity = helpers::serialize(&quantity); - CallFuture::new(self.transport().execute("parity_setMaxTransactionGas", vec![quantity])) + self.transport() + .execute("parity_setMaxTransactionGas", vec![quantity]) + .await } /// Changes minimal gas price for transaction to be accepted to the queue - pub fn set_min_gas_price(&self, quantity: &H256) -> CallFuture { + pub async fn set_min_gas_price(&self, quantity: &H256) -> Result { let quantity = helpers::serialize(&quantity); - CallFuture::new(self.transport().execute("parity_setMinGasPrice", vec![quantity])) + self.transport().execute("parity_setMinGasPrice", vec![quantity]).await } /// Changes the operating mode of Parity. - pub fn set_mode(&self, mode: &str) -> CallFuture { + pub async fn set_mode(&self, mode: &str) -> Result { let mode = helpers::serialize(&mode); - CallFuture::new(self.transport().execute("parity_setMode", vec![mode])) + self.transport().execute("parity_setMode", vec![mode]).await } /// Changes limit for transactions in queue. (NOT WORKING !) - pub fn set_transactions_limit(&self, limit: &H256) -> CallFuture { + pub async fn set_transactions_limit(&self, limit: &H256) -> Result { let limit = helpers::serialize(&limit); - CallFuture::new(self.transport().execute("parity_setTransactionsLimit", vec![limit])) + self.transport() + .execute("parity_setTransactionsLimit", vec![limit]) + .await } /// Returns a ReleaseInfo object describing the release which is available for upgrade or null if none is available. - pub fn upgrade_ready(&self) -> CallFuture, T::Out> { - CallFuture::new(self.transport().execute("parity_upgradeReady", vec![])) + pub async fn upgrade_ready(&self) -> Result> { + self.transport().execute("parity_upgradeReady", vec![]).await } } diff --git a/src/api/personal.rs b/src/api/personal.rs index 9e7e9918..2fd0ac8e 100644 --- a/src/api/personal.rs +++ b/src/api/personal.rs @@ -2,7 +2,8 @@ use crate::prelude::*; use crate::{ api::Namespace, - helpers::{self, CallFuture}, + error::Result, + helpers, types::{Address, Bytes, RawTransaction, TransactionRequest, H256, H520}, Transport, }; @@ -28,78 +29,75 @@ impl Namespace for Personal { impl Personal { /// Returns a list of available accounts. - pub fn list_accounts(&self) -> CallFuture, T::Out> { - CallFuture::new(self.transport.execute("personal_listAccounts", vec![])) + pub async fn list_accounts(&self) -> Result> { + self.transport.execute("personal_listAccounts", vec![]).await } /// Creates a new account and protects it with given password. /// Returns the address of created account. - pub fn new_account(&self, password: &str) -> CallFuture { + pub async fn new_account(&self, password: &str) -> Result
{ let password = helpers::serialize(&password); - CallFuture::new(self.transport.execute("personal_newAccount", vec![password])) + self.transport.execute("personal_newAccount", vec![password]).await } /// Unlocks the account with given password for some period of time (or single transaction). /// Returns `true` if the call was successful. - pub fn unlock_account(&self, address: Address, password: &str, duration: Option) -> CallFuture { + pub async fn unlock_account(&self, address: Address, password: &str, duration: Option) -> Result { 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]), - ) + + self.transport + .execute("personal_unlockAccount", vec![address, password, duration]) + .await } /// Sends a transaction from locked account. /// Returns transaction hash. - pub fn send_transaction(&self, transaction: TransactionRequest, password: &str) -> CallFuture { + pub async fn send_transaction(&self, transaction: TransactionRequest, password: &str) -> Result { let transaction = helpers::serialize(&transaction); let password = helpers::serialize(&password); - CallFuture::new( - self.transport - .execute("personal_sendTransaction", vec![transaction, password]), - ) + + self.transport + .execute("personal_sendTransaction", vec![transaction, password]) + .await } /// Signs an Ethereum specific message with `sign(keccak256("\x19Ethereum Signed Message: " + len(data) + data)))` /// /// The account does not need to be unlocked to make this call, and will not be left unlocked after. /// Returns encoded signature. - pub fn sign(&self, data: Bytes, account: Address, password: &str) -> CallFuture { + pub async fn sign(&self, data: Bytes, account: Address, password: &str) -> Result { let data = helpers::serialize(&data); let address = helpers::serialize(&account); let password = helpers::serialize(&password); - CallFuture::new(self.transport.execute("personal_sign", vec![data, address, password])) + self.transport + .execute("personal_sign", vec![data, address, password]) + .await } /// 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 async fn sign_transaction(&self, transaction: TransactionRequest, password: &str) -> Result { let transaction = helpers::serialize(&transaction); let password = helpers::serialize(&password); - CallFuture::new( - self.transport - .execute("personal_signTransaction", vec![transaction, password]), - ) + + self.transport + .execute("personal_signTransaction", vec![transaction, password]) + .await } /// Imports a raw key and protects it with the given password. /// Returns the address of created account. - pub fn import_raw_key(&self, private_key: &[u8; 32], password: &str) -> CallFuture { + pub async fn import_raw_key(&self, private_key: &[u8; 32], password: &str) -> Result
{ let private_key = hex::encode(private_key); let private_key = helpers::serialize(&private_key); let password = helpers::serialize(&password); - CallFuture::new( - self.transport - .execute("personal_importRawKey", vec![private_key, password]), - ) + self.transport + .execute("personal_importRawKey", vec![private_key, password]) + .await } } diff --git a/src/api/traces.rs b/src/api/traces.rs index 7e5110a6..8a3e1d53 100644 --- a/src/api/traces.rs +++ b/src/api/traces.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::{ api::Namespace, - helpers::{self, CallFuture}, + helpers, types::{BlockId, BlockNumber, BlockTrace, Bytes, CallRequest, Index, Trace, TraceFilter, TraceType, H256}, Transport, }; @@ -27,90 +27,77 @@ 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 async fn call( &self, req: CallRequest, trace_type: Vec, block: Option) -> Result { let req = helpers::serialize(&req); let block = block.unwrap_or(BlockNumber::Latest); let block = helpers::serialize(&block); let trace_type = helpers::serialize(&trace_type); - CallFuture::new(self.transport.execute("trace_call", vec![req, trace_type, block])) + self.transport.execute("trace_call", vec![req, trace_type, block]).await } /// Performs multiple call traces on top of the same block. Allows to trace dependent transactions. - pub fn call_many( - &self, - reqs_with_trace_types: Vec<(CallRequest, Vec)>, - block: Option, - ) -> CallFuture, T::Out> { + pub async fn call_many( &self, reqs_with_trace_types: Vec<(CallRequest, Vec)>, block: Option) -> Result> { let reqs_with_trace_types = helpers::serialize(&reqs_with_trace_types); let block = block.unwrap_or_else(|| BlockNumber::Latest.into()); let block = helpers::serialize(&block); - CallFuture::new( + self.transport - .execute("trace_callMany", vec![reqs_with_trace_types, block]), - ) + .execute("trace_callMany", vec![reqs_with_trace_types, block]) + .await } /// Traces a call to `eth_sendRawTransaction` without making the call, returning the traces - pub fn raw_transaction(&self, data: Bytes, trace_type: Vec) -> CallFuture { + pub async fn raw_transaction(&self, data: Bytes, trace_type: Vec) -> Result { let data = helpers::serialize(&data); let trace_type = helpers::serialize(&trace_type); - CallFuture::new(self.transport.execute("trace_rawTransaction", vec![data, trace_type])) + self.transport.execute("trace_rawTransaction", vec![data, trace_type]).await } /// Replays a transaction, returning the traces - pub fn replay_transaction(&self, hash: H256, trace_type: Vec) -> CallFuture { + pub async fn replay_transaction(&self, hash: H256, trace_type: Vec) -> Result { let hash = helpers::serialize(&hash); let trace_type = helpers::serialize(&trace_type); - CallFuture::new( + self.transport - .execute("trace_replayTransaction", vec![hash, trace_type]), - ) + .execute("trace_replayTransaction", vec![hash, trace_type]) + .await } /// 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, T::Out> { + pub async fn replay_block_transactions( &self, block: BlockNumber, trace_type: Vec,) -> Result> { let block = helpers::serialize(&block); let trace_type = helpers::serialize(&trace_type); - CallFuture::new( + self.transport - .execute("trace_replayBlockTransactions", vec![block, trace_type]), - ) + .execute("trace_replayBlockTransactions", vec![block, trace_type]) + .await } /// Returns traces created at given block - pub fn block(&self, block: BlockNumber) -> CallFuture, T::Out> { + pub async fn block(&self, block: BlockNumber) -> Result> { let block = helpers::serialize(&block); - CallFuture::new(self.transport.execute("trace_block", vec![block])) + self.transport.execute("trace_block", vec![block]).await } /// Return traces matching the given filter /// /// See [TraceFilterBuilder](../types/struct.TraceFilterBuilder.html) - pub fn filter(&self, filter: TraceFilter) -> CallFuture, T::Out> { + pub async fn filter(&self, filter: TraceFilter) -> Result> { let filter = helpers::serialize(&filter); - CallFuture::new(self.transport.execute("trace_filter", vec![filter])) + self.transport.execute("trace_filter", vec![filter]).await } /// Returns trace at the given position - pub fn get(&self, hash: H256, index: Vec) -> CallFuture { + pub async fn get(&self, hash: H256, index: Vec) -> Result { let hash = helpers::serialize(&hash); let index = helpers::serialize(&index); - CallFuture::new(self.transport.execute("trace_get", vec![hash, index])) + self.transport.execute("trace_get", vec![hash, index]).await } /// Returns all traces of a given transaction - pub fn transaction(&self, hash: H256) -> CallFuture, T::Out> { + pub async fn transaction(&self, hash: H256) -> Result> { let hash = helpers::serialize(&hash); - CallFuture::new(self.transport.execute("trace_transaction", vec![hash])) + self.transport.execute("trace_transaction", vec![hash]).await } } diff --git a/src/api/txpool.rs b/src/api/txpool.rs index 87882a1f..eaa59de9 100644 --- a/src/api/txpool.rs +++ b/src/api/txpool.rs @@ -2,7 +2,7 @@ use crate::{ api::Namespace, - helpers::CallFuture, + error::Result, types::{TxpoolContentInfo, TxpoolInspectInfo, TxpoolStatus}, Transport, }; @@ -28,18 +28,18 @@ impl Namespace for Txpool { impl Txpool { /// returns txpool content info - pub fn content(&self) -> CallFuture { - CallFuture::new(self.transport.execute("txpool_content", vec![])) + pub async fn content(&self) -> Result { + self.transport.execute("txpool_content", vec![]).await } /// returns txpool inspect info - pub fn inspect(&self) -> CallFuture { - CallFuture::new(self.transport.execute("txpool_inspect", vec![])) + pub async fn inspect(&self) -> Result { + self.transport.execute("txpool_inspect", vec![]).await } /// returns txpool status - pub fn status(&self) -> CallFuture { - CallFuture::new(self.transport.execute("txpool_status", vec![])) + pub async fn status(&self) -> Result { + self.transport.execute("txpool_status", vec![]).await } } diff --git a/src/api/web3.rs b/src/api/web3.rs index 200fcde9..22509634 100644 --- a/src/api/web3.rs +++ b/src/api/web3.rs @@ -3,7 +3,8 @@ use crate::prelude::*; use crate::{ api::Namespace, - helpers::{self, CallFuture}, + error::Result, + helpers, types::{Bytes, H256}, Transport, }; @@ -29,14 +30,14 @@ impl Namespace for Web3 { impl Web3 { /// Returns client version - pub fn client_version(&self) -> CallFuture { - CallFuture::new(self.transport.execute("web3_clientVersion", vec![])) + pub async fn client_version(&self) -> Result { + self.transport.execute("web3_clientVersion", vec![]).await } /// Returns sha3 of the given data - pub fn sha3(&self, bytes: Bytes) -> CallFuture { + pub async fn sha3(&self, bytes: Bytes) -> Result { let bytes = helpers::serialize(&bytes); - CallFuture::new(self.transport.execute("web3_sha3", vec![bytes])) + self.transport.execute("web3_sha3", vec![bytes]).await } } diff --git a/src/confirm.rs b/src/confirm.rs index b0fb189a..4677242a 100644 --- a/src/confirm.rs +++ b/src/confirm.rs @@ -6,8 +6,8 @@ use crate::{ types::{Bytes, TransactionReceipt, TransactionRequest, H256, U64}, Transport, }; -use futures::{Future, StreamExt}; use core::time::Duration; +use futures::{Future, StreamExt}; /// Checks whether an event has been confirmed. pub trait ConfirmationCheck { diff --git a/src/contract/deploy.rs b/src/contract/deploy.rs index a0eab97b..6f40a0ff 100644 --- a/src/contract/deploy.rs +++ b/src/contract/deploy.rs @@ -12,7 +12,7 @@ use crate::{ use crate::{signing::Key, types::TransactionParameters}; use alloc::collections::BTreeMap; use core::time; -use futures::{Future, TryFutureExt}; +use futures::Future; pub use crate::contract::error::deploy::Error; @@ -82,17 +82,12 @@ impl Builder { let poll_interval = self.poll_interval; let confirmations = self.confirmations; - self.do_execute(code, params, from, move |tx| { - crate::api::Personal::new(transport.clone()) + self.do_execute(code, params, from, move |tx| async move { + let signed_tx = crate::api::Personal::new(transport.clone()) .sign_transaction(tx, password) - .and_then(move |signed_tx| { - confirm::send_raw_transaction_with_confirmation( - transport, - signed_tx.raw, - poll_interval, - confirmations, - ) - }) + .await?; + confirm::send_raw_transaction_with_confirmation(transport, signed_tx.raw, poll_interval, confirmations) + .await }) .await } diff --git a/src/helpers.rs b/src/helpers.rs index 64553b5a..86acc8ab 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -2,12 +2,6 @@ use crate::error; use crate::prelude::*; -use core::{marker::PhantomData, pin::Pin}; -use futures::{ - task::{Context, Poll}, - Future, -}; -use pin_project::pin_project; /// Takes any type which is deserializable from rpc::Value and such a value and /// yields the deserialized value @@ -20,39 +14,6 @@ pub fn serialize(t: &T) -> &dyn erased_serde::Serial t as _ } -/// Calls decode on the result of the wrapped future. -#[pin_project] -#[derive(Debug)] -pub struct CallFuture { - #[pin] - inner: F, - _marker: PhantomData, -} - -impl CallFuture { - /// Create a new CallFuture wrapping the inner future. - pub fn new(inner: F) -> Self { - CallFuture { - inner, - _marker: PhantomData, - } - } -} - -impl Future for CallFuture -where - T: serde::de::DeserializeOwned, - F: Future>>, -{ - type Output = error::Result; - - fn poll(self: Pin<&mut Self>, ctx: &mut Context) -> Poll { - let this = self.project(); - let x = ready!(this.inner.poll(ctx)); - Poll::Ready(x.and_then(|data| json_rpc::decode_response(&data))) - } -} - pub(crate) mod json_rpc { use crate::prelude::*; use crate::Error; @@ -85,8 +46,8 @@ pub(crate) mod json_rpc { } pub fn decode_response<'de, T: Deserialize<'de>>(response: &'de [u8]) -> Result { - let response: Response = json::from_slice(response) - .or(Err(Error::Decoder("Failed to decode the rpc response".into())))?; + let response: Response = + json::from_slice(response).or(Err(Error::Decoder("Failed to decode the rpc response".into())))?; if let Some(result) = response.result { return Ok(result); } @@ -114,17 +75,11 @@ pub mod tests { // given let mut transport = $crate::transports::test::TestTransport::default(); transport.set_response($returned); - let result = { - let eth = $namespace::new(&transport); - - // when - eth.$name($($param.into(), )+) - }; - + let eth = $namespace::new(&transport); + let result = futures::executor::block_on(eth.$name($($param.into(), )+)); // then transport.assert_request($method, &$results.into_iter().map(Into::into).collect::>()); transport.assert_no_more_requests(); - let result = futures::executor::block_on(result); assert_eq!(result, Ok($expected.into())); } }; @@ -149,17 +104,11 @@ pub mod tests { // given let mut transport = $crate::transports::test::TestTransport::default(); transport.set_response($returned); - let result = { - let eth = $namespace::new(&transport); - - // when - eth.$name() - }; - + let eth = $namespace::new(&transport); + let result = futures::executor::block_on(eth.$name()); // then transport.assert_request($method, &[]); transport.assert_no_more_requests(); - let result = futures::executor::block_on(result); assert_eq!(result, Ok($expected.into())); } }; diff --git a/src/lib.rs b/src/lib.rs index dc938eda..7d2d5f56 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ #![recursion_limit = "256"] #![cfg_attr(not(any(feature = "std", feature = "test", test)), no_std)] +use futures::Future; #[cfg(test)] use jsonrpc_core as rpc; @@ -35,6 +36,7 @@ mod prelude { } use prelude::*; +use serde::de::DeserializeOwned; /// Re-export of the `futures` crate. #[macro_use] @@ -64,16 +66,43 @@ type Value<'a> = &'a dyn erased_serde::Serialize; /// Transport implementation pub trait Transport: Clone { /// The type of future this transport returns when a call is made. - type Out: core::future::Future>>; + type Out: core::future::Future>; /// Execute remote method with given parameters. - fn execute(&self, method: &'static str, params: Vec) -> Self::Out; + fn execute(&self, method: &'static str, params: Vec) -> Self::Out; } impl Transport for &T { - type Out = T::Out; + type Out = T::Out; - fn execute(&self, method: &'static str, params: Vec) -> Self::Out { + fn execute(&self, method: &'static str, params: Vec) -> Self::Out { (*self).execute(method, params) } } + +/// A future extension to resolve the immediately ready futures +pub trait ExpectReady: Future { + /// Assume the future is ready and return the Output. + fn expect_ready(self) -> Self::Output; +} + +impl ExpectReady for F { + fn expect_ready(self) -> Self::Output { + expect_ready(self) + } +} + +/// Retreive the output of a Future driven by PinkHttp +/// +/// When using PinkHttp as the transport, the Futures returned by any API should be always +/// ready immediate because of pink's blocking HTTP api. +pub fn expect_ready(fut: F) -> ::Output { + let waker = futures::task::noop_waker_ref(); + let mut cx = core::task::Context::from_waker(waker); + use core::task::Poll::*; + pin_mut!(fut); + match fut.poll(&mut cx) { + Ready(v) => v, + Pending => panic!("Failed to resolve a ready future"), + } +} diff --git a/src/transports/mod.rs b/src/transports/mod.rs index 9ff7a798..7a778ef8 100644 --- a/src/transports/mod.rs +++ b/src/transports/mod.rs @@ -50,4 +50,4 @@ pub mod eip_1193; #[cfg(feature = "pink")] pub mod pink_http; #[cfg(feature = "pink")] -pub use pink_http::{resolve_ready, PinkHttp}; +pub use pink_http::PinkHttp; diff --git a/src/transports/pink_http.rs b/src/transports/pink_http.rs index e33ff3cb..af5e36c3 100644 --- a/src/transports/pink_http.rs +++ b/src/transports/pink_http.rs @@ -9,11 +9,13 @@ use core::{ }; use serde::de::DeserializeOwned; -use crate::helpers::CallFuture; use crate::prelude::*; use crate::{error::TransportError, helpers::json_rpc}; use crate::{Error, Transport}; +// Deprecated +pub use crate::expect_ready as resolve_ready; + /// A Transport using pink http API /// /// # Example @@ -21,9 +23,10 @@ use crate::{Error, Transport}; /// fn get_web3_sha3() { /// use pink_web3::api::{Web3, Namespace}; /// use pink_web3::transports::pink_http::PinkHttp; +/// use pink_web3::ExpectReady; /// let phttp = PinkHttp::new("http://localhost:3333"); /// let web3 = Web3::new(phttp); -/// let result = web3.web3().sha3(b"123".to_vec().into()).resolve(); +/// let result = web3.web3().sha3(b"123".to_vec().into()).expect_ready(); /// assert!(result.is_ok()); /// } /// ``` @@ -49,12 +52,10 @@ impl Future for Response { } } -type RpcResult = Result, Error>; - impl Transport for PinkHttp { - type Out = Ready; + type Out = Ready>; - fn execute(&self, method: &'static str, params: Vec) -> Self::Out { + fn execute(&self, method: &'static str, params: Vec) -> Self::Out { let request = json_rpc::encode_request(method, params); let body = request.as_bytes(); let headers: Vec<(String, String)> = vec![("Content-Type".into(), "application/json".into())]; @@ -62,28 +63,6 @@ impl Transport for PinkHttp { if response.status_code / 100 != 2 { return ready(Err(Error::Transport(TransportError::Code(response.status_code)))); } - ready(Ok(response.body)) - } -} - -impl CallFuture> { - /// Blocking resolves the output - pub fn resolve(self) -> ::Output { - resolve_ready(self) - } -} - -/// Retreive the output of a Future driven by PinkHttp -/// -/// When using PinkHttp as the transport, the Futures returned by any API should be always -/// ready immediate because of pink's blocking HTTP api. -pub fn resolve_ready(fut: F) -> ::Output { - let waker = futures::task::noop_waker_ref(); - let mut cx = task::Context::from_waker(waker); - use task::Poll::*; - pin_mut!(fut); - match fut.poll(&mut cx) { - Ready(v) => v, - Pending => panic!("Failed to resolve a ready future"), + ready(json_rpc::decode_response(&response.body)) } } diff --git a/src/transports/test.rs b/src/transports/test.rs index 3a621f40..70a37b18 100644 --- a/src/transports/test.rs +++ b/src/transports/test.rs @@ -1,5 +1,7 @@ //! Test Transport -use crate::{error, helpers::json_rpc, rpc, Transport}; +use serde::de::DeserializeOwned; + +use crate::{error, helpers::json_rpc, rpc, Error, Transport}; use core::future::Ready; use std::{cell::RefCell, collections::VecDeque, rc::Rc}; @@ -12,14 +14,13 @@ pub struct TestTransport { } impl Transport for TestTransport { - type Out = Ready>>; + type Out = Ready>; - fn execute(&self, method: &'static str, params: Vec) -> Self::Out { + fn execute(&self, method: &'static str, params: Vec) -> Self::Out { let request = json_rpc::encode_request(method, params); self.requests.borrow_mut().push((method.into(), request)); let response = self.responses.borrow_mut().pop_front().unwrap(); - let returning = format!(r#"{{ "id": 0, "jsonrpc": "2.0", "result": {} }}"#, serde_json::to_string(&response).unwrap()); - core::future::ready(Ok(returning.as_bytes().to_vec())) + core::future::ready(serde_json::from_value(response).or(Err(Error::InvalidResponse("Invalid response".into())))) } } diff --git a/src/types/traces.rs b/src/types/traces.rs index f8e18e82..af0e925c 100644 --- a/src/types/traces.rs +++ b/src/types/traces.rs @@ -1,8 +1,8 @@ //! Types for the Parity Ad-Hoc Trace API use crate::prelude::*; use crate::types::{Action, ActionType, Bytes, Res, H160, H256, U256}; -use serde::{Deserialize, Serialize}; use alloc::collections::BTreeMap; +use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize)] /// Description of the type of trace to make diff --git a/src/types/txpool.rs b/src/types/txpool.rs index d812b909..b8b7912d 100644 --- a/src/types/txpool.rs +++ b/src/types/txpool.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use crate::types::{Address, Transaction, U64}; -use serde::{Deserialize, Serialize}; use alloc::collections::BTreeMap; +use serde::{Deserialize, Serialize}; /// Transaction Pool Content Info ///