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