alloy_provider/provider/
trait.rs

1//! Ethereum JSON-RPC provider.
2
3#![allow(unknown_lints, elided_named_lifetimes)]
4
5use super::{DynProvider, Empty, EthCallMany, MulticallBuilder};
6use crate::{
7    heart::PendingTransactionError,
8    utils::{self, Eip1559Estimation, Eip1559Estimator},
9    EthCall, EthGetBlock, Identity, PendingTransaction, PendingTransactionBuilder,
10    PendingTransactionConfig, ProviderBuilder, ProviderCall, RootProvider, RpcWithBlock,
11    SendableTx,
12};
13use alloy_consensus::BlockHeader;
14use alloy_eips::eip2718::Encodable2718;
15use alloy_json_rpc::{RpcError, RpcRecv, RpcSend};
16use alloy_network::{Ethereum, Network};
17use alloy_network_primitives::{BlockResponse, ReceiptResponse};
18use alloy_primitives::{
19    hex, Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, TxHash, B256, U128,
20    U256, U64,
21};
22use alloy_rpc_client::{ClientRef, NoParams, PollerBuilder, WeakClient};
23use alloy_rpc_types_eth::{
24    erc4337::TransactionConditional,
25    simulate::{SimulatePayload, SimulatedBlock},
26    AccessListResult, BlockId, BlockNumberOrTag, Bundle, EIP1186AccountProofResponse,
27    EthCallResponse, FeeHistory, Filter, FilterChanges, Index, Log, SyncStatus,
28};
29use alloy_transport::TransportResult;
30use serde_json::value::RawValue;
31use std::borrow::Cow;
32
33/// A task that polls the provider with `eth_getFilterChanges`, returning a list of `R`.
34///
35/// See [`PollerBuilder`] for more details.
36pub type FilterPollerBuilder<R> = PollerBuilder<(U256,), Vec<R>>;
37
38/// Ethereum JSON-RPC interface.
39///
40/// # Subscriptions
41///
42/// The provider supports `pubsub` subscriptions to new block headers and
43/// pending transactions. This is only available on `pubsub` clients, such as
44/// Websockets or IPC.
45///
46/// For a polling alternatives available over HTTP, use the `watch_*` methods.
47/// However, be aware that polling increases RPC usage drastically.
48///
49/// ## Special treatment of EIP-1559
50///
51/// While many RPC features are encapsulated by traits like [`DebugApi`],
52/// EIP-1559 fee estimation is generally assumed to be on by default. We
53/// generally assume that EIP-1559 is supported by the client and will
54/// proactively use it by default.
55///
56/// As a result, the provider supports EIP-1559 fee estimation the ethereum
57/// [`TransactionBuilder`] will use it by default. We acknowledge that this
58/// means EIP-1559 has a privileged status in comparison to other transaction
59/// types. Networks that DO NOT support EIP-1559 should create their own
60/// [`TransactionBuilder`] and Fillers to change this behavior.
61///
62/// [`TransactionBuilder`]: alloy_network::TransactionBuilder
63/// [`DebugApi`]: crate::ext::DebugApi
64#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
65#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
66#[auto_impl::auto_impl(&, &mut, Rc, Arc, Box)]
67pub trait Provider<N: Network = Ethereum>: Send + Sync {
68    /// Returns the root provider.
69    fn root(&self) -> &RootProvider<N>;
70
71    /// Returns the [`ProviderBuilder`](crate::ProviderBuilder) to build on.
72    fn builder() -> ProviderBuilder<Identity, Identity, N>
73    where
74        Self: Sized,
75    {
76        ProviderBuilder::default()
77    }
78
79    /// Returns the RPC client used to send requests.
80    ///
81    /// NOTE: this method should not be overridden.
82    #[inline]
83    fn client(&self) -> ClientRef<'_> {
84        self.root().client()
85    }
86
87    /// Returns a [`Weak`](std::sync::Weak) RPC client used to send requests.
88    ///
89    /// NOTE: this method should not be overridden.
90    #[inline]
91    fn weak_client(&self) -> WeakClient {
92        self.root().weak_client()
93    }
94
95    /// Returns a type erased provider wrapped in Arc. See [`DynProvider`].
96    ///
97    /// ```no_run
98    /// use alloy_provider::{DynProvider, Provider, ProviderBuilder};
99    ///
100    /// # async fn f() -> Result<(), Box<dyn std::error::Error>> {
101    /// let provider: DynProvider =
102    ///     ProviderBuilder::new().on_builtin("http://localhost:8080").await?.erased();
103    /// let block = provider.get_block_number().await?;
104    /// # Ok(())
105    /// # }
106    /// ```
107    #[auto_impl(keep_default_for(&, &mut, Rc, Arc, Box))]
108    #[doc(alias = "boxed")]
109    fn erased(self) -> DynProvider<N>
110    where
111        Self: Sized + 'static,
112    {
113        DynProvider::new(self)
114    }
115
116    /// Gets the accounts in the remote node. This is usually empty unless you're using a local
117    /// node.
118    fn get_accounts(&self) -> ProviderCall<NoParams, Vec<Address>> {
119        self.client().request_noparams("eth_accounts").into()
120    }
121
122    /// Returns the base fee per blob gas (blob gas price) in wei.
123    fn get_blob_base_fee(&self) -> ProviderCall<NoParams, U128, u128> {
124        self.client()
125            .request_noparams("eth_blobBaseFee")
126            .map_resp(utils::convert_u128 as fn(U128) -> u128)
127            .into()
128    }
129
130    /// Get the last block number available.
131    fn get_block_number(&self) -> ProviderCall<NoParams, U64, BlockNumber> {
132        self.client()
133            .request_noparams("eth_blockNumber")
134            .map_resp(utils::convert_u64 as fn(U64) -> u64)
135            .into()
136    }
137
138    /// Execute a smart contract call with a transaction request and state
139    /// overrides, without publishing a transaction.
140    ///
141    /// This function returns [`EthCall`] which can be used to execute the
142    /// call, or to add [`StateOverride`] or a [`BlockId`]. If no overrides
143    /// or block ID is provided, the call will be executed on the pending block
144    /// with the current state.
145    ///
146    /// [`StateOverride`]: alloy_rpc_types_eth::state::StateOverride
147    ///
148    /// ## Example
149    ///
150    /// ```
151    /// # use alloy_provider::Provider;
152    /// # use alloy_eips::BlockId;
153    /// # use alloy_rpc_types_eth::state::StateOverride;
154    /// # use alloy_transport::BoxTransport;
155    /// # async fn example<P: Provider>(
156    /// #    provider: P,
157    /// #    my_overrides: StateOverride
158    /// # ) -> Result<(), Box<dyn std::error::Error>> {
159    /// # let tx = alloy_rpc_types_eth::transaction::TransactionRequest::default();
160    /// // Execute a call on the latest block, with no state overrides
161    /// let output = provider.call(tx).await?;
162    /// # Ok(())
163    /// # }
164    /// ```
165    #[doc(alias = "eth_call")]
166    #[doc(alias = "call_with_overrides")]
167    fn call(&self, tx: N::TransactionRequest) -> EthCall<N, Bytes> {
168        EthCall::call(self.weak_client(), tx).block(BlockNumberOrTag::Pending.into())
169    }
170
171    /// Execute a list of [`Bundle`] against the provided [`StateContext`] and [`StateOverride`],
172    /// without publishing a transaction.
173    ///
174    /// This function returns [`EthCallMany`] builder which is used to execute the call, and also
175    /// set the [`StateContext`] and [`StateOverride`].
176    ///
177    /// [`StateContext`]: alloy_rpc_types_eth::StateContext
178    /// [`StateOverride`]: alloy_rpc_types_eth::state::StateOverride
179    #[doc(alias = "eth_callMany")]
180    fn call_many<'req>(
181        &self,
182        bundles: &'req Vec<Bundle>,
183    ) -> EthCallMany<'req, N, Vec<Vec<EthCallResponse>>> {
184        EthCallMany::new(self.weak_client(), bundles)
185    }
186
187    /// Execute a multicall by leveraging the [`MulticallBuilder`].
188    ///
189    /// This function returns a [`MulticallBuilder`] which is used to add multiple calls and execute
190    /// them.
191    ///
192    /// ## Example
193    ///
194    /// ```ignore
195    /// use alloy_primitives::address;
196    /// use alloy_provider::{MulticallBuilder, Provider, ProviderBuilder};
197    /// use alloy_sol_types::sol;
198    ///
199    /// sol! {
200    ///    #[sol(rpc)]
201    ///    #[derive(Debug, PartialEq)]
202    ///    interface ERC20 {
203    ///        function totalSupply() external view returns (uint256 totalSupply);
204    ///        function balanceOf(address owner) external view returns (uint256 balance);
205    ///    }
206    /// }
207    ///
208    /// #[tokio::main]
209    /// async fn main() {
210    ///     let weth = address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2");
211    ///     let provider = ProviderBuilder::new().on_http("https://eth.merkle.io".parse().unwrap());
212    ///     let erc20 = ERC20::new(weth, &provider);
213    ///
214    ///     let ts_call = erc20.totalSupply();
215    ///     let balance_call = erc20.balanceOf(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045"));
216    ///
217    ///     let multicall = provider.multicall().add(ts_call).add(balance_call);
218    ///
219    ///     let (_block_num, (total_supply, balance)) = multicall.aggregate().await.unwrap();
220    ///
221    ///     println!("Total Supply: {:?}, Balance: {:?}", total_supply, balance);
222    /// }
223    /// ```
224    #[auto_impl(keep_default_for(&, &mut, Rc, Arc, Box))]
225    fn multicall(&self) -> MulticallBuilder<Empty, &Self, N>
226    where
227        Self: Sized,
228    {
229        MulticallBuilder::new(self)
230    }
231
232    /// Executes an arbitrary number of transactions on top of the requested state.
233    ///
234    /// The transactions are packed into individual blocks. Overrides can be provided.
235    #[doc(alias = "eth_simulateV1")]
236    fn simulate<'req>(
237        &self,
238        payload: &'req SimulatePayload,
239    ) -> RpcWithBlock<&'req SimulatePayload, Vec<SimulatedBlock<N::BlockResponse>>> {
240        self.client().request("eth_simulateV1", payload).into()
241    }
242
243    /// Gets the chain ID.
244    fn get_chain_id(&self) -> ProviderCall<NoParams, U64, u64> {
245        self.client()
246            .request_noparams("eth_chainId")
247            .map_resp(utils::convert_u64 as fn(U64) -> u64)
248            .into()
249    }
250
251    /// Create an [EIP-2930] access list.
252    ///
253    /// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930
254    fn create_access_list<'a>(
255        &self,
256        request: &'a N::TransactionRequest,
257    ) -> RpcWithBlock<&'a N::TransactionRequest, AccessListResult> {
258        self.client().request("eth_createAccessList", request).into()
259    }
260
261    /// Create an [`EthCall`] future to estimate the gas required for a
262    /// transaction.
263    ///
264    /// The future can be used to specify a [`StateOverride`] or [`BlockId`]
265    /// before dispatching the call. If no overrides or block ID is provided,
266    /// the gas estimate will be computed for the pending block with the
267    /// current state.
268    ///
269    /// [`StateOverride`]: alloy_rpc_types_eth::state::StateOverride
270    ///
271    /// # Note
272    ///
273    /// Not all client implementations support state overrides for eth_estimateGas.
274    fn estimate_gas(&self, tx: N::TransactionRequest) -> EthCall<N, U64, u64> {
275        EthCall::gas_estimate(self.weak_client(), tx)
276            .block(BlockNumberOrTag::Pending.into())
277            .map_resp(utils::convert_u64)
278    }
279
280    /// Estimates the EIP1559 `maxFeePerGas` and `maxPriorityFeePerGas` fields.
281    ///
282    /// Receives an [Eip1559Estimator] that can be used to modify
283    /// how to estimate these fees.
284    async fn estimate_eip1559_fees_with(
285        &self,
286        estimator: Eip1559Estimator,
287    ) -> TransportResult<Eip1559Estimation> {
288        let fee_history = self
289            .get_fee_history(
290                utils::EIP1559_FEE_ESTIMATION_PAST_BLOCKS,
291                BlockNumberOrTag::Latest,
292                &[utils::EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE],
293            )
294            .await?;
295
296        // if the base fee of the Latest block is 0 then we need check if the latest block even has
297        // a base fee/supports EIP1559
298        let base_fee_per_gas = match fee_history.latest_block_base_fee() {
299            Some(base_fee) if base_fee != 0 => base_fee,
300            _ => {
301                // empty response, fetch basefee from latest block directly
302                self.get_block_by_number(BlockNumberOrTag::Latest)
303                    .await?
304                    .ok_or(RpcError::NullResp)?
305                    .header()
306                    .as_ref()
307                    .base_fee_per_gas()
308                    .ok_or(RpcError::UnsupportedFeature("eip1559"))?
309                    .into()
310            }
311        };
312
313        Ok(estimator.estimate(base_fee_per_gas, &fee_history.reward.unwrap_or_default()))
314    }
315
316    /// Estimates the EIP1559 `maxFeePerGas` and `maxPriorityFeePerGas` fields.
317    ///
318    /// Uses the builtin estimator [`utils::eip1559_default_estimator`] function.
319    async fn estimate_eip1559_fees(&self) -> TransportResult<Eip1559Estimation> {
320        self.estimate_eip1559_fees_with(Eip1559Estimator::default()).await
321    }
322
323    /// Returns a collection of historical gas information [FeeHistory] which
324    /// can be used to calculate the EIP1559 fields `maxFeePerGas` and `maxPriorityFeePerGas`.
325    /// `block_count` can range from 1 to 1024 blocks in a single request.
326    async fn get_fee_history(
327        &self,
328        block_count: u64,
329        last_block: BlockNumberOrTag,
330        reward_percentiles: &[f64],
331    ) -> TransportResult<FeeHistory> {
332        self.client()
333            .request("eth_feeHistory", (U64::from(block_count), last_block, reward_percentiles))
334            .await
335    }
336
337    /// Gets the current gas price in wei.
338    fn get_gas_price(&self) -> ProviderCall<NoParams, U128, u128> {
339        self.client()
340            .request_noparams("eth_gasPrice")
341            .map_resp(utils::convert_u128 as fn(U128) -> u128)
342            .into()
343    }
344
345    /// Retrieves account information ([Account](alloy_consensus::Account)) for the given [Address]
346    /// at the particular [BlockId].
347    fn get_account(&self, address: Address) -> RpcWithBlock<Address, alloy_consensus::Account> {
348        self.client().request("eth_getAccount", address).into()
349    }
350
351    /// Gets the balance of the account.
352    ///
353    /// Defaults to the latest block. See also [`RpcWithBlock::block_id`].
354    fn get_balance(&self, address: Address) -> RpcWithBlock<Address, U256, U256> {
355        self.client().request("eth_getBalance", address).into()
356    }
357
358    /// Gets a block by either its hash, tag, or number
359    ///
360    /// By default this fetches the block with only the transaction hashes, and not full
361    /// transactions.
362    ///
363    /// To get full transactions one can do:
364    ///
365    /// ```ignore
366    /// let block = provider.get_block(BlockId::latest()).full().await.unwrap();
367    /// ```
368    fn get_block(&self, block: BlockId) -> EthGetBlock<N::BlockResponse> {
369        match block {
370            BlockId::Hash(hash) => EthGetBlock::by_hash(hash.block_hash, self.client()),
371            BlockId::Number(number) => EthGetBlock::by_number(number, self.client()),
372        }
373    }
374
375    /// Gets a block by its [BlockHash]
376    ///
377    /// By default this fetches the block with only the transaction hashes populated in the block,
378    /// and not the full transactions.
379    ///
380    ///
381    ///
382    /// # Example
383    ///
384    /// ```no_run
385    /// # use alloy_provider::{Provider, ProviderBuilder};
386    /// # use alloy_primitives::b256;
387    ///
388    /// #[tokio::main]
389    /// async fn main() {
390    ///     let provider = ProviderBuilder::new().on_http("https://eth.merkle.io".parse().unwrap());
391    ///     let block_hash = b256!("6032d03ee8e43e8999c2943152a4daebfc4b75b7f7a9647d2677299d215127da");
392    ///
393    ///     // Gets a block by its hash with only transactions hashes.
394    ///     let block = provider.get_block_by_hash(block_hash).await.unwrap();
395    ///
396    ///     // Gets a block by its hash with full transactions.
397    ///     let block = provider.get_block_by_hash(block_hash).full().await.unwrap();
398    /// }
399    /// ```
400    fn get_block_by_hash(&self, hash: BlockHash) -> EthGetBlock<N::BlockResponse> {
401        EthGetBlock::by_hash(hash, self.client())
402    }
403
404    /// Gets a block by its [BlockNumberOrTag]
405    ///
406    /// By default this fetches the block with only the transaction hashes populated in the block,
407    /// and not the full transactions.
408    ///
409    /// # Example
410    ///
411    /// ```no_run
412    /// # use alloy_provider::{Provider, ProviderBuilder};
413    /// # use alloy_eips::BlockNumberOrTag;
414    ///
415    /// #[tokio::main]
416    /// async fn main() {
417    ///     let provider = ProviderBuilder::new().on_http("https://eth.merkle.io".parse().unwrap());
418    ///     let num = BlockNumberOrTag::Number(0);
419    ///
420    ///     // Gets a block by its number with only transactions hashes.
421    ///     let block = provider.get_block_by_number(num).await.unwrap();
422    ///
423    ///     // Gets a block by its number with full transactions.
424    ///     let block = provider.get_block_by_number(num).full().await.unwrap();
425    /// }
426    /// ```
427    fn get_block_by_number(&self, number: BlockNumberOrTag) -> EthGetBlock<N::BlockResponse> {
428        EthGetBlock::by_number(number, self.client())
429    }
430
431    /// Returns the number of transactions in a block from a block matching the given block hash.
432    async fn get_block_transaction_count_by_hash(
433        &self,
434        hash: BlockHash,
435    ) -> TransportResult<Option<u64>> {
436        self.client()
437            .request("eth_getBlockTransactionCountByHash", (hash,))
438            .await
439            .map(|opt_count: Option<U64>| opt_count.map(|count| count.to::<u64>()))
440    }
441
442    /// Returns the number of transactions in a block matching the given block number.
443    async fn get_block_transaction_count_by_number(
444        &self,
445        block_number: BlockNumberOrTag,
446    ) -> TransportResult<Option<u64>> {
447        self.client()
448            .request("eth_getBlockTransactionCountByNumber", (block_number,))
449            .await
450            .map(|opt_count: Option<U64>| opt_count.map(|count| count.to::<u64>()))
451    }
452
453    /// Gets the selected block [BlockId] receipts.
454    fn get_block_receipts(
455        &self,
456        block: BlockId,
457    ) -> ProviderCall<(BlockId,), Option<Vec<N::ReceiptResponse>>> {
458        self.client().request("eth_getBlockReceipts", (block,)).into()
459    }
460
461    /// Gets the bytecode located at the corresponding [Address].
462    fn get_code_at(&self, address: Address) -> RpcWithBlock<Address, Bytes> {
463        self.client().request("eth_getCode", address).into()
464    }
465
466    /// Watch for new blocks by polling the provider with
467    /// [`eth_getFilterChanges`](Self::get_filter_changes).
468    ///
469    /// Returns a builder that is used to configure the poller. See [`PollerBuilder`] for more
470    /// details.
471    ///
472    /// # Examples
473    ///
474    /// Get the next 5 blocks:
475    ///
476    /// ```no_run
477    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
478    /// use futures::StreamExt;
479    ///
480    /// let poller = provider.watch_blocks().await?;
481    /// let mut stream = poller.into_stream().flat_map(futures::stream::iter).take(5);
482    /// while let Some(block_hash) = stream.next().await {
483    ///    println!("new block: {block_hash}");
484    /// }
485    /// # Ok(())
486    /// # }
487    /// ```
488    async fn watch_blocks(&self) -> TransportResult<FilterPollerBuilder<B256>> {
489        let id = self.new_block_filter().await?;
490        Ok(PollerBuilder::new(self.weak_client(), "eth_getFilterChanges", (id,)))
491    }
492
493    /// Watch for new pending transaction by polling the provider with
494    /// [`eth_getFilterChanges`](Self::get_filter_changes).
495    ///
496    /// Returns a builder that is used to configure the poller. See [`PollerBuilder`] for more
497    /// details.
498    ///
499    /// # Examples
500    ///
501    /// Get the next 5 pending transaction hashes:
502    ///
503    /// ```no_run
504    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
505    /// use futures::StreamExt;
506    ///
507    /// let poller = provider.watch_pending_transactions().await?;
508    /// let mut stream = poller.into_stream().flat_map(futures::stream::iter).take(5);
509    /// while let Some(tx_hash) = stream.next().await {
510    ///    println!("new pending transaction hash: {tx_hash}");
511    /// }
512    /// # Ok(())
513    /// # }
514    /// ```
515    async fn watch_pending_transactions(&self) -> TransportResult<FilterPollerBuilder<B256>> {
516        let id = self.new_pending_transactions_filter(false).await?;
517        Ok(PollerBuilder::new(self.weak_client(), "eth_getFilterChanges", (id,)))
518    }
519
520    /// Watch for new logs using the given filter by polling the provider with
521    /// [`eth_getFilterChanges`](Self::get_filter_changes).
522    ///
523    /// Returns a builder that is used to configure the poller. See [`PollerBuilder`] for more
524    /// details.
525    ///
526    /// # Examples
527    ///
528    /// Get the next 5 USDC transfer logs:
529    ///
530    /// ```no_run
531    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
532    /// use alloy_primitives::{address, b256};
533    /// use alloy_rpc_types_eth::Filter;
534    /// use futures::StreamExt;
535    ///
536    /// let address = address!("a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48");
537    /// let transfer_signature = b256!("ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef");
538    /// let filter = Filter::new().address(address).event_signature(transfer_signature);
539    ///
540    /// let poller = provider.watch_logs(&filter).await?;
541    /// let mut stream = poller.into_stream().flat_map(futures::stream::iter).take(5);
542    /// while let Some(log) = stream.next().await {
543    ///    println!("new log: {log:#?}");
544    /// }
545    /// # Ok(())
546    /// # }
547    /// ```
548    async fn watch_logs(&self, filter: &Filter) -> TransportResult<FilterPollerBuilder<Log>> {
549        let id = self.new_filter(filter).await?;
550        Ok(PollerBuilder::new(self.weak_client(), "eth_getFilterChanges", (id,)))
551    }
552
553    /// Watch for new pending transaction bodies by polling the provider with
554    /// [`eth_getFilterChanges`](Self::get_filter_changes).
555    ///
556    /// Returns a builder that is used to configure the poller. See [`PollerBuilder`] for more
557    /// details.
558    ///
559    /// # Support
560    ///
561    /// This endpoint might not be supported by all clients.
562    ///
563    /// # Examples
564    ///
565    /// Get the next 5 pending transaction bodies:
566    ///
567    /// ```no_run
568    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
569    /// use futures::StreamExt;
570    ///
571    /// let poller = provider.watch_full_pending_transactions().await?;
572    /// let mut stream = poller.into_stream().flat_map(futures::stream::iter).take(5);
573    /// while let Some(tx) = stream.next().await {
574    ///    println!("new pending transaction: {tx:#?}");
575    /// }
576    /// # Ok(())
577    /// # }
578    /// ```
579    async fn watch_full_pending_transactions(
580        &self,
581    ) -> TransportResult<FilterPollerBuilder<N::TransactionResponse>> {
582        let id = self.new_pending_transactions_filter(true).await?;
583        Ok(PollerBuilder::new(self.weak_client(), "eth_getFilterChanges", (id,)))
584    }
585
586    /// Get a list of values that have been added since the last poll.
587    ///
588    /// The return value depends on what stream `id` corresponds to.
589    /// See [`FilterChanges`] for all possible return values.
590    #[auto_impl(keep_default_for(&, &mut, Rc, Arc, Box))]
591    async fn get_filter_changes<R: RpcRecv>(&self, id: U256) -> TransportResult<Vec<R>>
592    where
593        Self: Sized,
594    {
595        self.client().request("eth_getFilterChanges", (id,)).await
596    }
597
598    /// Get a list of values that have been added since the last poll.
599    ///
600    /// This returns an enum over all possible return values. You probably want to use
601    /// [`get_filter_changes`](Self::get_filter_changes) instead.
602    async fn get_filter_changes_dyn(&self, id: U256) -> TransportResult<FilterChanges> {
603        self.client().request("eth_getFilterChanges", (id,)).await
604    }
605
606    /// Retrieves a [`Vec<Log>`] for the given filter ID.
607    async fn get_filter_logs(&self, id: U256) -> TransportResult<Vec<Log>> {
608        self.client().request("eth_getFilterLogs", (id,)).await
609    }
610
611    /// Request provider to uninstall the filter with the given ID.
612    async fn uninstall_filter(&self, id: U256) -> TransportResult<bool> {
613        self.client().request("eth_uninstallFilter", (id,)).await
614    }
615
616    /// Watch for the confirmation of a single pending transaction with the given configuration.
617    ///
618    /// Note that this is handled internally rather than calling any specific RPC method, and as
619    /// such should not be overridden.
620    #[inline]
621    async fn watch_pending_transaction(
622        &self,
623        config: PendingTransactionConfig,
624    ) -> Result<PendingTransaction, PendingTransactionError> {
625        self.root().watch_pending_transaction(config).await
626    }
627
628    /// Retrieves a [`Vec<Log>`] with the given [Filter].
629    async fn get_logs(&self, filter: &Filter) -> TransportResult<Vec<Log>> {
630        self.client().request("eth_getLogs", (filter,)).await
631    }
632
633    /// Get the account and storage values of the specified account including the merkle proofs.
634    ///
635    /// This call can be used to verify that the data has not been tampered with.
636    fn get_proof(
637        &self,
638        address: Address,
639        keys: Vec<StorageKey>,
640    ) -> RpcWithBlock<(Address, Vec<StorageKey>), EIP1186AccountProofResponse> {
641        self.client().request("eth_getProof", (address, keys)).into()
642    }
643
644    /// Gets the specified storage value from [Address].
645    fn get_storage_at(
646        &self,
647        address: Address,
648        key: U256,
649    ) -> RpcWithBlock<(Address, U256), StorageValue> {
650        self.client().request("eth_getStorageAt", (address, key)).into()
651    }
652
653    /// Gets a transaction by its [TxHash].
654    fn get_transaction_by_hash(
655        &self,
656        hash: TxHash,
657    ) -> ProviderCall<(TxHash,), Option<N::TransactionResponse>> {
658        self.client().request("eth_getTransactionByHash", (hash,)).into()
659    }
660
661    /// Gets a transaction by block hash and transaction index position.
662    fn get_transaction_by_block_hash_and_index(
663        &self,
664        block_hash: B256,
665        index: usize,
666    ) -> ProviderCall<(B256, Index), Option<N::TransactionResponse>> {
667        self.client()
668            .request("eth_getTransactionByBlockHashAndIndex", (block_hash, Index(index)))
669            .into()
670    }
671
672    /// Gets a raw transaction by block hash and transaction index position.
673    fn get_raw_transaction_by_block_hash_and_index(
674        &self,
675        block_hash: B256,
676        index: usize,
677    ) -> ProviderCall<(B256, Index), Option<Bytes>> {
678        self.client()
679            .request("eth_getRawTransactionByBlockHashAndIndex", (block_hash, Index(index)))
680            .into()
681    }
682
683    /// Gets a transaction by block number and transaction index position.
684    fn get_transaction_by_block_number_and_index(
685        &self,
686        block_number: BlockNumberOrTag,
687        index: usize,
688    ) -> ProviderCall<(BlockNumberOrTag, Index), Option<N::TransactionResponse>> {
689        self.client()
690            .request("eth_getTransactionByBlockNumberAndIndex", (block_number, Index(index)))
691            .into()
692    }
693
694    /// Gets a raw transaction by block number and transaction index position.
695    fn get_raw_transaction_by_block_number_and_index(
696        &self,
697        block_number: BlockNumberOrTag,
698        index: usize,
699    ) -> ProviderCall<(BlockNumberOrTag, Index), Option<Bytes>> {
700        self.client()
701            .request("eth_getRawTransactionByBlockNumberAndIndex", (block_number, Index(index)))
702            .into()
703    }
704
705    /// Returns the EIP-2718 encoded transaction if it exists, see also
706    /// [Decodable2718](alloy_eips::eip2718::Decodable2718).
707    ///
708    /// If the transaction is an EIP-4844 transaction that is still in the pool (pending) it will
709    /// include the sidecar, otherwise it will the consensus variant without the sidecar:
710    /// [TxEip4844](alloy_consensus::transaction::eip4844::TxEip4844).
711    ///
712    /// This can be decoded into [TxEnvelope](alloy_consensus::transaction::TxEnvelope).
713    fn get_raw_transaction_by_hash(&self, hash: TxHash) -> ProviderCall<(TxHash,), Option<Bytes>> {
714        self.client().request("eth_getRawTransactionByHash", (hash,)).into()
715    }
716
717    /// Gets the transaction count (AKA "nonce") of the corresponding address.
718    #[doc(alias = "get_nonce")]
719    #[doc(alias = "get_account_nonce")]
720    fn get_transaction_count(
721        &self,
722        address: Address,
723    ) -> RpcWithBlock<Address, U64, u64, fn(U64) -> u64> {
724        self.client()
725            .request("eth_getTransactionCount", address)
726            .map_resp(utils::convert_u64 as fn(U64) -> u64)
727            .into()
728    }
729
730    /// Gets a transaction receipt if it exists, by its [TxHash].
731    fn get_transaction_receipt(
732        &self,
733        hash: TxHash,
734    ) -> ProviderCall<(TxHash,), Option<N::ReceiptResponse>> {
735        self.client().request("eth_getTransactionReceipt", (hash,)).into()
736    }
737
738    /// Gets an uncle block through the tag [BlockId] and index [u64].
739    async fn get_uncle(&self, tag: BlockId, idx: u64) -> TransportResult<Option<N::BlockResponse>> {
740        let idx = U64::from(idx);
741        match tag {
742            BlockId::Hash(hash) => {
743                self.client()
744                    .request("eth_getUncleByBlockHashAndIndex", (hash.block_hash, idx))
745                    .await
746            }
747            BlockId::Number(number) => {
748                self.client().request("eth_getUncleByBlockNumberAndIndex", (number, idx)).await
749            }
750        }
751    }
752
753    /// Gets the number of uncles for the block specified by the tag [BlockId].
754    async fn get_uncle_count(&self, tag: BlockId) -> TransportResult<u64> {
755        match tag {
756            BlockId::Hash(hash) => self
757                .client()
758                .request("eth_getUncleCountByBlockHash", (hash.block_hash,))
759                .await
760                .map(|count: U64| count.to::<u64>()),
761            BlockId::Number(number) => self
762                .client()
763                .request("eth_getUncleCountByBlockNumber", (number,))
764                .await
765                .map(|count: U64| count.to::<u64>()),
766        }
767    }
768
769    /// Returns a suggestion for the current `maxPriorityFeePerGas` in wei.
770    fn get_max_priority_fee_per_gas(&self) -> ProviderCall<NoParams, U128, u128> {
771        self.client()
772            .request_noparams("eth_maxPriorityFeePerGas")
773            .map_resp(utils::convert_u128 as fn(U128) -> u128)
774            .into()
775    }
776
777    /// Notify the provider that we are interested in new blocks.
778    ///
779    /// Returns the ID to use with [`eth_getFilterChanges`](Self::get_filter_changes).
780    ///
781    /// See also [`watch_blocks`](Self::watch_blocks) to configure a poller.
782    async fn new_block_filter(&self) -> TransportResult<U256> {
783        self.client().request_noparams("eth_newBlockFilter").await
784    }
785
786    /// Notify the provider that we are interested in logs that match the given filter.
787    ///
788    /// Returns the ID to use with [`eth_getFilterChanges`](Self::get_filter_changes).
789    ///
790    /// See also [`watch_logs`](Self::watch_logs) to configure a poller.
791    async fn new_filter(&self, filter: &Filter) -> TransportResult<U256> {
792        self.client().request("eth_newFilter", (filter,)).await
793    }
794
795    /// Notify the provider that we are interested in new pending transactions.
796    ///
797    /// If `full` is `true`, the stream will consist of full transaction bodies instead of just the
798    /// hashes. This not supported by all clients.
799    ///
800    /// Returns the ID to use with [`eth_getFilterChanges`](Self::get_filter_changes).
801    ///
802    /// See also [`watch_pending_transactions`](Self::watch_pending_transactions) to configure a
803    /// poller.
804    async fn new_pending_transactions_filter(&self, full: bool) -> TransportResult<U256> {
805        // NOTE: We don't want to send `false` as the client might not support it.
806        let param = if full { &[true][..] } else { &[] };
807        self.client().request("eth_newPendingTransactionFilter", param).await
808    }
809
810    /// Broadcasts a raw transaction RLP bytes to the network.
811    ///
812    /// See [`send_transaction`](Self::send_transaction) for more details.
813    async fn send_raw_transaction(
814        &self,
815        encoded_tx: &[u8],
816    ) -> TransportResult<PendingTransactionBuilder<N>> {
817        let rlp_hex = hex::encode_prefixed(encoded_tx);
818        let tx_hash = self.client().request("eth_sendRawTransaction", (rlp_hex,)).await?;
819        Ok(PendingTransactionBuilder::new(self.root().clone(), tx_hash))
820    }
821
822    /// Broadcasts a raw transaction RLP bytes with a conditional [`TransactionConditional`] to the
823    /// network.
824    ///
825    /// TransactionConditional represents the preconditions that determine the inclusion of the
826    /// transaction, enforced out-of-protocol by the sequencer.
827    ///
828    /// Note: This endpoint is only available on certain networks, e.g. opstack chains, polygon,
829    /// bsc.
830    ///
831    /// See [`TransactionConditional`] for more details.
832    async fn send_raw_transaction_conditional(
833        &self,
834        encoded_tx: &[u8],
835        conditional: TransactionConditional,
836    ) -> TransportResult<PendingTransactionBuilder<N>> {
837        let rlp_hex = hex::encode_prefixed(encoded_tx);
838        let tx_hash = self
839            .client()
840            .request("eth_sendRawTransactionConditional", (rlp_hex, conditional))
841            .await?;
842        Ok(PendingTransactionBuilder::new(self.root().clone(), tx_hash))
843    }
844
845    /// Broadcasts a transaction to the network.
846    ///
847    /// Returns a [`PendingTransactionBuilder`] which can be used to configure
848    /// how and when to await the transaction's confirmation.
849    ///
850    /// # Examples
851    ///
852    /// See [`PendingTransactionBuilder`](crate::PendingTransactionBuilder) for more examples.
853    ///
854    /// ```no_run
855    /// # 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>> {
856    /// let tx_hash = provider.send_transaction(tx)
857    ///     .await?
858    ///     .with_required_confirmations(2)
859    ///     .with_timeout(Some(std::time::Duration::from_secs(60)))
860    ///     .watch()
861    ///     .await?;
862    /// # Ok(())
863    /// # }
864    /// ```
865    async fn send_transaction(
866        &self,
867        tx: N::TransactionRequest,
868    ) -> TransportResult<PendingTransactionBuilder<N>> {
869        self.send_transaction_internal(SendableTx::Builder(tx)).await
870    }
871
872    /// Broadcasts a transaction envelope to the network.
873    ///
874    /// Returns a [`PendingTransactionBuilder`] which can be used to configure
875    /// how and when to await the transaction's confirmation.
876    async fn send_tx_envelope(
877        &self,
878        tx: N::TxEnvelope,
879    ) -> TransportResult<PendingTransactionBuilder<N>> {
880        self.send_transaction_internal(SendableTx::Envelope(tx)).await
881    }
882
883    /// This method allows [`ProviderLayer`] and [`TxFiller`] to build the
884    /// transaction and send it to the network without changing user-facing
885    /// APIs. Generally implementors should NOT override this method.
886    ///
887    /// [`send_transaction`]: Self::send_transaction
888    /// [`ProviderLayer`]: crate::ProviderLayer
889    /// [`TxFiller`]: crate::TxFiller
890    #[doc(hidden)]
891    async fn send_transaction_internal(
892        &self,
893        tx: SendableTx<N>,
894    ) -> TransportResult<PendingTransactionBuilder<N>> {
895        // Make sure to initialize heartbeat before we submit transaction, so that
896        // we don't miss it if user will subscriber to it immediately after sending.
897        let _handle = self.root().get_heart();
898
899        match tx {
900            SendableTx::Builder(mut tx) => {
901                alloy_network::TransactionBuilder::prep_for_submission(&mut tx);
902                let tx_hash = self.client().request("eth_sendTransaction", (tx,)).await?;
903                Ok(PendingTransactionBuilder::new(self.root().clone(), tx_hash))
904            }
905            SendableTx::Envelope(tx) => {
906                let encoded_tx = tx.encoded_2718();
907                self.send_raw_transaction(&encoded_tx).await
908            }
909        }
910    }
911
912    /// Subscribe to a stream of new block headers.
913    ///
914    /// # Errors
915    ///
916    /// This method is only available on `pubsub` clients, such as WebSockets or IPC, and will
917    /// return a [`PubsubUnavailable`](alloy_transport::TransportErrorKind::PubsubUnavailable)
918    /// transport error if the client does not support it.
919    ///
920    /// For a polling alternative available over HTTP, use [`Provider::watch_blocks`].
921    /// However, be aware that polling increases RPC usage drastically.
922    ///
923    /// # Examples
924    ///
925    /// ```no_run
926    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
927    /// use futures::StreamExt;
928    ///
929    /// let sub = provider.subscribe_blocks().await?;
930    /// let mut stream = sub.into_stream().take(5);
931    /// while let Some(block) = stream.next().await {
932    ///    println!("new block: {block:#?}");
933    /// }
934    /// # Ok(())
935    /// # }
936    /// ```
937    #[cfg(feature = "pubsub")]
938    async fn subscribe_blocks(
939        &self,
940    ) -> TransportResult<alloy_pubsub::Subscription<N::HeaderResponse>> {
941        self.root().pubsub_frontend()?;
942        let id = self.client().request("eth_subscribe", ("newHeads",)).await?;
943        self.root().get_subscription(id).await
944    }
945
946    /// Subscribe to a stream of pending transaction hashes.
947    ///
948    /// # Errors
949    ///
950    /// This method is only available on `pubsub` clients, such as WebSockets or IPC, and will
951    /// return a [`PubsubUnavailable`](alloy_transport::TransportErrorKind::PubsubUnavailable)
952    /// transport error if the client does not support it.
953    ///
954    /// For a polling alternative available over HTTP, use [`Provider::watch_pending_transactions`].
955    /// However, be aware that polling increases RPC usage drastically.
956    ///
957    /// # Examples
958    ///
959    /// ```no_run
960    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
961    /// use futures::StreamExt;
962    ///
963    /// let sub = provider.subscribe_pending_transactions().await?;
964    /// let mut stream = sub.into_stream().take(5);
965    /// while let Some(tx_hash) = stream.next().await {
966    ///    println!("new pending transaction hash: {tx_hash}");
967    /// }
968    /// # Ok(())
969    /// # }
970    /// ```
971    #[cfg(feature = "pubsub")]
972    async fn subscribe_pending_transactions(
973        &self,
974    ) -> TransportResult<alloy_pubsub::Subscription<B256>> {
975        self.root().pubsub_frontend()?;
976        let id = self.client().request("eth_subscribe", ("newPendingTransactions",)).await?;
977        self.root().get_subscription(id).await
978    }
979
980    /// Subscribe to a stream of pending transaction bodies.
981    ///
982    /// # Support
983    ///
984    /// This endpoint is compatible only with Geth client version 1.11.0 or later.
985    ///
986    /// # Errors
987    ///
988    /// This method is only available on `pubsub` clients, such as WebSockets or IPC, and will
989    /// return a [`PubsubUnavailable`](alloy_transport::TransportErrorKind::PubsubUnavailable)
990    /// transport error if the client does not support it.
991    ///
992    /// For a polling alternative available over HTTP, use
993    /// [`Provider::watch_full_pending_transactions`]. However, be aware that polling increases
994    /// RPC usage drastically.
995    ///
996    /// # Examples
997    ///
998    /// ```no_run
999    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
1000    /// use futures::StreamExt;
1001    ///
1002    /// let sub = provider.subscribe_full_pending_transactions().await?;
1003    /// let mut stream = sub.into_stream().take(5);
1004    /// while let Some(tx) = stream.next().await {
1005    ///    println!("{tx:#?}");
1006    /// }
1007    /// # Ok(())
1008    /// # }
1009    /// ```
1010    #[cfg(feature = "pubsub")]
1011    async fn subscribe_full_pending_transactions(
1012        &self,
1013    ) -> TransportResult<alloy_pubsub::Subscription<N::TransactionResponse>> {
1014        self.root().pubsub_frontend()?;
1015        let id = self.client().request("eth_subscribe", ("newPendingTransactions", true)).await?;
1016        self.root().get_subscription(id).await
1017    }
1018
1019    /// Subscribe to a stream of logs matching given filter.
1020    ///
1021    /// # Errors
1022    ///
1023    /// This method is only available on `pubsub` clients, such as WebSockets or IPC, and will
1024    /// return a [`PubsubUnavailable`](alloy_transport::TransportErrorKind::PubsubUnavailable)
1025    /// transport error if the client does not support it.
1026    ///
1027    /// For a polling alternative available over HTTP, use
1028    /// [`Provider::watch_logs`]. However, be aware that polling increases
1029    /// RPC usage drastically.
1030    ///
1031    /// # Examples
1032    ///
1033    /// ```no_run
1034    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
1035    /// use futures::StreamExt;
1036    /// use alloy_primitives::keccak256;
1037    /// use alloy_rpc_types_eth::Filter;
1038    ///
1039    /// let signature = keccak256("Transfer(address,address,uint256)".as_bytes());
1040    ///
1041    /// let sub = provider.subscribe_logs(&Filter::new().event_signature(signature)).await?;
1042    /// let mut stream = sub.into_stream().take(5);
1043    /// while let Some(tx) = stream.next().await {
1044    ///    println!("{tx:#?}");
1045    /// }
1046    /// # Ok(())
1047    /// # }
1048    /// ```
1049    #[cfg(feature = "pubsub")]
1050    async fn subscribe_logs(
1051        &self,
1052        filter: &Filter,
1053    ) -> TransportResult<alloy_pubsub::Subscription<Log>> {
1054        self.root().pubsub_frontend()?;
1055        let id = self.client().request("eth_subscribe", ("logs", filter)).await?;
1056        self.root().get_subscription(id).await
1057    }
1058
1059    /// Subscribe to an RPC event.
1060    #[cfg(feature = "pubsub")]
1061    #[auto_impl(keep_default_for(&, &mut, Rc, Arc, Box))]
1062    async fn subscribe<P, R>(&self, params: P) -> TransportResult<alloy_pubsub::Subscription<R>>
1063    where
1064        P: RpcSend,
1065        R: RpcRecv,
1066        Self: Sized,
1067    {
1068        self.root().pubsub_frontend()?;
1069        let id = self.client().request("eth_subscribe", params).await?;
1070        self.root().get_subscription(id).await
1071    }
1072
1073    /// Cancels a subscription given the subscription ID.
1074    #[cfg(feature = "pubsub")]
1075    async fn unsubscribe(&self, id: B256) -> TransportResult<()> {
1076        self.root().unsubscribe(id)
1077    }
1078
1079    /// Gets syncing info.
1080    fn syncing(&self) -> ProviderCall<NoParams, SyncStatus> {
1081        self.client().request_noparams("eth_syncing").into()
1082    }
1083
1084    /// Gets the client version.
1085    #[doc(alias = "web3_client_version")]
1086    fn get_client_version(&self) -> ProviderCall<NoParams, String> {
1087        self.client().request_noparams("web3_clientVersion").into()
1088    }
1089
1090    /// Gets the `Keccak-256` hash of the given data.
1091    #[doc(alias = "web3_sha3")]
1092    fn get_sha3(&self, data: &[u8]) -> ProviderCall<(String,), B256> {
1093        self.client().request("web3_sha3", (hex::encode_prefixed(data),)).into()
1094    }
1095
1096    /// Gets the network ID. Same as `eth_chainId`.
1097    fn get_net_version(&self) -> ProviderCall<NoParams, U64, u64> {
1098        self.client()
1099            .request_noparams("net_version")
1100            .map_resp(utils::convert_u64 as fn(U64) -> u64)
1101            .into()
1102    }
1103
1104    /* ---------------------------------------- raw calls --------------------------------------- */
1105
1106    /// Sends a raw JSON-RPC request.
1107    ///
1108    /// # Examples
1109    ///
1110    /// ```no_run
1111    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
1112    /// use alloy_rpc_types_eth::BlockNumberOrTag;
1113    /// use alloy_rpc_client::NoParams;
1114    ///
1115    /// // No parameters: `()`
1116    /// let block_number = provider.raw_request("eth_blockNumber".into(), NoParams::default()).await?;
1117    ///
1118    /// // One parameter: `(param,)` or `[param]`
1119    /// let block = provider.raw_request("eth_getBlockByNumber".into(), (BlockNumberOrTag::Latest,)).await?;
1120    ///
1121    /// // Two or more parameters: `(param1, param2, ...)` or `[param1, param2, ...]`
1122    /// let full_block = provider.raw_request("eth_getBlockByNumber".into(), (BlockNumberOrTag::Latest, true)).await?;
1123    /// # Ok(())
1124    /// # }
1125    /// ```
1126    ///
1127    /// [`PubsubUnavailable`]: alloy_transport::TransportErrorKind::PubsubUnavailable
1128    async fn raw_request<P, R>(&self, method: Cow<'static, str>, params: P) -> TransportResult<R>
1129    where
1130        P: RpcSend,
1131        R: RpcRecv,
1132        Self: Sized,
1133    {
1134        self.client().request(method, &params).await
1135    }
1136
1137    /// Sends a raw JSON-RPC request with type-erased parameters and return.
1138    ///
1139    /// # Examples
1140    ///
1141    /// ```no_run
1142    /// # async fn example(provider: impl alloy_provider::Provider) -> Result<(), Box<dyn std::error::Error>> {
1143    /// use alloy_rpc_types_eth::BlockNumberOrTag;
1144    ///
1145    /// // No parameters: `()`
1146    /// let params = serde_json::value::to_raw_value(&())?;
1147    /// let block_number = provider.raw_request_dyn("eth_blockNumber".into(), &params).await?;
1148    ///
1149    /// // One parameter: `(param,)` or `[param]`
1150    /// let params = serde_json::value::to_raw_value(&(BlockNumberOrTag::Latest,))?;
1151    /// let block = provider.raw_request_dyn("eth_getBlockByNumber".into(), &params).await?;
1152    ///
1153    /// // Two or more parameters: `(param1, param2, ...)` or `[param1, param2, ...]`
1154    /// let params = serde_json::value::to_raw_value(&(BlockNumberOrTag::Latest, true))?;
1155    /// let full_block = provider.raw_request_dyn("eth_getBlockByNumber".into(), &params).await?;
1156    /// # Ok(())
1157    /// # }
1158    /// ```
1159    async fn raw_request_dyn(
1160        &self,
1161        method: Cow<'static, str>,
1162        params: &RawValue,
1163    ) -> TransportResult<Box<RawValue>> {
1164        self.client().request(method, params).await
1165    }
1166
1167    /// Creates a new [`TransactionRequest`](alloy_network::Network).
1168    #[inline]
1169    fn transaction_request(&self) -> N::TransactionRequest {
1170        Default::default()
1171    }
1172}
1173
1174#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
1175#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
1176impl<N: Network> Provider<N> for RootProvider<N> {
1177    #[inline]
1178    fn root(&self) -> &Self {
1179        self
1180    }
1181
1182    #[inline]
1183    fn client(&self) -> ClientRef<'_> {
1184        self.inner.client_ref()
1185    }
1186
1187    #[inline]
1188    fn weak_client(&self) -> WeakClient {
1189        self.inner.weak_client()
1190    }
1191
1192    #[inline]
1193    async fn watch_pending_transaction(
1194        &self,
1195        config: PendingTransactionConfig,
1196    ) -> Result<PendingTransaction, PendingTransactionError> {
1197        let block_number =
1198            if let Some(receipt) = self.get_transaction_receipt(*config.tx_hash()).await? {
1199                // The transaction is already confirmed.
1200                if config.required_confirmations() <= 1 {
1201                    return Ok(PendingTransaction::ready(*config.tx_hash()));
1202                }
1203                // Transaction has custom confirmations, so let the heart know about its block
1204                // number and let it handle the situation.
1205                receipt.block_number()
1206            } else {
1207                None
1208            };
1209
1210        self.get_heart()
1211            .watch_tx(config, block_number)
1212            .await
1213            .map_err(|_| PendingTransactionError::FailedToRegister)
1214    }
1215}
1216
1217#[cfg(test)]
1218mod tests {
1219    use super::*;
1220    use crate::{builder, ProviderBuilder, WalletProvider};
1221    use alloy_consensus::Transaction;
1222    use alloy_network::{AnyNetwork, EthereumWallet, TransactionBuilder};
1223    use alloy_node_bindings::Anvil;
1224    use alloy_primitives::{address, b256, bytes, keccak256};
1225    use alloy_rpc_client::{BuiltInConnectionString, RpcClient};
1226    use alloy_rpc_types_eth::{request::TransactionRequest, Block};
1227    use alloy_signer_local::PrivateKeySigner;
1228    use alloy_transport::layers::{RetryBackoffLayer, RetryPolicy};
1229    use std::{io::Read, str::FromStr, time::Duration};
1230
1231    // For layer transport tests
1232    #[cfg(feature = "hyper")]
1233    use alloy_transport_http::{
1234        hyper,
1235        hyper::body::Bytes as HyperBytes,
1236        hyper_util::{
1237            client::legacy::{Client, Error},
1238            rt::TokioExecutor,
1239        },
1240        HyperResponse, HyperResponseFut,
1241    };
1242    #[cfg(feature = "hyper")]
1243    use http_body_util::Full;
1244    #[cfg(feature = "hyper")]
1245    use tower::{Layer, Service};
1246
1247    #[tokio::test]
1248    async fn test_provider_builder() {
1249        let provider = RootProvider::builder().with_recommended_fillers().on_anvil();
1250        let num = provider.get_block_number().await.unwrap();
1251        assert_eq!(0, num);
1252    }
1253
1254    #[tokio::test]
1255    async fn test_builder_helper_fn() {
1256        let provider = builder().with_recommended_fillers().on_anvil();
1257        let num = provider.get_block_number().await.unwrap();
1258        assert_eq!(0, num);
1259    }
1260
1261    #[cfg(feature = "hyper")]
1262    #[tokio::test]
1263    async fn test_default_hyper_transport() {
1264        let anvil = Anvil::new().spawn();
1265        let hyper_t = alloy_transport_http::HyperTransport::new_hyper(anvil.endpoint_url());
1266
1267        let rpc_client = alloy_rpc_client::RpcClient::new(hyper_t, true);
1268
1269        let provider = RootProvider::<Ethereum>::new(rpc_client);
1270        let num = provider.get_block_number().await.unwrap();
1271        assert_eq!(0, num);
1272    }
1273
1274    #[cfg(feature = "hyper")]
1275    #[tokio::test]
1276    async fn test_hyper_layer_transport() {
1277        struct LoggingLayer;
1278
1279        impl<S> Layer<S> for LoggingLayer {
1280            type Service = LoggingService<S>;
1281
1282            fn layer(&self, inner: S) -> Self::Service {
1283                LoggingService { inner }
1284            }
1285        }
1286
1287        #[derive(Clone)] // required
1288        struct LoggingService<S> {
1289            inner: S,
1290        }
1291
1292        impl<S, B> Service<hyper::Request<B>> for LoggingService<S>
1293        where
1294            S: Service<hyper::Request<B>, Response = HyperResponse, Error = Error>
1295                + Clone
1296                + Send
1297                + Sync
1298                + 'static,
1299            S::Future: Send,
1300            S::Error: std::error::Error + Send + Sync + 'static,
1301            B: From<Vec<u8>> + Send + 'static + Clone + Sync + std::fmt::Debug,
1302        {
1303            type Response = HyperResponse;
1304            type Error = Error;
1305            type Future = HyperResponseFut;
1306
1307            fn poll_ready(
1308                &mut self,
1309                cx: &mut std::task::Context<'_>,
1310            ) -> std::task::Poll<Result<(), Self::Error>> {
1311                self.inner.poll_ready(cx)
1312            }
1313
1314            fn call(&mut self, req: hyper::Request<B>) -> Self::Future {
1315                println!("Logging Layer - HyperRequest {req:?}");
1316
1317                let fut = self.inner.call(req);
1318
1319                Box::pin(fut)
1320            }
1321        }
1322        use http::header::{self, HeaderValue};
1323        use tower_http::{
1324            sensitive_headers::SetSensitiveRequestHeadersLayer, set_header::SetRequestHeaderLayer,
1325        };
1326        let anvil = Anvil::new().spawn();
1327        let hyper_client = Client::builder(TokioExecutor::new()).build_http::<Full<HyperBytes>>();
1328
1329        // Setup tower serive with multiple layers modifying request headers
1330        let service = tower::ServiceBuilder::new()
1331            .layer(SetRequestHeaderLayer::if_not_present(
1332                header::USER_AGENT,
1333                HeaderValue::from_static("alloy app"),
1334            ))
1335            .layer(SetRequestHeaderLayer::overriding(
1336                header::AUTHORIZATION,
1337                HeaderValue::from_static("some-jwt-token"),
1338            ))
1339            .layer(SetRequestHeaderLayer::appending(
1340                header::SET_COOKIE,
1341                HeaderValue::from_static("cookie-value"),
1342            ))
1343            .layer(SetSensitiveRequestHeadersLayer::new([header::AUTHORIZATION])) // Hides the jwt token as sensitive.
1344            .layer(LoggingLayer)
1345            .service(hyper_client);
1346
1347        let layer_transport = alloy_transport_http::HyperClient::with_service(service);
1348
1349        let http_hyper =
1350            alloy_transport_http::Http::with_client(layer_transport, anvil.endpoint_url());
1351
1352        let rpc_client = alloy_rpc_client::RpcClient::new(http_hyper, true);
1353
1354        let provider = RootProvider::<Ethereum>::new(rpc_client);
1355        let num = provider.get_block_number().await.unwrap();
1356        assert_eq!(0, num);
1357
1358        // Test Cloning with service
1359        let cloned_t = provider.client().transport().clone();
1360
1361        let rpc_client = alloy_rpc_client::RpcClient::new(cloned_t, true);
1362
1363        let provider = RootProvider::<Ethereum>::new(rpc_client);
1364        let num = provider.get_block_number().await.unwrap();
1365        assert_eq!(0, num);
1366    }
1367
1368    #[cfg(feature = "hyper")]
1369    #[tokio::test]
1370    #[cfg_attr(windows, ignore = "no reth on windows")]
1371    async fn test_auth_layer_transport() {
1372        crate::ext::test::async_ci_only(|| async move {
1373            use alloy_node_bindings::Reth;
1374            use alloy_rpc_types_engine::JwtSecret;
1375            use alloy_transport_http::{AuthLayer, AuthService, Http, HyperClient};
1376
1377            let secret = JwtSecret::random();
1378
1379            let reth =
1380                Reth::new().arg("--rpc.jwtsecret").arg(hex::encode(secret.as_bytes())).spawn();
1381
1382            let hyper_client =
1383                Client::builder(TokioExecutor::new()).build_http::<Full<HyperBytes>>();
1384
1385            let service =
1386                tower::ServiceBuilder::new().layer(AuthLayer::new(secret)).service(hyper_client);
1387
1388            let layer_transport: HyperClient<
1389                Full<HyperBytes>,
1390                AuthService<
1391                    Client<
1392                        alloy_transport_http::hyper_util::client::legacy::connect::HttpConnector,
1393                        Full<HyperBytes>,
1394                    >,
1395                >,
1396            > = HyperClient::with_service(service);
1397
1398            let http_hyper = Http::with_client(layer_transport, reth.endpoint_url());
1399
1400            let rpc_client = alloy_rpc_client::RpcClient::new(http_hyper, true);
1401
1402            let provider = RootProvider::<Ethereum>::new(rpc_client);
1403
1404            let num = provider.get_block_number().await.unwrap();
1405            assert_eq!(0, num);
1406        })
1407        .await;
1408    }
1409
1410    #[tokio::test]
1411    async fn test_builder_helper_fn_any_network() {
1412        let anvil = Anvil::new().spawn();
1413        let provider =
1414            builder::<AnyNetwork>().with_recommended_fillers().on_http(anvil.endpoint_url());
1415        let num = provider.get_block_number().await.unwrap();
1416        assert_eq!(0, num);
1417    }
1418
1419    #[cfg(feature = "reqwest")]
1420    #[tokio::test]
1421    async fn object_safety() {
1422        let provider = ProviderBuilder::new().on_anvil();
1423
1424        let refdyn = &provider as &dyn Provider<_>;
1425        let num = refdyn.get_block_number().await.unwrap();
1426        assert_eq!(0, num);
1427    }
1428
1429    #[cfg(feature = "ws")]
1430    #[tokio::test]
1431    async fn subscribe_blocks_http() {
1432        let provider = ProviderBuilder::new().on_anvil_with_config(|a| a.block_time(1));
1433
1434        let err = provider.subscribe_blocks().await.unwrap_err();
1435        let alloy_json_rpc::RpcError::Transport(
1436            alloy_transport::TransportErrorKind::PubsubUnavailable,
1437        ) = err
1438        else {
1439            panic!("{err:?}");
1440        };
1441    }
1442
1443    // Ensures we can connect to a websocket using `wss`.
1444    #[cfg(feature = "ws")]
1445    #[tokio::test]
1446    async fn websocket_tls_setup() {
1447        for url in ["wss://mainnet.infura.io/ws/v3/b0f825787ba840af81e46c6a64d20754"] {
1448            let _ = ProviderBuilder::<_, _, Ethereum>::default().connect(url).await.unwrap();
1449        }
1450    }
1451
1452    #[cfg(feature = "ws")]
1453    #[tokio::test]
1454    async fn subscribe_blocks_ws() {
1455        use futures::stream::StreamExt;
1456
1457        let anvil = Anvil::new().block_time_f64(0.2).spawn();
1458        let ws = alloy_rpc_client::WsConnect::new(anvil.ws_endpoint());
1459        let client = alloy_rpc_client::RpcClient::connect_pubsub(ws).await.unwrap();
1460        let provider = RootProvider::<Ethereum>::new(client);
1461
1462        let sub = provider.subscribe_blocks().await.unwrap();
1463        let mut stream = sub.into_stream().take(5);
1464        let mut next = None;
1465        while let Some(header) = stream.next().await {
1466            if let Some(next) = &mut next {
1467                assert_eq!(header.number, *next);
1468                *next += 1;
1469            } else {
1470                next = Some(header.number + 1);
1471            }
1472        }
1473    }
1474
1475    #[tokio::test]
1476    #[cfg(feature = "ws")]
1477    async fn subscribe_blocks_ws_remote() {
1478        use futures::stream::StreamExt;
1479
1480        let url = "wss://eth-mainnet.g.alchemy.com/v2/viFmeVzhg6bWKVMIWWS8MhmzREB-D4f7";
1481        let ws = alloy_rpc_client::WsConnect::new(url);
1482        let Ok(client) = alloy_rpc_client::RpcClient::connect_pubsub(ws).await else { return };
1483        let provider = RootProvider::<Ethereum>::new(client);
1484        let sub = provider.subscribe_blocks().await.unwrap();
1485        let mut stream = sub.into_stream().take(1);
1486        while let Some(header) = stream.next().await {
1487            println!("New block {:?}", header);
1488            assert!(header.number > 0);
1489        }
1490    }
1491
1492    #[tokio::test]
1493    async fn test_custom_retry_policy() {
1494        #[derive(Debug, Clone)]
1495        struct CustomPolicy;
1496        impl RetryPolicy for CustomPolicy {
1497            fn should_retry(&self, _err: &alloy_transport::TransportError) -> bool {
1498                true
1499            }
1500
1501            fn backoff_hint(
1502                &self,
1503                _error: &alloy_transport::TransportError,
1504            ) -> Option<std::time::Duration> {
1505                None
1506            }
1507        }
1508
1509        let retry_layer = RetryBackoffLayer::new_with_policy(10, 100, 10000, CustomPolicy);
1510        let anvil = Anvil::new().spawn();
1511        let client = RpcClient::builder().layer(retry_layer).http(anvil.endpoint_url());
1512
1513        let provider = RootProvider::<Ethereum>::new(client);
1514        let num = provider.get_block_number().await.unwrap();
1515        assert_eq!(0, num);
1516    }
1517
1518    #[tokio::test]
1519    async fn test_send_tx() {
1520        let provider = ProviderBuilder::new().on_anvil_with_wallet();
1521        let tx = TransactionRequest {
1522            value: Some(U256::from(100)),
1523            to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
1524            gas_price: Some(20e9 as u128),
1525            gas: Some(21000),
1526            ..Default::default()
1527        };
1528
1529        let builder = provider.send_transaction(tx.clone()).await.expect("failed to send tx");
1530        let hash1 = *builder.tx_hash();
1531        let hash2 = builder.watch().await.expect("failed to await pending tx");
1532        assert_eq!(hash1, hash2);
1533
1534        let builder = provider.send_transaction(tx).await.expect("failed to send tx");
1535        let hash1 = *builder.tx_hash();
1536        let hash2 =
1537            builder.get_receipt().await.expect("failed to await pending tx").transaction_hash;
1538        assert_eq!(hash1, hash2);
1539    }
1540
1541    #[tokio::test]
1542    async fn test_watch_confirmed_tx() {
1543        let provider = ProviderBuilder::new().on_anvil_with_wallet();
1544        let tx = TransactionRequest {
1545            value: Some(U256::from(100)),
1546            to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
1547            gas_price: Some(20e9 as u128),
1548            gas: Some(21000),
1549            ..Default::default()
1550        };
1551
1552        let builder = provider.send_transaction(tx.clone()).await.expect("failed to send tx");
1553        let hash1 = *builder.tx_hash();
1554
1555        // Wait until tx is confirmed.
1556        loop {
1557            if provider
1558                .get_transaction_receipt(hash1)
1559                .await
1560                .expect("failed to await pending tx")
1561                .is_some()
1562            {
1563                break;
1564            }
1565        }
1566
1567        // Submit another tx.
1568        let tx2 = TransactionRequest {
1569            value: Some(U256::from(100)),
1570            to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
1571            gas_price: Some(20e9 as u128),
1572            gas: Some(21000),
1573            ..Default::default()
1574        };
1575        provider.send_transaction(tx2).await.expect("failed to send tx").watch().await.unwrap();
1576
1577        // Only subscribe for watching _after_ tx was confirmed and we submitted a new one.
1578        let watch = builder.watch();
1579        // Wrap watch future in timeout to prevent it from hanging.
1580        let watch_with_timeout = tokio::time::timeout(Duration::from_secs(1), watch);
1581        let hash2 = watch_with_timeout
1582            .await
1583            .expect("Watching tx timed out")
1584            .expect("failed to await pending tx");
1585        assert_eq!(hash1, hash2);
1586    }
1587
1588    #[tokio::test]
1589    async fn gets_block_number() {
1590        let provider = ProviderBuilder::new().on_anvil();
1591        let num = provider.get_block_number().await.unwrap();
1592        assert_eq!(0, num)
1593    }
1594
1595    #[tokio::test]
1596    async fn gets_block_number_with_raw_req() {
1597        let provider = ProviderBuilder::new().on_anvil();
1598        let num: U64 =
1599            provider.raw_request("eth_blockNumber".into(), NoParams::default()).await.unwrap();
1600        assert_eq!(0, num.to::<u64>())
1601    }
1602
1603    #[cfg(feature = "anvil-api")]
1604    #[tokio::test]
1605    async fn gets_transaction_count() {
1606        let provider = ProviderBuilder::new().on_anvil();
1607        let accounts = provider.get_accounts().await.unwrap();
1608        let sender = accounts[0];
1609
1610        // Initial tx count should be 0
1611        let count = provider.get_transaction_count(sender).await.unwrap();
1612        assert_eq!(count, 0);
1613
1614        // Send Tx
1615        let tx = TransactionRequest {
1616            value: Some(U256::from(100)),
1617            from: Some(sender),
1618            to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
1619            gas_price: Some(20e9 as u128),
1620            gas: Some(21000),
1621            ..Default::default()
1622        };
1623        let _ = provider.send_transaction(tx).await.unwrap().get_receipt().await;
1624
1625        // Tx count should be 1
1626        let count = provider.get_transaction_count(sender).await.unwrap();
1627        assert_eq!(count, 1);
1628
1629        // Tx count should be 0 at block 0
1630        let count = provider.get_transaction_count(sender).block_id(0.into()).await.unwrap();
1631        assert_eq!(count, 0);
1632    }
1633
1634    #[tokio::test]
1635    async fn gets_block_by_hash() {
1636        let provider = ProviderBuilder::new().on_anvil();
1637        let num = 0;
1638        let tag: BlockNumberOrTag = num.into();
1639        let block = provider.get_block_by_number(tag).full().await.unwrap().unwrap();
1640        let hash = block.header.hash;
1641        let block = provider.get_block_by_hash(hash).full().await.unwrap().unwrap();
1642        assert_eq!(block.header.hash, hash);
1643    }
1644
1645    #[tokio::test]
1646    async fn gets_block_by_hash_with_raw_req() {
1647        let provider = ProviderBuilder::new().on_anvil();
1648        let num = 0;
1649        let tag: BlockNumberOrTag = num.into();
1650        let block = provider.get_block_by_number(tag).full().await.unwrap().unwrap();
1651        let hash = block.header.hash;
1652        let block: Block = provider
1653            .raw_request::<(B256, bool), Block>("eth_getBlockByHash".into(), (hash, true))
1654            .await
1655            .unwrap();
1656        assert_eq!(block.header.hash, hash);
1657    }
1658
1659    #[tokio::test]
1660    async fn gets_block_by_number_full() {
1661        let provider = ProviderBuilder::new().on_anvil();
1662        let num = 0;
1663        let tag: BlockNumberOrTag = num.into();
1664        let block = provider.get_block_by_number(tag).full().await.unwrap().unwrap();
1665        assert_eq!(block.header.number, num);
1666    }
1667
1668    #[tokio::test]
1669    async fn gets_block_by_number() {
1670        let provider = ProviderBuilder::new().on_anvil();
1671        let num = 0;
1672        let tag: BlockNumberOrTag = num.into();
1673        let block = provider.get_block_by_number(tag).full().await.unwrap().unwrap();
1674        assert_eq!(block.header.number, num);
1675    }
1676
1677    #[tokio::test]
1678    async fn gets_client_version() {
1679        let provider = ProviderBuilder::new().on_anvil();
1680        let version = provider.get_client_version().await.unwrap();
1681        assert!(version.contains("anvil"), "{version}");
1682    }
1683
1684    #[tokio::test]
1685    async fn gets_sha3() {
1686        let provider = ProviderBuilder::new().on_anvil();
1687        let data = b"alloy";
1688        let hash = provider.get_sha3(data).await.unwrap();
1689        assert_eq!(hash, keccak256(data));
1690    }
1691
1692    #[tokio::test]
1693    async fn gets_chain_id() {
1694        let dev_chain_id: u64 = 13371337;
1695
1696        let provider = ProviderBuilder::new().on_anvil_with_config(|a| a.chain_id(dev_chain_id));
1697
1698        let chain_id = provider.get_chain_id().await.unwrap();
1699        assert_eq!(chain_id, dev_chain_id);
1700    }
1701
1702    #[tokio::test]
1703    async fn gets_network_id() {
1704        let dev_chain_id: u64 = 13371337;
1705        let provider = ProviderBuilder::new().on_anvil_with_config(|a| a.chain_id(dev_chain_id));
1706
1707        let chain_id = provider.get_net_version().await.unwrap();
1708        assert_eq!(chain_id, dev_chain_id);
1709    }
1710
1711    #[tokio::test]
1712    async fn gets_storage_at() {
1713        let provider = ProviderBuilder::new().on_anvil();
1714        let addr = Address::with_last_byte(16);
1715        let storage = provider.get_storage_at(addr, U256::ZERO).await.unwrap();
1716        assert_eq!(storage, U256::ZERO);
1717    }
1718
1719    #[tokio::test]
1720    async fn gets_transaction_by_hash_not_found() {
1721        let provider = ProviderBuilder::new().on_anvil();
1722        let tx_hash = b256!("5c03fab9114ceb98994b43892ade87ddfd9ae7e8f293935c3bd29d435dc9fd95");
1723        let tx = provider.get_transaction_by_hash(tx_hash).await.expect("failed to fetch tx");
1724
1725        assert!(tx.is_none());
1726    }
1727
1728    #[tokio::test]
1729    async fn gets_transaction_by_hash() {
1730        let provider = ProviderBuilder::new().on_anvil_with_wallet();
1731
1732        let req = TransactionRequest::default()
1733            .from(provider.default_signer_address())
1734            .to(Address::repeat_byte(5))
1735            .value(U256::ZERO)
1736            .input(bytes!("deadbeef").into());
1737
1738        let tx_hash = *provider.send_transaction(req).await.expect("failed to send tx").tx_hash();
1739
1740        let tx = provider
1741            .get_transaction_by_hash(tx_hash)
1742            .await
1743            .expect("failed to fetch tx")
1744            .expect("tx not included");
1745        assert_eq!(tx.input(), &bytes!("deadbeef"));
1746    }
1747
1748    #[tokio::test]
1749    #[ignore]
1750    async fn gets_logs() {
1751        let provider = ProviderBuilder::new().on_anvil();
1752        let filter = Filter::new()
1753            .at_block_hash(b256!(
1754                "b20e6f35d4b46b3c4cd72152faec7143da851a0dc281d390bdd50f58bfbdb5d3"
1755            ))
1756            .event_signature(b256!(
1757                "e1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"
1758            ));
1759        let logs = provider.get_logs(&filter).await.unwrap();
1760        assert_eq!(logs.len(), 1);
1761    }
1762
1763    #[tokio::test]
1764    #[ignore]
1765    async fn gets_tx_receipt() {
1766        let provider = ProviderBuilder::new().on_anvil();
1767        let receipt = provider
1768            .get_transaction_receipt(b256!(
1769                "5c03fab9114ceb98994b43892ade87ddfd9ae7e8f293935c3bd29d435dc9fd95"
1770            ))
1771            .await
1772            .unwrap();
1773        assert!(receipt.is_some());
1774        let receipt = receipt.unwrap();
1775        assert_eq!(
1776            receipt.transaction_hash,
1777            b256!("5c03fab9114ceb98994b43892ade87ddfd9ae7e8f293935c3bd29d435dc9fd95")
1778        );
1779    }
1780
1781    #[tokio::test]
1782    async fn gets_max_priority_fee_per_gas() {
1783        let provider = ProviderBuilder::new().on_anvil();
1784        let _fee = provider.get_max_priority_fee_per_gas().await.unwrap();
1785    }
1786
1787    #[tokio::test]
1788    async fn gets_fee_history() {
1789        let provider = ProviderBuilder::new().on_anvil();
1790        let block_number = provider.get_block_number().await.unwrap();
1791        let fee_history = provider
1792            .get_fee_history(
1793                utils::EIP1559_FEE_ESTIMATION_PAST_BLOCKS,
1794                BlockNumberOrTag::Number(block_number),
1795                &[utils::EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE],
1796            )
1797            .await
1798            .unwrap();
1799        assert_eq!(fee_history.oldest_block, 0_u64);
1800    }
1801
1802    #[tokio::test]
1803    async fn gets_block_transaction_count_by_hash() {
1804        let provider = ProviderBuilder::new().on_anvil();
1805        let block = provider.get_block(BlockId::latest()).await.unwrap().unwrap();
1806        let hash = block.header.hash;
1807        let tx_count = provider.get_block_transaction_count_by_hash(hash).await.unwrap();
1808        assert!(tx_count.is_some());
1809    }
1810
1811    #[tokio::test]
1812    async fn gets_block_transaction_count_by_number() {
1813        let provider = ProviderBuilder::new().on_anvil();
1814        let tx_count =
1815            provider.get_block_transaction_count_by_number(BlockNumberOrTag::Latest).await.unwrap();
1816        assert!(tx_count.is_some());
1817    }
1818
1819    #[tokio::test]
1820    async fn gets_block_receipts() {
1821        let provider = ProviderBuilder::new().on_anvil();
1822        let receipts =
1823            provider.get_block_receipts(BlockId::Number(BlockNumberOrTag::Latest)).await.unwrap();
1824        assert!(receipts.is_some());
1825    }
1826
1827    #[tokio::test]
1828    async fn sends_raw_transaction() {
1829        let provider = ProviderBuilder::new().on_anvil();
1830        let pending = provider
1831            .send_raw_transaction(
1832                // Transfer 1 ETH from default EOA address to the Genesis address.
1833                bytes!("f865808477359400825208940000000000000000000000000000000000000000018082f4f5a00505e227c1c636c76fac55795db1a40a4d24840d81b40d2fe0cc85767f6bd202a01e91b437099a8a90234ac5af3cb7ca4fb1432e133f75f9a91678eaf5f487c74b").as_ref()
1834            )
1835            .await.unwrap();
1836        assert_eq!(
1837            pending.tx_hash().to_string(),
1838            "0x9dae5cf33694a02e8a7d5de3fe31e9d05ca0ba6e9180efac4ab20a06c9e598a3"
1839        );
1840    }
1841
1842    #[tokio::test]
1843    async fn connect_boxed() {
1844        let anvil = Anvil::new().spawn();
1845
1846        let provider = RootProvider::<Ethereum>::connect(anvil.endpoint().as_str()).await;
1847
1848        match provider {
1849            Ok(provider) => {
1850                let num = provider.get_block_number().await.unwrap();
1851                assert_eq!(0, num);
1852            }
1853            Err(e) => {
1854                assert_eq!(
1855                    format!("{}",e),
1856                    "hyper not supported by BuiltinConnectionString. Please instantiate a hyper client manually"
1857                );
1858            }
1859        }
1860    }
1861
1862    #[tokio::test]
1863    async fn any_network_wallet_filler() {
1864        use alloy_serde::WithOtherFields;
1865        let anvil = Anvil::new().spawn();
1866        let signer: PrivateKeySigner =
1867            "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".parse().unwrap();
1868        let wallet = EthereumWallet::from(signer);
1869
1870        let provider = ProviderBuilder::new()
1871            .network::<AnyNetwork>()
1872            .wallet(wallet)
1873            .on_http(anvil.endpoint_url());
1874
1875        let tx = TransactionRequest::default()
1876            .with_to(address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"))
1877            .value(U256::from(325235));
1878
1879        let tx = WithOtherFields::new(tx);
1880
1881        let builder = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap();
1882
1883        assert!(builder.status());
1884    }
1885
1886    #[tokio::test]
1887    async fn builtin_connect_boxed() {
1888        let anvil = Anvil::new().spawn();
1889
1890        let conn: BuiltInConnectionString = anvil.endpoint().parse().unwrap();
1891
1892        let transport = conn.connect_boxed().await.unwrap();
1893
1894        let client = alloy_rpc_client::RpcClient::new(transport, true);
1895
1896        let provider = RootProvider::<Ethereum>::new(client);
1897
1898        let num = provider.get_block_number().await.unwrap();
1899        assert_eq!(0, num);
1900    }
1901
1902    #[tokio::test]
1903    async fn test_uncle_count() {
1904        let provider = ProviderBuilder::new().on_anvil();
1905
1906        let count = provider.get_uncle_count(0.into()).await.unwrap();
1907        assert_eq!(count, 0);
1908    }
1909
1910    #[tokio::test]
1911    #[cfg(any(
1912        feature = "reqwest-default-tls",
1913        feature = "reqwest-rustls-tls",
1914        feature = "reqwest-native-tls",
1915    ))]
1916    #[ignore = "ignore until <https://github.com/paradigmxyz/reth/pull/14727> is in"]
1917    async fn call_mainnet() {
1918        use alloy_network::TransactionBuilder;
1919        use alloy_sol_types::SolValue;
1920
1921        let url = "https://docs-demo.quiknode.pro/";
1922        let provider = ProviderBuilder::new().on_http(url.parse().unwrap());
1923        let req = TransactionRequest::default()
1924            .with_to(address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")) // WETH
1925            .with_input(bytes!("06fdde03")); // `name()`
1926        let result = provider.call(req.clone()).await.unwrap();
1927        assert_eq!(String::abi_decode(&result, true).unwrap(), "Wrapped Ether");
1928
1929        let result = provider.call(req).block(0.into()).await.unwrap();
1930        assert_eq!(result.to_string(), "0x");
1931    }
1932
1933    #[tokio::test]
1934    async fn call_many_mainnet() {
1935        use alloy_rpc_types_eth::{BlockOverrides, StateContext};
1936
1937        let url = "https://docs-demo.quiknode.pro/";
1938        let provider = ProviderBuilder::new().on_http(url.parse().unwrap());
1939        let tx1 = TransactionRequest::default()
1940            .with_to(address!("6b175474e89094c44da98b954eedeac495271d0f"))
1941            .with_gas_limit(1000000)
1942            .with_gas_price(2023155498)
1943            .with_input(hex!("a9059cbb000000000000000000000000bc0E63965946815d105E7591407704e6e1964E590000000000000000000000000000000000000000000000000000000005f5e100"));
1944        let tx2 = TransactionRequest::default()
1945            .with_to(address!("833589fcd6edb6e08f4c7c32d4f71b54bda02913"))
1946            .with_gas_price(2023155498)
1947            .with_input(hex!(
1948                "70a08231000000000000000000000000bc0E63965946815d105E7591407704e6e1964E59"
1949            ));
1950
1951        let transactions = vec![tx1.clone(), tx2.clone()];
1952
1953        let block_override =
1954            BlockOverrides { number: Some(U256::from(12279785)), ..Default::default() };
1955
1956        let bundles = vec![Bundle { transactions, block_override: Some(block_override.clone()) }];
1957
1958        let context = StateContext {
1959            block_number: Some(BlockId::number(12279785)),
1960            transaction_index: Some(1.into()),
1961        };
1962
1963        let results = provider.call_many(&bundles).context(&context).await.unwrap();
1964
1965        let tx1_res = EthCallResponse {
1966            value: Some(
1967                hex!("0000000000000000000000000000000000000000000000000000000000000001").into(),
1968            ),
1969            error: None,
1970        };
1971        let tx2_res = EthCallResponse { value: Some(Bytes::new()), error: None };
1972        let expected = vec![vec![tx1_res.clone(), tx2_res.clone()]];
1973
1974        assert_eq!(results, expected);
1975
1976        // Two bundles
1977        let bundles = vec![
1978            Bundle {
1979                transactions: vec![tx1.clone()],
1980                block_override: Some(block_override.clone()),
1981            },
1982            Bundle {
1983                transactions: vec![tx2.clone()],
1984                block_override: Some(block_override.clone()),
1985            },
1986        ];
1987
1988        let results = provider.call_many(&bundles).context(&context).await.unwrap();
1989        let expected = vec![vec![tx1_res.clone()], vec![tx2_res.clone()]];
1990        assert_eq!(results, expected);
1991
1992        // Two bundles by extending existing.
1993        let b1 =
1994            vec![Bundle { transactions: vec![tx1], block_override: Some(block_override.clone()) }];
1995        let b2 = vec![Bundle { transactions: vec![tx2], block_override: Some(block_override) }];
1996
1997        let results = provider.call_many(&b1).context(&context).extend_bundles(&b2).await.unwrap();
1998        assert_eq!(results, expected);
1999    }
2000
2001    #[tokio::test]
2002    #[cfg(feature = "hyper-tls")]
2003    async fn hyper_https() {
2004        let url = "https://reth-ethereum.ithaca.xyz/rpc";
2005
2006        // With the `hyper` feature enabled .connect builds the provider based on
2007        // `HyperTransport`.
2008        let provider = ProviderBuilder::new().connect(url).await.unwrap();
2009
2010        let _num = provider.get_block_number().await.unwrap();
2011    }
2012
2013    #[tokio::test]
2014    async fn test_empty_transactions() {
2015        let provider = ProviderBuilder::new().on_anvil();
2016
2017        let block = provider.get_block_by_number(0.into()).await.unwrap().unwrap();
2018        assert!(block.transactions.is_hashes());
2019    }
2020
2021    #[tokio::test]
2022    async fn disable_test() {
2023        let provider = ProviderBuilder::new()
2024            .disable_recommended_fillers()
2025            .with_cached_nonce_management()
2026            .on_anvil();
2027
2028        let tx = TransactionRequest::default()
2029            .with_kind(alloy_primitives::TxKind::Create)
2030            .value(U256::from(1235))
2031            .with_input(Bytes::from_str("ffffffffffffff").unwrap());
2032
2033        let err = provider.send_transaction(tx).await.unwrap_err().to_string();
2034        assert!(err.contains("missing properties: [(\"NonceManager\", [\"from\"])]"));
2035    }
2036
2037    #[tokio::test]
2038    async fn capture_anvil_logs() {
2039        let mut anvil = Anvil::new().keep_stdout().spawn();
2040
2041        let provider = ProviderBuilder::new().on_http(anvil.endpoint_url());
2042
2043        let tx = TransactionRequest::default()
2044            .with_from(address!("f39Fd6e51aad88F6F4ce6aB8827279cffFb92266"))
2045            .with_to(address!("70997970C51812dc3A010C7d01b50e0d17dc79C8"))
2046            .value(U256::from(100));
2047
2048        let _ = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap();
2049
2050        anvil.child_mut().kill().unwrap();
2051
2052        let mut output = String::new();
2053        anvil.child_mut().stdout.take().unwrap().read_to_string(&mut output).unwrap();
2054
2055        assert_eq!(anvil.chain_id(), 31337);
2056        assert_eq!(anvil.addresses().len(), 10);
2057        assert_eq!(anvil.keys().len(), 10);
2058
2059        assert!(output.contains("eth_sendTransaction"));
2060        assert!(output.contains("Block Number: 1"))
2061    }
2062
2063    #[tokio::test]
2064    async fn custom_estimator() {
2065        let provider = ProviderBuilder::new()
2066            .disable_recommended_fillers()
2067            .with_cached_nonce_management()
2068            .on_anvil();
2069
2070        let _ = provider
2071            .estimate_eip1559_fees_with(Eip1559Estimator::new(|_fee, _rewards| Eip1559Estimation {
2072                max_fee_per_gas: 0,
2073                max_priority_fee_per_gas: 0,
2074            }))
2075            .await;
2076    }
2077}