1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
use crate::{
gas_oracle::{GasOracle, GasOracleMiddleware},
NonceManagerMiddleware, SignerMiddleware,
};
use ethers_core::types::Address;
use ethers_providers::Middleware;
use ethers_signers::Signer;
/// A builder trait to compose different [`Middleware`] layers and then build a composed
/// [`Provider`](ethers_providers::Provider) architecture.
///
/// [`Middleware`] composition acts in a wrapping fashion. Adding a new layer results in wrapping
/// its predecessor.
///
/// ```rust
/// use ethers_providers::{Middleware, Provider, Http};
/// use std::sync::Arc;
/// use std::convert::TryFrom;
/// use ethers_signers::{LocalWallet, Signer};
/// use ethers_middleware::{*, gas_escalator::*, gas_oracle::*};
///
/// fn builder_example() {
/// let key = "fdb33e2105f08abe41a8ee3b758726a31abdd57b7a443f470f23efce853af169";
/// let signer = key.parse::<LocalWallet>().unwrap();
/// let address = signer.address();
/// let escalator = GeometricGasPrice::new(1.125, 60_u64, None::<u64>);
/// let gas_oracle = GasNow::new();
///
/// let provider = Provider::<Http>::try_from("http://localhost:8545")
/// .unwrap()
/// .wrap_into(|p| GasEscalatorMiddleware::new(p, escalator, Frequency::PerBlock))
/// .gas_oracle(gas_oracle)
/// .with_signer(signer)
/// .nonce_manager(address); // Outermost layer
/// }
///
/// fn builder_example_raw_wrap() {
/// let key = "fdb33e2105f08abe41a8ee3b758726a31abdd57b7a443f470f23efce853af169";
/// let signer = key.parse::<LocalWallet>().unwrap();
/// let address = signer.address();
/// let escalator = GeometricGasPrice::new(1.125, 60_u64, None::<u64>);
///
/// let provider = Provider::<Http>::try_from("http://localhost:8545")
/// .unwrap()
/// .wrap_into(|p| GasEscalatorMiddleware::new(p, escalator, Frequency::PerBlock))
/// .wrap_into(|p| SignerMiddleware::new(p, signer))
/// .wrap_into(|p| GasOracleMiddleware::new(p, GasNow::new()))
/// .wrap_into(|p| NonceManagerMiddleware::new(p, address)); // Outermost layer
/// }
/// ```
pub trait MiddlewareBuilder: Middleware + Sized + 'static {
/// Wraps `self` inside a new [`Middleware`].
///
/// `f` Consumes `self`. Must be used to return a new [`Middleware`] wrapping `self`.
fn wrap_into<F, T>(self, f: F) -> T
where
F: FnOnce(Self) -> T,
T: Middleware,
{
f(self)
}
/// Wraps `self` inside a [`SignerMiddleware`].
fn with_signer<S>(self, s: S) -> SignerMiddleware<Self, S>
where
S: Signer,
{
SignerMiddleware::new(self, s)
}
/// Wraps `self` inside a [`NonceManagerMiddleware`].
fn nonce_manager(self, address: Address) -> NonceManagerMiddleware<Self> {
NonceManagerMiddleware::new(self, address)
}
/// Wraps `self` inside a [`GasOracleMiddleware`].
fn gas_oracle<G>(self, gas_oracle: G) -> GasOracleMiddleware<Self, G>
where
G: GasOracle,
{
GasOracleMiddleware::new(self, gas_oracle)
}
}
impl<M> MiddlewareBuilder for M where M: Middleware + Sized + 'static {}