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