abuse Deref for using provider methods in the Client
This commit is contained in:
parent
8a8e33c9c8
commit
0f12894765
|
@ -13,10 +13,8 @@ async fn main() -> Result<(), failure::Error> {
|
|||
)?
|
||||
.connect(&provider);
|
||||
|
||||
// get the account's nonce
|
||||
let nonce = provider
|
||||
.get_transaction_count(client.signer.address, None)
|
||||
.await?;
|
||||
// get the account's nonce (we abuse the Deref to access the provider's functions)
|
||||
let nonce = client.get_transaction_count(client.address(), None).await?;
|
||||
|
||||
// craft the transaction
|
||||
let tx = UnsignedTransaction {
|
||||
|
@ -29,7 +27,7 @@ async fn main() -> Result<(), failure::Error> {
|
|||
};
|
||||
|
||||
// send it!
|
||||
let tx = client.send_transaction(tx).await?;
|
||||
let tx = client.sign_and_send_transaction(tx).await?;
|
||||
|
||||
// get the mined tx
|
||||
let tx = client.get_transaction(tx.hash).await?;
|
||||
|
|
|
@ -7,7 +7,7 @@ mod http;
|
|||
|
||||
use crate::{
|
||||
signers::{Client, Signer},
|
||||
types::{Address, BlockNumber, Bytes, Transaction, TransactionRequest, TxHash, U256},
|
||||
types::{Address, BlockNumber, Transaction, TransactionRequest, TxHash, U256},
|
||||
utils,
|
||||
};
|
||||
|
||||
|
@ -46,10 +46,12 @@ impl<P: JsonRpcClient> Provider<P> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Gets the latest block number via the `eth_BlockNumber` API
|
||||
pub async fn get_block_number(&self) -> Result<U256, P::Error> {
|
||||
self.0.request("eth_blockNumber", None::<()>).await
|
||||
}
|
||||
|
||||
/// Gets the transaction which matches the provided hash via the `eth_getTransactionByHash` API
|
||||
pub async fn get_transaction<T: Send + Sync + Into<TxHash>>(
|
||||
&self,
|
||||
hash: T,
|
||||
|
@ -58,12 +60,14 @@ impl<P: JsonRpcClient> Provider<P> {
|
|||
self.0.request("eth_getTransactionByHash", Some(hash)).await
|
||||
}
|
||||
|
||||
/// Broadcasts the transaction request via the `eth_sendTransaction` API
|
||||
pub async fn send_transaction(&self, tx: TransactionRequest) -> Result<TxHash, P::Error> {
|
||||
self.0.request("eth_sendTransaction", Some(tx)).await
|
||||
}
|
||||
|
||||
pub async fn send_raw_transaction(&self, rlp: &Bytes) -> Result<TxHash, P::Error> {
|
||||
let rlp = utils::serialize(&rlp);
|
||||
/// Broadcasts a raw RLP encoded transaction via the `eth_sendRawTransaction` API
|
||||
pub async fn send_raw_transaction(&self, tx: &Transaction) -> Result<TxHash, P::Error> {
|
||||
let rlp = utils::serialize(&tx.rlp());
|
||||
self.0.request("eth_sendRawTransaction", Some(rlp)).await
|
||||
}
|
||||
|
||||
|
|
|
@ -1,31 +1,45 @@
|
|||
use crate::{
|
||||
providers::{JsonRpcClient, Provider},
|
||||
signers::Signer,
|
||||
types::{Transaction, TxHash, UnsignedTransaction},
|
||||
types::{Address, Transaction, UnsignedTransaction},
|
||||
};
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Client<'a, S, P> {
|
||||
pub provider: &'a Provider<P>,
|
||||
pub signer: S,
|
||||
pub(crate) provider: &'a Provider<P>,
|
||||
pub(crate) signer: S,
|
||||
}
|
||||
|
||||
impl<'a, S: Signer, P: JsonRpcClient> Client<'a, S, P> {
|
||||
pub async fn send_transaction(&self, tx: UnsignedTransaction) -> Result<Transaction, P::Error> {
|
||||
/// Signs the transaction and then broadcasts its RLP encoding via the `eth_sendRawTransaction`
|
||||
/// API
|
||||
pub async fn sign_and_send_transaction(
|
||||
&self,
|
||||
tx: UnsignedTransaction,
|
||||
) -> Result<Transaction, P::Error> {
|
||||
// sign the transaction
|
||||
let signed_tx = self.signer.sign_transaction(tx.clone());
|
||||
|
||||
// broadcast it
|
||||
self.provider.send_raw_transaction(&signed_tx.rlp()).await?;
|
||||
self.provider.send_raw_transaction(&signed_tx).await?;
|
||||
|
||||
Ok(signed_tx)
|
||||
}
|
||||
|
||||
// TODO: Forward all other calls to the provider
|
||||
pub async fn get_transaction<T: Send + Sync + Into<TxHash>>(
|
||||
&self,
|
||||
hash: T,
|
||||
) -> Result<Transaction, P::Error> {
|
||||
self.provider.get_transaction(hash).await
|
||||
pub fn address(&self) -> Address {
|
||||
self.signer.address()
|
||||
}
|
||||
}
|
||||
|
||||
// Abuse Deref to use the Provider's methods without re-writing everything.
|
||||
// This is an anti-pattern and should not be encouraged, but this improves the UX while
|
||||
// keeping the LoC low
|
||||
impl<'a, S, P> Deref for Client<'a, S, P> {
|
||||
type Target = &'a Provider<P>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.provider
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ pub use wallet::Wallet;
|
|||
mod client;
|
||||
pub(crate) use client::Client;
|
||||
|
||||
use crate::types::{Signature, Transaction, UnsignedTransaction};
|
||||
use crate::types::{Address, Signature, Transaction, UnsignedTransaction};
|
||||
|
||||
/// Trait for signing transactions and messages
|
||||
///
|
||||
|
@ -20,4 +20,7 @@ pub trait Signer {
|
|||
|
||||
/// Signs the transaction
|
||||
fn sign_transaction(&self, message: UnsignedTransaction) -> Transaction;
|
||||
|
||||
/// Returns the signer's Ethereum Address
|
||||
fn address(&self) -> Address;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@ impl<'a, N: Network> Signer for Wallet<N> {
|
|||
fn sign_transaction(&self, tx: UnsignedTransaction) -> Transaction {
|
||||
self.private_key.sign_transaction(tx, N::CHAIN_ID)
|
||||
}
|
||||
|
||||
fn address(&self) -> Address {
|
||||
self.address
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Network> Wallet<N> {
|
||||
|
|
Loading…
Reference in New Issue