remove provider/signers trait bound

This commit is contained in:
Georgios Konstantopoulos 2020-06-02 02:00:58 +03:00
parent 27ca5dd55a
commit b5a1b27e3a
No known key found for this signature in database
GPG Key ID: FA607837CD26EDBC
6 changed files with 68 additions and 29 deletions

View File

@ -19,7 +19,7 @@ pub type HttpProvider = Provider<Http>;
/// JSON-RPC provider. /// JSON-RPC provider.
pub trait JsonRpcClient: Debug { pub trait JsonRpcClient: Debug {
/// A JSON-RPC Error /// A JSON-RPC Error
type Error: Error; type Error: Error + Into<ProviderError>;
/// Sends a request with the provided JSON-RPC and parameters serialized as JSON /// Sends a request with the provided JSON-RPC and parameters serialized as JSON
async fn request<T: Serialize + Send + Sync, R: for<'a> Deserialize<'a>>( async fn request<T: Serialize + Send + Sync, R: for<'a> Deserialize<'a>>(

View File

@ -33,18 +33,18 @@ pub enum ProviderError {
} }
// JSON RPC bindings // JSON RPC bindings
impl<P> Provider<P> impl<P: JsonRpcClient> Provider<P> {
where
P: JsonRpcClient,
ProviderError: From<<P as JsonRpcClient>::Error>,
{
////// Blockchain Status ////// Blockchain Status
// //
// Functions for querying the state of the blockchain // Functions for querying the state of the blockchain
/// Gets the latest block number via the `eth_BlockNumber` API /// Gets the latest block number via the `eth_BlockNumber` API
pub async fn get_block_number(&self) -> Result<U256, ProviderError> { pub async fn get_block_number(&self) -> Result<U256, ProviderError> {
Ok(self.0.request("eth_blockNumber", None::<()>).await?) Ok(self
.0
.request("eth_blockNumber", None::<()>)
.await
.map_err(Into::into)?)
} }
/// Gets the block at `block_hash_or_number` (transaction hashes only) /// Gets the block at `block_hash_or_number` (transaction hashes only)
@ -78,12 +78,18 @@ where
BlockId::Hash(hash) => { BlockId::Hash(hash) => {
let hash = utils::serialize(&hash); let hash = utils::serialize(&hash);
let args = vec![hash, include_txs]; let args = vec![hash, include_txs];
self.0.request("eth_getBlockByHash", Some(args)).await? self.0
.request("eth_getBlockByHash", Some(args))
.await
.map_err(Into::into)?
} }
BlockId::Number(num) => { BlockId::Number(num) => {
let num = utils::serialize(&num); let num = utils::serialize(&num);
let args = vec![num, include_txs]; let args = vec![num, include_txs];
self.0.request("eth_getBlockByNumber", Some(args)).await? self.0
.request("eth_getBlockByNumber", Some(args))
.await
.map_err(Into::into)?
} }
}) })
} }
@ -97,7 +103,8 @@ where
Ok(self Ok(self
.0 .0
.request("eth_getTransactionByHash", Some(hash)) .request("eth_getTransactionByHash", Some(hash))
.await?) .await
.map_err(Into::into)?)
} }
/// Gets the transaction receipt with `transaction_hash` /// Gets the transaction receipt with `transaction_hash`
@ -109,17 +116,26 @@ where
Ok(self Ok(self
.0 .0
.request("eth_getTransactionReceipt", Some(hash)) .request("eth_getTransactionReceipt", Some(hash))
.await?) .await
.map_err(Into::into)?)
} }
/// Gets the current gas price as estimated by the node /// Gets the current gas price as estimated by the node
pub async fn get_gas_price(&self) -> Result<U256, ProviderError> { pub async fn get_gas_price(&self) -> Result<U256, ProviderError> {
Ok(self.0.request("eth_gasPrice", None::<()>).await?) Ok(self
.0
.request("eth_gasPrice", None::<()>)
.await
.map_err(Into::into)?)
} }
/// Gets the accounts on the node /// Gets the accounts on the node
pub async fn get_accounts(&self) -> Result<Vec<Address>, ProviderError> { pub async fn get_accounts(&self) -> Result<Vec<Address>, ProviderError> {
Ok(self.0.request("eth_accounts", None::<()>).await?) Ok(self
.0
.request("eth_accounts", None::<()>)
.await
.map_err(Into::into)?)
} }
/// Returns the nonce of the address /// Returns the nonce of the address
@ -133,7 +149,8 @@ where
Ok(self Ok(self
.0 .0
.request("eth_getTransactionCount", Some(&[from, block])) .request("eth_getTransactionCount", Some(&[from, block]))
.await?) .await
.map_err(Into::into)?)
} }
/// Returns the account's balance /// Returns the account's balance
@ -147,13 +164,18 @@ where
Ok(self Ok(self
.0 .0
.request("eth_getBalance", Some(&[from, block])) .request("eth_getBalance", Some(&[from, block]))
.await?) .await
.map_err(Into::into)?)
} }
/// Returns the currently configured chain id, a value used in replay-protected /// Returns the currently configured chain id, a value used in replay-protected
/// transaction signing as introduced by EIP-155. /// transaction signing as introduced by EIP-155.
pub async fn get_chainid(&self) -> Result<U256, ProviderError> { pub async fn get_chainid(&self) -> Result<U256, ProviderError> {
Ok(self.0.request("eth_chainId", None::<()>).await?) Ok(self
.0
.request("eth_chainId", None::<()>)
.await
.map_err(Into::into)?)
} }
////// Contract Execution ////// Contract Execution
@ -169,7 +191,11 @@ where
) -> Result<Bytes, ProviderError> { ) -> Result<Bytes, ProviderError> {
let tx = utils::serialize(&tx); let tx = utils::serialize(&tx);
let block = utils::serialize(&block.unwrap_or(BlockNumber::Latest)); let block = utils::serialize(&block.unwrap_or(BlockNumber::Latest));
Ok(self.0.request("eth_call", Some(vec![tx, block])).await?) Ok(self
.0
.request("eth_call", Some(vec![tx, block]))
.await
.map_err(Into::into)?)
} }
/// Send a transaction to a single Ethereum node and return the estimated amount of gas required (as a U256) to send it /// Send a transaction to a single Ethereum node and return the estimated amount of gas required (as a U256) to send it
@ -187,7 +213,11 @@ where
None => vec![tx], None => vec![tx],
}; };
Ok(self.0.request("eth_estimateGas", Some(args)).await?) Ok(self
.0
.request("eth_estimateGas", Some(args))
.await
.map_err(Into::into)?)
} }
/// Send the transaction to the entire Ethereum network and returns the transaction's hash /// Send the transaction to the entire Ethereum network and returns the transaction's hash
@ -209,21 +239,33 @@ where
} }
} }
Ok(self.0.request("eth_sendTransaction", Some(tx)).await?) Ok(self
.0
.request("eth_sendTransaction", Some(tx))
.await
.map_err(Into::into)?)
} }
/// Send the raw RLP encoded transaction to the entire Ethereum network and returns the transaction's hash /// Send the raw RLP encoded transaction to the entire Ethereum network and returns the transaction's hash
/// This will consume gas from the account that signed the transaction. /// This will consume gas from the account that signed the transaction.
pub async fn send_raw_transaction(&self, tx: &Transaction) -> Result<TxHash, ProviderError> { pub async fn send_raw_transaction(&self, tx: &Transaction) -> Result<TxHash, ProviderError> {
let rlp = utils::serialize(&tx.rlp()); let rlp = utils::serialize(&tx.rlp());
Ok(self.0.request("eth_sendRawTransaction", Some(rlp)).await?) Ok(self
.0
.request("eth_sendRawTransaction", Some(rlp))
.await
.map_err(Into::into)?)
} }
////// Contract state ////// Contract state
/// Returns an array (possibly empty) of logs that match the filter /// Returns an array (possibly empty) of logs that match the filter
pub async fn get_logs(&self, filter: &Filter) -> Result<Vec<Log>, ProviderError> { pub async fn get_logs(&self, filter: &Filter) -> Result<Vec<Log>, ProviderError> {
Ok(self.0.request("eth_getLogs", Some(filter)).await?) Ok(self
.0
.request("eth_getLogs", Some(filter))
.await
.map_err(Into::into)?)
} }
// TODO: get_code, get_storage_at // TODO: get_code, get_storage_at

View File

@ -40,8 +40,6 @@ impl<P, S> Client<P, S>
where where
S: Signer, S: Signer,
P: JsonRpcClient, P: JsonRpcClient,
ProviderError: From<<P as JsonRpcClient>::Error>,
ClientError: From<<S as Signer>::Error>,
{ {
/// Signs and broadcasts the transaction /// Signs and broadcasts the transaction
pub async fn send_transaction( pub async fn send_transaction(
@ -71,7 +69,7 @@ where
self.fill_transaction(&mut tx, block).await?; self.fill_transaction(&mut tx, block).await?;
// sign the transaction with the network // sign the transaction with the network
let signed_tx = signer.sign_transaction(tx)?; let signed_tx = signer.sign_transaction(tx).map_err(Into::into)?;
// broadcast it // broadcast it
self.provider.send_raw_transaction(&signed_tx).await?; self.provider.send_raw_transaction(&signed_tx).await?;

View File

@ -13,7 +13,7 @@ use std::error::Error;
/// Implement this trait to support different signing modes, e.g. Ledger, hosted etc. /// Implement this trait to support different signing modes, e.g. Ledger, hosted etc.
// TODO: We might need a `SignerAsync` trait for HSM use cases? // TODO: We might need a `SignerAsync` trait for HSM use cases?
pub trait Signer { pub trait Signer {
type Error: Error; type Error: Error + Into<ClientError>;
/// Signs the hash of the provided message after prefixing it /// Signs the hash of the provided message after prefixing it
fn sign_message<S: AsRef<[u8]>>(&self, message: S) -> Signature; fn sign_message<S: AsRef<[u8]>>(&self, message: S) -> Signature;

View File

@ -5,9 +5,7 @@ use ethers_providers::{JsonRpcClient, Provider};
use ethers_core::{ use ethers_core::{
rand::Rng, rand::Rng,
secp256k1, secp256k1,
types::{ types::{Address, PrivateKey, PublicKey, Signature, Transaction, TransactionRequest, TxError},
Address, PrivateKey, PublicKey, Signature, Transaction, TransactionRequest, TxError,
},
}; };
use std::str::FromStr; use std::str::FromStr;

View File

@ -14,7 +14,8 @@ async fn send_eth() {
// this private key belongs to the above mnemonic // this private key belongs to the above mnemonic
let wallet: Wallet = "380eb0f3d505f087e438eca80bc4df9a7faa24f868e69fc0440261a0fc0567dc" let wallet: Wallet = "380eb0f3d505f087e438eca80bc4df9a7faa24f868e69fc0440261a0fc0567dc"
.parse().unwrap(); .parse()
.unwrap();
// connect to the network // connect to the network
let provider = Provider::<Http>::try_from(url.as_str()).unwrap(); let provider = Provider::<Http>::try_from(url.as_str()).unwrap();