alloy_provider/provider/
trait.rs

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