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);
|
.connect(&provider);
|
||||||
|
|
||||||
// get the account's nonce
|
// get the account's nonce (we abuse the Deref to access the provider's functions)
|
||||||
let nonce = provider
|
let nonce = client.get_transaction_count(client.address(), None).await?;
|
||||||
.get_transaction_count(client.signer.address, None)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// craft the transaction
|
// craft the transaction
|
||||||
let tx = UnsignedTransaction {
|
let tx = UnsignedTransaction {
|
||||||
|
@ -29,7 +27,7 @@ async fn main() -> Result<(), failure::Error> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// send it!
|
// send it!
|
||||||
let tx = client.send_transaction(tx).await?;
|
let tx = client.sign_and_send_transaction(tx).await?;
|
||||||
|
|
||||||
// get the mined tx
|
// get the mined tx
|
||||||
let tx = client.get_transaction(tx.hash).await?;
|
let tx = client.get_transaction(tx.hash).await?;
|
||||||
|
|
|
@ -7,7 +7,7 @@ mod http;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
signers::{Client, Signer},
|
signers::{Client, Signer},
|
||||||
types::{Address, BlockNumber, Bytes, Transaction, TransactionRequest, TxHash, U256},
|
types::{Address, BlockNumber, Transaction, TransactionRequest, TxHash, U256},
|
||||||
utils,
|
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> {
|
pub async fn get_block_number(&self) -> Result<U256, P::Error> {
|
||||||
self.0.request("eth_blockNumber", None::<()>).await
|
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>>(
|
pub async fn get_transaction<T: Send + Sync + Into<TxHash>>(
|
||||||
&self,
|
&self,
|
||||||
hash: T,
|
hash: T,
|
||||||
|
@ -58,12 +60,14 @@ impl<P: JsonRpcClient> Provider<P> {
|
||||||
self.0.request("eth_getTransactionByHash", Some(hash)).await
|
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> {
|
pub async fn send_transaction(&self, tx: TransactionRequest) -> Result<TxHash, P::Error> {
|
||||||
self.0.request("eth_sendTransaction", Some(tx)).await
|
self.0.request("eth_sendTransaction", Some(tx)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_raw_transaction(&self, rlp: &Bytes) -> Result<TxHash, P::Error> {
|
/// Broadcasts a raw RLP encoded transaction via the `eth_sendRawTransaction` API
|
||||||
let rlp = utils::serialize(&rlp);
|
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
|
self.0.request("eth_sendRawTransaction", Some(rlp)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,31 +1,45 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
providers::{JsonRpcClient, Provider},
|
providers::{JsonRpcClient, Provider},
|
||||||
signers::Signer,
|
signers::Signer,
|
||||||
types::{Transaction, TxHash, UnsignedTransaction},
|
types::{Address, Transaction, UnsignedTransaction},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Client<'a, S, P> {
|
pub struct Client<'a, S, P> {
|
||||||
pub provider: &'a Provider<P>,
|
pub(crate) provider: &'a Provider<P>,
|
||||||
pub signer: S,
|
pub(crate) signer: S,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S: Signer, P: JsonRpcClient> Client<'a, S, P> {
|
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
|
// sign the transaction
|
||||||
let signed_tx = self.signer.sign_transaction(tx.clone());
|
let signed_tx = self.signer.sign_transaction(tx.clone());
|
||||||
|
|
||||||
// broadcast it
|
// broadcast it
|
||||||
self.provider.send_raw_transaction(&signed_tx.rlp()).await?;
|
self.provider.send_raw_transaction(&signed_tx).await?;
|
||||||
|
|
||||||
Ok(signed_tx)
|
Ok(signed_tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Forward all other calls to the provider
|
pub fn address(&self) -> Address {
|
||||||
pub async fn get_transaction<T: Send + Sync + Into<TxHash>>(
|
self.signer.address()
|
||||||
&self,
|
}
|
||||||
hash: T,
|
}
|
||||||
) -> Result<Transaction, P::Error> {
|
|
||||||
self.provider.get_transaction(hash).await
|
// 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;
|
mod client;
|
||||||
pub(crate) use client::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
|
/// Trait for signing transactions and messages
|
||||||
///
|
///
|
||||||
|
@ -20,4 +20,7 @@ pub trait Signer {
|
||||||
|
|
||||||
/// Signs the transaction
|
/// Signs the transaction
|
||||||
fn sign_transaction(&self, message: UnsignedTransaction) -> 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 {
|
fn sign_transaction(&self, tx: UnsignedTransaction) -> Transaction {
|
||||||
self.private_key.sign_transaction(tx, N::CHAIN_ID)
|
self.private_key.sign_transaction(tx, N::CHAIN_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn address(&self) -> Address {
|
||||||
|
self.address
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Network> Wallet<N> {
|
impl<N: Network> Wallet<N> {
|
||||||
|
|
Loading…
Reference in New Issue