Skip to main content

alloy_provider/provider/
trait.rs

1//! Ethereum JSON-RPC provider.
2
3#![allow(unknown_lints, mismatched_lifetime_syntaxes)]
4
5#[cfg(feature = "pubsub")]
6use super::get_block::SubFullBlocks;
7use super::{DynProvider, Empty, EthCallMany, MulticallBuilder, WatchBlocks, WatchHeaders};
8#[cfg(feature = "pubsub")]
9use crate::GetSubscription;
10use crate::{
11    heart::PendingTransactionError,
12    utils::{self, Eip1559Estimation, Eip1559Estimator},
13    EthCall, EthGetBlock, Identity, PendingTransaction, PendingTransactionBuilder,
14    PendingTransactionConfig, ProviderBuilder, ProviderCall, RootProvider, RpcWithBlock,
15    SendableTx,
16};
17use alloy_consensus::BlockHeader;
18use alloy_eips::{eip2718::Encodable2718, eip7928::BlockAccessList};
19use alloy_json_rpc::{RpcError, RpcRecv, RpcSend};
20use alloy_network::{Ethereum, Network};
21use alloy_network_primitives::{BlockResponse, ReceiptResponse};
22use alloy_primitives::{
23    hex, Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, TxHash, B256, U128,
24    U256, U64,
25};
26use alloy_rpc_client::{ClientRef, NoParams, PollerBuilder, WeakClient};
27#[cfg(feature = "pubsub")]
28use alloy_rpc_types_eth::pubsub::{Params, SubscriptionKind};
29use alloy_rpc_types_eth::{
30    erc4337::TransactionConditional,
31    simulate::{SimulatePayload, SimulatedBlock},
32    AccessListResult, BlockId, BlockNumberOrTag, Bundle, EIP1186AccountProofResponse,
33    EthCallResponse, FeeHistory, FillTransaction, Filter, FilterChanges, Index, Log,
34    StorageValuesRequest, StorageValuesResponse, SyncStatus,
35};
36use alloy_transport::TransportResult;
37use serde_json::value::RawValue;
38use std::borrow::Cow;
39
40/// A task that polls the provider with `eth_getFilterChanges`, returning a list of `R`.
41///
42/// See [`PollerBuilder`] for more details.
43pub type FilterPollerBuilder<R> = PollerBuilder<(U256,), Vec<R>>;
44
45/// Ethereum JSON-RPC interface.
46///
47/// # Subscriptions
48///
49/// The provider supports `pubsub` subscriptions to new block headers and
50/// pending transactions. This is only available on `pubsub` clients, such as
51/// Websockets or IPC.
52///
53/// For a polling alternatives available over HTTP, use the `watch_*` methods.
54/// However, be aware that polling increases RPC usage drastically.
55///
56/// ## Special treatment of EIP-1559
57///
58/// While many RPC features are encapsulated by extension traits,
59/// [EIP-1559] fee estimation is generally assumed to be on by default. We
60/// generally assume that [EIP-1559] is supported by the client and will
61/// proactively use it by default.
62///
63/// As a result, the provider supports [EIP-1559] fee estimation the ethereum
64/// [`TransactionBuilder`] will use it by default. We acknowledge that this
65/// means [EIP-1559] has a privileged status in comparison to other transaction
66/// types. Networks that DO NOT support [EIP-1559] should create their own
67/// [`TransactionBuilder`] and Fillers to change this behavior.
68///
69/// [`TransactionBuilder`]: alloy_network::TransactionBuilder
70/// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559
71#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
72#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
73#[auto_impl::auto_impl(&, &mut, Rc, Arc, Box)]
74pub trait Provider<N: Network = Ethereum>: Send + Sync {
75    /// Returns the root provider.
76    fn root(&self) -> &RootProvider<N>;
77
78    /// Returns the [`ProviderBuilder`] to build on.
79    fn builder() -> ProviderBuilder<Identity, Identity, N>
80    where
81        Self: Sized,
82    {
83        ProviderBuilder::default()
84    }
85
86    /// Returns the RPC client used to send requests.
87    ///
88    /// NOTE: this method should not be overridden.
89    #[inline]
90    fn client(&self) -> ClientRef<'_> {
91        self.root().client()
92    }
93
94    /// Returns a [`Weak`](std::sync::Weak) RPC client used to send requests.
95    ///
96    /// NOTE: this method should not be overridden.
97    #[inline]
98    fn weak_client(&self) -> WeakClient {
99        self.root().weak_client()
100    }
101
102    /// Returns a type erased provider wrapped in Arc. See [`DynProvider`].
103    ///
104    /// ```no_run
105    /// use alloy_provider::{DynProvider, Provider, ProviderBuilder};
106    ///
107    /// # async fn f() -> Result<(), Box<dyn std::error::Error>> {
108    /// let provider: DynProvider =
109    ///     ProviderBuilder::new().connect("http://localhost:8080").await?.erased();
110    /// let block = provider.get_block_number().await?;
111    /// # Ok(())
112    /// # }
113    /// ```
114    #[auto_impl(keep_default_for(&, &mut, Rc, Arc, Box))]
115    #[doc(alias = "boxed")]
116    fn erased(self) -> DynProvider<N>
117    where
118        Self: Sized + 'static,
119    {
120        DynProvider::new(self)
121    }
122
123    /// Gets the accounts in the remote node. This is usually empty unless you're using a local
124    /// node.
125    fn get_accounts(&self) -> ProviderCall<NoParams, Vec<Address>> {
126        self.client().request_noparams("eth_accounts").into()
127    }
128
129    /// Returns the base fee per blob gas (blob gas price) in wei.
130    fn get_blob_base_fee(&self) -> ProviderCall<NoParams, U128, u128> {
131        self.client()
132            .request_noparams("eth_blobBaseFee")
133            .map_resp(utils::convert_u128 as fn(U128) -> u128)
134            .into()
135    }
136
137    /// Get the last block number available.
138    fn get_block_number(&self) -> ProviderCall<NoParams, U64, BlockNumber> {
139        self.client()
140            .request_noparams("eth_blockNumber")
141            .map_resp(utils::convert_u64 as fn(U64) -> u64)
142            .into()
143    }
144
145    /// Get the block number for a given block identifier.
146    ///
147    /// This is a convenience function that fetches the block header when the block identifier is
148    /// not a number. Falls back to fetching the full block if header RPC is not supported.
149    async fn get_block_number_by_id(
150        &self,
151        block_id: BlockId,
152    ) -> TransportResult<Option<BlockNumber>> {
153        match block_id {
154            BlockId::Number(BlockNumberOrTag::Number(num)) => Ok(Some(num)),
155            BlockId::Number(BlockNumberOrTag::Latest) => self.get_block_number().await.map(Some),
156            _ => Ok(self.get_header(block_id).await?.map(|h| h.number())),
157        }
158    }
159
160    /// Execute a smart contract call with a transaction request and state
161    /// overrides, without publishing a transaction.
162    ///
163    /// This function returns [`EthCall`] which can be used to execute the
164    /// call, or to add a [`StateOverride`] or a [`BlockId`]. If no overrides
165    /// or block ID is provided, the call will be executed on the pending block
166    /// with the current state.
167    ///
168    /// [`StateOverride`]: alloy_rpc_types_eth::state::StateOverride
169    ///
170    /// # Examples
171    ///
172    /// ```no_run
173    /// # use alloy_provider::Provider;
174    /// # use alloy_eips::BlockId;
175    /// # use alloy_rpc_types_eth::state::StateOverride;
176    /// # use alloy_transport::BoxTransport;
177    /// # async fn example<P: Provider>(
178    /// #    provider: P,
179    /// #    my_overrides: StateOverride
180    /// # ) -> Result<(), Box<dyn std::error::Error>> {
181    /// # let tx = alloy_rpc_types_eth::transaction::TransactionRequest::default();
182    /// // Execute a call on the latest block, with no state overrides
183    /// let output = provider.call(tx).await?;
184    /// # Ok(())
185    /// # }
186    /// ```
187    #[doc(alias = "eth_call")]
188    #[doc(alias = "call_with_overrides")]
189    fn call(&self, tx: N::TransactionRequest) -> EthCall<N, Bytes> {
190        EthCall::call(self.weak_client(), tx).block(BlockNumberOrTag::Pending.into())
191    }
192
193    /// Execute a list of [`Bundle`]s against the provided [`StateContext`] and [`StateOverride`],
194    /// without publishing a transaction.
195    ///
196    /// This function returns an [`EthCallMany`] builder which is used to execute the call, and also
197    /// set the [`StateContext`] and [`StateOverride`].
198    ///
199    /// [`StateContext`]: alloy_rpc_types_eth::StateContext
200    /// [`StateOverride`]: alloy_rpc_types_eth::state::StateOverride
201    #[doc(alias = "eth_callMany")]
202    fn call_many<'req>(
203        &self,
204        bundles: &'req [Bundle],
205    ) -> EthCallMany<'req, N, Vec<Vec<EthCallResponse>>> {
206        EthCallMany::new(self.weak_client(), bundles)
207    }
208
209    /// Execute a multicall by leveraging the [`MulticallBuilder`].
210    ///
211    /// Call [`MulticallBuilder::dynamic`] to add calls dynamically instead.
212    ///
213    /// See the [`MulticallBuilder`] documentation for more details.
214    #[auto_impl(keep_default_for(&, &mut, Rc, Arc, Box))]
215    fn multicall(&self) -> MulticallBuilder<Empty, &Self, N>
216    where
217        Self: Sized,
218    {
219        MulticallBuilder::new(self)
220    }
221
222    /// Executes an arbitrary number of transactions on top of the requested state.
223    ///
224    /// The transactions are packed into individual blocks. Overrides can be provided.
225    #[doc(alias = "eth_simulateV1")]
226    fn simulate<'req>(
227        &self,
228        payload: &'req SimulatePayload,
229    ) -> RpcWithBlock<&'req SimulatePayload, Vec<SimulatedBlock<N::BlockResponse>>> {
230        self.client().request("eth_simulateV1", payload).into()
231    }
232
233    /// Gets the chain ID.
234    fn get_chain_id(&self) -> ProviderCall<NoParams, U64, u64> {
235        self.client()
236            .request_noparams("eth_chainId")
237            .map_resp(utils::convert_u64 as fn(U64) -> u64)
238            .into()
239    }
240
241    /// Create an [EIP-2930] access list.
242    ///
243    /// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930
244    fn create_access_list<'a>(
245        &self,
246        request: &'a N::TransactionRequest,
247    ) -> RpcWithBlock<&'a N::TransactionRequest, AccessListResult> {
248        self.client().request("eth_createAccessList", request).into()
249    }
250
251    /// Create an [`EthCall`] future to estimate the gas required for a
252    /// transaction.
253    ///
254    /// The future can be used to specify a [`StateOverride`] or [`BlockId`]
255    /// before dispatching the call. If no overrides or block ID is provided,
256    /// the gas estimate will be computed for the pending block with the
257    /// current state.
258    ///
259    /// [`StateOverride`]: alloy_rpc_types_eth::state::StateOverride
260    ///
261    /// # Note
262    ///
263    /// Not all client implementations support state overrides for `eth_estimateGas`.
264    fn estimate_gas(&self, tx: N::TransactionRequest) -> EthCall<N, U64, u64> {
265        EthCall::gas_estimate(self.weak_client(), tx)
266            .block(BlockNumberOrTag::Pending.into())
267            .map_resp(utils::convert_u64)
268    }
269
270    /// Estimates the [EIP-1559] `maxFeePerGas` and `maxPriorityFeePerGas` fields.
271    ///
272    /// Receives an [`Eip1559Estimator`] that can be used to modify
273    /// how to estimate these fees.
274    ///
275    /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559
276    async fn estimate_eip1559_fees_with(
277        &self,
278        estimator: Eip1559Estimator,
279    ) -> TransportResult<Eip1559Estimation> {
280        let fee_history = self
281            .get_fee_history(
282                utils::EIP1559_FEE_ESTIMATION_PAST_BLOCKS,
283                BlockNumberOrTag::Latest,
284                &[utils::EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE],
285            )
286            .await?;
287
288        // if the base fee of the Latest block is 0 then we need check if the latest block even has
289        // a base fee/supports EIP1559
290        let base_fee_per_gas = match fee_history.latest_block_base_fee() {
291            Some(base_fee) if base_fee != 0 => base_fee,
292            _ => {
293                // empty response, fetch basefee from latest block directly
294                self.get_block_by_number(BlockNumberOrTag::Latest)
295                    .await?
296                    .ok_or(RpcError::NullResp)?
297                    .header()
298                    .as_ref()
299                    .base_fee_per_gas()
300                    .ok_or(RpcError::UnsupportedFeature("eip1559"))?
301                    .into()
302            }
303        };
304
305        Ok(estimator.estimate(base_fee_per_gas, &fee_history.reward.unwrap_or_default()))
306    }
307
308    /// Estimates the [EIP-1559] `maxFeePerGas` and `maxPriorityFeePerGas` fields.
309    ///
310    /// Uses the builtin estimator [`utils::eip1559_default_estimator`] function.
311    ///
312    /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559
313    async fn estimate_eip1559_fees(&self) -> TransportResult<Eip1559Estimation> {
314        self.estimate_eip1559_fees_with(Eip1559Estimator::default()).await
315    }
316
317    /// Returns a collection of historical gas information [`FeeHistory`] which
318    /// can be used to calculate the [EIP-1559] fields `maxFeePerGas` and `maxPriorityFeePerGas`.
319    /// `block_count` can range from 1 to 1024 blocks in a single request.
320    ///
321    /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559
322    async fn get_fee_history(
323        &self,
324        block_count: u64,
325        last_block: BlockNumberOrTag,
326        reward_percentiles: &[f64],
327    ) -> TransportResult<FeeHistory> {
328        self.client()
329            .request("eth_feeHistory", (U64::from(block_count), last_block, reward_percentiles))
330            .await
331    }
332
333    /// Gets the current gas price in wei.
334    fn get_gas_price(&self) -> ProviderCall<NoParams, U128, u128> {
335        self.client()
336            .request_noparams("eth_gasPrice")
337            .map_resp(utils::convert_u128 as fn(U128) -> u128)
338            .into()
339    }
340
341    /// Retrieves account information ([`Account`](alloy_rpc_types_eth::Account)) for the given
342    /// [`Address`] at the particular [`BlockId`].
343    ///
344    /// Note: This is slightly different than `eth_getAccount` and not all clients support this
345    /// endpoint.
346    fn get_account_info(
347        &self,
348        address: Address,
349    ) -> RpcWithBlock<Address, alloy_rpc_types_eth::AccountInfo> {
350        self.client().request("eth_getAccountInfo", address).into()
351    }
352
353    /// Retrieves account information ([`TrieAccount`](alloy_consensus::TrieAccount)) for the given
354    /// [`Address`] at the particular [`BlockId`].
355    fn get_account(&self, address: Address) -> RpcWithBlock<Address, alloy_consensus::TrieAccount> {
356        self.client().request("eth_getAccount", address).into()
357    }
358
359    /// Gets the balance of the account.
360    ///
361    /// Defaults to the latest block. See also [`RpcWithBlock::block_id`].
362    fn get_balance(&self, address: Address) -> RpcWithBlock<Address, U256, U256> {
363        self.client().request("eth_getBalance", address).into()
364    }
365
366    /// Gets a block by either its hash, tag, or number
367    ///
368    /// By default this fetches the block with only the transaction hashes, and not full
369    /// transactions.
370    ///
371    /// To get full transactions one can do:
372    ///
373    /// ```ignore
374    /// let block = provider.get_block(BlockId::latest()).full().await.unwrap();
375    /// ```
376    fn get_block(&self, block: BlockId) -> EthGetBlock<N::BlockResponse> {
377        match block {
378            BlockId::Hash(hash) => EthGetBlock::by_hash(hash.block_hash, self.client()),
379            BlockId::Number(number) => EthGetBlock::by_number(number, self.client()),
380        }
381    }
382
383    /// Gets a block by its [`BlockHash`]
384    ///
385    /// By default this fetches the block with only the transaction hashes populated in the block,
386    /// and not the full transactions.
387    ///
388    /// # Examples
389    ///
390    /// ```no_run
391    /// # use alloy_provider::{Provider, ProviderBuilder};
392    /// # use alloy_primitives::b256;
393    ///
394    /// #[tokio::main]
395    /// async fn main() {
396    ///     let provider =
397    ///         ProviderBuilder::new().connect_http("https://eth.merkle.io".parse().unwrap());
398    ///     let block_hash = b256!("6032d03ee8e43e8999c2943152a4daebfc4b75b7f7a9647d2677299d215127da");
399    ///
400    ///     // Gets a block by its hash with only transactions hashes.
401    ///     let block = provider.get_block_by_hash(block_hash).await.unwrap();
402    ///
403    ///     // Gets a block by its hash with full transactions.
404    ///     let block = provider.get_block_by_hash(block_hash).full().await.unwrap();
405    /// }
406    /// ```
407    fn get_block_by_hash(&self, hash: BlockHash) -> EthGetBlock<N::BlockResponse> {
408        EthGetBlock::by_hash(hash, self.client())
409    }
410
411    /// Gets a block by its [`BlockNumberOrTag`]
412    ///
413    /// By default this fetches the block with only the transaction hashes populated in the block,
414    /// and not the full transactions.
415    ///
416    /// # Examples
417    ///
418    /// ```no_run
419    /// # use alloy_provider::{Provider, ProviderBuilder};
420    /// # use alloy_eips::BlockNumberOrTag;
421    ///
422    /// #[tokio::main]
423    /// async fn main() {
424    ///     let provider =
425    ///         ProviderBuilder::new().connect_http("https://eth.merkle.io".parse().unwrap());
426    ///     let num = BlockNumberOrTag::Number(0);
427    ///
428    ///     // Gets a block by its number with only transactions hashes.
429    ///     let block = provider.get_block_by_number(num).await.unwrap();
430    ///
431    ///     // Gets a block by its number with full transactions.
432    ///     let block = provider.get_block_by_number(num).full().await.unwrap();
433    /// }
434    /// ```
435    fn get_block_by_number(&self, number: BlockNumberOrTag) -> EthGetBlock<N::BlockResponse> {
436        EthGetBlock::by_number(number, self.client())
437    }
438
439    /// Returns the number of transactions in a block from a block matching the given block hash.
440    async fn get_block_transaction_count_by_hash(
441        &self,
442        hash: BlockHash,
443    ) -> TransportResult<Option<u64>> {
444        self.client()
445            .request("eth_getBlockTransactionCountByHash", (hash,))
446            .await
447            .map(|opt_count: Option<U64>| opt_count.map(|count| count.to::<u64>()))
448    }
449
450    /// Returns the number of transactions in a block matching the given block number.
451    async fn get_block_transaction_count_by_number(
452        &self,
453        block_number: BlockNumberOrTag,
454    ) -> TransportResult<Option<u64>> {
455        self.client()
456            .request("eth_getBlockTransactionCountByNumber", (block_number,))
457            .await
458            .map(|opt_count: Option<U64>| opt_count.map(|count| count.to::<u64>()))
459    }
460
461    /// Gets the selected block [`BlockId`] receipts.
462    fn get_block_receipts(
463        &self,
464        block: BlockId,
465    ) -> ProviderCall<(BlockId,), Option<Vec<N::ReceiptResponse>>> {
466        self.client().request("eth_getBlockReceipts", (block,)).into()
467    }
468
469    /// Gets the EIP-7928 block access list by [`BlockId`].
470    ///
471    /// Returns the block access list, or `None` if the block is not found.
472    async fn get_block_access_list(
473        &self,
474        block: BlockId,
475    ) -> TransportResult<Option<BlockAccessList>> {
476        match block {
477            BlockId::Hash(hash) => self.get_block_access_list_by_hash(hash.block_hash).await,
478            BlockId::Number(number) => self.get_block_access_list_by_number(number).await,
479        }
480    }
481
482    /// Gets the EIP-7928 block access list by [`BlockHash`].
483    ///
484    /// Returns the block access list, or `None` if the block is not found.
485    async fn get_block_access_list_by_hash(
486        &self,
487        hash: BlockHash,
488    ) -> TransportResult<Option<BlockAccessList>> {
489        self.client().request("eth_getBlockAccessListByBlockHash", (hash,)).await
490    }
491
492    /// Gets the EIP-7928 block access list by [`BlockNumberOrTag`].
493    ///
494    /// Returns the block access list, or `None` if the block is not found.
495    async fn get_block_access_list_by_number(
496        &self,
497        number: BlockNumberOrTag,
498    ) -> TransportResult<Option<BlockAccessList>> {
499        self.client().request("eth_getBlockAccessListByBlockNumber", (number,)).await
500    }
501
502    /// Gets the EIP-7928 block access list by [`BlockId`].
503    ///
504    /// Returns the  block access list raw, or `None` if the block is not found.
505    async fn get_block_access_list_raw(&self, block: BlockId) -> TransportResult<Option<Bytes>> {
506        self.client().request("eth_getBlockAccessListRaw", (block,)).await
507    }
508
509    /// Gets a block header by its [`BlockId`].
510    ///
511    /// # Examples
512    ///
513    /// ```no_run
514    /// # use alloy_provider::{Provider, ProviderBuilder};
515    /// # use alloy_eips::BlockId;
516    ///
517    /// #[tokio::main]
518    /// async fn main() {
519    ///     let provider =
520    ///         ProviderBuilder::new().connect_http("https://eth.merkle.io".parse().unwrap());
521    ///
522    ///     // Gets the latest block header.
523    ///     let header = provider.get_header(BlockId::latest()).await.unwrap();
524    ///
525    ///     // Gets the block header by number.
526    ///     let header = provider.get_header(BlockId::number(0)).await.unwrap();
527    /// }
528    /// ```
529    async fn get_header(&self, block: BlockId) -> TransportResult<Option<N::HeaderResponse>> {
530        match block {
531            BlockId::Hash(hash) => self.get_header_by_hash(hash.block_hash).await,
532            BlockId::Number(number) => self.get_header_by_number(number).await,
533        }
534    }
535
536    /// Gets a block header by its [`BlockHash`].
537    ///
538    /// # Examples
539    ///
540    /// ```no_run
541    /// # use alloy_provider::{Provider, ProviderBuilder};
542    /// # use alloy_primitives::b256;
543    ///
544    /// #[tokio::main]
545    /// async fn main() {
546    ///     let provider =
547    ///         ProviderBuilder::new().connect_http("https://eth.merkle.io".parse().unwrap());
548    ///     let block_hash = b256!("6032d03ee8e43e8999c2943152a4daebfc4b75b7f7a9647d2677299d215127da");
549    ///
550    ///     // Gets a block header by its hash.
551    ///     let header = provider.get_header_by_hash(block_hash).await.unwrap();
552    /// }
553    /// ```
554    async fn get_header_by_hash(
555        &self,
556        hash: BlockHash,
557    ) -> TransportResult<Option<N::HeaderResponse>> {
558        match self.client().request("eth_getHeaderByHash", (hash,)).await {
559            Ok(header) => Ok(header),
560            // eth_getHeaderByHash is non-standard; fall back to eth_getBlockByHash
561            Err(err) if err.as_error_resp().is_some_and(|e| e.code == -32601) => {
562                Ok(self.get_block_by_hash(hash).await?.map(|b| b.header().clone()))
563            }
564            Err(err) => Err(err),
565        }
566    }
567
568    /// Gets a block header by its [`BlockNumberOrTag`].
569    ///
570    /// # Examples
571    ///
572    /// ```no_run
573    /// # use alloy_provider::{Provider, ProviderBuilder};
574    /// # use alloy_eips::BlockNumberOrTag;
575    ///
576    /// #[tokio::main]
577    /// async fn main() {
578    ///     let provider =
579    ///         ProviderBuilder::new().connect_http("https://eth.merkle.io".parse().unwrap());
580    ///
581    ///     // Gets a block header by its number.
582    ///     let header = provider.get_header_by_number(BlockNumberOrTag::Number(0)).await.unwrap();
583    ///
584    ///     // Gets the latest block header.
585    ///     let header = provider.get_header_by_number(BlockNumberOrTag::Latest).await.unwrap();
586    /// }
587    /// ```
588    async fn get_header_by_number(
589        &self,
590        number: BlockNumberOrTag,
591    ) -> TransportResult<Option<N::HeaderResponse>> {
592        match self.client().request("eth_getHeaderByNumber", (number,)).await {
593            Ok(header) => Ok(header),
594            // eth_getHeaderByNumber is non-standard; fall back to eth_getBlockByNumber
595            Err(err) if err.as_error_resp().is_some_and(|e| e.code == -32601) => {
596                Ok(self.get_block_by_number(number).await?.map(|b| b.header().clone()))
597            }
598            Err(err) => Err(err),
599        }
600    }
601
602    /// Gets the bytecode located at the corresponding [`Address`].
603    fn get_code_at(&self, address: Address) -> RpcWithBlock<Address, Bytes> {
604        self.client().request("eth_getCode", address).into()
605    }
606
607    /// Watch for new blocks by polling the provider with
608    /// [`eth_getFilterChanges`](Self::get_filter_changes).
609    ///
610    /// Returns a builder that is used to configure the poller. See [`PollerBuilder`] for more
611    /// details.
612    ///
613    /// # Examples
614    ///
615    /// Get the next 5 blocks:
616    ///
617    /// ```no_run
618    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
619    /// use futures::StreamExt;
620    ///
621    /// let poller = provider.watch_blocks().await?;
622    /// let mut stream = poller.into_stream().flat_map(futures::stream::iter).take(5);
623    /// while let Some(block_hash) = stream.next().await {
624    ///    println!("new block: {block_hash}");
625    /// }
626    /// # Ok(())
627    /// # }
628    /// ```
629    async fn watch_blocks(&self) -> TransportResult<FilterPollerBuilder<B256>> {
630        let id = self.new_block_filter().await?;
631        Ok(PollerBuilder::new(self.weak_client(), "eth_getFilterChanges", (id,)))
632    }
633
634    /// Watch for new blocks by polling the provider with
635    /// [`eth_getFilterChanges`](Self::get_filter_changes) and transforming the returned block
636    /// hashes into full blocks bodies.
637    ///
638    /// Returns the [`WatchBlocks`] type which consumes the stream of block hashes from
639    /// [`PollerBuilder`] and returns a stream of [`BlockResponse`]s.
640    ///
641    /// # Examples
642    ///
643    /// Get the next 5 full blocks:
644    ///
645    /// ```no_run
646    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
647    /// use futures::StreamExt;
648    ///
649    /// let poller = provider.watch_full_blocks().await?.full();
650    /// let mut stream = poller.into_stream().flat_map(futures::stream::iter).take(5);
651    /// while let Some(block) = stream.next().await {
652    ///   println!("new block: {block:#?}");
653    /// }
654    /// # Ok(())
655    /// # }
656    /// ```
657    async fn watch_full_blocks(&self) -> TransportResult<WatchBlocks<N::BlockResponse>> {
658        let id = self.new_block_filter().await?;
659        let poller = PollerBuilder::new(self.weak_client(), "eth_getFilterChanges", (id,));
660
661        Ok(WatchBlocks::new(poller))
662    }
663
664    /// Watch for new blocks by polling the provider with
665    /// [`eth_getFilterChanges`](Self::get_filter_changes) and fetching the header for each
666    /// returned block hash.
667    ///
668    /// Returns the [`WatchHeaders`] type which consumes the stream of block hashes from
669    /// [`PollerBuilder`] and returns a stream of [`alloy_network_primitives::HeaderResponse`]s.
670    ///
671    /// Note that the backing RPC methods (`eth_getHeaderByHash` / `eth_getHeaderByNumber`) are
672    /// not supported by all clients.
673    ///
674    /// # Examples
675    ///
676    /// Get the next 5 headers:
677    ///
678    /// ```no_run
679    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
680    /// use futures::StreamExt;
681    ///
682    /// let poller = provider.watch_headers().await?;
683    /// let mut stream = poller.into_stream().take(5);
684    /// while let Some(header) = stream.next().await {
685    ///   println!("new header: {header:#?}");
686    /// }
687    /// # Ok(())
688    /// # }
689    /// ```
690    async fn watch_headers(&self) -> TransportResult<WatchHeaders<N::HeaderResponse>> {
691        let id = self.new_block_filter().await?;
692        let poller = PollerBuilder::new(self.weak_client(), "eth_getFilterChanges", (id,));
693
694        Ok(WatchHeaders::new(poller))
695    }
696
697    /// Watch for new pending transaction by polling the provider with
698    /// [`eth_getFilterChanges`](Self::get_filter_changes).
699    ///
700    /// Returns a builder that is used to configure the poller. See [`PollerBuilder`] for more
701    /// details.
702    ///
703    /// # Examples
704    ///
705    /// Get the next 5 pending transaction hashes:
706    ///
707    /// ```no_run
708    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
709    /// use futures::StreamExt;
710    ///
711    /// let poller = provider.watch_pending_transactions().await?;
712    /// let mut stream = poller.into_stream().flat_map(futures::stream::iter).take(5);
713    /// while let Some(tx_hash) = stream.next().await {
714    ///    println!("new pending transaction hash: {tx_hash}");
715    /// }
716    /// # Ok(())
717    /// # }
718    /// ```
719    async fn watch_pending_transactions(&self) -> TransportResult<FilterPollerBuilder<B256>> {
720        let id = self.new_pending_transactions_filter(false).await?;
721        Ok(PollerBuilder::new(self.weak_client(), "eth_getFilterChanges", (id,)))
722    }
723
724    /// Watch for new logs using the given filter by polling the provider with
725    /// [`eth_getFilterChanges`](Self::get_filter_changes).
726    ///
727    /// Returns a builder that is used to configure the poller. See [`PollerBuilder`] for more
728    /// details.
729    ///
730    /// # Examples
731    ///
732    /// Get the next 5 USDC transfer logs:
733    ///
734    /// ```no_run
735    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
736    /// use alloy_primitives::{address, b256};
737    /// use alloy_rpc_types_eth::Filter;
738    /// use futures::StreamExt;
739    ///
740    /// let address = address!("a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48");
741    /// let transfer_signature = b256!("ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef");
742    /// let filter = Filter::new().address(address).event_signature(transfer_signature);
743    ///
744    /// let poller = provider.watch_logs(&filter).await?;
745    /// let mut stream = poller.into_stream().flat_map(futures::stream::iter).take(5);
746    /// while let Some(log) = stream.next().await {
747    ///    println!("new log: {log:#?}");
748    /// }
749    /// # Ok(())
750    /// # }
751    /// ```
752    async fn watch_logs(&self, filter: &Filter) -> TransportResult<FilterPollerBuilder<Log>> {
753        let id = self.new_filter(filter).await?;
754        Ok(PollerBuilder::new(self.weak_client(), "eth_getFilterChanges", (id,)))
755    }
756
757    /// Watch for new pending transaction bodies by polling the provider with
758    /// [`eth_getFilterChanges`](Self::get_filter_changes).
759    ///
760    /// Returns a builder that is used to configure the poller. See [`PollerBuilder`] for more
761    /// details.
762    ///
763    /// # Support
764    ///
765    /// This endpoint might not be supported by all clients.
766    ///
767    /// # Examples
768    ///
769    /// Get the next 5 pending transaction bodies:
770    ///
771    /// ```no_run
772    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
773    /// use futures::StreamExt;
774    ///
775    /// let poller = provider.watch_full_pending_transactions().await?;
776    /// let mut stream = poller.into_stream().flat_map(futures::stream::iter).take(5);
777    /// while let Some(tx) = stream.next().await {
778    ///    println!("new pending transaction: {tx:#?}");
779    /// }
780    /// # Ok(())
781    /// # }
782    /// ```
783    async fn watch_full_pending_transactions(
784        &self,
785    ) -> TransportResult<FilterPollerBuilder<N::TransactionResponse>> {
786        let id = self.new_pending_transactions_filter(true).await?;
787        Ok(PollerBuilder::new(self.weak_client(), "eth_getFilterChanges", (id,)))
788    }
789
790    /// Get a list of values that have been added since the last poll.
791    ///
792    /// The return value depends on what stream `id` corresponds to.
793    /// See [`FilterChanges`] for all possible return values.
794    #[auto_impl(keep_default_for(&, &mut, Rc, Arc, Box))]
795    async fn get_filter_changes<R: RpcRecv>(&self, id: U256) -> TransportResult<Vec<R>>
796    where
797        Self: Sized,
798    {
799        self.client().request("eth_getFilterChanges", (id,)).await
800    }
801
802    /// Get a list of values that have been added since the last poll.
803    ///
804    /// This returns an enum over all possible return values. You probably want to use
805    /// [`get_filter_changes`](Self::get_filter_changes) instead.
806    async fn get_filter_changes_dyn(&self, id: U256) -> TransportResult<FilterChanges> {
807        self.client().request("eth_getFilterChanges", (id,)).await
808    }
809
810    /// Retrieves a [`Vec<Log>`] for the given filter ID.
811    async fn get_filter_logs(&self, id: U256) -> TransportResult<Vec<Log>> {
812        self.client().request("eth_getFilterLogs", (id,)).await
813    }
814
815    /// Request provider to uninstall the filter with the given ID.
816    async fn uninstall_filter(&self, id: U256) -> TransportResult<bool> {
817        self.client().request("eth_uninstallFilter", (id,)).await
818    }
819
820    /// Watch for the confirmation of a single pending transaction with the given configuration.
821    ///
822    /// Note that this is handled internally rather than calling any specific RPC method, and as
823    /// such should not be overridden.
824    #[inline]
825    async fn watch_pending_transaction(
826        &self,
827        config: PendingTransactionConfig,
828    ) -> Result<PendingTransaction, PendingTransactionError> {
829        self.root().watch_pending_transaction(config).await
830    }
831
832    /// Retrieves a [`Vec<Log>`] with the given [`Filter`].
833    async fn get_logs(&self, filter: &Filter) -> TransportResult<Vec<Log>> {
834        self.client().request("eth_getLogs", (filter,)).await
835    }
836
837    /// Get the account and storage values of the specified account including the merkle proofs.
838    ///
839    /// This call can be used to verify that the data has not been tampered with.
840    fn get_proof(
841        &self,
842        address: Address,
843        keys: Vec<StorageKey>,
844    ) -> RpcWithBlock<(Address, Vec<StorageKey>), EIP1186AccountProofResponse> {
845        self.client().request("eth_getProof", (address, keys)).into()
846    }
847
848    /// Gets the specified storage value from [`Address`].
849    fn get_storage_at(
850        &self,
851        address: Address,
852        key: U256,
853    ) -> RpcWithBlock<(Address, U256), StorageValue> {
854        self.client().request("eth_getStorageAt", (address, key)).into()
855    }
856
857    /// Batch-fetches storage values from multiple addresses at multiple keys.
858    ///
859    /// See [EIP spec](https://github.com/ethereum/execution-apis/issues/752).
860    fn get_storage_values(
861        &self,
862        requests: StorageValuesRequest,
863    ) -> RpcWithBlock<(StorageValuesRequest,), StorageValuesResponse> {
864        self.client().request("eth_getStorageValues", (requests,)).into()
865    }
866
867    /// Gets a transaction by its sender and nonce.
868    ///
869    /// Note: not supported by all clients.
870    fn get_transaction_by_sender_nonce(
871        &self,
872        sender: Address,
873        nonce: u64,
874    ) -> ProviderCall<(Address, U64), Option<N::TransactionResponse>> {
875        self.client()
876            .request("eth_getTransactionBySenderAndNonce", (sender, U64::from(nonce)))
877            .into()
878    }
879
880    /// Gets a transaction by its [`TxHash`].
881    fn get_transaction_by_hash(
882        &self,
883        hash: TxHash,
884    ) -> ProviderCall<(TxHash,), Option<N::TransactionResponse>> {
885        self.client().request("eth_getTransactionByHash", (hash,)).into()
886    }
887
888    /// Gets a transaction by block hash and transaction index position.
889    fn get_transaction_by_block_hash_and_index(
890        &self,
891        block_hash: B256,
892        index: usize,
893    ) -> ProviderCall<(B256, Index), Option<N::TransactionResponse>> {
894        self.client()
895            .request("eth_getTransactionByBlockHashAndIndex", (block_hash, Index(index)))
896            .into()
897    }
898
899    /// Gets a raw transaction by block hash and transaction index position.
900    fn get_raw_transaction_by_block_hash_and_index(
901        &self,
902        block_hash: B256,
903        index: usize,
904    ) -> ProviderCall<(B256, Index), Option<Bytes>> {
905        self.client()
906            .request("eth_getRawTransactionByBlockHashAndIndex", (block_hash, Index(index)))
907            .into()
908    }
909
910    /// Gets a transaction by block number and transaction index position.
911    fn get_transaction_by_block_number_and_index(
912        &self,
913        block_number: BlockNumberOrTag,
914        index: usize,
915    ) -> ProviderCall<(BlockNumberOrTag, Index), Option<N::TransactionResponse>> {
916        self.client()
917            .request("eth_getTransactionByBlockNumberAndIndex", (block_number, Index(index)))
918            .into()
919    }
920
921    /// Gets a raw transaction by block number and transaction index position.
922    fn get_raw_transaction_by_block_number_and_index(
923        &self,
924        block_number: BlockNumberOrTag,
925        index: usize,
926    ) -> ProviderCall<(BlockNumberOrTag, Index), Option<Bytes>> {
927        self.client()
928            .request("eth_getRawTransactionByBlockNumberAndIndex", (block_number, Index(index)))
929            .into()
930    }
931
932    /// Returns the [EIP-2718] encoded transaction if it exists, see also
933    /// [`Decodable2718`](alloy_eips::eip2718::Decodable2718).
934    ///
935    /// If the transaction is an [EIP-4844] transaction that is still in the pool (pending) it will
936    /// include the sidecar, otherwise it will the consensus variant without the sidecar:
937    /// [`TxEip4844`](alloy_consensus::transaction::eip4844::TxEip4844).
938    ///
939    /// This can be decoded into [`TxEnvelope`](alloy_consensus::transaction::TxEnvelope).
940    ///
941    /// [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718
942    /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844
943    fn get_raw_transaction_by_hash(&self, hash: TxHash) -> ProviderCall<(TxHash,), Option<Bytes>> {
944        self.client().request("eth_getRawTransactionByHash", (hash,)).into()
945    }
946
947    /// Gets the transaction count (AKA "nonce") of the corresponding address.
948    #[doc(alias = "get_nonce")]
949    #[doc(alias = "get_account_nonce")]
950    fn get_transaction_count(
951        &self,
952        address: Address,
953    ) -> RpcWithBlock<Address, U64, u64, fn(U64) -> u64> {
954        self.client()
955            .request("eth_getTransactionCount", address)
956            .map_resp(utils::convert_u64 as fn(U64) -> u64)
957            .into()
958    }
959
960    /// Gets a transaction receipt if it exists, by its [`TxHash`].
961    fn get_transaction_receipt(
962        &self,
963        hash: TxHash,
964    ) -> ProviderCall<(TxHash,), Option<N::ReceiptResponse>> {
965        self.client().request("eth_getTransactionReceipt", (hash,)).into()
966    }
967
968    /// Gets an uncle block through the tag [`BlockId`] and index `u64`.
969    async fn get_uncle(&self, tag: BlockId, idx: u64) -> TransportResult<Option<N::BlockResponse>> {
970        let idx = U64::from(idx);
971        match tag {
972            BlockId::Hash(hash) => {
973                self.client()
974                    .request("eth_getUncleByBlockHashAndIndex", (hash.block_hash, idx))
975                    .await
976            }
977            BlockId::Number(number) => {
978                self.client().request("eth_getUncleByBlockNumberAndIndex", (number, idx)).await
979            }
980        }
981    }
982
983    /// Gets the number of uncles for the block specified by the tag [`BlockId`].
984    async fn get_uncle_count(&self, tag: BlockId) -> TransportResult<u64> {
985        match tag {
986            BlockId::Hash(hash) => self
987                .client()
988                .request("eth_getUncleCountByBlockHash", (hash.block_hash,))
989                .await
990                .map(|count: U64| count.to::<u64>()),
991            BlockId::Number(number) => self
992                .client()
993                .request("eth_getUncleCountByBlockNumber", (number,))
994                .await
995                .map(|count: U64| count.to::<u64>()),
996        }
997    }
998
999    /// Returns a suggestion for the current `maxPriorityFeePerGas` in wei.
1000    fn get_max_priority_fee_per_gas(&self) -> ProviderCall<NoParams, U128, u128> {
1001        self.client()
1002            .request_noparams("eth_maxPriorityFeePerGas")
1003            .map_resp(utils::convert_u128 as fn(U128) -> u128)
1004            .into()
1005    }
1006
1007    /// Notify the provider that we are interested in new blocks.
1008    ///
1009    /// Returns the ID to use with [`eth_getFilterChanges`](Self::get_filter_changes).
1010    ///
1011    /// See also [`watch_blocks`](Self::watch_blocks) to configure a poller.
1012    async fn new_block_filter(&self) -> TransportResult<U256> {
1013        self.client().request_noparams("eth_newBlockFilter").await
1014    }
1015
1016    /// Notify the provider that we are interested in logs that match the given [`Filter`].
1017    ///
1018    /// Returns the ID to use with [`eth_getFilterChanges`](Self::get_filter_changes).
1019    ///
1020    /// See also [`watch_logs`](Self::watch_logs) to configure a poller.
1021    async fn new_filter(&self, filter: &Filter) -> TransportResult<U256> {
1022        self.client().request("eth_newFilter", (filter,)).await
1023    }
1024
1025    /// Notify the provider that we are interested in new pending transactions.
1026    ///
1027    /// If `full` is `true`, the stream will consist of full transaction bodies instead of just the
1028    /// hashes. This not supported by all clients.
1029    ///
1030    /// Returns the ID to use with [`eth_getFilterChanges`](Self::get_filter_changes).
1031    ///
1032    /// See also [`watch_pending_transactions`](Self::watch_pending_transactions) to configure a
1033    /// poller.
1034    async fn new_pending_transactions_filter(&self, full: bool) -> TransportResult<U256> {
1035        // NOTE: We don't want to send `false` as the client might not support it.
1036        let param = if full { &[true][..] } else { &[] };
1037        self.client().request("eth_newPendingTransactionFilter", param).await
1038    }
1039
1040    /// Broadcasts a raw transaction RLP bytes to the network.
1041    ///
1042    /// See [`send_transaction`](Self::send_transaction) for more details.
1043    async fn send_raw_transaction(
1044        &self,
1045        encoded_tx: &[u8],
1046    ) -> TransportResult<PendingTransactionBuilder<N>> {
1047        let rlp_hex = hex::encode_prefixed(encoded_tx);
1048        let tx_hash = self.client().request("eth_sendRawTransaction", (rlp_hex,)).await?;
1049        Ok(PendingTransactionBuilder::new(self.root().clone(), tx_hash))
1050    }
1051
1052    /// Broadcasts a raw transaction RLP bytes to the network and returns the transaction receipt
1053    /// after it has been mined.
1054    ///
1055    /// Unlike send_raw_transaction which returns immediately with
1056    /// a transaction hash, this method waits on the server side until the transaction is included
1057    /// in a block and returns the receipt directly. This is an optimization that reduces the number
1058    /// of RPC calls needed to confirm a transaction.
1059    ///
1060    /// This method implements the `eth_sendRawTransactionSync` RPC method as defined in
1061    /// [EIP-7966].
1062    ///
1063    /// [EIP-7966]: https://github.com/ethereum/EIPs/pull/9151
1064    ///
1065    /// # Error Handling
1066    ///
1067    /// If the transaction fails, you can extract the transaction hash from the error using
1068    /// [`RpcError::tx_hash_data`]:
1069    ///
1070    /// ```no_run
1071    /// # use alloy_json_rpc::RpcError;
1072    /// # use alloy_network_primitives::ReceiptResponse;
1073    /// # async fn example<N: alloy_network::Network>(provider: impl alloy_provider::Provider<N>, encoded_tx: &[u8]) {
1074    /// match provider.send_raw_transaction_sync(encoded_tx).await {
1075    ///     Ok(receipt) => {
1076    ///         println!("Transaction successful: {}", receipt.transaction_hash());
1077    ///     }
1078    ///     Err(rpc_err) => {
1079    ///         if let Some(tx_hash) = rpc_err.tx_hash_data() {
1080    ///             println!("Transaction failed but hash available: {}", tx_hash);
1081    ///         }
1082    ///     }
1083    /// }
1084    /// # }
1085    /// ```
1086    ///
1087    /// Note: This is only available on certain clients that support the
1088    /// `eth_sendRawTransactionSync` RPC method, such as Anvil.
1089    async fn send_raw_transaction_sync(
1090        &self,
1091        encoded_tx: &[u8],
1092    ) -> TransportResult<N::ReceiptResponse> {
1093        let rlp_hex = hex::encode_prefixed(encoded_tx);
1094        self.client().request("eth_sendRawTransactionSync", (rlp_hex,)).await
1095    }
1096
1097    /// Broadcasts a raw transaction RLP bytes with a conditional [`TransactionConditional`] to the
1098    /// network.
1099    ///
1100    /// [`TransactionConditional`] represents the preconditions that determine the inclusion of the
1101    /// transaction, enforced out-of-protocol by the sequencer.
1102    ///
1103    /// Note: This endpoint is only available on certain networks, e.g. opstack chains, polygon,
1104    /// bsc.
1105    ///
1106    /// See [`TransactionConditional`] for more details.
1107    async fn send_raw_transaction_conditional(
1108        &self,
1109        encoded_tx: &[u8],
1110        conditional: TransactionConditional,
1111    ) -> TransportResult<PendingTransactionBuilder<N>> {
1112        let rlp_hex = hex::encode_prefixed(encoded_tx);
1113        let tx_hash = self
1114            .client()
1115            .request("eth_sendRawTransactionConditional", (rlp_hex, conditional))
1116            .await?;
1117        Ok(PendingTransactionBuilder::new(self.root().clone(), tx_hash))
1118    }
1119
1120    /// Broadcasts a transaction to the network.
1121    ///
1122    /// Returns a [`PendingTransactionBuilder`] which can be used to configure
1123    /// how and when to await the transaction's confirmation.
1124    ///
1125    /// # Examples
1126    ///
1127    /// See [`PendingTransactionBuilder`](crate::PendingTransactionBuilder) for more examples.
1128    ///
1129    /// ```no_run
1130    /// # async fn example<N: alloy_network::Network>(provider: impl alloy_provider::Provider, tx: alloy_rpc_types_eth::transaction::TransactionRequest) -> Result<(), Box<dyn std::error::Error>> {
1131    /// let tx_hash = provider.send_transaction(tx)
1132    ///     .await?
1133    ///     .with_required_confirmations(2)
1134    ///     .with_timeout(Some(std::time::Duration::from_secs(60)))
1135    ///     .watch()
1136    ///     .await?;
1137    /// # Ok(())
1138    /// # }
1139    /// ```
1140    async fn send_transaction(
1141        &self,
1142        tx: N::TransactionRequest,
1143    ) -> TransportResult<PendingTransactionBuilder<N>> {
1144        self.send_transaction_internal(SendableTx::Builder(tx)).await
1145    }
1146
1147    /// Broadcasts a transaction envelope to the network.
1148    ///
1149    /// Returns a [`PendingTransactionBuilder`] which can be used to configure
1150    /// how and when to await the transaction's confirmation.
1151    async fn send_tx_envelope(
1152        &self,
1153        tx: N::TxEnvelope,
1154    ) -> TransportResult<PendingTransactionBuilder<N>> {
1155        self.send_transaction_internal(SendableTx::Envelope(tx)).await
1156    }
1157
1158    /// This method allows [`ProviderLayer`] and [`TxFiller`] to build the
1159    /// transaction and send it to the network without changing user-facing
1160    /// APIs. Generally implementers should NOT override this method.
1161    ///
1162    /// [`ProviderLayer`]: crate::ProviderLayer
1163    /// [`TxFiller`]: crate::fillers::TxFiller
1164    #[doc(hidden)]
1165    async fn send_transaction_internal(
1166        &self,
1167        tx: SendableTx<N>,
1168    ) -> TransportResult<PendingTransactionBuilder<N>> {
1169        // Make sure to initialize heartbeat before we submit transaction, so that
1170        // we don't miss it if user will subscriber to it immediately after sending.
1171        let _handle = self.root().get_heart();
1172
1173        match tx {
1174            SendableTx::Builder(mut tx) => {
1175                alloy_network::NetworkTransactionBuilder::prep_for_submission(&mut tx);
1176                let tx_hash = self.client().request("eth_sendTransaction", (tx,)).await?;
1177                Ok(PendingTransactionBuilder::new(self.root().clone(), tx_hash))
1178            }
1179            SendableTx::Envelope(tx) => {
1180                let encoded_tx = tx.encoded_2718();
1181                self.send_raw_transaction(&encoded_tx).await
1182            }
1183        }
1184    }
1185
1186    /// Sends a transaction and waits for its receipt in a single call.
1187    ///
1188    /// This method combines transaction submission and receipt retrieval into a single
1189    /// async operation, providing a simpler API compared to the two-step process of
1190    /// [`send_transaction`](Self::send_transaction) followed by waiting for confirmation.
1191    ///
1192    /// Returns the transaction receipt directly after submission and confirmation.
1193    ///
1194    /// # Example
1195    /// ```no_run
1196    /// # use alloy_network_primitives::ReceiptResponse;
1197    /// # async fn example<N: alloy_network::Network>(provider: impl alloy_provider::Provider<N>, tx: N::TransactionRequest) -> Result<(), Box<dyn std::error::Error>> {
1198    /// let receipt = provider.send_transaction_sync(tx).await?;
1199    /// println!("Transaction hash: {}", receipt.transaction_hash());
1200    /// # Ok(())
1201    /// # }
1202    /// ```
1203    ///
1204    /// # Error Handling
1205    ///
1206    /// If the transaction fails, you can extract the transaction hash from the error using
1207    /// [`RpcError::tx_hash_data`]:
1208    ///
1209    /// ```no_run
1210    /// # use alloy_json_rpc::RpcError;
1211    /// # use alloy_network_primitives::ReceiptResponse;
1212    /// # async fn example<N: alloy_network::Network>(provider: impl alloy_provider::Provider<N>, tx: N::TransactionRequest) {
1213    /// match provider.send_transaction_sync(tx).await {
1214    ///     Ok(receipt) => {
1215    ///         println!("Transaction successful: {}", receipt.transaction_hash());
1216    ///     }
1217    ///     Err(rpc_err) => {
1218    ///         if let Some(tx_hash) = rpc_err.tx_hash_data() {
1219    ///             println!("Transaction failed but hash available: {}", tx_hash);
1220    ///         }
1221    ///     }
1222    /// }
1223    /// # }
1224    /// ```
1225    async fn send_transaction_sync(
1226        &self,
1227        tx: N::TransactionRequest,
1228    ) -> TransportResult<N::ReceiptResponse> {
1229        self.send_transaction_sync_internal(SendableTx::Builder(tx)).await
1230    }
1231
1232    /// This method allows [`ProviderLayer`] and [`TxFiller`] to build the
1233    /// transaction and send it to the network without changing user-facing
1234    /// APIs. Generally implementers should NOT override this method.
1235    ///
1236    /// If the input is a [`SendableTx::Builder`] then this utilizes `eth_sendTransactionSync` by
1237    /// default.
1238    ///
1239    /// [`ProviderLayer`]: crate::ProviderLayer
1240    /// [`TxFiller`]: crate::fillers::TxFiller
1241    #[doc(hidden)]
1242    async fn send_transaction_sync_internal(
1243        &self,
1244        tx: SendableTx<N>,
1245    ) -> TransportResult<N::ReceiptResponse> {
1246        // Make sure to initialize heartbeat before we submit transaction, so that
1247        // we don't miss it if user will subscriber to it immediately after sending.
1248        let _handle = self.root().get_heart();
1249
1250        match tx {
1251            SendableTx::Builder(mut tx) => {
1252                alloy_network::NetworkTransactionBuilder::prep_for_submission(&mut tx);
1253                let receipt = self.client().request("eth_sendTransactionSync", (tx,)).await?;
1254                Ok(receipt)
1255            }
1256            SendableTx::Envelope(tx) => {
1257                let encoded_tx = tx.encoded_2718();
1258                self.send_raw_transaction_sync(&encoded_tx).await
1259            }
1260        }
1261    }
1262
1263    /// Signs a transaction that can be submitted to the network later using
1264    /// [`send_raw_transaction`](Self::send_raw_transaction).
1265    ///
1266    /// The `eth_signTransaction` method is not supported by regular nodes.
1267    async fn sign_transaction(&self, tx: N::TransactionRequest) -> TransportResult<Bytes> {
1268        self.client().request("eth_signTransaction", (tx,)).await
1269    }
1270
1271    /// Fills a transaction with missing fields using default values.
1272    ///
1273    /// This method prepares a transaction by populating missing fields such as gas limit,
1274    /// gas price, or nonce with appropriate default values. The response includes both the
1275    /// RLP-encoded signed transaction and the filled transaction.
1276    async fn fill_transaction(
1277        &self,
1278        tx: N::TransactionRequest,
1279    ) -> TransportResult<FillTransaction<N::TxEnvelope>>
1280    where
1281        N::TxEnvelope: RpcRecv,
1282    {
1283        self.client().request("eth_fillTransaction", (tx,)).await
1284    }
1285
1286    /// Subscribe to a stream of new block headers.
1287    ///
1288    /// # Errors
1289    ///
1290    /// This method is only available on `pubsub` clients, such as WebSockets or IPC, and will
1291    /// return a [`PubsubUnavailable`](alloy_transport::TransportErrorKind::PubsubUnavailable)
1292    /// transport error if the client does not support it.
1293    ///
1294    /// For a polling alternative available over HTTP, use [`Provider::watch_blocks`].
1295    /// However, be aware that polling increases RPC usage drastically.
1296    ///
1297    /// # Examples
1298    ///
1299    /// ```no_run
1300    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
1301    /// use futures::StreamExt;
1302    ///
1303    /// let sub = provider.subscribe_blocks().await?;
1304    /// let mut stream = sub.into_stream().take(5);
1305    /// while let Some(block) = stream.next().await {
1306    ///    println!("new block: {block:#?}");
1307    /// }
1308    /// # Ok(())
1309    /// # }
1310    /// ```
1311    #[cfg(feature = "pubsub")]
1312    fn subscribe_blocks(&self) -> GetSubscription<(SubscriptionKind,), N::HeaderResponse> {
1313        let rpc_call = self.client().request("eth_subscribe", (SubscriptionKind::NewHeads,));
1314        GetSubscription::new(self.weak_client(), rpc_call)
1315    }
1316
1317    /// Subscribe to a stream of full block bodies.
1318    ///
1319    /// # Errors
1320    ///
1321    /// This method is only available on `pubsub` clients, such as WebSockets or IPC, and will
1322    /// return a [`PubsubUnavailable`](alloy_transport::TransportErrorKind::PubsubUnavailable)
1323    /// transport error if the client does not support it.
1324    ///
1325    /// # Examples
1326    ///
1327    /// ```no_run
1328    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
1329    /// use futures::StreamExt;
1330    ///
1331    /// let sub = provider.subscribe_full_blocks().full().channel_size(10);
1332    /// let mut stream = sub.into_stream().await?.take(5);
1333    ///
1334    /// while let Some(block) = stream.next().await {
1335    ///   println!("{block:#?}");
1336    /// }
1337    /// # Ok(())
1338    /// # }
1339    /// ```
1340    #[cfg(feature = "pubsub")]
1341    fn subscribe_full_blocks(&self) -> SubFullBlocks<N> {
1342        SubFullBlocks::new(self.subscribe_blocks(), self.weak_client())
1343    }
1344
1345    /// Subscribe to a stream of pending transaction hashes.
1346    ///
1347    /// # Errors
1348    ///
1349    /// This method is only available on `pubsub` clients, such as WebSockets or IPC, and will
1350    /// return a [`PubsubUnavailable`](alloy_transport::TransportErrorKind::PubsubUnavailable)
1351    /// transport error if the client does not support it.
1352    ///
1353    /// For a polling alternative available over HTTP, use [`Provider::watch_pending_transactions`].
1354    /// However, be aware that polling increases RPC usage drastically.
1355    ///
1356    /// # Examples
1357    ///
1358    /// ```no_run
1359    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
1360    /// use futures::StreamExt;
1361    ///
1362    /// let sub = provider.subscribe_pending_transactions().await?;
1363    /// let mut stream = sub.into_stream().take(5);
1364    /// while let Some(tx_hash) = stream.next().await {
1365    ///    println!("new pending transaction hash: {tx_hash}");
1366    /// }
1367    /// # Ok(())
1368    /// # }
1369    /// ```
1370    #[cfg(feature = "pubsub")]
1371    fn subscribe_pending_transactions(&self) -> GetSubscription<(SubscriptionKind,), B256> {
1372        let rpc_call =
1373            self.client().request("eth_subscribe", (SubscriptionKind::NewPendingTransactions,));
1374        GetSubscription::new(self.weak_client(), rpc_call)
1375    }
1376
1377    /// Subscribe to a stream of pending transaction bodies.
1378    ///
1379    /// # Support
1380    ///
1381    /// This endpoint is compatible only with Geth client version 1.11.0 or later.
1382    ///
1383    /// # Errors
1384    ///
1385    /// This method is only available on `pubsub` clients, such as WebSockets or IPC, and will
1386    /// return a [`PubsubUnavailable`](alloy_transport::TransportErrorKind::PubsubUnavailable)
1387    /// transport error if the client does not support it.
1388    ///
1389    /// For a polling alternative available over HTTP, use
1390    /// [`Provider::watch_full_pending_transactions`]. However, be aware that polling increases
1391    /// RPC usage drastically.
1392    ///
1393    /// # Examples
1394    ///
1395    /// ```no_run
1396    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
1397    /// use futures::StreamExt;
1398    ///
1399    /// let sub = provider.subscribe_full_pending_transactions().await?;
1400    /// let mut stream = sub.into_stream().take(5);
1401    /// while let Some(tx) = stream.next().await {
1402    ///    println!("{tx:#?}");
1403    /// }
1404    /// # Ok(())
1405    /// # }
1406    /// ```
1407    #[cfg(feature = "pubsub")]
1408    fn subscribe_full_pending_transactions(
1409        &self,
1410    ) -> GetSubscription<(SubscriptionKind, Params), N::TransactionResponse> {
1411        let rpc_call = self.client().request(
1412            "eth_subscribe",
1413            (SubscriptionKind::NewPendingTransactions, Params::Bool(true)),
1414        );
1415        GetSubscription::new(self.weak_client(), rpc_call)
1416    }
1417
1418    /// Subscribe to a stream of logs matching given filter.
1419    ///
1420    /// # Errors
1421    ///
1422    /// This method is only available on `pubsub` clients, such as WebSockets or IPC, and will
1423    /// return a [`PubsubUnavailable`](alloy_transport::TransportErrorKind::PubsubUnavailable)
1424    /// transport error if the client does not support it.
1425    ///
1426    /// For a polling alternative available over HTTP, use
1427    /// [`Provider::watch_logs`]. However, be aware that polling increases
1428    /// RPC usage drastically.
1429    ///
1430    /// # Examples
1431    ///
1432    /// ```no_run
1433    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
1434    /// use futures::StreamExt;
1435    /// use alloy_primitives::keccak256;
1436    /// use alloy_rpc_types_eth::Filter;
1437    ///
1438    /// let signature = keccak256("Transfer(address,address,uint256)".as_bytes());
1439    ///
1440    /// let sub = provider.subscribe_logs(&Filter::new().event_signature(signature)).await?;
1441    /// let mut stream = sub.into_stream().take(5);
1442    /// while let Some(tx) = stream.next().await {
1443    ///    println!("{tx:#?}");
1444    /// }
1445    /// # Ok(())
1446    /// # }
1447    /// ```
1448    #[cfg(feature = "pubsub")]
1449    fn subscribe_logs(&self, filter: &Filter) -> GetSubscription<(SubscriptionKind, Params), Log> {
1450        let rpc_call = self.client().request(
1451            "eth_subscribe",
1452            (SubscriptionKind::Logs, Params::Logs(Box::new(filter.clone()))),
1453        );
1454        GetSubscription::new(self.weak_client(), rpc_call)
1455    }
1456
1457    /// Subscribe to an RPC event.
1458    #[cfg(feature = "pubsub")]
1459    #[auto_impl(keep_default_for(&, &mut, Rc, Arc, Box))]
1460    fn subscribe<P, R>(&self, params: P) -> GetSubscription<P, R>
1461    where
1462        P: RpcSend,
1463        R: RpcRecv,
1464        Self: Sized,
1465    {
1466        let rpc_call = self.client().request("eth_subscribe", params);
1467        GetSubscription::new(self.weak_client(), rpc_call)
1468    }
1469
1470    /// Subscribe to a non-standard subscription method without parameters.
1471    ///
1472    /// This is a helper method for creating subscriptions to methods that are not
1473    /// "eth_subscribe" and don't require parameters. It automatically marks the
1474    /// request as a subscription.
1475    ///
1476    /// # Examples
1477    ///
1478    /// ```no_run
1479    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
1480    /// use futures::StreamExt;
1481    ///
1482    /// let sub = provider.subscribe_to::<alloy_rpc_types_admin::PeerEvent>("admin_peerEvents").await?;
1483    /// let mut stream = sub.into_stream().take(5);
1484    /// while let Some(event) = stream.next().await {
1485    ///    println!("peer event: {event:#?}");
1486    /// }
1487    /// # Ok(())
1488    /// # }
1489    /// ```
1490    #[cfg(feature = "pubsub")]
1491    #[auto_impl(keep_default_for(&, &mut, Rc, Arc, Box))]
1492    fn subscribe_to<R>(&self, method: &'static str) -> GetSubscription<NoParams, R>
1493    where
1494        R: RpcRecv,
1495        Self: Sized,
1496    {
1497        let mut rpc_call = self.client().request_noparams(method);
1498        rpc_call.set_is_subscription();
1499        GetSubscription::new(self.weak_client(), rpc_call)
1500    }
1501
1502    /// Cancels a subscription given the subscription ID.
1503    #[cfg(feature = "pubsub")]
1504    async fn unsubscribe(&self, id: B256) -> TransportResult<()> {
1505        self.root().unsubscribe(id)
1506    }
1507
1508    /// Gets syncing info.
1509    fn syncing(&self) -> ProviderCall<NoParams, SyncStatus> {
1510        self.client().request_noparams("eth_syncing").into()
1511    }
1512
1513    /// Gets the client version.
1514    #[doc(alias = "web3_client_version")]
1515    fn get_client_version(&self) -> ProviderCall<NoParams, String> {
1516        self.client().request_noparams("web3_clientVersion").into()
1517    }
1518
1519    /// Gets the `Keccak-256` hash of the given data.
1520    #[doc(alias = "web3_sha3")]
1521    fn get_sha3(&self, data: &[u8]) -> ProviderCall<(String,), B256> {
1522        self.client().request("web3_sha3", (hex::encode_prefixed(data),)).into()
1523    }
1524
1525    /// Gets the network ID. Same as `eth_chainId`.
1526    fn get_net_version(&self) -> ProviderCall<NoParams, U64, u64> {
1527        self.client()
1528            .request_noparams("net_version")
1529            .map_resp(utils::convert_u64 as fn(U64) -> u64)
1530            .into()
1531    }
1532
1533    /* ---------------------------------------- raw calls --------------------------------------- */
1534
1535    /// Sends a raw JSON-RPC request.
1536    ///
1537    /// # Examples
1538    ///
1539    /// ```no_run
1540    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
1541    /// use alloy_rpc_types_eth::BlockNumberOrTag;
1542    /// use alloy_rpc_client::NoParams;
1543    ///
1544    /// // No parameters: `()`
1545    /// let block_number: String = provider.raw_request("eth_blockNumber".into(), NoParams::default()).await?;
1546    ///
1547    /// // One parameter: `(param,)` or `[param]`
1548    /// let block: serde_json::Value = provider.raw_request("eth_getBlockByNumber".into(), (BlockNumberOrTag::Latest,)).await?;
1549    ///
1550    /// // Two or more parameters: `(param1, param2, ...)` or `[param1, param2, ...]`
1551    /// let full_block: serde_json::Value = provider.raw_request("eth_getBlockByNumber".into(), (BlockNumberOrTag::Latest, true)).await?;
1552    /// # Ok(())
1553    /// # }
1554    /// ```
1555    ///
1556    /// [`PubsubUnavailable`]: alloy_transport::TransportErrorKind::PubsubUnavailable
1557    async fn raw_request<P, R>(&self, method: Cow<'static, str>, params: P) -> TransportResult<R>
1558    where
1559        P: RpcSend,
1560        R: RpcRecv,
1561        Self: Sized,
1562    {
1563        self.client().request(method, &params).await
1564    }
1565
1566    /// Sends a raw JSON-RPC request with type-erased parameters and return.
1567    ///
1568    /// # Examples
1569    ///
1570    /// ```no_run
1571    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
1572    /// use alloy_rpc_types_eth::BlockNumberOrTag;
1573    ///
1574    /// // No parameters: `()`
1575    /// let params = serde_json::value::to_raw_value(&())?;
1576    /// let block_number = provider.raw_request_dyn("eth_blockNumber".into(), &params).await?;
1577    ///
1578    /// // One parameter: `(param,)` or `[param]`
1579    /// let params = serde_json::value::to_raw_value(&(BlockNumberOrTag::Latest,))?;
1580    /// let block = provider.raw_request_dyn("eth_getBlockByNumber".into(), &params).await?;
1581    ///
1582    /// // Two or more parameters: `(param1, param2, ...)` or `[param1, param2, ...]`
1583    /// let params = serde_json::value::to_raw_value(&(BlockNumberOrTag::Latest, true))?;
1584    /// let full_block = provider.raw_request_dyn("eth_getBlockByNumber".into(), &params).await?;
1585    /// # Ok(())
1586    /// # }
1587    /// ```
1588    async fn raw_request_dyn(
1589        &self,
1590        method: Cow<'static, str>,
1591        params: &RawValue,
1592    ) -> TransportResult<Box<RawValue>> {
1593        self.client().request(method, params).await
1594    }
1595
1596    /// Creates a new [`TransactionRequest`](alloy_network::Network).
1597    #[inline]
1598    fn transaction_request(&self) -> N::TransactionRequest {
1599        Default::default()
1600    }
1601}
1602
1603#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
1604#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
1605impl<N: Network> Provider<N> for RootProvider<N> {
1606    #[inline]
1607    fn root(&self) -> &Self {
1608        self
1609    }
1610
1611    #[inline]
1612    fn client(&self) -> ClientRef<'_> {
1613        self.inner.client_ref()
1614    }
1615
1616    #[inline]
1617    fn weak_client(&self) -> WeakClient {
1618        self.inner.weak_client()
1619    }
1620
1621    #[inline]
1622    async fn watch_pending_transaction(
1623        &self,
1624        config: PendingTransactionConfig,
1625    ) -> Result<PendingTransaction, PendingTransactionError> {
1626        let block_number =
1627            if let Some(receipt) = self.get_transaction_receipt(*config.tx_hash()).await? {
1628                // The transaction is already confirmed.
1629                if config.required_confirmations() <= 1 {
1630                    return Ok(PendingTransaction::ready(*config.tx_hash()));
1631                }
1632                // Transaction has custom confirmations, so let the heart know about its block
1633                // number and let it handle the situation.
1634                receipt.block_number()
1635            } else {
1636                None
1637            };
1638
1639        self.get_heart()
1640            .watch_tx(config, block_number)
1641            .await
1642            .map_err(|_| PendingTransactionError::FailedToRegister)
1643    }
1644}
1645
1646#[cfg(test)]
1647mod tests {
1648    use super::*;
1649    use crate::{builder, ext::test::async_ci_only, ProviderBuilder, WalletProvider};
1650    use alloy_consensus::{Transaction, TxEnvelope};
1651    use alloy_network::{
1652        AnyNetwork, EthereumWallet, NetworkTransactionBuilder, TransactionBuilder,
1653    };
1654    use alloy_node_bindings::{utils::run_with_tempdir, Anvil, Reth};
1655    use alloy_primitives::{address, b256, bytes, keccak256};
1656    use alloy_rlp::Decodable;
1657    use alloy_rpc_client::{BuiltInConnectionString, RpcClient};
1658    use alloy_rpc_types_eth::{request::TransactionRequest, Block};
1659    use alloy_signer_local::PrivateKeySigner;
1660    use alloy_transport::layers::{RetryBackoffLayer, RetryPolicy};
1661    use std::{io::Read, str::FromStr, time::Duration};
1662
1663    // For layer transport tests
1664    use alloy_consensus::transaction::SignerRecoverable;
1665    #[cfg(feature = "hyper")]
1666    use alloy_transport_http::{
1667        hyper,
1668        hyper::body::Bytes as HyperBytes,
1669        hyper_util::{
1670            client::legacy::{Client, Error},
1671            rt::TokioExecutor,
1672        },
1673        HyperResponse, HyperResponseFut,
1674    };
1675    #[cfg(feature = "hyper")]
1676    use http_body_util::Full;
1677    #[cfg(feature = "hyper")]
1678    use tower::{Layer, Service};
1679
1680    #[tokio::test]
1681    async fn test_provider_builder() {
1682        let provider =
1683            RootProvider::<Ethereum>::builder().with_recommended_fillers().connect_anvil();
1684        let num = provider.get_block_number().await.unwrap();
1685        assert_eq!(0, num);
1686    }
1687
1688    #[tokio::test]
1689    async fn test_builder_helper_fn() {
1690        let provider = builder::<Ethereum>().with_recommended_fillers().connect_anvil();
1691        let num = provider.get_block_number().await.unwrap();
1692        assert_eq!(0, num);
1693    }
1694
1695    #[cfg(feature = "hyper")]
1696    #[tokio::test]
1697    async fn test_default_hyper_transport() {
1698        let anvil = Anvil::new().spawn();
1699        let hyper_t = alloy_transport_http::HyperTransport::new_hyper(anvil.endpoint_url());
1700
1701        let rpc_client = alloy_rpc_client::RpcClient::new(hyper_t, true);
1702
1703        let provider = RootProvider::<Ethereum>::new(rpc_client);
1704        let num = provider.get_block_number().await.unwrap();
1705        assert_eq!(0, num);
1706    }
1707
1708    #[cfg(feature = "hyper")]
1709    #[tokio::test]
1710    async fn test_hyper_layer_transport() {
1711        struct LoggingLayer;
1712
1713        impl<S> Layer<S> for LoggingLayer {
1714            type Service = LoggingService<S>;
1715
1716            fn layer(&self, inner: S) -> Self::Service {
1717                LoggingService { inner }
1718            }
1719        }
1720
1721        #[derive(Clone)] // required
1722        struct LoggingService<S> {
1723            inner: S,
1724        }
1725
1726        impl<S, B> Service<hyper::Request<B>> for LoggingService<S>
1727        where
1728            S: Service<hyper::Request<B>, Response = HyperResponse, Error = Error>
1729                + Clone
1730                + Send
1731                + Sync
1732                + 'static,
1733            S::Future: Send,
1734            S::Error: std::error::Error + Send + Sync + 'static,
1735            B: From<Vec<u8>> + Send + 'static + Clone + Sync + std::fmt::Debug,
1736        {
1737            type Response = HyperResponse;
1738            type Error = Error;
1739            type Future = HyperResponseFut;
1740
1741            fn poll_ready(
1742                &mut self,
1743                cx: &mut std::task::Context<'_>,
1744            ) -> std::task::Poll<Result<(), Self::Error>> {
1745                self.inner.poll_ready(cx)
1746            }
1747
1748            fn call(&mut self, req: hyper::Request<B>) -> Self::Future {
1749                println!("Logging Layer - HyperRequest {req:?}");
1750
1751                let fut = self.inner.call(req);
1752
1753                Box::pin(fut)
1754            }
1755        }
1756        use http::header::{self, HeaderValue};
1757        use tower_http::{
1758            sensitive_headers::SetSensitiveRequestHeadersLayer, set_header::SetRequestHeaderLayer,
1759        };
1760        let anvil = Anvil::new().spawn();
1761        let hyper_client = Client::builder(TokioExecutor::new()).build_http::<Full<HyperBytes>>();
1762
1763        // Setup tower service with multiple layers modifying request headers
1764        let service = tower::ServiceBuilder::new()
1765            .layer(SetRequestHeaderLayer::if_not_present(
1766                header::USER_AGENT,
1767                HeaderValue::from_static("alloy app"),
1768            ))
1769            .layer(SetRequestHeaderLayer::overriding(
1770                header::AUTHORIZATION,
1771                HeaderValue::from_static("some-jwt-token"),
1772            ))
1773            .layer(SetRequestHeaderLayer::appending(
1774                header::SET_COOKIE,
1775                HeaderValue::from_static("cookie-value"),
1776            ))
1777            .layer(SetSensitiveRequestHeadersLayer::new([header::AUTHORIZATION])) // Hides the jwt token as sensitive.
1778            .layer(LoggingLayer)
1779            .service(hyper_client);
1780
1781        let layer_transport = alloy_transport_http::HyperClient::with_service(service);
1782
1783        let http_hyper =
1784            alloy_transport_http::Http::with_client(layer_transport, anvil.endpoint_url());
1785
1786        let rpc_client = alloy_rpc_client::RpcClient::new(http_hyper, true);
1787
1788        let provider = RootProvider::<Ethereum>::new(rpc_client);
1789        let num = provider.get_block_number().await.unwrap();
1790        assert_eq!(0, num);
1791
1792        // Test Cloning with service
1793        let cloned_t = provider.client().transport().clone();
1794
1795        let rpc_client = alloy_rpc_client::RpcClient::new(cloned_t, true);
1796
1797        let provider = RootProvider::<Ethereum>::new(rpc_client);
1798        let num = provider.get_block_number().await.unwrap();
1799        assert_eq!(0, num);
1800    }
1801
1802    #[cfg(feature = "hyper")]
1803    #[tokio::test]
1804    #[cfg_attr(windows, ignore = "no reth on windows")]
1805    async fn test_auth_layer_transport() {
1806        crate::ext::test::async_ci_only(|| async move {
1807            use alloy_node_bindings::Reth;
1808            use alloy_rpc_types_engine::JwtSecret;
1809            use alloy_transport_http::{AuthLayer, Http, HyperClient};
1810
1811            let secret = JwtSecret::random();
1812
1813            let reth =
1814                Reth::new().arg("--rpc.jwtsecret").arg(hex::encode(secret.as_bytes())).spawn();
1815
1816            let layer_transport = HyperClient::new().layer(AuthLayer::new(secret));
1817
1818            let http_hyper = Http::with_client(layer_transport, reth.endpoint_url());
1819
1820            let rpc_client = alloy_rpc_client::RpcClient::new(http_hyper, true);
1821
1822            let provider = RootProvider::<Ethereum>::new(rpc_client);
1823
1824            let num = provider.get_block_number().await.unwrap();
1825            assert_eq!(0, num);
1826        })
1827        .await;
1828    }
1829
1830    #[tokio::test]
1831    async fn test_builder_helper_fn_any_network() {
1832        let anvil = Anvil::new().spawn();
1833        let provider =
1834            builder::<AnyNetwork>().with_recommended_fillers().connect_http(anvil.endpoint_url());
1835        let num = provider.get_block_number().await.unwrap();
1836        assert_eq!(0, num);
1837    }
1838
1839    #[cfg(feature = "reqwest")]
1840    #[tokio::test]
1841    async fn object_safety() {
1842        let provider = ProviderBuilder::new().connect_anvil();
1843
1844        let refdyn = &provider as &dyn Provider<_>;
1845        let num = refdyn.get_block_number().await.unwrap();
1846        assert_eq!(0, num);
1847    }
1848
1849    #[cfg(feature = "ws")]
1850    #[tokio::test]
1851    async fn subscribe_blocks_http() {
1852        let provider = ProviderBuilder::new().connect_anvil_with_config(|a| a.block_time(1));
1853
1854        let err = provider.subscribe_blocks().await.unwrap_err();
1855        let alloy_json_rpc::RpcError::Transport(
1856            alloy_transport::TransportErrorKind::PubsubUnavailable,
1857        ) = err
1858        else {
1859            panic!("{err:?}");
1860        };
1861    }
1862
1863    // Ensures we can connect to a websocket using `wss`.
1864    #[cfg(feature = "ws")]
1865    #[tokio::test]
1866    async fn websocket_tls_setup() {
1867        for url in ["wss://mainnet.infura.io/ws/v3/b0f825787ba840af81e46c6a64d20754"] {
1868            let _ = ProviderBuilder::<_, _, Ethereum>::default().connect(url).await.unwrap();
1869        }
1870    }
1871
1872    #[cfg(feature = "ws")]
1873    #[tokio::test]
1874    async fn subscribe_blocks_ws() {
1875        use futures::stream::StreamExt;
1876
1877        let anvil = Anvil::new().block_time_f64(0.2).spawn();
1878        let ws = alloy_rpc_client::WsConnect::new(anvil.ws_endpoint());
1879        let client = alloy_rpc_client::RpcClient::connect_pubsub(ws).await.unwrap();
1880        let provider = RootProvider::<Ethereum>::new(client);
1881
1882        let sub = provider.subscribe_blocks().await.unwrap();
1883        let mut stream = sub.into_stream().take(5);
1884        let mut next = None;
1885        while let Some(header) = stream.next().await {
1886            if let Some(next) = &mut next {
1887                assert_eq!(header.number, *next);
1888                *next += 1;
1889            } else {
1890                next = Some(header.number + 1);
1891            }
1892        }
1893    }
1894
1895    #[cfg(feature = "ws")]
1896    #[tokio::test]
1897    async fn subscribe_full_blocks() {
1898        use futures::StreamExt;
1899
1900        let anvil = Anvil::new().block_time_f64(0.2).spawn();
1901        let ws = alloy_rpc_client::WsConnect::new(anvil.ws_endpoint());
1902        let client = alloy_rpc_client::RpcClient::connect_pubsub(ws).await.unwrap();
1903
1904        let provider = RootProvider::<Ethereum>::new(client);
1905
1906        let sub = provider.subscribe_full_blocks().hashes().channel_size(10);
1907
1908        let mut stream = sub.into_stream().await.unwrap().take(5);
1909
1910        let mut next = None;
1911        while let Some(Ok(block)) = stream.next().await {
1912            if let Some(next) = &mut next {
1913                assert_eq!(block.header().number, *next);
1914                *next += 1;
1915            } else {
1916                next = Some(block.header().number + 1);
1917            }
1918        }
1919    }
1920
1921    #[tokio::test]
1922    #[cfg(feature = "ws")]
1923    async fn subscribe_blocks_ws_remote() {
1924        use futures::stream::StreamExt;
1925
1926        let url = "wss://eth-mainnet.g.alchemy.com/v2/viFmeVzhg6bWKVMIWWS8MhmzREB-D4f7";
1927        let ws = alloy_rpc_client::WsConnect::new(url);
1928        let Ok(client) = alloy_rpc_client::RpcClient::connect_pubsub(ws).await else { return };
1929        let provider = RootProvider::<Ethereum>::new(client);
1930        let sub = provider.subscribe_blocks().await.unwrap();
1931        let mut stream = sub.into_stream().take(1);
1932        while let Some(header) = stream.next().await {
1933            println!("New block {header:?}");
1934            assert!(header.number > 0);
1935        }
1936    }
1937
1938    #[tokio::test]
1939    async fn test_custom_retry_policy() {
1940        #[derive(Debug, Clone)]
1941        struct CustomPolicy;
1942        impl RetryPolicy for CustomPolicy {
1943            fn should_retry(&self, _err: &alloy_transport::TransportError) -> bool {
1944                true
1945            }
1946
1947            fn backoff_hint(
1948                &self,
1949                _error: &alloy_transport::TransportError,
1950            ) -> Option<std::time::Duration> {
1951                None
1952            }
1953        }
1954
1955        let retry_layer = RetryBackoffLayer::new_with_policy(10, 100, 10000, CustomPolicy);
1956        let anvil = Anvil::new().spawn();
1957        let client = RpcClient::builder().layer(retry_layer).http(anvil.endpoint_url());
1958
1959        let provider = RootProvider::<Ethereum>::new(client);
1960        let num = provider.get_block_number().await.unwrap();
1961        assert_eq!(0, num);
1962    }
1963
1964    #[tokio::test]
1965    async fn test_send_tx() {
1966        let provider = ProviderBuilder::new().connect_anvil_with_wallet();
1967        let tx = TransactionRequest {
1968            value: Some(U256::from(100)),
1969            to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
1970            gas_price: Some(20e9 as u128),
1971            gas: Some(21000),
1972            ..Default::default()
1973        };
1974
1975        let builder = provider.send_transaction(tx.clone()).await.expect("failed to send tx");
1976        let hash1 = *builder.tx_hash();
1977        let hash2 = builder.watch().await.expect("failed to await pending tx");
1978        assert_eq!(hash1, hash2);
1979
1980        let builder = provider.send_transaction(tx).await.expect("failed to send tx");
1981        let hash1 = *builder.tx_hash();
1982        let hash2 =
1983            builder.get_receipt().await.expect("failed to await pending tx").transaction_hash;
1984        assert_eq!(hash1, hash2);
1985    }
1986
1987    #[tokio::test]
1988    async fn test_send_tx_sync() {
1989        let provider = ProviderBuilder::new().connect_anvil_with_wallet();
1990        let tx = TransactionRequest {
1991            value: Some(U256::from(100)),
1992            to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
1993            gas_price: Some(20e9 as u128),
1994            gas: Some(21000),
1995            ..Default::default()
1996        };
1997
1998        let _receipt =
1999            provider.send_transaction_sync(tx.clone()).await.expect("failed to send tx sync");
2000    }
2001
2002    #[tokio::test]
2003    async fn test_send_raw_transaction_sync() {
2004        let provider = ProviderBuilder::new().connect_anvil_with_wallet();
2005
2006        // Create a transaction
2007        let tx = TransactionRequest {
2008            nonce: Some(0),
2009            value: Some(U256::from(100)),
2010            to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
2011            gas_price: Some(20e9 as u128),
2012            gas: Some(21000),
2013            ..Default::default()
2014        };
2015
2016        // Build and sign the transaction to get the envelope
2017        let tx_envelope = tx.build(&provider.wallet()).await.expect("failed to build tx");
2018
2019        // Encode the transaction
2020        let encoded = tx_envelope.encoded_2718();
2021
2022        // Send using the sync method - this directly returns the receipt
2023        let receipt =
2024            provider.send_raw_transaction_sync(&encoded).await.expect("failed to send raw tx sync");
2025
2026        // Verify receipt
2027        assert_eq!(receipt.to(), Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045")));
2028        // The main idea that returned receipt should be already mined
2029        assert!(receipt.block_number().is_some(), "transaction should be mined");
2030        assert!(receipt.transaction_hash() != B256::ZERO, "should have valid tx hash");
2031    }
2032
2033    #[tokio::test]
2034    async fn test_watch_confirmed_tx() {
2035        let provider = ProviderBuilder::new().connect_anvil_with_wallet();
2036        let tx = TransactionRequest {
2037            value: Some(U256::from(100)),
2038            to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
2039            gas_price: Some(20e9 as u128),
2040            gas: Some(21000),
2041            ..Default::default()
2042        };
2043
2044        let builder = provider.send_transaction(tx).await.expect("failed to send tx");
2045        let hash1 = *builder.tx_hash();
2046
2047        // Wait until tx is confirmed.
2048        loop {
2049            if provider
2050                .get_transaction_receipt(hash1)
2051                .await
2052                .expect("failed to await pending tx")
2053                .is_some()
2054            {
2055                break;
2056            }
2057        }
2058
2059        // Submit another tx.
2060        let tx2 = TransactionRequest {
2061            value: Some(U256::from(100)),
2062            to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
2063            gas_price: Some(20e9 as u128),
2064            gas: Some(21000),
2065            ..Default::default()
2066        };
2067        provider.send_transaction(tx2).await.expect("failed to send tx").watch().await.unwrap();
2068
2069        // Only subscribe for watching _after_ tx was confirmed and we submitted a new one.
2070        let watch = builder.watch();
2071        // Wrap watch future in timeout to prevent it from hanging.
2072        let watch_with_timeout = tokio::time::timeout(Duration::from_secs(1), watch);
2073        let hash2 = watch_with_timeout
2074            .await
2075            .expect("Watching tx timed out")
2076            .expect("failed to await pending tx");
2077        assert_eq!(hash1, hash2);
2078    }
2079
2080    #[tokio::test]
2081    async fn gets_block_number() {
2082        let provider = ProviderBuilder::new().connect_anvil();
2083        let num = provider.get_block_number().await.unwrap();
2084        assert_eq!(0, num)
2085    }
2086
2087    #[tokio::test]
2088    async fn gets_block_number_for_id() {
2089        let provider = ProviderBuilder::new().connect_anvil();
2090
2091        let block_num = provider
2092            .get_block_number_by_id(BlockId::Number(BlockNumberOrTag::Number(0)))
2093            .await
2094            .unwrap();
2095        assert_eq!(block_num, Some(0));
2096
2097        let block_num = provider
2098            .get_block_number_by_id(BlockId::Number(BlockNumberOrTag::Latest))
2099            .await
2100            .unwrap();
2101        assert_eq!(block_num, Some(0));
2102
2103        let block =
2104            provider.get_block_by_number(BlockNumberOrTag::Number(0)).await.unwrap().unwrap();
2105        let hash = block.header.hash;
2106        let block_num = provider.get_block_number_by_id(BlockId::Hash(hash.into())).await.unwrap();
2107        assert_eq!(block_num, Some(0));
2108    }
2109
2110    #[tokio::test]
2111    async fn gets_block_number_with_raw_req() {
2112        let provider = ProviderBuilder::new().connect_anvil();
2113        let num: U64 =
2114            provider.raw_request("eth_blockNumber".into(), NoParams::default()).await.unwrap();
2115        assert_eq!(0, num.to::<u64>())
2116    }
2117
2118    #[cfg(feature = "anvil-api")]
2119    #[tokio::test]
2120    async fn gets_transaction_count() {
2121        let provider = ProviderBuilder::new().connect_anvil();
2122        let accounts = provider.get_accounts().await.unwrap();
2123        let sender = accounts[0];
2124
2125        // Initial tx count should be 0
2126        let count = provider.get_transaction_count(sender).await.unwrap();
2127        assert_eq!(count, 0);
2128
2129        // Send Tx
2130        let tx = TransactionRequest {
2131            value: Some(U256::from(100)),
2132            from: Some(sender),
2133            to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
2134            gas_price: Some(20e9 as u128),
2135            gas: Some(21000),
2136            ..Default::default()
2137        };
2138        let _ = provider.send_transaction(tx).await.unwrap().get_receipt().await;
2139
2140        // Tx count should be 1
2141        let count = provider.get_transaction_count(sender).await.unwrap();
2142        assert_eq!(count, 1);
2143
2144        // Tx count should be 0 at block 0
2145        let count = provider.get_transaction_count(sender).block_id(0.into()).await.unwrap();
2146        assert_eq!(count, 0);
2147    }
2148
2149    #[tokio::test]
2150    async fn gets_block_by_hash() {
2151        let provider = ProviderBuilder::new().connect_anvil();
2152        let num = 0;
2153        let tag: BlockNumberOrTag = num.into();
2154        let block = provider.get_block_by_number(tag).full().await.unwrap().unwrap();
2155        let hash = block.header.hash;
2156        let block = provider.get_block_by_hash(hash).full().await.unwrap().unwrap();
2157        assert_eq!(block.header.hash, hash);
2158    }
2159
2160    #[tokio::test]
2161    async fn gets_block_by_hash_with_raw_req() {
2162        let provider = ProviderBuilder::new().connect_anvil();
2163        let num = 0;
2164        let tag: BlockNumberOrTag = num.into();
2165        let block = provider.get_block_by_number(tag).full().await.unwrap().unwrap();
2166        let hash = block.header.hash;
2167        let block: Block = provider
2168            .raw_request::<(B256, bool), Block>("eth_getBlockByHash".into(), (hash, true))
2169            .await
2170            .unwrap();
2171        assert_eq!(block.header.hash, hash);
2172    }
2173
2174    #[tokio::test]
2175    async fn gets_block_by_number_full() {
2176        let provider = ProviderBuilder::new().connect_anvil();
2177        let num = 0;
2178        let tag: BlockNumberOrTag = num.into();
2179        let block = provider.get_block_by_number(tag).full().await.unwrap().unwrap();
2180        assert_eq!(block.header.number, num);
2181    }
2182
2183    #[tokio::test]
2184    async fn gets_block_by_number() {
2185        let provider = ProviderBuilder::new().connect_anvil();
2186        let num = 0;
2187        let tag: BlockNumberOrTag = num.into();
2188        let block = provider.get_block_by_number(tag).full().await.unwrap().unwrap();
2189        assert_eq!(block.header.number, num);
2190    }
2191
2192    #[tokio::test]
2193    async fn gets_client_version() {
2194        let provider = ProviderBuilder::new().connect_anvil();
2195        let version = provider.get_client_version().await.unwrap();
2196        assert!(version.contains("anvil"), "{version}");
2197    }
2198
2199    #[tokio::test]
2200    async fn gets_sha3() {
2201        let provider = ProviderBuilder::new().connect_anvil();
2202        let data = b"alloy";
2203        let hash = provider.get_sha3(data).await.unwrap();
2204        assert_eq!(hash, keccak256(data));
2205    }
2206
2207    #[tokio::test]
2208    async fn gets_chain_id() {
2209        let dev_chain_id: u64 = 13371337;
2210
2211        let provider =
2212            ProviderBuilder::new().connect_anvil_with_config(|a| a.chain_id(dev_chain_id));
2213
2214        let chain_id = provider.get_chain_id().await.unwrap();
2215        assert_eq!(chain_id, dev_chain_id);
2216    }
2217
2218    #[tokio::test]
2219    async fn gets_network_id() {
2220        let dev_chain_id: u64 = 13371337;
2221        let provider =
2222            ProviderBuilder::new().connect_anvil_with_config(|a| a.chain_id(dev_chain_id));
2223
2224        let chain_id = provider.get_net_version().await.unwrap();
2225        assert_eq!(chain_id, dev_chain_id);
2226    }
2227
2228    #[tokio::test]
2229    async fn gets_storage_at() {
2230        let provider = ProviderBuilder::new().connect_anvil();
2231        let addr = Address::with_last_byte(16);
2232        let storage = provider.get_storage_at(addr, U256::ZERO).await.unwrap();
2233        assert_eq!(storage, U256::ZERO);
2234    }
2235
2236    #[tokio::test]
2237    async fn gets_transaction_by_hash_not_found() {
2238        let provider = ProviderBuilder::new().connect_anvil();
2239        let tx_hash = b256!("5c03fab9114ceb98994b43892ade87ddfd9ae7e8f293935c3bd29d435dc9fd95");
2240        let tx = provider.get_transaction_by_hash(tx_hash).await.expect("failed to fetch tx");
2241
2242        assert!(tx.is_none());
2243    }
2244
2245    #[tokio::test]
2246    async fn gets_transaction_by_hash() {
2247        let provider = ProviderBuilder::new().connect_anvil_with_wallet();
2248
2249        let req = TransactionRequest::default()
2250            .from(provider.default_signer_address())
2251            .to(Address::repeat_byte(5))
2252            .value(U256::ZERO)
2253            .input(bytes!("deadbeef").into());
2254
2255        let tx_hash = *provider.send_transaction(req).await.expect("failed to send tx").tx_hash();
2256
2257        let tx = provider
2258            .get_transaction_by_hash(tx_hash)
2259            .await
2260            .expect("failed to fetch tx")
2261            .expect("tx not included");
2262        assert_eq!(tx.input(), &bytes!("deadbeef"));
2263    }
2264
2265    #[tokio::test]
2266    #[ignore]
2267    async fn gets_logs() {
2268        let provider = ProviderBuilder::new().connect_anvil();
2269        let filter = Filter::new()
2270            .at_block_hash(b256!(
2271                "b20e6f35d4b46b3c4cd72152faec7143da851a0dc281d390bdd50f58bfbdb5d3"
2272            ))
2273            .event_signature(b256!(
2274                "e1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"
2275            ));
2276        let logs = provider.get_logs(&filter).await.unwrap();
2277        assert_eq!(logs.len(), 1);
2278    }
2279
2280    #[tokio::test]
2281    #[ignore]
2282    async fn gets_tx_receipt() {
2283        let provider = ProviderBuilder::new().connect_anvil();
2284        let receipt = provider
2285            .get_transaction_receipt(b256!(
2286                "5c03fab9114ceb98994b43892ade87ddfd9ae7e8f293935c3bd29d435dc9fd95"
2287            ))
2288            .await
2289            .unwrap();
2290        assert!(receipt.is_some());
2291        let receipt = receipt.unwrap();
2292        assert_eq!(
2293            receipt.transaction_hash,
2294            b256!("5c03fab9114ceb98994b43892ade87ddfd9ae7e8f293935c3bd29d435dc9fd95")
2295        );
2296    }
2297
2298    #[tokio::test]
2299    async fn gets_max_priority_fee_per_gas() {
2300        let provider = ProviderBuilder::new().connect_anvil();
2301        let _fee = provider.get_max_priority_fee_per_gas().await.unwrap();
2302    }
2303
2304    #[tokio::test]
2305    async fn gets_fee_history() {
2306        let provider = ProviderBuilder::new().connect_anvil();
2307        let block_number = provider.get_block_number().await.unwrap();
2308        let fee_history = provider
2309            .get_fee_history(
2310                utils::EIP1559_FEE_ESTIMATION_PAST_BLOCKS,
2311                BlockNumberOrTag::Number(block_number),
2312                &[utils::EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE],
2313            )
2314            .await
2315            .unwrap();
2316        assert_eq!(fee_history.oldest_block, 0_u64);
2317    }
2318
2319    #[tokio::test]
2320    async fn gets_block_transaction_count_by_hash() {
2321        let provider = ProviderBuilder::new().connect_anvil();
2322        let block = provider.get_block(BlockId::latest()).await.unwrap().unwrap();
2323        let hash = block.header.hash;
2324        let tx_count = provider.get_block_transaction_count_by_hash(hash).await.unwrap();
2325        assert!(tx_count.is_some());
2326    }
2327
2328    #[tokio::test]
2329    async fn gets_block_transaction_count_by_number() {
2330        let provider = ProviderBuilder::new().connect_anvil();
2331        let tx_count =
2332            provider.get_block_transaction_count_by_number(BlockNumberOrTag::Latest).await.unwrap();
2333        assert!(tx_count.is_some());
2334    }
2335
2336    #[tokio::test]
2337    async fn gets_block_receipts() {
2338        let provider = ProviderBuilder::new().connect_anvil();
2339        let receipts =
2340            provider.get_block_receipts(BlockId::Number(BlockNumberOrTag::Latest)).await.unwrap();
2341        assert!(receipts.is_some());
2342    }
2343
2344    #[tokio::test]
2345    async fn sends_raw_transaction() {
2346        let provider = ProviderBuilder::new().connect_anvil();
2347        let pending = provider
2348            .send_raw_transaction(
2349                // Transfer 1 ETH from default EOA address to the Genesis address.
2350                bytes!("f865808477359400825208940000000000000000000000000000000000000000018082f4f5a00505e227c1c636c76fac55795db1a40a4d24840d81b40d2fe0cc85767f6bd202a01e91b437099a8a90234ac5af3cb7ca4fb1432e133f75f9a91678eaf5f487c74b").as_ref()
2351            )
2352            .await.unwrap();
2353        assert_eq!(
2354            pending.tx_hash().to_string(),
2355            "0x9dae5cf33694a02e8a7d5de3fe31e9d05ca0ba6e9180efac4ab20a06c9e598a3"
2356        );
2357    }
2358
2359    #[tokio::test]
2360    async fn connect_boxed() {
2361        let anvil = Anvil::new().spawn();
2362
2363        let provider = RootProvider::<Ethereum>::connect(anvil.endpoint().as_str()).await;
2364
2365        match provider {
2366            Ok(provider) => {
2367                let num = provider.get_block_number().await.unwrap();
2368                assert_eq!(0, num);
2369            }
2370            Err(e) => {
2371                assert_eq!(
2372                    format!("{e}"),
2373                    "hyper not supported by BuiltinConnectionString. Please instantiate a hyper client manually"
2374                );
2375            }
2376        }
2377    }
2378
2379    #[tokio::test]
2380    async fn any_network_wallet_filler() {
2381        use alloy_serde::WithOtherFields;
2382        let anvil = Anvil::new().spawn();
2383        let signer: PrivateKeySigner =
2384            "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".parse().unwrap();
2385        let wallet = EthereumWallet::from(signer);
2386
2387        let provider = ProviderBuilder::new()
2388            .network::<AnyNetwork>()
2389            .wallet(wallet)
2390            .connect_http(anvil.endpoint_url());
2391
2392        let tx = TransactionRequest::default()
2393            .with_to(address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"))
2394            .value(U256::from(325235));
2395
2396        let tx = WithOtherFields::new(tx);
2397
2398        let builder = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap();
2399
2400        assert!(builder.status());
2401    }
2402
2403    #[tokio::test]
2404    async fn builtin_connect_boxed() {
2405        let anvil = Anvil::new().spawn();
2406
2407        let conn: BuiltInConnectionString = anvil.endpoint().parse().unwrap();
2408
2409        let transport = conn.connect_boxed().await.unwrap();
2410
2411        let client = alloy_rpc_client::RpcClient::new(transport, true);
2412
2413        let provider = RootProvider::<Ethereum>::new(client);
2414
2415        let num = provider.get_block_number().await.unwrap();
2416        assert_eq!(0, num);
2417    }
2418
2419    #[tokio::test]
2420    async fn test_uncle_count() {
2421        let provider = ProviderBuilder::new().connect_anvil();
2422
2423        let count = provider.get_uncle_count(0.into()).await.unwrap();
2424        assert_eq!(count, 0);
2425    }
2426
2427    #[tokio::test]
2428    #[cfg(any(
2429        feature = "reqwest-default-tls",
2430        feature = "reqwest-rustls-tls",
2431        feature = "reqwest-native-tls",
2432    ))]
2433    #[ignore = "ignore until <https://github.com/paradigmxyz/reth/pull/14727> is in"]
2434    async fn call_mainnet() {
2435        use alloy_network::TransactionBuilder;
2436        use alloy_sol_types::SolValue;
2437
2438        let url = "https://docs-demo.quiknode.pro/";
2439        let provider = ProviderBuilder::new().connect_http(url.parse().unwrap());
2440        let req = TransactionRequest::default()
2441            .with_to(address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")) // WETH
2442            .with_input(bytes!("06fdde03")); // `name()`
2443        let result = provider.call(req.clone()).await.unwrap();
2444        assert_eq!(String::abi_decode(&result).unwrap(), "Wrapped Ether");
2445
2446        let result = provider.call(req).block(0.into()).await.unwrap();
2447        assert_eq!(result.to_string(), "0x");
2448    }
2449
2450    #[tokio::test]
2451    async fn call_many_mainnet() {
2452        use alloy_rpc_types_eth::{BlockOverrides, StateContext};
2453
2454        let url = "https://docs-demo.quiknode.pro/";
2455        let provider = ProviderBuilder::new().connect_http(url.parse().unwrap());
2456        let tx1 = TransactionRequest::default()
2457            .with_to(address!("6b175474e89094c44da98b954eedeac495271d0f"))
2458            .with_gas_limit(1000000)
2459            .with_gas_price(2023155498)
2460            .with_input(hex!("a9059cbb000000000000000000000000bc0E63965946815d105E7591407704e6e1964E590000000000000000000000000000000000000000000000000000000005f5e100"));
2461        let tx2 = TransactionRequest::default()
2462            .with_to(address!("833589fcd6edb6e08f4c7c32d4f71b54bda02913"))
2463            .with_gas_price(2023155498)
2464            .with_input(hex!(
2465                "70a08231000000000000000000000000bc0E63965946815d105E7591407704e6e1964E59"
2466            ));
2467
2468        let transactions = vec![tx1.clone(), tx2.clone()];
2469
2470        let block_override =
2471            BlockOverrides { number: Some(U256::from(12279785)), ..Default::default() };
2472
2473        let bundles = vec![Bundle { transactions, block_override: Some(block_override.clone()) }];
2474
2475        let context = StateContext {
2476            block_number: Some(BlockId::number(12279785)),
2477            transaction_index: Some(1.into()),
2478        };
2479
2480        let results = provider.call_many(&bundles).context(&context).await.unwrap();
2481
2482        let tx1_res = EthCallResponse {
2483            value: Some(
2484                hex!("0000000000000000000000000000000000000000000000000000000000000001").into(),
2485            ),
2486            error: None,
2487        };
2488        let tx2_res = EthCallResponse { value: Some(Bytes::new()), error: None };
2489        let expected = vec![vec![tx1_res.clone(), tx2_res.clone()]];
2490
2491        assert_eq!(results, expected);
2492
2493        // Two bundles
2494        let bundles = vec![
2495            Bundle {
2496                transactions: vec![tx1.clone()],
2497                block_override: Some(block_override.clone()),
2498            },
2499            Bundle {
2500                transactions: vec![tx2.clone()],
2501                block_override: Some(block_override.clone()),
2502            },
2503        ];
2504
2505        let results = provider.call_many(&bundles).context(&context).await.unwrap();
2506        let expected = vec![vec![tx1_res.clone()], vec![tx2_res.clone()]];
2507        assert_eq!(results, expected);
2508
2509        // Two bundles by extending existing.
2510        let b1 =
2511            vec![Bundle { transactions: vec![tx1], block_override: Some(block_override.clone()) }];
2512        let b2 = vec![Bundle { transactions: vec![tx2], block_override: Some(block_override) }];
2513
2514        let results = provider.call_many(&b1).context(&context).extend_bundles(&b2).await.unwrap();
2515        assert_eq!(results, expected);
2516    }
2517
2518    #[tokio::test]
2519    #[cfg(feature = "hyper-tls")]
2520    async fn hyper_https() {
2521        let url = "https://ethereum.reth.rs/rpc";
2522
2523        // With the `hyper` feature enabled .connect builds the provider based on
2524        // `HyperTransport`.
2525        let provider = ProviderBuilder::new().connect(url).await.unwrap();
2526
2527        let _num = provider.get_block_number().await.unwrap();
2528    }
2529
2530    #[tokio::test]
2531    async fn test_empty_transactions() {
2532        let provider = ProviderBuilder::new().connect_anvil();
2533
2534        let block = provider.get_block_by_number(0.into()).await.unwrap().unwrap();
2535        assert!(block.transactions.is_hashes());
2536    }
2537
2538    #[tokio::test]
2539    async fn disable_test() {
2540        let provider = ProviderBuilder::new()
2541            .disable_recommended_fillers()
2542            .with_cached_nonce_management()
2543            .connect_anvil();
2544
2545        let tx = TransactionRequest::default()
2546            .with_kind(alloy_primitives::TxKind::Create)
2547            .value(U256::from(1235))
2548            .with_input(Bytes::from_str("ffffffffffffff").unwrap());
2549
2550        let err = provider.send_transaction(tx).await.unwrap_err().to_string();
2551        assert!(err.contains("missing properties: [(\"NonceManager\", [\"from\"])]"));
2552    }
2553
2554    #[tokio::test]
2555    async fn capture_anvil_logs() {
2556        let mut anvil = Anvil::new().keep_stdout().spawn();
2557
2558        let provider = ProviderBuilder::new().connect_http(anvil.endpoint_url());
2559
2560        let tx = TransactionRequest::default()
2561            .with_from(address!("f39Fd6e51aad88F6F4ce6aB8827279cffFb92266"))
2562            .with_to(address!("70997970C51812dc3A010C7d01b50e0d17dc79C8"))
2563            .value(U256::from(100));
2564
2565        let _ = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap();
2566
2567        anvil.child_mut().kill().unwrap();
2568
2569        let mut output = String::new();
2570        anvil.child_mut().stdout.take().unwrap().read_to_string(&mut output).unwrap();
2571
2572        assert_eq!(anvil.chain_id(), 31337);
2573        assert_eq!(anvil.addresses().len(), 10);
2574        assert_eq!(anvil.keys().len(), 10);
2575
2576        assert!(output.contains("eth_sendTransaction"));
2577        assert!(output.contains("Block Number: 1"))
2578    }
2579
2580    #[tokio::test]
2581    async fn custom_estimator() {
2582        let provider = ProviderBuilder::new()
2583            .disable_recommended_fillers()
2584            .with_cached_nonce_management()
2585            .connect_anvil();
2586
2587        let _ = provider
2588            .estimate_eip1559_fees_with(Eip1559Estimator::new(|_fee, _rewards| Eip1559Estimation {
2589                max_fee_per_gas: 0,
2590                max_priority_fee_per_gas: 0,
2591            }))
2592            .await;
2593    }
2594
2595    #[tokio::test]
2596    #[cfg(not(windows))]
2597    async fn eth_sign_transaction() {
2598        async_ci_only(|| async {
2599            run_with_tempdir("reth-sign-tx", |dir| async {
2600                let reth = Reth::new().dev().disable_discovery().data_dir(dir).spawn();
2601                let provider = ProviderBuilder::new().connect_http(reth.endpoint_url());
2602
2603                let accounts = provider.get_accounts().await.unwrap();
2604                let from = accounts[0];
2605
2606                let tx = TransactionRequest::default()
2607                    .from(from)
2608                    .to(Address::random())
2609                    .value(U256::from(100))
2610                    .gas_limit(21000);
2611
2612                let signed_tx = provider.sign_transaction(tx).await.unwrap().to_vec();
2613
2614                let tx = TxEnvelope::decode(&mut signed_tx.as_slice()).unwrap();
2615
2616                let signer = tx.recover_signer().unwrap();
2617
2618                assert_eq!(signer, from);
2619            })
2620            .await
2621        })
2622        .await;
2623    }
2624
2625    #[cfg(feature = "throttle")]
2626    use alloy_transport::layers::ThrottleLayer;
2627
2628    #[cfg(feature = "throttle")]
2629    #[tokio::test]
2630    async fn test_throttled_provider() {
2631        let request_per_second = 10;
2632        let throttle_layer = ThrottleLayer::new(request_per_second);
2633
2634        let anvil = Anvil::new().spawn();
2635        let client = RpcClient::builder().layer(throttle_layer).http(anvil.endpoint_url());
2636        let provider = RootProvider::<Ethereum>::new(client);
2637
2638        let num_requests = 10;
2639        let start = std::time::Instant::now();
2640        for _ in 0..num_requests {
2641            provider.get_block_number().await.unwrap();
2642        }
2643
2644        let elapsed = start.elapsed();
2645        assert_eq!(elapsed.as_secs_f64().round() as u32, 1);
2646    }
2647
2648    #[tokio::test]
2649    #[cfg(feature = "hyper")]
2650    async fn test_connect_hyper_tls() {
2651        let p = ProviderBuilder::new().connect("https://ethereum.reth.rs/rpc").await.unwrap();
2652
2653        let _num = p.get_block_number().await.unwrap();
2654
2655        let anvil = Anvil::new().spawn();
2656        let p = ProviderBuilder::new().connect(&anvil.endpoint()).await.unwrap();
2657
2658        let _num = p.get_block_number().await.unwrap();
2659    }
2660
2661    #[tokio::test]
2662    async fn test_send_transaction_sync() {
2663        use alloy_network::TransactionBuilder;
2664        use alloy_primitives::{address, U256};
2665
2666        let anvil = Anvil::new().spawn();
2667        let provider = ProviderBuilder::new().connect_http(anvil.endpoint_url());
2668
2669        let tx = TransactionRequest::default()
2670            .with_from(address!("f39Fd6e51aad88F6F4ce6aB8827279cffFb92266"))
2671            .with_to(address!("70997970C51812dc3A010C7d01b50e0d17dc79C8"))
2672            .with_value(U256::from(100));
2673
2674        // Test the sync transaction sending
2675        let receipt = provider.send_transaction_sync(tx).await.unwrap();
2676
2677        // Verify we can access transaction metadata from the receipt
2678        let tx_hash = receipt.transaction_hash;
2679        assert!(!tx_hash.is_zero());
2680        assert_eq!(receipt.transaction_hash, tx_hash);
2681        assert!(receipt.status());
2682    }
2683
2684    #[tokio::test]
2685    async fn test_send_transaction_sync_with_fillers() {
2686        use alloy_network::TransactionBuilder;
2687        use alloy_primitives::{address, U256};
2688
2689        let provider = ProviderBuilder::new().connect_anvil_with_wallet();
2690
2691        // Create transaction without specifying gas or nonce - fillers should handle this
2692        let tx = TransactionRequest::default()
2693            .with_from(provider.default_signer_address())
2694            .with_to(address!("70997970C51812dc3A010C7d01b50e0d17dc79C8"))
2695            .with_value(U256::from(100));
2696        // Note: No gas limit, gas price, or nonce specified - fillers will provide these
2697
2698        // Test that sync transactions work with filler pipeline
2699        let receipt = provider.send_transaction_sync(tx).await.unwrap();
2700
2701        // Verify immediate access works
2702        let tx_hash = receipt.transaction_hash;
2703        assert!(!tx_hash.is_zero());
2704
2705        // Verify receipt shows fillers worked (gas was estimated and used)
2706        assert_eq!(receipt.transaction_hash, tx_hash);
2707        assert!(receipt.status());
2708        assert!(receipt.gas_used() > 0, "fillers should have estimated gas");
2709    }
2710
2711    #[tokio::test]
2712    async fn test_fill_transaction() {
2713        use alloy_network::TransactionBuilder;
2714        use alloy_primitives::{address, U256};
2715
2716        let provider = ProviderBuilder::new().connect_anvil_with_wallet();
2717
2718        let tx = TransactionRequest::default()
2719            .with_from(provider.default_signer_address())
2720            .with_to(address!("70997970C51812dc3A010C7d01b50e0d17dc79C8"))
2721            .with_value(U256::from(100));
2722
2723        let filled = provider.fill_transaction(tx).await.unwrap();
2724
2725        // Verify the response contains RLP-encoded raw bytes
2726        assert!(!filled.raw.is_empty(), "raw transaction bytes should not be empty");
2727
2728        // Verify the filled transaction has required fields populated
2729        let filled_tx = &filled.tx;
2730        assert!(filled_tx.to().is_some(), "filled transaction should have to address");
2731        assert!(filled_tx.gas_limit() > 0, "filled transaction should have gas limit");
2732        assert!(filled_tx.max_fee_per_gas() > 0, "filled transaction should have max fee per gas");
2733    }
2734}