ethers_providers/
middleware.rs

1use async_trait::async_trait;
2use auto_impl::auto_impl;
3use ethers_core::types::{
4    transaction::{eip2718::TypedTransaction, eip2930::AccessListWithGasUsed},
5    *,
6};
7use futures_util::future::join_all;
8use serde::{de::DeserializeOwned, Serialize};
9use std::fmt::Debug;
10use url::Url;
11
12use crate::{
13    erc, EscalatingPending, EscalationPolicy, FilterKind, FilterWatcher, JsonRpcClient, LogQuery,
14    MiddlewareError, NodeInfo, PeerInfo, PendingTransaction, Provider, ProviderError, PubsubClient,
15    SubscriptionStream,
16};
17
18/// A middleware allows customizing requests send and received from an ethereum node.
19///
20/// Writing a middleware is as simple as:
21/// 1. implementing the [`inner`](crate::Middleware::inner) method to point to the next layer in the
22/// "middleware onion", 2. implementing the
23/// [`MiddlewareError`](crate::MiddlewareError) trait on your middleware's
24/// error type 3. implementing any of the methods you want to override
25///
26/// ```
27/// use ethers_providers::{Middleware, MiddlewareError};
28/// use ethers_core::types::{U64, TransactionRequest, U256, transaction::eip2718::TypedTransaction, BlockId};
29/// use thiserror::Error;
30/// use async_trait::async_trait;
31///
32/// #[derive(Debug)]
33/// struct MyMiddleware<M>(M);
34///
35/// #[derive(Error, Debug)]
36/// pub enum MyError<M: Middleware> {
37///     #[error("{0}")]
38///     MiddlewareError(M::Error),
39///
40///     // Add your middleware's specific errors here
41/// }
42///
43/// impl<M: Middleware> MiddlewareError for MyError<M> {
44///     type Inner = M::Error;
45///
46///     fn from_err(src: M::Error) -> MyError<M> {
47///         MyError::MiddlewareError(src)
48///     }
49///
50///     fn as_inner(&self) -> Option<&Self::Inner> {
51///         match self {
52///             MyError::MiddlewareError(e) => Some(e),
53///             _ => None,
54///         }
55///     }
56/// }
57///
58/// #[async_trait]
59/// impl<M> Middleware for MyMiddleware<M>
60/// where
61///     M: Middleware,
62/// {
63///     type Error = MyError<M>;
64///     type Provider = M::Provider;
65///     type Inner = M;
66///
67///     fn inner(&self) -> &M {
68///         &self.0
69///     }
70///
71///     /// Overrides the default `get_block_number` method to always return 0
72///     async fn get_block_number(&self) -> Result<U64, Self::Error> {
73///         Ok(U64::zero())
74///     }
75///
76///     /// Overrides the default `estimate_gas` method to log that it was called,
77///     /// before forwarding the call to the next layer.
78///     async fn estimate_gas(&self, tx: &TypedTransaction, block: Option<BlockId>) -> Result<U256, Self::Error> {
79///         println!("Estimating gas...");
80///         self.inner().estimate_gas(tx, block).await.map_err(MiddlewareError::from_err)
81///     }
82/// }
83/// ```
84#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
85#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
86#[auto_impl(&, Box, Arc)]
87pub trait Middleware: Sync + Send + Debug {
88    /// Error type returned by most operations
89    type Error: MiddlewareError<Inner = <<Self as Middleware>::Inner as Middleware>::Error>;
90    /// The JSON-RPC client type at the bottom of the stack
91    type Provider: JsonRpcClient;
92    /// The next-lower middleware in the middleware stack
93    type Inner: Middleware<Provider = Self::Provider>;
94
95    /// Get a reference to the next-lower middleware in the middleware stack
96    fn inner(&self) -> &Self::Inner;
97
98    /// Convert a provider error into the associated error type by successively
99    /// converting it to every intermediate middleware error
100    fn convert_err(p: ProviderError) -> Self::Error {
101        Self::Error::from_provider_err(p)
102    }
103
104    /// The HTTP or Websocket provider.
105    fn provider(&self) -> &Provider<Self::Provider> {
106        self.inner().provider()
107    }
108
109    /// Return the default sender (if any). This will typically be the
110    /// connected node's first address, or the address of a Signer in a lower
111    /// middleware stack
112    fn default_sender(&self) -> Option<Address> {
113        self.inner().default_sender()
114    }
115
116    /// Returns the current client version using the `web3_clientVersion` RPC.
117    async fn client_version(&self) -> Result<String, Self::Error> {
118        self.inner().client_version().await.map_err(MiddlewareError::from_err)
119    }
120
121    /// Fill necessary details of a transaction for dispatch
122    ///
123    /// This function is defined on providers to behave as follows:
124    /// 1. populate the `from` field with the default sender
125    /// 2. resolve any ENS names in the tx `to` field
126    /// 3. Estimate gas usage
127    /// 4. Poll and set legacy or 1559 gas prices
128    /// 5. Set the chain_id with the provider's, if not already set
129    ///
130    /// It does NOT set the nonce by default.
131    ///
132    /// Middleware are encouraged to override any values _before_ delegating
133    /// to the inner implementation AND/OR modify the values provided by the
134    /// default implementation _after_ delegating.
135    ///
136    /// E.g. a middleware wanting to double gas prices should consider doing so
137    /// _after_ delegating and allowing the default implementation to poll gas.
138    async fn fill_transaction(
139        &self,
140        tx: &mut TypedTransaction,
141        block: Option<BlockId>,
142    ) -> Result<(), Self::Error> {
143        self.inner().fill_transaction(tx, block).await.map_err(MiddlewareError::from_err)
144    }
145
146    /// Get the block number
147    async fn get_block_number(&self) -> Result<U64, Self::Error> {
148        self.inner().get_block_number().await.map_err(MiddlewareError::from_err)
149    }
150
151    /// Get the block header by number or hash
152    async fn get_header<T: Into<BlockId> + Send + Sync>(
153        &self,
154        block_hash_or_number: T,
155    ) -> Result<Option<Block<Transaction>>, Self::Error> {
156        self.inner().get_header(block_hash_or_number).await.map_err(MiddlewareError::from_err)
157    }
158
159    /// Sends the transaction to the entire Ethereum network and returns the
160    /// transaction's hash. This will consume gas from the account that signed
161    /// the transaction. This call will fail if no signer is available, and the
162    /// RPC node does  not have an unlocked accounts
163    async fn send_transaction<T: Into<TypedTransaction> + Send + Sync>(
164        &self,
165        tx: T,
166        block: Option<BlockId>,
167    ) -> Result<PendingTransaction<'_, Self::Provider>, Self::Error> {
168        self.inner().send_transaction(tx, block).await.map_err(MiddlewareError::from_err)
169    }
170
171    /// Send a transaction with a simple escalation policy.
172    ///
173    /// `policy` should be a boxed function that maps `original_gas_price`
174    /// and `number_of_previous_escalations` -> `new_gas_price`.
175    ///
176    /// e.g. `Box::new(|start, escalation_index| start * 1250.pow(escalations) /
177    /// 1000.pow(escalations))`
178    async fn send_escalating<'a>(
179        &'a self,
180        tx: &TypedTransaction,
181        escalations: usize,
182        policy: EscalationPolicy,
183    ) -> Result<EscalatingPending<'a, Self::Provider>, Self::Error> {
184        let mut original = tx.clone();
185        self.fill_transaction(&mut original, None).await?;
186
187        // set the nonce, if no nonce is found
188        if original.nonce().is_none() {
189            let nonce =
190                self.get_transaction_count(tx.from().copied().unwrap_or_default(), None).await?;
191            original.set_nonce(nonce);
192        }
193
194        let gas_price = original.gas_price().expect("filled");
195        let sign_futs: Vec<_> = (0..escalations)
196            .map(|i| {
197                let new_price = policy(gas_price, i);
198                let mut r = original.clone();
199                r.set_gas_price(new_price);
200                r
201            })
202            .map(|req| async move {
203                self.sign_transaction(&req, self.default_sender().unwrap_or_default())
204                    .await
205                    .map(|sig| req.rlp_signed(&sig))
206            })
207            .collect();
208
209        // we reverse for convenience. Ensuring that we can always just
210        // `pop()` the next tx off the back later
211        let mut signed = join_all(sign_futs).await.into_iter().collect::<Result<Vec<_>, _>>()?;
212        signed.reverse();
213
214        Ok(EscalatingPending::new(self.provider(), signed))
215    }
216
217    ////// Ethereum Naming Service
218    // The Ethereum Naming Service (ENS) allows easy to remember and use names to
219    // be assigned to Ethereum addresses. Any provider operation which takes an address
220    // may also take an ENS name.
221    //
222    // ENS also provides the ability for a reverse lookup, which determines the name for an address
223    // if it has been configured.
224
225    /// Returns the address that the `ens_name` resolves to (or None if not configured).
226    ///
227    /// # Panics
228    ///
229    /// If the bytes returned from the ENS registrar/resolver cannot be interpreted as
230    /// an address. This should theoretically never happen.
231    async fn resolve_name(&self, ens_name: &str) -> Result<Address, Self::Error> {
232        self.inner().resolve_name(ens_name).await.map_err(MiddlewareError::from_err)
233    }
234
235    /// Returns the ENS name the `address` resolves to (or None if not configured).
236    ///
237    /// # Panics
238    ///
239    /// If the bytes returned from the ENS registrar/resolver cannot be interpreted as
240    /// a string. This should theoretically never happen.
241    async fn lookup_address(&self, address: Address) -> Result<String, Self::Error> {
242        self.inner().lookup_address(address).await.map_err(MiddlewareError::from_err)
243    }
244
245    /// Returns the avatar HTTP link of the avatar that the `ens_name` resolves to (or None
246    /// if not configured)
247    ///
248    /// # Examples
249    ///
250    /// ```no_run
251    /// # use ethers_providers::{Provider, Http, Middleware};
252    /// # async fn foo(provider: Provider<Http>) -> Result<(), Box<dyn std::error::Error>> {
253    /// let avatar = provider.resolve_avatar("parishilton.eth").await?;
254    /// assert_eq!(avatar.to_string(), "https://i.imgur.com/YW3Hzph.jpg");
255    /// # Ok(()) }
256    /// ```
257    ///
258    /// # Panics
259    ///
260    /// If the bytes returned from the ENS registrar/resolver cannot be interpreted as
261    /// a string. This should theoretically never happen.
262    async fn resolve_avatar(&self, ens_name: &str) -> Result<Url, Self::Error> {
263        self.inner().resolve_avatar(ens_name).await.map_err(MiddlewareError::from_err)
264    }
265
266    /// Returns the URL (not necesserily HTTP) of the image behind a token.
267    ///
268    /// # Example
269    /// ```no_run
270    /// # use ethers_providers::{Provider, Http, Middleware};
271    /// use ethers_providers::erc::ERCNFT;
272    /// # async fn foo(provider: Provider<Http>) -> Result<(), Box<dyn std::error::Error>> {
273    /// let token = "erc721:0xc92ceddfb8dd984a89fb494c376f9a48b999aafc/9018".parse()?;
274    /// let token_image = provider.resolve_nft(token).await?;
275    /// assert_eq!(
276    ///     token_image.to_string(),
277    ///     "https://creature.mypinata.cloud/ipfs/QmNwj3aUzXfG4twV3no7hJRYxLLAWNPk6RrfQaqJ6nVJFa/9018.jpg"
278    /// );
279    /// # Ok(()) }
280    /// ```
281    ///
282    /// # Panics
283    ///
284    /// If the bytes returned from the ENS registrar/resolver cannot be interpreted as
285    /// a string. This should theoretically never happen.
286    async fn resolve_nft(&self, token: erc::ERCNFT) -> Result<Url, Self::Error> {
287        self.inner().resolve_nft(token).await.map_err(MiddlewareError::from_err)
288    }
289
290    /// Fetch a field for the `ens_name` (no None if not configured).
291    ///
292    /// # Panics
293    ///
294    /// If the bytes returned from the ENS registrar/resolver cannot be interpreted as
295    /// a string. This should theoretically never happen.
296    async fn resolve_field(&self, ens_name: &str, field: &str) -> Result<String, Self::Error> {
297        self.inner().resolve_field(ens_name, field).await.map_err(MiddlewareError::from_err)
298    }
299
300    /// Gets the block at `block_hash_or_number` (transaction hashes only)
301    async fn get_block<T: Into<BlockId> + Send + Sync>(
302        &self,
303        block_hash_or_number: T,
304    ) -> Result<Option<Block<TxHash>>, Self::Error> {
305        self.inner().get_block(block_hash_or_number).await.map_err(MiddlewareError::from_err)
306    }
307
308    /// Gets the block at `block_hash_or_number` (full transactions included)
309    async fn get_block_with_txs<T: Into<BlockId> + Send + Sync>(
310        &self,
311        block_hash_or_number: T,
312    ) -> Result<Option<Block<Transaction>>, Self::Error> {
313        self.inner()
314            .get_block_with_txs(block_hash_or_number)
315            .await
316            .map_err(MiddlewareError::from_err)
317    }
318
319    /// Gets the block uncle count at `block_hash_or_number`
320    async fn get_uncle_count<T: Into<BlockId> + Send + Sync>(
321        &self,
322        block_hash_or_number: T,
323    ) -> Result<U256, Self::Error> {
324        self.inner().get_uncle_count(block_hash_or_number).await.map_err(MiddlewareError::from_err)
325    }
326
327    /// Gets the block uncle at `block_hash_or_number` and `idx`
328    async fn get_uncle<T: Into<BlockId> + Send + Sync>(
329        &self,
330        block_hash_or_number: T,
331        idx: U64,
332    ) -> Result<Option<Block<H256>>, Self::Error> {
333        self.inner().get_uncle(block_hash_or_number, idx).await.map_err(MiddlewareError::from_err)
334    }
335
336    /// Returns the nonce of the address
337    async fn get_transaction_count<T: Into<NameOrAddress> + Send + Sync>(
338        &self,
339        from: T,
340        block: Option<BlockId>,
341    ) -> Result<U256, Self::Error> {
342        self.inner().get_transaction_count(from, block).await.map_err(MiddlewareError::from_err)
343    }
344
345    /// Sends a transaction to a single Ethereum node and return the estimated amount of gas
346    /// required (as a U256) to send it This is free, but only an estimate. Providing too little
347    /// gas will result in a transaction being rejected (while still consuming all provided
348    /// gas).
349    async fn estimate_gas(
350        &self,
351        tx: &TypedTransaction,
352        block: Option<BlockId>,
353    ) -> Result<U256, Self::Error> {
354        self.inner().estimate_gas(tx, block).await.map_err(MiddlewareError::from_err)
355    }
356
357    /// Sends the read-only (constant) transaction to a single Ethereum node and return the result
358    /// (as bytes) of executing it. This is free, since it does not change any state on the
359    /// blockchain.
360    async fn call(
361        &self,
362        tx: &TypedTransaction,
363        block: Option<BlockId>,
364    ) -> Result<Bytes, Self::Error> {
365        self.inner().call(tx, block).await.map_err(MiddlewareError::from_err)
366    }
367
368    /// Return current client syncing status. If IsFalse sync is over.
369    async fn syncing(&self) -> Result<SyncingStatus, Self::Error> {
370        self.inner().syncing().await.map_err(MiddlewareError::from_err)
371    }
372
373    /// Returns the currently configured chain id, a value used in replay-protected
374    /// transaction signing as introduced by EIP-155.
375    async fn get_chainid(&self) -> Result<U256, Self::Error> {
376        self.inner().get_chainid().await.map_err(MiddlewareError::from_err)
377    }
378
379    /// Returns the network version.
380    async fn get_net_version(&self) -> Result<String, Self::Error> {
381        self.inner().get_net_version().await.map_err(MiddlewareError::from_err)
382    }
383
384    /// Returns the account's balance
385    async fn get_balance<T: Into<NameOrAddress> + Send + Sync>(
386        &self,
387        from: T,
388        block: Option<BlockId>,
389    ) -> Result<U256, Self::Error> {
390        self.inner().get_balance(from, block).await.map_err(MiddlewareError::from_err)
391    }
392
393    /// Gets the transaction with `transaction_hash`
394    async fn get_transaction<T: Send + Sync + Into<TxHash>>(
395        &self,
396        transaction_hash: T,
397    ) -> Result<Option<Transaction>, Self::Error> {
398        self.inner().get_transaction(transaction_hash).await.map_err(MiddlewareError::from_err)
399    }
400
401    /// Gets the transaction with block and index
402    async fn get_transaction_by_block_and_index<T: Into<BlockId> + Send + Sync>(
403        &self,
404        block_hash_or_number: T,
405        idx: U64,
406    ) -> Result<Option<Transaction>, Self::Error> {
407        self.inner()
408            .get_transaction_by_block_and_index(block_hash_or_number, idx)
409            .await
410            .map_err(MiddlewareError::from_err)
411    }
412
413    /// Gets the transaction receipt with `transaction_hash`
414    async fn get_transaction_receipt<T: Send + Sync + Into<TxHash>>(
415        &self,
416        transaction_hash: T,
417    ) -> Result<Option<TransactionReceipt>, Self::Error> {
418        self.inner()
419            .get_transaction_receipt(transaction_hash)
420            .await
421            .map_err(MiddlewareError::from_err)
422    }
423
424    /// Returns all receipts for a block.
425    ///
426    /// Note that this uses the `eth_getBlockReceipts` RPC, which is
427    /// non-standard and currently supported by Erigon.
428    async fn get_block_receipts<T: Into<BlockNumber> + Send + Sync>(
429        &self,
430        block: T,
431    ) -> Result<Vec<TransactionReceipt>, Self::Error> {
432        self.inner().get_block_receipts(block).await.map_err(MiddlewareError::from_err)
433    }
434
435    /// Gets the current gas price as estimated by the node
436    async fn get_gas_price(&self) -> Result<U256, Self::Error> {
437        self.inner().get_gas_price().await.map_err(MiddlewareError::from_err)
438    }
439
440    /// Gets a heuristic recommendation of max fee per gas and max priority fee per gas for
441    /// EIP-1559 compatible transactions.
442    async fn estimate_eip1559_fees(
443        &self,
444        estimator: Option<fn(U256, Vec<Vec<U256>>) -> (U256, U256)>,
445    ) -> Result<(U256, U256), Self::Error> {
446        self.inner().estimate_eip1559_fees(estimator).await.map_err(MiddlewareError::from_err)
447    }
448
449    /// Gets the accounts on the node
450    async fn get_accounts(&self) -> Result<Vec<Address>, Self::Error> {
451        self.inner().get_accounts().await.map_err(MiddlewareError::from_err)
452    }
453
454    /// Send the raw RLP encoded transaction to the entire Ethereum network and returns the
455    /// transaction's hash This will consume gas from the account that signed the transaction.
456    async fn send_raw_transaction<'a>(
457        &'a self,
458        tx: Bytes,
459    ) -> Result<PendingTransaction<'a, Self::Provider>, Self::Error> {
460        self.inner().send_raw_transaction(tx).await.map_err(MiddlewareError::from_err)
461    }
462
463    /// This returns true if either the middleware stack contains a `SignerMiddleware`, or the
464    /// JSON-RPC provider has an unlocked key that can sign using the `eth_sign` call. If none of
465    /// the above conditions are met, then the middleware stack is not capable of signing data.
466    async fn is_signer(&self) -> bool {
467        self.inner().is_signer().await
468    }
469
470    /// Signs data using a specific account. This account needs to be unlocked,
471    /// or the middleware stack must contain a `SignerMiddleware`
472    async fn sign<T: Into<Bytes> + Send + Sync>(
473        &self,
474        data: T,
475        from: &Address,
476    ) -> Result<Signature, Self::Error> {
477        self.inner().sign(data, from).await.map_err(MiddlewareError::from_err)
478    }
479
480    /// Sign a transaction via RPC call
481    async fn sign_transaction(
482        &self,
483        tx: &TypedTransaction,
484        from: Address,
485    ) -> Result<Signature, Self::Error> {
486        self.inner().sign_transaction(tx, from).await.map_err(MiddlewareError::from_err)
487    }
488
489    ////// Contract state
490
491    /// Returns an array (possibly empty) of logs that match the filter
492    async fn get_logs(&self, filter: &Filter) -> Result<Vec<Log>, Self::Error> {
493        self.inner().get_logs(filter).await.map_err(MiddlewareError::from_err)
494    }
495
496    /// Returns a stream of logs are loaded in pages of given page size
497    fn get_logs_paginated<'a>(
498        &'a self,
499        filter: &Filter,
500        page_size: u64,
501    ) -> LogQuery<'a, Self::Provider> {
502        self.inner().get_logs_paginated(filter, page_size)
503    }
504
505    /// Install a new filter on the node.
506    ///
507    /// This method is hidden because filter lifecycle  should be managed by
508    /// the [`FilterWatcher`]
509    #[doc(hidden)]
510    async fn new_filter(&self, filter: FilterKind<'_>) -> Result<U256, Self::Error> {
511        self.inner().new_filter(filter).await.map_err(MiddlewareError::from_err)
512    }
513
514    /// Uninstalls a filter.
515    ///
516    /// This method is hidden because filter lifecycle  should be managed by
517    /// the [`FilterWatcher`]
518    #[doc(hidden)]
519    async fn uninstall_filter<T: Into<U256> + Send + Sync>(
520        &self,
521        id: T,
522    ) -> Result<bool, Self::Error> {
523        self.inner().uninstall_filter(id).await.map_err(MiddlewareError::from_err)
524    }
525
526    /// Streams event logs matching the filter.
527    ///
528    /// This function streams via a polling system, by repeatedly dispatching
529    /// RPC requests. If possible, prefer using a WS or IPC connection and the
530    /// `stream` interface
531    async fn watch<'a>(
532        &'a self,
533        filter: &Filter,
534    ) -> Result<FilterWatcher<'a, Self::Provider, Log>, Self::Error> {
535        self.inner().watch(filter).await.map_err(MiddlewareError::from_err)
536    }
537
538    /// Streams pending transactions.
539    ///
540    /// This function streams via a polling system, by repeatedly dispatching
541    /// RPC requests. If possible, prefer using a WS or IPC connection and the
542    /// `stream` interface
543    async fn watch_pending_transactions(
544        &self,
545    ) -> Result<FilterWatcher<'_, Self::Provider, H256>, Self::Error> {
546        self.inner().watch_pending_transactions().await.map_err(MiddlewareError::from_err)
547    }
548
549    /// Polling method for a filter, which returns an array of logs which occurred since last poll.
550    ///
551    /// This method must be called with one of the following return types, depending on the filter
552    /// type:
553    /// - `eth_newBlockFilter`: [`H256`], returns block hashes
554    /// - `eth_newPendingTransactionFilter`: [`H256`], returns transaction hashes
555    /// - `eth_newFilter`: [`Log`], returns raw logs
556    ///
557    /// If one of these types is not used, decoding will fail and the method will
558    /// return an error.
559    ///
560    /// [`H256`]: ethers_core::types::H256
561    /// [`Log`]: ethers_core::types::Log
562    ///
563    /// This method is hidden because filter lifecycle  should be managed by
564    /// the [`FilterWatcher`]
565    #[doc(hidden)]
566    async fn get_filter_changes<T, R>(&self, id: T) -> Result<Vec<R>, Self::Error>
567    where
568        T: Into<U256> + Send + Sync,
569        R: Serialize + DeserializeOwned + Send + Sync + Debug,
570    {
571        self.inner().get_filter_changes(id).await.map_err(MiddlewareError::from_err)
572    }
573
574    /// Streams new block hashes
575    ///
576    /// This function streams via a polling system, by repeatedly dispatching
577    /// RPC requests. If possible, prefer using a WS or IPC connection and the
578    /// `stream` interface
579    async fn watch_blocks(&self) -> Result<FilterWatcher<'_, Self::Provider, H256>, Self::Error> {
580        self.inner().watch_blocks().await.map_err(MiddlewareError::from_err)
581    }
582
583    /// Returns the deployed code at a given address
584    async fn get_code<T: Into<NameOrAddress> + Send + Sync>(
585        &self,
586        at: T,
587        block: Option<BlockId>,
588    ) -> Result<Bytes, Self::Error> {
589        self.inner().get_code(at, block).await.map_err(MiddlewareError::from_err)
590    }
591
592    /// Get the storage of an address for a particular slot location
593    async fn get_storage_at<T: Into<NameOrAddress> + Send + Sync>(
594        &self,
595        from: T,
596        location: H256,
597        block: Option<BlockId>,
598    ) -> Result<H256, Self::Error> {
599        self.inner().get_storage_at(from, location, block).await.map_err(MiddlewareError::from_err)
600    }
601
602    /// Returns the EIP-1186 proof response
603    /// <https://github.com/ethereum/EIPs/issues/1186>
604    async fn get_proof<T: Into<NameOrAddress> + Send + Sync>(
605        &self,
606        from: T,
607        locations: Vec<H256>,
608        block: Option<BlockId>,
609    ) -> Result<EIP1186ProofResponse, Self::Error> {
610        self.inner().get_proof(from, locations, block).await.map_err(MiddlewareError::from_err)
611    }
612
613    /// Returns an indication if this node is currently mining.
614    async fn mining(&self) -> Result<bool, Self::Error> {
615        self.inner().mining().await.map_err(MiddlewareError::from_err)
616    }
617
618    // Personal namespace
619    // NOTE: This will eventually need to be enabled by users explicitly because the personal
620    // namespace is being deprecated:
621    // Issue: https://github.com/ethereum/go-ethereum/issues/25948
622    // PR: https://github.com/ethereum/go-ethereum/pull/26390
623
624    /// Sends the given key to the node to be encrypted with the provided
625    /// passphrase and stored.
626    ///
627    /// The key represents a secp256k1 private key and should be 32 bytes.
628    async fn import_raw_key(
629        &self,
630        private_key: Bytes,
631        passphrase: String,
632    ) -> Result<Address, Self::Error> {
633        self.inner()
634            .import_raw_key(private_key, passphrase)
635            .await
636            .map_err(MiddlewareError::from_err)
637    }
638
639    /// Prompts the node to decrypt the given account from its keystore.
640    ///
641    /// If the duration provided is `None`, then the account will be unlocked
642    /// indefinitely. Otherwise, the account will be unlocked for the provided
643    /// number of seconds.
644    async fn unlock_account<T: Into<Address> + Send + Sync>(
645        &self,
646        account: T,
647        passphrase: String,
648        duration: Option<u64>,
649    ) -> Result<bool, Self::Error> {
650        self.inner()
651            .unlock_account(account, passphrase, duration)
652            .await
653            .map_err(MiddlewareError::from_err)
654    }
655
656    // Admin namespace
657
658    /// Requests adding the given peer, returning a boolean representing
659    /// whether or not the peer was accepted for tracking.
660    async fn add_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
661        self.inner().add_peer(enode_url).await.map_err(MiddlewareError::from_err)
662    }
663
664    /// Requests adding the given peer as a trusted peer, which the node will
665    /// always connect to even when its peer slots are full.
666    async fn add_trusted_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
667        self.inner().add_trusted_peer(enode_url).await.map_err(MiddlewareError::from_err)
668    }
669
670    /// Returns general information about the node as well as information about the running p2p
671    /// protocols (e.g. `eth`, `snap`).
672    async fn node_info(&self) -> Result<NodeInfo, Self::Error> {
673        self.inner().node_info().await.map_err(MiddlewareError::from_err)
674    }
675
676    /// Returns the list of peers currently connected to the node.
677    async fn peers(&self) -> Result<Vec<PeerInfo>, Self::Error> {
678        self.inner().peers().await.map_err(MiddlewareError::from_err)
679    }
680
681    /// Requests to remove the given peer, returning true if the enode was successfully parsed and
682    /// the peer was removed.
683    async fn remove_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
684        self.inner().remove_peer(enode_url).await.map_err(MiddlewareError::from_err)
685    }
686
687    /// Requests to remove the given peer, returning a boolean representing whether or not the
688    /// enode url passed was validated. A return value of `true` does not necessarily mean that the
689    /// peer was disconnected.
690    async fn remove_trusted_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
691        self.inner().remove_trusted_peer(enode_url).await.map_err(MiddlewareError::from_err)
692    }
693
694    // Miner namespace
695
696    /// Starts the miner.
697    async fn start_mining(&self) -> Result<(), Self::Error> {
698        self.inner().start_mining().await.map_err(MiddlewareError::from_err)
699    }
700
701    /// Stop terminates the miner, both at the consensus engine level as well as at
702    /// the block creation level.
703    async fn stop_mining(&self) -> Result<(), Self::Error> {
704        self.inner().stop_mining().await.map_err(MiddlewareError::from_err)
705    }
706
707    // Mempool inspection for Geth's API
708
709    /// Returns the details of all transactions currently pending for inclusion in the next
710    /// block(s), as well as the ones that are being scheduled for future execution only.
711    /// Ref: [Here](https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_content)
712    async fn txpool_content(&self) -> Result<TxpoolContent, Self::Error> {
713        self.inner().txpool_content().await.map_err(MiddlewareError::from_err)
714    }
715
716    /// Returns a summary of all the transactions currently pending for inclusion in the next
717    /// block(s), as well as the ones that are being scheduled for future execution only.
718    /// Ref: [Here](https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_inspect)
719    async fn txpool_inspect(&self) -> Result<TxpoolInspect, Self::Error> {
720        self.inner().txpool_inspect().await.map_err(MiddlewareError::from_err)
721    }
722
723    /// Returns the number of transactions currently pending for inclusion in the next block(s), as
724    /// well as the ones that are being scheduled for future execution only.
725    /// Ref: [Here](https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_status)
726    async fn txpool_status(&self) -> Result<TxpoolStatus, Self::Error> {
727        self.inner().txpool_status().await.map_err(MiddlewareError::from_err)
728    }
729
730    // Geth `trace` support
731
732    /// After replaying any previous transactions in the same block,
733    /// Replays a transaction, returning the traces configured with passed options
734    async fn debug_trace_transaction(
735        &self,
736        tx_hash: TxHash,
737        trace_options: GethDebugTracingOptions,
738    ) -> Result<GethTrace, Self::Error> {
739        self.inner()
740            .debug_trace_transaction(tx_hash, trace_options)
741            .await
742            .map_err(MiddlewareError::from_err)
743    }
744
745    /// Executes the given call and returns a number of possible traces for it
746    async fn debug_trace_call<T: Into<TypedTransaction> + Send + Sync>(
747        &self,
748        req: T,
749        block: Option<BlockId>,
750        trace_options: GethDebugTracingCallOptions,
751    ) -> Result<GethTrace, Self::Error> {
752        self.inner()
753            .debug_trace_call(req, block, trace_options)
754            .await
755            .map_err(MiddlewareError::from_err)
756    }
757
758    /// Replays all transactions in a given block (specified by block number) and returns the traces
759    /// configured with passed options
760    /// Ref:
761    /// [Here](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debugtraceblockbynumber)
762    async fn debug_trace_block_by_number(
763        &self,
764        block: Option<BlockNumber>,
765        trace_options: GethDebugTracingOptions,
766    ) -> Result<Vec<GethTrace>, Self::Error> {
767        self.inner()
768            .debug_trace_block_by_number(block, trace_options)
769            .await
770            .map_err(MiddlewareError::from_err)
771    }
772
773    /// Replays all transactions in a given block (specified by block hash) and returns the traces
774    /// configured with passed options
775    /// Ref:
776    /// [Here](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debugtraceblockbyhash)
777    async fn debug_trace_block_by_hash(
778        &self,
779        block: H256,
780        trace_options: GethDebugTracingOptions,
781    ) -> Result<Vec<GethTrace>, Self::Error> {
782        self.inner()
783            .debug_trace_block_by_hash(block, trace_options)
784            .await
785            .map_err(MiddlewareError::from_err)
786    }
787
788    // Parity `trace` support
789
790    /// Executes the given call and returns a number of possible traces for it
791    async fn trace_call<T: Into<TypedTransaction> + Send + Sync>(
792        &self,
793        req: T,
794        trace_type: Vec<TraceType>,
795        block: Option<BlockNumber>,
796    ) -> Result<BlockTrace, Self::Error> {
797        self.inner().trace_call(req, trace_type, block).await.map_err(MiddlewareError::from_err)
798    }
799
800    /// Executes given calls and returns a number of possible traces for each
801    /// call
802    async fn trace_call_many<T: Into<TypedTransaction> + Send + Sync>(
803        &self,
804        req: Vec<(T, Vec<TraceType>)>,
805        block: Option<BlockNumber>,
806    ) -> Result<Vec<BlockTrace>, Self::Error> {
807        self.inner().trace_call_many(req, block).await.map_err(MiddlewareError::from_err)
808    }
809
810    /// Traces a call to `eth_sendRawTransaction` without making the call, returning the traces
811    async fn trace_raw_transaction(
812        &self,
813        data: Bytes,
814        trace_type: Vec<TraceType>,
815    ) -> Result<BlockTrace, Self::Error> {
816        self.inner()
817            .trace_raw_transaction(data, trace_type)
818            .await
819            .map_err(MiddlewareError::from_err)
820    }
821
822    /// Replays a transaction, returning the traces
823    async fn trace_replay_transaction(
824        &self,
825        hash: H256,
826        trace_type: Vec<TraceType>,
827    ) -> Result<BlockTrace, Self::Error> {
828        self.inner()
829            .trace_replay_transaction(hash, trace_type)
830            .await
831            .map_err(MiddlewareError::from_err)
832    }
833
834    /// Replays all transactions in a block returning the requested traces for each transaction
835    async fn trace_replay_block_transactions(
836        &self,
837        block: BlockNumber,
838        trace_type: Vec<TraceType>,
839    ) -> Result<Vec<BlockTrace>, Self::Error> {
840        self.inner()
841            .trace_replay_block_transactions(block, trace_type)
842            .await
843            .map_err(MiddlewareError::from_err)
844    }
845
846    /// Returns traces created at given block
847    async fn trace_block(&self, block: BlockNumber) -> Result<Vec<Trace>, Self::Error> {
848        self.inner().trace_block(block).await.map_err(MiddlewareError::from_err)
849    }
850
851    /// Return traces matching the given filter
852    async fn trace_filter(&self, filter: TraceFilter) -> Result<Vec<Trace>, Self::Error> {
853        self.inner().trace_filter(filter).await.map_err(MiddlewareError::from_err)
854    }
855
856    /// Returns trace at the given position
857    async fn trace_get<T: Into<U64> + Send + Sync>(
858        &self,
859        hash: H256,
860        index: Vec<T>,
861    ) -> Result<Trace, Self::Error> {
862        self.inner().trace_get(hash, index).await.map_err(MiddlewareError::from_err)
863    }
864
865    /// Returns all traces of a given transaction
866    async fn trace_transaction(&self, hash: H256) -> Result<Vec<Trace>, Self::Error> {
867        self.inner().trace_transaction(hash).await.map_err(MiddlewareError::from_err)
868    }
869
870    // Parity namespace
871
872    /// Returns all receipts for that block. Must be done on a parity node.
873    async fn parity_block_receipts<T: Into<BlockNumber> + Send + Sync>(
874        &self,
875        block: T,
876    ) -> Result<Vec<TransactionReceipt>, Self::Error> {
877        self.inner().parity_block_receipts(block).await.map_err(MiddlewareError::from_err)
878    }
879
880    /// Create a new subscription
881    ///
882    /// This method is hidden as subscription lifecycles are intended to be
883    /// handled by a [`SubscriptionStream`] object.
884    #[doc(hidden)]
885    async fn subscribe<T, R>(
886        &self,
887        params: T,
888    ) -> Result<SubscriptionStream<'_, Self::Provider, R>, Self::Error>
889    where
890        T: Debug + Serialize + Send + Sync,
891        R: DeserializeOwned + Send + Sync,
892        <Self as Middleware>::Provider: PubsubClient,
893    {
894        self.inner().subscribe(params).await.map_err(MiddlewareError::from_err)
895    }
896
897    /// Instruct the RPC to cancel a subscription by its ID
898    ///
899    /// This method is hidden as subscription lifecycles are intended to be
900    /// handled by a [`SubscriptionStream`] object
901    #[doc(hidden)]
902    async fn unsubscribe<T>(&self, id: T) -> Result<bool, Self::Error>
903    where
904        T: Into<U256> + Send + Sync,
905        <Self as Middleware>::Provider: PubsubClient,
906    {
907        self.inner().unsubscribe(id).await.map_err(MiddlewareError::from_err)
908    }
909
910    /// Subscribe to a stream of incoming blocks.
911    ///
912    /// This function is only available on pubsub clients, such as Websockets
913    /// or IPC. For a polling alternative available over HTTP, use
914    /// [`Middleware::watch_blocks`]. However, be aware that polling increases
915    /// RPC usage drastically.
916    async fn subscribe_blocks(
917        &self,
918    ) -> Result<SubscriptionStream<'_, Self::Provider, Block<TxHash>>, Self::Error>
919    where
920        <Self as Middleware>::Provider: PubsubClient,
921    {
922        self.inner().subscribe_blocks().await.map_err(MiddlewareError::from_err)
923    }
924
925    /// Subscribe to a stream of pending transaction hashes.
926    ///
927    /// This function is only available on pubsub clients, such as Websockets
928    /// or IPC. For a polling alternative available over HTTP, use
929    /// [`Middleware::watch_pending_transactions`]. However, be aware that
930    /// polling increases RPC usage drastically.
931    async fn subscribe_pending_txs(
932        &self,
933    ) -> Result<SubscriptionStream<'_, Self::Provider, TxHash>, Self::Error>
934    where
935        <Self as Middleware>::Provider: PubsubClient,
936    {
937        self.inner().subscribe_pending_txs().await.map_err(MiddlewareError::from_err)
938    }
939
940    /// Subscribe to a stream of pending transaction bodies.
941    ///
942    /// This function is only available on pubsub clients, such as Websockets
943    /// or IPC. For a polling alternative available over HTTP, use
944    /// [`Middleware::watch_pending_transactions`]. However, be aware that
945    /// polling increases RPC usage drastically.
946    ///
947    /// Note: This endpoint is compatible only with Geth client version 1.11.0 or later.
948    async fn subscribe_full_pending_txs(
949        &self,
950    ) -> Result<SubscriptionStream<'_, Self::Provider, Transaction>, Self::Error>
951    where
952        <Self as Middleware>::Provider: PubsubClient,
953    {
954        self.inner().subscribe_full_pending_txs().await.map_err(MiddlewareError::from_err)
955    }
956
957    /// Subscribe to a stream of event logs matchin the provided [`Filter`].
958    ///
959    /// This function is only available on pubsub clients, such as Websockets
960    /// or IPC. For a polling alternative available over HTTP, use
961    /// [`Middleware::watch`]. However, be aware that polling increases
962    /// RPC usage drastically.
963    async fn subscribe_logs<'a>(
964        &'a self,
965        filter: &Filter,
966    ) -> Result<SubscriptionStream<'a, Self::Provider, Log>, Self::Error>
967    where
968        <Self as Middleware>::Provider: PubsubClient,
969    {
970        self.inner().subscribe_logs(filter).await.map_err(MiddlewareError::from_err)
971    }
972
973    /// Query the node for a [`FeeHistory`] object. This objct contains
974    /// information about the EIP-1559 base fee in past blocks, as well as gas
975    /// utilization within those blocks.
976    ///
977    /// See the
978    /// [EIP-1559 documentation](https://eips.ethereum.org/EIPS/eip-1559) for
979    /// details
980    async fn fee_history<T: Into<U256> + serde::Serialize + Send + Sync>(
981        &self,
982        block_count: T,
983        last_block: BlockNumber,
984        reward_percentiles: &[f64],
985    ) -> Result<FeeHistory, Self::Error> {
986        self.inner()
987            .fee_history(block_count, last_block, reward_percentiles)
988            .await
989            .map_err(MiddlewareError::from_err)
990    }
991
992    /// Query the node for an EIP-2930 Access List.
993    ///
994    /// See the
995    /// [EIP-2930 documentation](https://eips.ethereum.org/EIPS/eip-2930) for
996    /// details
997    async fn create_access_list(
998        &self,
999        tx: &TypedTransaction,
1000        block: Option<BlockId>,
1001    ) -> Result<AccessListWithGasUsed, Self::Error> {
1002        self.inner().create_access_list(tx, block).await.map_err(MiddlewareError::from_err)
1003    }
1004}
1005
1006#[cfg(feature = "celo")]
1007#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
1008#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
1009/// Celo-specific extension trait
1010pub trait CeloMiddleware: Middleware {
1011    /// Get validator BLS public keys
1012    async fn get_validators_bls_public_keys<T: Into<BlockId> + Send + Sync>(
1013        &self,
1014        block_id: T,
1015    ) -> Result<Vec<String>, ProviderError> {
1016        self.provider()
1017            .get_validators_bls_public_keys(block_id)
1018            .await
1019            .map_err(MiddlewareError::from_err)
1020    }
1021}
1022
1023#[cfg(feature = "celo")]
1024#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
1025#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
1026impl<T> CeloMiddleware for T where T: Middleware {}