Struct ethers_flashbots::FlashbotsMiddleware
source · pub struct FlashbotsMiddleware<M, S> { /* private fields */ }Expand description
A middleware used to send bundles to a Flashbots relay.
NOTE: This middleware does NOT sign your transactions. Use another method to sign your transactions, and then forward the signed transactions to the middleware.
You can either send custom bundles (see BundleRequest) or send
transactions as you normally would (see [Middleware::send_transaction]) from
another middleware.
If you use [Middleware::send_transaction] then a bundle will be constructed
for you with the following assumptions:
- You do not want to allow the transaction to revert
- You do not care to set a minimum or maximum timestamp for the bundle
- The block you are targetting with your bundle is the next block
- You do not want to simulate the bundle before sending to the relay
Example
use ethers::prelude::*;
use std::convert::TryFrom;
use ethers_flashbots::FlashbotsMiddleware;
use url::Url;
let provider = Provider::<Http>::try_from("http://localhost:8545")
.expect("Could not instantiate HTTP provider");
// Used to sign Flashbots relay requests - this is your searcher identity
let signer: LocalWallet = "380eb0f3d505f087e438eca80bc4df9a7faa24f868e69fc0440261a0fc0567dc"
.parse()?;
// Used to sign transactions
let wallet: LocalWallet = "380eb0f3d505f087e438eca80bc4df9a7faa24f868e69fc0440261a0fc0567dc"
.parse()?;
// Note: The order is important! You want the signer
// middleware to sign your transactions *before* they
// are sent to your Flashbots middleware.
let mut client = SignerMiddleware::new(
FlashbotsMiddleware::new(
provider,
Url::parse("https://relay.flashbots.net")?,
signer
),
wallet
);
// This transaction will now be send as a Flashbots bundle!
let tx = TransactionRequest::pay("vitalik.eth", 100);
let pending_tx = client.send_transaction(tx, None).await?;Implementations§
source§impl<M: Middleware, S: Signer> FlashbotsMiddleware<M, S>
impl<M: Middleware, S: Signer> FlashbotsMiddleware<M, S>
sourcepub fn new(inner: M, relay_url: impl Into<Url>, relay_signer: S) -> Self
pub fn new(inner: M, relay_url: impl Into<Url>, relay_signer: S) -> Self
Initialize a new Flashbots middleware.
The signer is used to sign requests to the relay.
sourcepub fn simulation_relay(&self) -> Option<&Relay<S>>
pub fn simulation_relay(&self) -> Option<&Relay<S>>
Get the relay client used by the middleware to simulate bundles if set.
sourcepub fn set_simulation_relay(&mut self, relay_url: impl Into<Url>)
pub fn set_simulation_relay(&mut self, relay_url: impl Into<Url>)
Set a separate relay to use for simulating bundles.
This can either be a full Flashbots relay or a node that implements
the eth_callBundle remote procedure call.
sourcepub async fn simulate_bundle(
&self,
bundle: &BundleRequest
) -> Result<SimulatedBundle, FlashbotsMiddlewareError<M, S>>
pub async fn simulate_bundle(
&self,
bundle: &BundleRequest
) -> Result<SimulatedBundle, FlashbotsMiddlewareError<M, S>>
Simulate a bundle.
See eth_callBundle for more information.
sourcepub async fn send_bundle(
&self,
bundle: &BundleRequest
) -> Result<PendingBundle<'_, <Self as Middleware>::Provider>, FlashbotsMiddlewareError<M, S>>
pub async fn send_bundle(
&self,
bundle: &BundleRequest
) -> Result<PendingBundle<'_, <Self as Middleware>::Provider>, FlashbotsMiddlewareError<M, S>>
Send a bundle to the relayer.
See eth_sendBundle for more information.
sourcepub async fn get_bundle_stats(
&self,
bundle_hash: BundleHash,
block_number: U64
) -> Result<BundleStats, FlashbotsMiddlewareError<M, S>>
pub async fn get_bundle_stats(
&self,
bundle_hash: BundleHash,
block_number: U64
) -> Result<BundleStats, FlashbotsMiddlewareError<M, S>>
Get stats for a particular bundle.
sourcepub async fn get_user_stats(
&self
) -> Result<UserStats, FlashbotsMiddlewareError<M, S>>
pub async fn get_user_stats(
&self
) -> Result<UserStats, FlashbotsMiddlewareError<M, S>>
Get stats for your searcher identity.
Your searcher identity is determined by the signer you constructed the middleware with.
Trait Implementations§
source§impl<M, S> Middleware for FlashbotsMiddleware<M, S>where
M: Middleware,
S: Signer,
impl<M, S> Middleware for FlashbotsMiddleware<M, S>where
M: Middleware,
S: Signer,
type Error = FlashbotsMiddlewareError<M, S>
type Provider = <M as Middleware>::Provider
type Inner = M
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
Self: 'async_trait,
'a: 'async_trait,
fn default_sender(&self) -> Option<H160>
fn client_version<'life0, 'async_trait>(
&'life0 self
) -> Pin<Box<dyn Future<Output = Result<String, Self::Error>> + Send + 'async_trait, Global>>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, Global>>where
'life0: 'async_trait,
'life1: '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, Global>>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, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
fn send_transaction<'life0, 'async_trait, T>(
&'life0 self,
tx: T,
block: Option<BlockId>
) -> Pin<Box<dyn Future<Output = Result<PendingTransaction<'life0, Self::Provider>, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<TypedTransaction> + Send + Sync,
Self: 'async_trait,
§fn send_escalating<'a, 'life0, 'async_trait>(
&'a self,
tx: &'life0 TypedTransaction,
escalations: usize,
policy: Box<dyn Fn(U256, usize) -> U256 + Sync + Send + 'static, Global>
) -> Pin<Box<dyn Future<Output = Result<EscalatingPending<'a, Self::Provider>, Self::Error>> + Send + 'async_trait, Global>>where
'a: 'async_trait,
'life0: 'async_trait,
Self: 'async_trait,
fn send_escalating<'a, 'life0, 'async_trait>(
&'a self,
tx: &'life0 TypedTransaction,
escalations: usize,
policy: Box<dyn Fn(U256, usize) -> U256 + Sync + Send + 'static, Global>
) -> Pin<Box<dyn Future<Output = Result<EscalatingPending<'a, Self::Provider>, Self::Error>> + Send + 'async_trait, Global>>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<H160, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn lookup_address<'life0, 'async_trait>(
&'life0 self,
address: H160
) -> Pin<Box<dyn Future<Output = Result<String, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
fn resolve_avatar<'life0, 'life1, 'async_trait>(
&'life0 self,
ens_name: &'life1 str
) -> Pin<Box<dyn Future<Output = Result<Url, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn resolve_nft<'life0, 'async_trait>(
&'life0 self,
token: ERCNFT
) -> Pin<Box<dyn Future<Output = Result<Url, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
fn resolve_field<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
ens_name: &'life1 str,
field: &'life2 str
) -> Pin<Box<dyn Future<Output = Result<String, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn get_block<'life0, 'async_trait, T>(
&'life0 self,
block_hash_or_number: T
) -> Pin<Box<dyn Future<Output = Result<Option<Block<H256>>, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<BlockId> + Send + Sync,
Self: 'async_trait,
fn get_block_with_txs<'life0, 'async_trait, T>(
&'life0 self,
block_hash_or_number: T
) -> Pin<Box<dyn Future<Output = Result<Option<Block<Transaction>>, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<BlockId> + Send + Sync,
Self: 'async_trait,
fn get_uncle_count<'life0, 'async_trait, T>(
&'life0 self,
block_hash_or_number: T
) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<BlockId> + Send + Sync,
Self: 'async_trait,
fn get_uncle<'life0, 'async_trait, T>(
&'life0 self,
block_hash_or_number: T,
idx: U64
) -> Pin<Box<dyn Future<Output = Result<Option<Block<H256>>, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<BlockId> + Send + Sync,
Self: 'async_trait,
fn get_transaction_count<'life0, 'async_trait, T>(
&'life0 self,
from: T,
block: Option<BlockId>
) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<NameOrAddress> + Send + Sync,
Self: 'async_trait,
fn estimate_gas<'life0, 'life1, 'async_trait>(
&'life0 self,
tx: &'life1 TypedTransaction,
block: Option<BlockId>
) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait, Global>>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, Global>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn syncing<'life0, 'async_trait>(
&'life0 self
) -> Pin<Box<dyn Future<Output = Result<SyncingStatus, Self::Error>> + Send + 'async_trait, Global>>where
'life0: '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, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
fn get_net_version<'life0, 'async_trait>(
&'life0 self
) -> Pin<Box<dyn Future<Output = Result<String, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
fn get_balance<'life0, 'async_trait, T>(
&'life0 self,
from: T,
block: Option<BlockId>
) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<NameOrAddress> + Send + Sync,
Self: 'async_trait,
fn get_transaction<'life0, 'async_trait, T>(
&'life0 self,
transaction_hash: T
) -> Pin<Box<dyn Future<Output = Result<Option<Transaction>, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Send + Sync + Into<H256>,
Self: 'async_trait,
fn get_transaction_receipt<'life0, 'async_trait, T>(
&'life0 self,
transaction_hash: T
) -> Pin<Box<dyn Future<Output = Result<Option<TransactionReceipt>, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Send + Sync + Into<H256>,
Self: 'async_trait,
fn get_block_receipts<'life0, 'async_trait, T>(
&'life0 self,
block: T
) -> Pin<Box<dyn Future<Output = Result<Vec<TransactionReceipt, Global>, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<BlockNumber> + Send + Sync,
Self: 'async_trait,
fn get_gas_price<'life0, 'async_trait>(
&'life0 self
) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
fn estimate_eip1559_fees<'life0, 'async_trait>(
&'life0 self,
estimator: Option<fn(_: U256, _: Vec<Vec<U256, Global>, Global>) -> (U256, U256)>
) -> Pin<Box<dyn Future<Output = Result<(U256, U256), Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
fn get_accounts<'life0, 'async_trait>(
&'life0 self
) -> Pin<Box<dyn Future<Output = Result<Vec<H160, Global>, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
§fn is_signer<'life0, 'async_trait>(
&'life0 self
) -> Pin<Box<dyn Future<Output = bool> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
fn is_signer<'life0, 'async_trait>(
&'life0 self
) -> Pin<Box<dyn Future<Output = bool> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
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.fn sign<'life0, 'life1, 'async_trait, T>(
&'life0 self,
data: T,
from: &'life1 H160
) -> Pin<Box<dyn Future<Output = Result<Signature, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
'life1: 'async_trait,
T: 'async_trait + Into<Bytes> + Send + Sync,
Self: 'async_trait,
§fn sign_transaction<'life0, 'life1, 'async_trait>(
&'life0 self,
tx: &'life1 TypedTransaction,
from: H160
) -> Pin<Box<dyn Future<Output = Result<Signature, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn sign_transaction<'life0, 'life1, 'async_trait>(
&'life0 self,
tx: &'life1 TypedTransaction,
from: H160
) -> Pin<Box<dyn Future<Output = Result<Signature, Self::Error>> + Send + 'async_trait, Global>>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, Global>, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
§fn get_logs_paginated<'a>(
&'a self,
filter: &Filter,
page_size: u64
) -> LogQuery<'a, Self::Provider>
fn get_logs_paginated<'a>(
&'a self,
filter: &Filter,
page_size: u64
) -> LogQuery<'a, Self::Provider>
fn new_filter<'life0, 'life1, 'async_trait>(
&'life0 self,
filter: FilterKind<'life1>
) -> Pin<Box<dyn Future<Output = Result<U256, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn uninstall_filter<'life0, 'async_trait, T>(
&'life0 self,
id: T
) -> Pin<Box<dyn Future<Output = Result<bool, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<U256> + Send + Sync,
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, Global>>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<'life0, Self::Provider, H256>, Self::Error>> + Send + 'async_trait, Global>>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, Global>, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: Into<U256> + Send + Sync + 'async_trait,
R: Serialize + DeserializeOwned + Send + Sync + Debug + 'async_trait,
Self: 'async_trait,
fn watch_blocks<'life0, 'async_trait>(
&'life0 self
) -> Pin<Box<dyn Future<Output = Result<FilterWatcher<'life0, Self::Provider, H256>, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
fn get_code<'life0, 'async_trait, T>(
&'life0 self,
at: T,
block: Option<BlockId>
) -> Pin<Box<dyn Future<Output = Result<Bytes, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<NameOrAddress> + Send + Sync,
Self: 'async_trait,
fn get_storage_at<'life0, 'async_trait, T>(
&'life0 self,
from: T,
location: H256,
block: Option<BlockId>
) -> Pin<Box<dyn Future<Output = Result<H256, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<NameOrAddress> + Send + Sync,
Self: 'async_trait,
fn get_proof<'life0, 'async_trait, T>(
&'life0 self,
from: T,
locations: Vec<H256, Global>,
block: Option<BlockId>
) -> Pin<Box<dyn Future<Output = Result<EIP1186ProofResponse, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<NameOrAddress> + Send + Sync,
Self: 'async_trait,
fn txpool_content<'life0, 'async_trait>(
&'life0 self
) -> Pin<Box<dyn Future<Output = Result<TxpoolContent, Self::Error>> + Send + 'async_trait, Global>>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, Global>>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, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
§fn debug_trace_transaction<'life0, 'async_trait>(
&'life0 self,
tx_hash: H256,
trace_options: GethDebugTracingOptions
) -> Pin<Box<dyn Future<Output = Result<GethTrace, ProviderError>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
fn debug_trace_transaction<'life0, 'async_trait>(
&'life0 self,
tx_hash: H256,
trace_options: GethDebugTracingOptions
) -> Pin<Box<dyn Future<Output = Result<GethTrace, ProviderError>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
§fn trace_call<'life0, 'async_trait, T>(
&'life0 self,
req: T,
trace_type: Vec<TraceType, Global>,
block: Option<BlockNumber>
) -> Pin<Box<dyn Future<Output = Result<BlockTrace, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<TypedTransaction> + Send + Sync,
Self: 'async_trait,
fn trace_call<'life0, 'async_trait, T>(
&'life0 self,
req: T,
trace_type: Vec<TraceType, Global>,
block: Option<BlockNumber>
) -> Pin<Box<dyn Future<Output = Result<BlockTrace, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<TypedTransaction> + Send + Sync,
Self: 'async_trait,
fn trace_call_many<'life0, 'async_trait, T>(
&'life0 self,
req: Vec<(T, Vec<TraceType, Global>), Global>,
block: Option<BlockNumber>
) -> Pin<Box<dyn Future<Output = Result<Vec<BlockTrace, Global>, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
T: 'async_trait + Into<TypedTransaction> + Send + Sync,
Self: 'async_trait,
§fn trace_raw_transaction<'life0, 'async_trait>(
&'life0 self,
data: Bytes,
trace_type: Vec<TraceType, Global>
) -> Pin<Box<dyn Future<Output = Result<BlockTrace, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
fn trace_raw_transaction<'life0, 'async_trait>(
&'life0 self,
data: Bytes,
trace_type: Vec<TraceType, Global>
) -> Pin<Box<dyn Future<Output = Result<BlockTrace, Self::Error>> + Send + 'async_trait, Global>>where
'life0: 'async_trait,
Self: 'async_trait,
eth_sendRawTransaction without making the call, returning the traces