Trait ethers_providers::Middleware[][src]

pub trait Middleware: Sync + Send + Debug {
    type Error: Sync + Send + Error + FromErr<<Self::Inner as Middleware>::Error>;
    type Provider: JsonRpcClient;
    type Inner: Middleware<Provider = Self::Provider>;
Show 59 methods fn inner(&self) -> &Self::Inner; fn provider(&self) -> &Provider<Self::Provider> { ... }
fn default_sender(&self) -> Option<Address> { ... }
fn client_version<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<String, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn fill_transaction<'life0, 'life1, 'async_trait>(
        &'life0 self,
        tx: &'life1 mut TypedTransaction,
        block: Option<BlockId>
    ) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_block_number<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<U64, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn send_transaction<'life0, 'async_trait, T: Into<TypedTransaction> + Send + Sync>(
        &'life0 self,
        tx: T,
        block: Option<BlockId>
    ) -> Pin<Box<dyn Future<Output = Result<PendingTransaction<'_, Self::Provider>, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn send_escalating<'a, 'life0, 'async_trait>(
        &'a self,
        tx: &'life0 TypedTransaction,
        escalations: usize,
        policy: EscalationPolicy
    ) -> Pin<Box<dyn Future<Output = Result<EscalatingPending<'a, Self::Provider>, Self::Error>> + Send + 'async_trait>>
    where
        'a: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn resolve_name<'life0, 'life1, 'async_trait>(
        &'life0 self,
        ens_name: &'life1 str
    ) -> Pin<Box<dyn Future<Output = Result<Address, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: 'async_trait
, { ... }
fn lookup_address<'life0, 'async_trait>(
        &'life0 self,
        address: Address
    ) -> Pin<Box<dyn Future<Output = Result<String, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_block<'life0, 'async_trait, T: Into<BlockId> + Send + Sync>(
        &'life0 self,
        block_hash_or_number: T
    ) -> Pin<Box<dyn Future<Output = Result<Option<Block<TxHash>>, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_block_with_txs<'life0, 'async_trait, T: Into<BlockId> + Send + Sync>(
        &'life0 self,
        block_hash_or_number: T
    ) -> Pin<Box<dyn Future<Output = Result<Option<Block<Transaction>>, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_uncle_count<'life0, 'async_trait, T: Into<BlockId> + Send + Sync>(
        &'life0 self,
        block_hash_or_number: T
    ) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_uncle<'life0, 'async_trait, T: Into<BlockId> + Send + Sync>(
        &'life0 self,
        block_hash_or_number: T,
        idx: U64
    ) -> Pin<Box<dyn Future<Output = Result<Option<Block<H256>>, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_transaction_count<'life0, 'async_trait, T: Into<NameOrAddress> + Send + Sync>(
        &'life0 self,
        from: T,
        block: Option<BlockId>
    ) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn estimate_gas<'life0, 'life1, 'async_trait>(
        &'life0 self,
        tx: &'life1 TypedTransaction
    ) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: 'async_trait
, { ... }
fn call<'life0, 'life1, 'async_trait>(
        &'life0 self,
        tx: &'life1 TypedTransaction,
        block: Option<BlockId>
    ) -> Pin<Box<dyn Future<Output = Result<Bytes, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_chainid<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_net_version<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<U64, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_balance<'life0, 'async_trait, T: Into<NameOrAddress> + Send + Sync>(
        &'life0 self,
        from: T,
        block: Option<BlockId>
    ) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_transaction<'life0, 'async_trait, T: Send + Sync + Into<TxHash>>(
        &'life0 self,
        transaction_hash: T
    ) -> Pin<Box<dyn Future<Output = Result<Option<Transaction>, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_transaction_receipt<'life0, 'async_trait, T: Send + Sync + Into<TxHash>>(
        &'life0 self,
        transaction_hash: T
    ) -> Pin<Box<dyn Future<Output = Result<Option<TransactionReceipt>, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_block_receipts<'life0, 'async_trait, T: Into<BlockNumber> + Send + Sync>(
        &'life0 self,
        block: T
    ) -> Pin<Box<dyn Future<Output = Result<Vec<TransactionReceipt>, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_gas_price<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn estimate_eip1559_fees<'life0, 'async_trait>(
        &'life0 self,
        estimator: Option<fn(_: U256, _: Vec<Vec<U256>>) -> (U256, U256)>
    ) -> Pin<Box<dyn Future<Output = Result<(U256, U256), Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_accounts<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<Vec<Address>, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn send_raw_transaction<'a, 'async_trait>(
        &'a self,
        tx: Bytes
    ) -> Pin<Box<dyn Future<Output = Result<PendingTransaction<'a, Self::Provider>, Self::Error>> + Send + 'async_trait>>
    where
        'a: 'async_trait,
        Self: 'async_trait
, { ... }
fn is_signer<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = bool> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn sign<'life0, 'life1, 'async_trait, T: Into<Bytes> + Send + Sync>(
        &'life0 self,
        data: T,
        from: &'life1 Address
    ) -> Pin<Box<dyn Future<Output = Result<Signature, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: 'async_trait
, { ... }
fn sign_transaction<'life0, 'life1, 'async_trait>(
        &'life0 self,
        tx: &'life1 TypedTransaction,
        from: Address
    ) -> Pin<Box<dyn Future<Output = Result<Signature, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_logs<'life0, 'life1, 'async_trait>(
        &'life0 self,
        filter: &'life1 Filter
    ) -> Pin<Box<dyn Future<Output = Result<Vec<Log>, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: 'async_trait
, { ... }
fn new_filter<'life0, 'life1, 'async_trait>(
        &'life0 self,
        filter: FilterKind<'life1>
    ) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: 'async_trait
, { ... }
fn uninstall_filter<'life0, 'async_trait, T: Into<U256> + Send + Sync>(
        &'life0 self,
        id: T
    ) -> Pin<Box<dyn Future<Output = Result<bool, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn watch<'a, 'life0, 'async_trait>(
        &'a self,
        filter: &'life0 Filter
    ) -> Pin<Box<dyn Future<Output = Result<FilterWatcher<'a, Self::Provider, Log>, Self::Error>> + Send + 'async_trait>>
    where
        'a: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn watch_pending_transactions<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<FilterWatcher<'_, Self::Provider, H256>, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_filter_changes<'life0, 'async_trait, T, R>(
        &'life0 self,
        id: T
    ) -> Pin<Box<dyn Future<Output = Result<Vec<R>, Self::Error>> + Send + 'async_trait>>
    where
        T: Into<U256> + Send + Sync,
        R: Serialize + DeserializeOwned + Send + Sync + Debug,
        T: 'async_trait,
        R: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn watch_blocks<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<FilterWatcher<'_, Self::Provider, H256>, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_code<'life0, 'async_trait, T: Into<NameOrAddress> + Send + Sync>(
        &'life0 self,
        at: T,
        block: Option<BlockId>
    ) -> Pin<Box<dyn Future<Output = Result<Bytes, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_storage_at<'life0, 'async_trait, T: Into<NameOrAddress> + Send + Sync>(
        &'life0 self,
        from: T,
        location: H256,
        block: Option<BlockId>
    ) -> Pin<Box<dyn Future<Output = Result<H256, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn get_proof<'life0, 'async_trait, T: Into<NameOrAddress> + Send + Sync>(
        &'life0 self,
        from: T,
        locations: Vec<H256>,
        block: Option<BlockId>
    ) -> Pin<Box<dyn Future<Output = Result<EIP1186ProofResponse, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn txpool_content<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<TxpoolContent, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn txpool_inspect<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<TxpoolInspect, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn txpool_status<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<TxpoolStatus, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn trace_call<'life0, 'async_trait, T: Into<TypedTransaction> + Send + Sync>(
        &'life0 self,
        req: T,
        trace_type: Vec<TraceType>,
        block: Option<BlockNumber>
    ) -> Pin<Box<dyn Future<Output = Result<BlockTrace, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn trace_raw_transaction<'life0, 'async_trait>(
        &'life0 self,
        data: Bytes,
        trace_type: Vec<TraceType>
    ) -> Pin<Box<dyn Future<Output = Result<BlockTrace, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn trace_replay_transaction<'life0, 'async_trait>(
        &'life0 self,
        hash: H256,
        trace_type: Vec<TraceType>
    ) -> Pin<Box<dyn Future<Output = Result<BlockTrace, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn trace_replay_block_transactions<'life0, 'async_trait>(
        &'life0 self,
        block: BlockNumber,
        trace_type: Vec<TraceType>
    ) -> Pin<Box<dyn Future<Output = Result<Vec<BlockTrace>, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn trace_block<'life0, 'async_trait>(
        &'life0 self,
        block: BlockNumber
    ) -> Pin<Box<dyn Future<Output = Result<Vec<Trace>, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn trace_filter<'life0, 'async_trait>(
        &'life0 self,
        filter: TraceFilter
    ) -> Pin<Box<dyn Future<Output = Result<Vec<Trace>, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn trace_get<'life0, 'async_trait, T: Into<U64> + Send + Sync>(
        &'life0 self,
        hash: H256,
        index: Vec<T>
    ) -> Pin<Box<dyn Future<Output = Result<Trace, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn trace_transaction<'life0, 'async_trait>(
        &'life0 self,
        hash: H256
    ) -> Pin<Box<dyn Future<Output = Result<Vec<Trace>, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn parity_block_receipts<'life0, 'async_trait, T: Into<BlockNumber> + Send + Sync>(
        &'life0 self,
        block: T
    ) -> Pin<Box<dyn Future<Output = Result<Vec<TransactionReceipt>, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn subscribe<'life0, 'async_trait, T, R>(
        &'life0 self,
        params: T
    ) -> Pin<Box<dyn Future<Output = Result<SubscriptionStream<'_, Self::Provider, R>, Self::Error>> + Send + 'async_trait>>
    where
        T: Debug + Serialize + Send + Sync,
        R: DeserializeOwned + Send + Sync,
        <Self as Middleware>::Provider: PubsubClient,
        T: 'async_trait,
        R: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn unsubscribe<'life0, 'async_trait, T>(
        &'life0 self,
        id: T
    ) -> Pin<Box<dyn Future<Output = Result<bool, Self::Error>> + Send + 'async_trait>>
    where
        T: Into<U256> + Send + Sync,
        <Self as Middleware>::Provider: PubsubClient,
        T: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn subscribe_blocks<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<SubscriptionStream<'_, Self::Provider, Block<TxHash>>, Self::Error>> + Send + 'async_trait>>
    where
        <Self as Middleware>::Provider: PubsubClient,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn subscribe_pending_txs<'life0, 'async_trait>(
        &'life0 self
    ) -> Pin<Box<dyn Future<Output = Result<SubscriptionStream<'_, Self::Provider, TxHash>, Self::Error>> + Send + 'async_trait>>
    where
        <Self as Middleware>::Provider: PubsubClient,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn subscribe_logs<'a, 'life0, 'async_trait>(
        &'a self,
        filter: &'life0 Filter
    ) -> Pin<Box<dyn Future<Output = Result<SubscriptionStream<'a, Self::Provider, Log>, Self::Error>> + Send + 'async_trait>>
    where
        <Self as Middleware>::Provider: PubsubClient,
        'a: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait
, { ... }
fn fee_history<'life0, 'life1, 'async_trait, T: Into<U256> + Serialize + Send + Sync>(
        &'life0 self,
        block_count: T,
        last_block: BlockNumber,
        reward_percentiles: &'life1 [f64]
    ) -> Pin<Box<dyn Future<Output = Result<FeeHistory, Self::Error>> + Send + 'async_trait>>
    where
        T: 'async_trait,
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: 'async_trait
, { ... }
fn create_access_list<'life0, 'life1, 'async_trait>(
        &'life0 self,
        tx: &'life1 TypedTransaction,
        block: Option<BlockId>
    ) -> Pin<Box<dyn Future<Output = Result<AccessListWithGasUsed, Self::Error>> + Send + 'async_trait>>
    where
        'life0: 'async_trait,
        'life1: 'async_trait,
        Self: 'async_trait
, { ... }
}
Expand description

A middleware allows customizing requests send and received from an ethereum node.

Writing a middleware is as simple as:

  1. implementing the inner method to point to the next layer in the “middleware onion”, 2. implementing the FromErr trait on your middleware’s error type 3. implementing any of the methods you want to override
use ethers_providers::{Middleware, FromErr};
use ethers_core::types::{U64, TransactionRequest, U256, transaction::eip2718::TypedTransaction};
use thiserror::Error;
use async_trait::async_trait;

#[derive(Debug)]
struct MyMiddleware<M>(M);

#[derive(Error, Debug)]
pub enum MyError<M: Middleware> {
    #[error("{0}")]
    MiddlewareError(M::Error),

    // Add your middleware's specific errors here
}

impl<M: Middleware> FromErr<M::Error> for MyError<M> {
    fn from(src: M::Error) -> MyError<M> {
        MyError::MiddlewareError(src)
    }
}

#[async_trait]
impl<M> Middleware for MyMiddleware<M>
where
    M: Middleware,
{
    type Error = MyError<M>;
    type Provider = M::Provider;
    type Inner = M;

    fn inner(&self) -> &M {
        &self.0
    }

    /// Overrides the default `get_block_number` method to always return 0
    async fn get_block_number(&self) -> Result<U64, Self::Error> {
        Ok(U64::zero())
    }

    /// Overrides the default `estimate_gas` method to log that it was called,
    /// before forwarding the call to the next layer.
    async fn estimate_gas(&self, tx: &TypedTransaction) -> Result<U256, Self::Error> {
        println!("Estimating gas...");
        self.inner().estimate_gas(tx).await.map_err(FromErr::from)
    }
}

Associated Types

Required methods

The next middleware in the stack

Provided methods

The HTTP or Websocket provider.

Fill necessary details of a transaction for dispatch

This function is defined on providers to behave as follows:

  1. populate the from field with the default sender
  2. resolve any ENS names in the tx to field
  3. Estimate gas usage without access lists
  4. Estimate gas usage with access lists
  5. Enable access lists IFF they are cheaper
  6. Poll and set legacy or 1559 gas prices

It does NOT set the nonce by default. It MAY override the gas amount set by the user, if access lists are cheaper.

Middleware are encouraged to override any values before delegating to the inner implementation AND/OR modify the values provided by the default implementation after delegating.

E.g. a middleware wanting to double gas prices should consider doing so after delegating and allowing the default implementation to poll gas.

Send a transaction with a simple escalation policy.

policy should be a boxed function that maps original_gas_price and number_of_previous_escalations -> new_gas_price.

e.g. Box::new(|start, escalation_index| start * 1250.pow(escalations) / 1000.pow(escalations))

This returns true if either the middleware stack contains a SignerMiddleware, or the JSON-RPC provider has an unlocked key that can sign using the eth_sign call. If none of the above conditions are met, then the middleware stack is not capable of signing data.

Sign a transaction via RPC call

Executes the given call and returns a number of possible traces for it

Traces a call to eth_sendRawTransaction without making the call, returning the traces

Replays a transaction, returning the traces

Replays all transactions in a block returning the requested traces for each transaction

Returns traces created at given block

Return traces matching the given filter

Returns trace at the given position

Returns all traces of a given transaction

Returns all receipts for that block. Must be done on a parity node.

Implementations on Foreign Types

Implementors