alloy_provider/provider/
trait.rs

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