Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

feature: bubble up jsonrpc error response via trait #2122

Closed
wants to merge 10 commits into from
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@

### Unreleased

- Add `MiddlewareError` and `RpcError` traits to support access to deeply nested
RPC errors [#2122](https://github.com/gakonst/ethers-rs/pull/2122)
- Convert provider errors to arbitrary middleware errors
[#1920](https://github.com/gakonst/ethers-rs/pull/1920)
- Add a subset of the `admin` namespace
Expand Down
15 changes: 12 additions & 3 deletions ethers-contract/tests/it/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ mod eth_tests {
utils::{keccak256, Anvil},
};
use ethers_derive_eip712::*;
use ethers_providers::{Http, Middleware, PendingTransaction, Provider, StreamExt};
use ethers_providers::{
Http, Middleware, MiddlewareError, PendingTransaction, Provider, StreamExt,
};
use ethers_signers::{LocalWallet, Signer};
use std::{convert::TryFrom, iter::FromIterator, sync::Arc, time::Duration};

Expand All @@ -24,13 +26,20 @@ mod eth_tests {

#[derive(Debug)]
pub struct MwErr<M: Middleware>(M::Error);
impl<M> ethers_providers::FromErr<M::Error> for MwErr<M>

impl<M: Middleware> MiddlewareError for MwErr<M>
where
M: Middleware,
{
fn from(src: M::Error) -> Self {
type Inner = M::Error;

fn from_err(src: M::Error) -> Self {
Self(src)
}

fn as_inner(&self) -> Option<&Self::Inner> {
Some(&self.0)
}
}

impl<M: Middleware> std::fmt::Display for MwErr<M> {
Expand Down
15 changes: 12 additions & 3 deletions ethers-middleware/src/gas_escalator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub use linear::LinearGasPrice;

use async_trait::async_trait;
use ethers_core::types::{BlockId, TransactionRequest, TxHash, U256};
use ethers_providers::{interval, FromErr, Middleware, PendingTransaction, StreamExt};
use ethers_providers::{interval, Middleware, MiddlewareError, PendingTransaction, StreamExt};
use futures_util::lock::Mutex;
use instant::Instant;
use std::{pin::Pin, sync::Arc};
Expand Down Expand Up @@ -238,10 +238,19 @@ where
}

// Boilerplate
impl<M: Middleware> FromErr<M::Error> for GasEscalatorError<M> {
fn from(src: M::Error) -> GasEscalatorError<M> {
impl<M: Middleware> MiddlewareError for GasEscalatorError<M> {
type Inner = M::Error;

fn from_err(src: M::Error) -> GasEscalatorError<M> {
GasEscalatorError::MiddlewareError(src)
}

fn as_inner(&self) -> Option<&Self::Inner> {
match self {
GasEscalatorError::MiddlewareError(e) => Some(e),
_ => None,
}
}
}

#[derive(Error, Debug)]
Expand Down
17 changes: 13 additions & 4 deletions ethers-middleware/src/gas_oracle/middleware.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::{GasOracle, GasOracleError};
use async_trait::async_trait;
use ethers_core::types::{transaction::eip2718::TypedTransaction, *};
use ethers_providers::{FromErr, Middleware, PendingTransaction};
use ethers_providers::{Middleware, MiddlewareError as METrait, PendingTransaction};
use thiserror::Error;

/// Middleware used for fetching gas prices over an API instead of `eth_gasPrice`.
Expand Down Expand Up @@ -33,10 +33,19 @@ pub enum MiddlewareError<M: Middleware> {
UnsupportedTxType,
}

impl<M: Middleware> FromErr<M::Error> for MiddlewareError<M> {
fn from(src: M::Error) -> MiddlewareError<M> {
impl<M: Middleware> METrait for MiddlewareError<M> {
type Inner = M::Error;

fn from_err(src: M::Error) -> MiddlewareError<M> {
MiddlewareError::MiddlewareError(src)
}

fn as_inner(&self) -> Option<&Self::Inner> {
match self {
MiddlewareError::MiddlewareError(e) => Some(e),
_ => None,
}
}
}

#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
Expand Down Expand Up @@ -86,7 +95,7 @@ where
}
};

self.inner().fill_transaction(tx, block).await.map_err(FromErr::from)
self.inner().fill_transaction(tx, block).await.map_err(METrait::from_err)
}

async fn get_gas_price(&self) -> Result<U256, Self::Error> {
Expand Down
24 changes: 16 additions & 8 deletions ethers-middleware/src/nonce_manager.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use async_trait::async_trait;
use ethers_core::types::{transaction::eip2718::TypedTransaction, *};
use ethers_providers::{FromErr, Middleware, PendingTransaction};
use ethers_providers::{Middleware, MiddlewareError, PendingTransaction};
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use thiserror::Error;

Expand Down Expand Up @@ -40,7 +40,7 @@ where
.inner
.get_transaction_count(self.address, block)
.await
.map_err(FromErr::from)?;
.map_err(MiddlewareError::from_err)?;
self.nonce.store(nonce.as_u64(), Ordering::SeqCst);
self.initialized.store(true, Ordering::SeqCst);
Ok(nonce)
Expand All @@ -60,7 +60,7 @@ where
.inner
.get_transaction_count(self.address, block)
.await
.map_err(FromErr::from)?;
.map_err(MiddlewareError::from_err)?;
self.nonce.store(nonce.as_u64(), Ordering::SeqCst);
self.initialized.store(true, Ordering::SeqCst);
}
Expand All @@ -77,10 +77,18 @@ pub enum NonceManagerError<M: Middleware> {
MiddlewareError(M::Error),
}

impl<M: Middleware> FromErr<M::Error> for NonceManagerError<M> {
fn from(src: M::Error) -> Self {
impl<M: Middleware> MiddlewareError for NonceManagerError<M> {
type Inner = M::Error;

fn from_err(src: M::Error) -> Self {
NonceManagerError::MiddlewareError(src)
}

fn as_inner(&self) -> Option<&Self::Inner> {
match self {
NonceManagerError::MiddlewareError(e) => Some(e),
}
}
}

#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
Expand All @@ -106,7 +114,7 @@ where
tx.set_nonce(self.get_transaction_count_with_manager(block).await?);
}

Ok(self.inner().fill_transaction(tx, block).await.map_err(FromErr::from)?)
Ok(self.inner().fill_transaction(tx, block).await.map_err(MiddlewareError::from_err)?)
}

/// Signs and broadcasts the transaction. The optional parameter `block` can be passed so that
Expand All @@ -132,10 +140,10 @@ where
// was a nonce mismatch
self.nonce.store(nonce.as_u64(), Ordering::SeqCst);
tx.set_nonce(nonce);
self.inner.send_transaction(tx, block).await.map_err(FromErr::from)
self.inner.send_transaction(tx, block).await.map_err(MiddlewareError::from_err)
} else {
// propagate the error otherwise
Err(FromErr::from(err))
Err(MiddlewareError::from_err(err))
}
}
}
Expand Down
23 changes: 16 additions & 7 deletions ethers-middleware/src/policy.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ethers_core::types::{transaction::eip2718::TypedTransaction, BlockId};
use ethers_providers::{FromErr, Middleware, PendingTransaction};
use ethers_providers::{Middleware, MiddlewareError, PendingTransaction};

use async_trait::async_trait;
use std::fmt::Debug;
Expand Down Expand Up @@ -52,12 +52,6 @@ pub struct PolicyMiddleware<M, P> {
pub(crate) policy: P,
}

impl<M: Middleware, P: Policy> FromErr<M::Error> for PolicyMiddlewareError<M, P> {
fn from(src: M::Error) -> PolicyMiddlewareError<M, P> {
PolicyMiddlewareError::MiddlewareError(src)
}
}

impl<M, P> PolicyMiddleware<M, P>
where
M: Middleware,
Expand All @@ -80,6 +74,21 @@ pub enum PolicyMiddlewareError<M: Middleware, P: Policy> {
MiddlewareError(M::Error),
}

impl<M: Middleware, P: Policy> MiddlewareError for PolicyMiddlewareError<M, P> {
type Inner = M::Error;

fn from_err(src: M::Error) -> Self {
PolicyMiddlewareError::MiddlewareError(src)
}

fn as_inner(&self) -> Option<&Self::Inner> {
match self {
PolicyMiddlewareError::MiddlewareError(e) => Some(e),
_ => None,
}
}
}

#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<M, P> Middleware for PolicyMiddleware<M, P>
Expand Down
23 changes: 16 additions & 7 deletions ethers-middleware/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use ethers_core::types::{
transaction::{eip2718::TypedTransaction, eip2930::AccessListWithGasUsed},
Address, BlockId, Bytes, Chain, Signature, TransactionRequest, U256,
};
use ethers_providers::{maybe, FromErr, Middleware, PendingTransaction};
use ethers_providers::{maybe, Middleware, MiddlewareError, PendingTransaction};
use ethers_signers::Signer;
use std::convert::TryFrom;

Expand Down Expand Up @@ -67,12 +67,6 @@ pub struct SignerMiddleware<M, S> {
pub(crate) address: Address,
}

impl<M: Middleware, S: Signer> FromErr<M::Error> for SignerMiddlewareError<M, S> {
fn from(src: M::Error) -> SignerMiddlewareError<M, S> {
SignerMiddlewareError::MiddlewareError(src)
}
}

#[derive(Error, Debug)]
/// Error thrown when the client interacts with the blockchain
pub enum SignerMiddlewareError<M: Middleware, S: Signer> {
Expand Down Expand Up @@ -101,6 +95,21 @@ pub enum SignerMiddlewareError<M: Middleware, S: Signer> {
DifferentChainID,
}

impl<M: Middleware, S: Signer> MiddlewareError for SignerMiddlewareError<M, S> {
type Inner = M::Error;

fn from_err(src: M::Error) -> Self {
SignerMiddlewareError::MiddlewareError(src)
}

fn as_inner(&self) -> Option<&Self::Inner> {
match self {
SignerMiddlewareError::MiddlewareError(e) => Some(e),
_ => None,
}
}
}

// Helper functions for locally signing transactions
impl<M, S> SignerMiddleware<M, S>
where
Expand Down
Loading