Skip to main content

alloy_provider/fillers/
mod.rs

1//! Transaction fillers.
2//!
3//! Fillers decorate a [`Provider`], filling transaction details before they
4//! are sent to the network, like nonces, gas limits, and gas prices.
5//!
6//! Fillers are called before any other layer in the provider.
7//!
8//! # Implementing a filler
9//!
10//! Fillers implement the [`TxFiller`] trait. Before a filler is called, [`TxFiller::status`] is
11//! called to determine whether the filler has any work to do. If this function returns
12//! [`FillerControlFlow::Ready`], the filler will be called.
13//!
14//! # Composing fillers
15//!
16//! To layer fillers, a utility filler is provided called [`JoinFill`], which is a composition of
17//! two fillers, left and right. The left filler is called before the right filler.
18//!
19//! [`Provider`]: crate::Provider
20
21mod chain_id;
22use alloy_eips::{BlockId, BlockNumberOrTag};
23use alloy_primitives::{
24    Address, BlockHash, BlockNumber, StorageKey, StorageValue, TxHash, B256, U128, U256,
25};
26use alloy_rpc_client::NoParams;
27#[cfg(feature = "pubsub")]
28use alloy_rpc_types_eth::pubsub::{Params, SubscriptionKind};
29use alloy_rpc_types_eth::{Bundle, Index, SyncStatus};
30pub use chain_id::ChainIdFiller;
31use std::borrow::Cow;
32
33mod wallet;
34pub use wallet::WalletFiller;
35
36mod nonce;
37pub use nonce::{CachedNonceManager, NonceFiller, NonceManager, SimpleNonceManager};
38
39mod gas;
40pub use gas::{
41    BlobGasEstimator, BlobGasEstimatorFn, BlobGasEstimatorFunction, BlobGasFiller, GasFillable,
42    GasFiller,
43};
44
45mod join_fill;
46pub use join_fill::JoinFill;
47use tracing::error;
48
49#[cfg(feature = "pubsub")]
50use crate::GetSubscription;
51use crate::{
52    provider::SendableTx, EthCall, EthCallMany, EthGetBlock, FilterPollerBuilder, Identity,
53    PendingTransaction, PendingTransactionBuilder, PendingTransactionConfig,
54    PendingTransactionError, Provider, ProviderCall, ProviderLayer, RootProvider, RpcWithBlock,
55    SendableTxErr,
56};
57use alloy_json_rpc::RpcError;
58use alloy_network::{AnyNetwork, Ethereum, Network};
59use alloy_primitives::{Bytes, U64};
60use alloy_rpc_types_eth::{
61    erc4337::TransactionConditional,
62    simulate::{SimulatePayload, SimulatedBlock},
63    AccessListResult, EIP1186AccountProofResponse, EthCallResponse, FeeHistory, Filter,
64    FilterChanges, Log, StorageValuesRequest, StorageValuesResponse,
65};
66use alloy_transport::{TransportError, TransportResult};
67use async_trait::async_trait;
68use futures_utils_wasm::impl_future;
69use serde_json::value::RawValue;
70use std::marker::PhantomData;
71
72/// The recommended filler, a preconfigured set of layers handling gas estimation, nonce
73/// management, and chain-id fetching.
74pub type RecommendedFiller =
75    JoinFill<JoinFill<JoinFill<Identity, GasFiller>, NonceFiller>, ChainIdFiller>;
76
77/// Error type for failures in the `fill_envelope` function.
78#[derive(Debug, thiserror::Error)]
79pub enum FillEnvelopeError<T> {
80    /// A transport error occurred during the filling process.
81    #[error("transport error during filling: {0}")]
82    Transport(TransportError),
83
84    /// The transaction is not ready to be converted to an envelope.
85    #[error("transaction not ready: {0}")]
86    NotReady(SendableTxErr<T>),
87}
88
89/// The control flow for a filler.
90#[derive(Clone, Debug, PartialEq, Eq)]
91pub enum FillerControlFlow {
92    /// The filler is missing a required property.
93    ///
94    /// To allow joining fillers while preserving their associated missing
95    /// lists, this variant contains a list of `(name, missing)` tuples. When
96    /// absorbing another control flow, if both are missing, the missing lists
97    /// are combined.
98    Missing(Vec<(&'static str, Vec<&'static str>)>),
99    /// The filler is ready to fill in the transaction request.
100    Ready,
101    /// The filler has filled in all properties that it can fill.
102    Finished,
103}
104
105impl FillerControlFlow {
106    /// Absorb the control flow of another filler.
107    ///
108    /// # Behavior:
109    /// - If either is finished, return the unfinished one
110    /// - If either is ready, return ready.
111    /// - If both are missing, return missing.
112    pub fn absorb(self, other: Self) -> Self {
113        if other.is_finished() {
114            return self;
115        }
116
117        if self.is_finished() {
118            return other;
119        }
120
121        if other.is_ready() || self.is_ready() {
122            return Self::Ready;
123        }
124
125        if let (Self::Missing(mut a), Self::Missing(b)) = (self, other) {
126            a.extend(b);
127            return Self::Missing(a);
128        }
129
130        unreachable!()
131    }
132
133    /// Creates a new `Missing` control flow.
134    pub fn missing(name: &'static str, missing: Vec<&'static str>) -> Self {
135        Self::Missing(vec![(name, missing)])
136    }
137
138    /// Returns true if the filler is missing a required property.
139    pub fn as_missing(&self) -> Option<&[(&'static str, Vec<&'static str>)]> {
140        match self {
141            Self::Missing(missing) => Some(missing),
142            _ => None,
143        }
144    }
145
146    /// Returns `true` if the filler is missing information required to fill in
147    /// the transaction request.
148    pub const fn is_missing(&self) -> bool {
149        matches!(self, Self::Missing(_))
150    }
151
152    /// Returns `true` if the filler is ready to fill in the transaction
153    /// request.
154    pub const fn is_ready(&self) -> bool {
155        matches!(self, Self::Ready)
156    }
157
158    /// Returns `true` if the filler is finished filling in the transaction
159    /// request.
160    pub const fn is_finished(&self) -> bool {
161        matches!(self, Self::Finished)
162    }
163}
164
165/// A layer that can fill in a `TransactionRequest` with additional information.
166///
167/// ## Lifecycle Notes
168///
169/// The [`FillerControlFlow`] determines the lifecycle of a filler. Fillers
170/// may be in one of three states:
171/// - **Missing**: The filler is missing a required property to fill in the transaction request.
172///   [`TxFiller::status`] should return [`FillerControlFlow::Missing`]. with a list of the missing
173///   properties.
174/// - **Ready**: The filler is ready to fill in the transaction request. [`TxFiller::status`] should
175///   return [`FillerControlFlow::Ready`].
176/// - **Finished**: The filler has filled in all properties that it can fill. [`TxFiller::status`]
177///   should return [`FillerControlFlow::Finished`].
178#[doc(alias = "TransactionFiller")]
179pub trait TxFiller<N: Network = Ethereum>: Clone + Send + Sync + std::fmt::Debug {
180    /// The properties that this filler retrieves from the RPC. to fill in the
181    /// TransactionRequest.
182    type Fillable: Send + Sync + 'static;
183
184    /// Joins this filler with another filler to compose multiple fillers.
185    fn join_with<T>(self, other: T) -> JoinFill<Self, T>
186    where
187        T: TxFiller<N>,
188    {
189        JoinFill::new(self, other)
190    }
191
192    /// Return a control-flow enum indicating whether the filler is ready to
193    /// fill in the transaction request, or if it is missing required
194    /// properties.
195    fn status(&self, tx: &N::TransactionRequest) -> FillerControlFlow;
196
197    /// Returns `true` if the filler should continue filling.
198    fn continue_filling(&self, tx: &SendableTx<N>) -> bool {
199        tx.as_builder().is_some_and(|tx| self.status(tx).is_ready())
200    }
201
202    /// Returns `true` if the filler is ready to fill in the transaction request.
203    fn ready(&self, tx: &N::TransactionRequest) -> bool {
204        self.status(tx).is_ready()
205    }
206
207    /// Returns `true` if the filler is finished filling in the transaction request.
208    fn finished(&self, tx: &N::TransactionRequest) -> bool {
209        self.status(tx).is_finished()
210    }
211
212    /// Performs any synchronous filling. This should be called before
213    /// [`TxFiller::prepare`] and [`TxFiller::fill`] to fill in any properties
214    /// that can be filled synchronously.
215    fn fill_sync(&self, tx: &mut SendableTx<N>);
216
217    /// Prepares fillable properties, potentially by making an RPC request.
218    fn prepare<P: Provider<N>>(
219        &self,
220        provider: &P,
221        tx: &N::TransactionRequest,
222    ) -> impl_future!(<Output = TransportResult<Self::Fillable>>);
223
224    /// Fills in the transaction request with the fillable properties.
225    fn fill(
226        &self,
227        fillable: Self::Fillable,
228        tx: SendableTx<N>,
229    ) -> impl_future!(<Output = TransportResult<SendableTx<N>>>);
230
231    /// Fills in the transaction request and try to convert it to an envelope.
232    fn fill_envelope(
233        &self,
234        fillable: Self::Fillable,
235        tx: SendableTx<N>,
236    ) -> impl_future!(<Output = Result<N::TxEnvelope, FillEnvelopeError<N::TransactionRequest>>>)
237    {
238        async move {
239            let tx = self.fill(fillable, tx).await.map_err(FillEnvelopeError::Transport)?;
240            let envelope = tx.try_into_envelope().map_err(FillEnvelopeError::NotReady)?;
241            Ok(envelope)
242        }
243    }
244
245    /// Prepares and fills the transaction request with the fillable properties.
246    fn prepare_and_fill<P>(
247        &self,
248        provider: &P,
249        tx: SendableTx<N>,
250    ) -> impl_future!(<Output = TransportResult<SendableTx<N>>>)
251    where
252        P: Provider<N>,
253    {
254        async move {
255            if tx.is_envelope() {
256                return Ok(tx);
257            }
258
259            let fillable =
260                self.prepare(provider, tx.as_builder().expect("checked by is_envelope")).await?;
261
262            self.fill(fillable, tx).await
263        }
264    }
265
266    /// Prepares transaction request with necessary fillers required for eth_call operations
267    /// asynchronously
268    fn prepare_call(
269        &self,
270        tx: &mut N::TransactionRequest,
271    ) -> impl_future!(<Output = TransportResult<()>>) {
272        let _ = tx;
273        // This is a no-op by default
274        futures::future::ready(Ok(()))
275    }
276
277    /// Prepares transaction request with necessary fillers required for eth_call operations
278    /// synchronously
279    fn prepare_call_sync(&self, tx: &mut N::TransactionRequest) -> TransportResult<()> {
280        let _ = tx;
281        // No-op default
282        Ok(())
283    }
284}
285
286/// A [`Provider`] that applies one or more [`TxFiller`]s.
287///
288/// Fills arbitrary properties in a transaction request by composing multiple
289/// fill layers. This struct should always be the outermost layer in a provider
290/// stack, and this is enforced when using [`ProviderBuilder::filler`] to
291/// construct this layer.
292///
293/// Users should NOT use this struct directly. Instead, use
294/// [`ProviderBuilder::filler`] to construct and apply it to a stack.
295///
296/// [`ProviderBuilder::filler`]: crate::ProviderBuilder::filler
297#[derive(Clone, Debug)]
298pub struct FillProvider<F, P, N = Ethereum>
299where
300    F: TxFiller<N>,
301    P: Provider<N>,
302    N: Network,
303{
304    pub(crate) inner: P,
305    pub(crate) filler: F,
306    _pd: PhantomData<fn() -> N>,
307}
308
309impl<F, P, N> FillProvider<F, P, N>
310where
311    F: TxFiller<N>,
312    P: Provider<N>,
313    N: Network,
314{
315    /// Creates a new `FillProvider` with the given filler and inner provider.
316    pub fn new(inner: P, filler: F) -> Self {
317        Self { inner, filler, _pd: PhantomData }
318    }
319
320    /// Returns a reference to the filler.
321    pub const fn filler(&self) -> &F {
322        &self.filler
323    }
324
325    /// Returns a mutable reference to the filler.
326    pub const fn filler_mut(&mut self) -> &mut F {
327        &mut self.filler
328    }
329
330    /// Returns a reference to the inner provider.
331    pub const fn inner(&self) -> &P {
332        &self.inner
333    }
334
335    /// Returns a mutable reference to the inner provider.
336    pub const fn inner_mut(&mut self) -> &mut P {
337        &mut self.inner
338    }
339
340    /// Joins a filler to this provider
341    pub fn join_with<Other: TxFiller<N>>(
342        self,
343        other: Other,
344    ) -> FillProvider<JoinFill<F, Other>, P, N> {
345        self.filler.join_with(other).layer(self.inner)
346    }
347
348    async fn fill_inner(&self, mut tx: SendableTx<N>) -> TransportResult<SendableTx<N>> {
349        let mut count = 0;
350
351        while self.filler.continue_filling(&tx) {
352            self.filler.fill_sync(&mut tx);
353            tx = self.filler.prepare_and_fill(&self.inner, tx).await?;
354
355            count += 1;
356            if count >= 20 {
357                const ERROR: &str = "Tx filler loop detected. This indicates a bug in some filler implementation. Please file an issue containing this message.";
358                error!(
359                    ?tx, ?self.filler,
360                    ERROR
361                );
362                panic!("{}, {:?}, {:?}", ERROR, tx, self.filler);
363            }
364        }
365        Ok(tx)
366    }
367
368    /// Fills the transaction request, using the configured fillers
369    ///
370    /// # Example
371    ///
372    /// ```rust
373    /// # use alloy_consensus::{TypedTransaction, SignableTransaction};
374    /// # use alloy_primitives::{Address, U256};
375    /// # use alloy_provider::{Provider, ProviderBuilder};
376    /// # use alloy_rpc_types_eth::TransactionRequest;
377    /// # use alloy_network::{NetworkTransactionBuilder, TransactionBuilder};
378    ///
379    /// # #[cfg(feature = "anvil-node")]
380    /// async fn example() -> Result<(), Box<dyn std::error::Error>> {
381    ///     // Do not add a wallet: this example needs the filled request, not a signed envelope.
382    ///     let provider = ProviderBuilder::new().connect_anvil();
383    ///     let from = provider
384    ///         .get_accounts()
385    ///         .await?
386    ///         .into_iter()
387    ///         .next()
388    ///         .expect("Anvil provides funded accounts");
389    ///
390    ///     let tx_request = TransactionRequest::default()
391    ///         .with_from(from)
392    ///         .with_to(Address::ZERO)
393    ///         .with_value(U256::from(1000));
394    ///
395    ///     // Fill transaction with provider data
396    ///     let filled_tx = provider.fill(tx_request).await?;
397    ///
398    ///     // Build unsigned transaction
399    ///     let typed_tx =
400    ///         filled_tx.as_builder().expect("filled tx is a builder").clone().build_unsigned()?;
401    ///
402    ///     // Encode, e.g. for offline signing
403    ///     let mut encoded = Vec::new();
404    ///     typed_tx.encode_for_signing(&mut encoded);
405    ///
406    ///     // Decode unsigned transaction
407    ///     let decoded = TypedTransaction::decode_unsigned(&mut encoded.as_slice())?;
408    ///
409    ///     Ok(())
410    /// }
411    /// # #[cfg(not(feature = "anvil-node"))]
412    /// # fn example() {}
413    /// ```
414    pub async fn fill(&self, tx: N::TransactionRequest) -> TransportResult<SendableTx<N>> {
415        self.fill_inner(SendableTx::Builder(tx)).await
416    }
417
418    /// Prepares a transaction request for eth_call operations using the configured fillers
419    pub fn prepare_call(
420        &self,
421        mut tx: N::TransactionRequest,
422    ) -> TransportResult<N::TransactionRequest> {
423        self.filler.prepare_call_sync(&mut tx)?;
424        Ok(tx)
425    }
426}
427
428#[cfg_attr(target_family = "wasm", async_trait(?Send))]
429#[cfg_attr(not(target_family = "wasm"), async_trait)]
430impl<F, P, N> Provider<N> for FillProvider<F, P, N>
431where
432    F: TxFiller<N>,
433    P: Provider<N>,
434    N: Network,
435{
436    fn root(&self) -> &RootProvider<N> {
437        self.inner.root()
438    }
439
440    fn get_accounts(&self) -> ProviderCall<NoParams, Vec<Address>> {
441        self.inner.get_accounts()
442    }
443
444    fn get_blob_base_fee(&self) -> ProviderCall<NoParams, U128, u128> {
445        self.inner.get_blob_base_fee()
446    }
447
448    fn get_block_number(&self) -> ProviderCall<NoParams, U64, BlockNumber> {
449        self.inner.get_block_number()
450    }
451
452    fn call<'req>(&self, tx: N::TransactionRequest) -> EthCall<N, Bytes> {
453        let mut tx = tx;
454        let _ = self.filler.prepare_call_sync(&mut tx);
455        self.inner.call(tx)
456    }
457
458    fn call_many<'req>(
459        &self,
460        bundles: &'req [Bundle],
461    ) -> EthCallMany<'req, N, Vec<Vec<EthCallResponse>>> {
462        self.inner.call_many(bundles)
463    }
464
465    fn simulate<'req>(
466        &self,
467        payload: &'req SimulatePayload,
468    ) -> RpcWithBlock<&'req SimulatePayload, Vec<SimulatedBlock<N::BlockResponse>>> {
469        self.inner.simulate(payload)
470    }
471
472    fn get_chain_id(&self) -> ProviderCall<NoParams, U64, u64> {
473        self.inner.get_chain_id()
474    }
475
476    fn create_access_list<'a>(
477        &self,
478        request: &'a N::TransactionRequest,
479    ) -> RpcWithBlock<&'a N::TransactionRequest, AccessListResult> {
480        self.inner.create_access_list(request)
481    }
482
483    fn estimate_gas<'req>(&self, tx: N::TransactionRequest) -> EthCall<N, U64, u64> {
484        let mut tx = tx;
485        let _ = self.filler.prepare_call_sync(&mut tx);
486        self.inner.estimate_gas(tx)
487    }
488
489    async fn get_fee_history(
490        &self,
491        block_count: u64,
492        last_block: BlockNumberOrTag,
493        reward_percentiles: &[f64],
494    ) -> TransportResult<FeeHistory> {
495        self.inner.get_fee_history(block_count, last_block, reward_percentiles).await
496    }
497
498    fn get_gas_price(&self) -> ProviderCall<NoParams, U128, u128> {
499        self.inner.get_gas_price()
500    }
501
502    fn get_account_info(
503        &self,
504        address: Address,
505    ) -> RpcWithBlock<Address, alloy_rpc_types_eth::AccountInfo> {
506        self.inner.get_account_info(address)
507    }
508
509    fn get_account(&self, address: Address) -> RpcWithBlock<Address, alloy_consensus::TrieAccount> {
510        self.inner.get_account(address)
511    }
512
513    fn get_balance(&self, address: Address) -> RpcWithBlock<Address, U256, U256> {
514        self.inner.get_balance(address)
515    }
516
517    fn get_block(&self, block: BlockId) -> EthGetBlock<N::BlockResponse> {
518        self.inner.get_block(block)
519    }
520
521    fn get_block_by_hash(&self, hash: BlockHash) -> EthGetBlock<N::BlockResponse> {
522        self.inner.get_block_by_hash(hash)
523    }
524
525    fn get_block_by_number(&self, number: BlockNumberOrTag) -> EthGetBlock<N::BlockResponse> {
526        self.inner.get_block_by_number(number)
527    }
528
529    async fn get_block_transaction_count_by_hash(
530        &self,
531        hash: BlockHash,
532    ) -> TransportResult<Option<u64>> {
533        self.inner.get_block_transaction_count_by_hash(hash).await
534    }
535
536    async fn get_block_transaction_count_by_number(
537        &self,
538        block_number: BlockNumberOrTag,
539    ) -> TransportResult<Option<u64>> {
540        self.inner.get_block_transaction_count_by_number(block_number).await
541    }
542
543    fn get_block_receipts(
544        &self,
545        block: BlockId,
546    ) -> ProviderCall<(BlockId,), Option<Vec<N::ReceiptResponse>>> {
547        self.inner.get_block_receipts(block)
548    }
549
550    async fn get_header(&self, block: BlockId) -> TransportResult<Option<N::HeaderResponse>> {
551        self.inner.get_header(block).await
552    }
553
554    async fn get_header_by_hash(
555        &self,
556        hash: BlockHash,
557    ) -> TransportResult<Option<N::HeaderResponse>> {
558        self.inner.get_header_by_hash(hash).await
559    }
560
561    async fn get_header_by_number(
562        &self,
563        number: BlockNumberOrTag,
564    ) -> TransportResult<Option<N::HeaderResponse>> {
565        self.inner.get_header_by_number(number).await
566    }
567
568    fn get_code_at(&self, address: Address) -> RpcWithBlock<Address, Bytes> {
569        self.inner.get_code_at(address)
570    }
571
572    async fn watch_blocks(&self) -> TransportResult<FilterPollerBuilder<B256>> {
573        self.inner.watch_blocks().await
574    }
575
576    async fn watch_pending_transactions(&self) -> TransportResult<FilterPollerBuilder<B256>> {
577        self.inner.watch_pending_transactions().await
578    }
579
580    async fn watch_logs(&self, filter: &Filter) -> TransportResult<FilterPollerBuilder<Log>> {
581        self.inner.watch_logs(filter).await
582    }
583
584    async fn watch_full_pending_transactions(
585        &self,
586    ) -> TransportResult<FilterPollerBuilder<N::TransactionResponse>> {
587        self.inner.watch_full_pending_transactions().await
588    }
589
590    async fn get_filter_changes_dyn(&self, id: U256) -> TransportResult<FilterChanges> {
591        self.inner.get_filter_changes_dyn(id).await
592    }
593
594    async fn get_filter_logs(&self, id: U256) -> TransportResult<Vec<Log>> {
595        self.inner.get_filter_logs(id).await
596    }
597
598    async fn uninstall_filter(&self, id: U256) -> TransportResult<bool> {
599        self.inner.uninstall_filter(id).await
600    }
601
602    async fn watch_pending_transaction(
603        &self,
604        config: PendingTransactionConfig,
605    ) -> Result<PendingTransaction, PendingTransactionError> {
606        self.inner.watch_pending_transaction(config).await
607    }
608
609    async fn get_logs(&self, filter: &Filter) -> TransportResult<Vec<Log>> {
610        self.inner.get_logs(filter).await
611    }
612
613    fn get_proof(
614        &self,
615        address: Address,
616        keys: Vec<StorageKey>,
617    ) -> RpcWithBlock<(Address, Vec<StorageKey>), EIP1186AccountProofResponse> {
618        self.inner.get_proof(address, keys)
619    }
620
621    fn get_storage_at(
622        &self,
623        address: Address,
624        key: U256,
625    ) -> RpcWithBlock<(Address, U256), StorageValue> {
626        self.inner.get_storage_at(address, key)
627    }
628
629    fn get_storage_values(
630        &self,
631        requests: StorageValuesRequest,
632    ) -> RpcWithBlock<(StorageValuesRequest,), StorageValuesResponse> {
633        self.inner.get_storage_values(requests)
634    }
635
636    fn get_transaction_by_hash(
637        &self,
638        hash: TxHash,
639    ) -> ProviderCall<(TxHash,), Option<N::TransactionResponse>> {
640        self.inner.get_transaction_by_hash(hash)
641    }
642
643    fn get_transaction_by_sender_nonce(
644        &self,
645        sender: Address,
646        nonce: u64,
647    ) -> ProviderCall<(Address, U64), Option<N::TransactionResponse>> {
648        self.inner.get_transaction_by_sender_nonce(sender, nonce)
649    }
650
651    fn get_transaction_by_block_hash_and_index(
652        &self,
653        block_hash: B256,
654        index: usize,
655    ) -> ProviderCall<(B256, Index), Option<N::TransactionResponse>> {
656        self.inner.get_transaction_by_block_hash_and_index(block_hash, index)
657    }
658
659    fn get_raw_transaction_by_block_hash_and_index(
660        &self,
661        block_hash: B256,
662        index: usize,
663    ) -> ProviderCall<(B256, Index), Option<Bytes>> {
664        self.inner.get_raw_transaction_by_block_hash_and_index(block_hash, index)
665    }
666
667    fn get_transaction_by_block_number_and_index(
668        &self,
669        block_number: BlockNumberOrTag,
670        index: usize,
671    ) -> ProviderCall<(BlockNumberOrTag, Index), Option<N::TransactionResponse>> {
672        self.inner.get_transaction_by_block_number_and_index(block_number, index)
673    }
674
675    fn get_raw_transaction_by_block_number_and_index(
676        &self,
677        block_number: BlockNumberOrTag,
678        index: usize,
679    ) -> ProviderCall<(BlockNumberOrTag, Index), Option<Bytes>> {
680        self.inner.get_raw_transaction_by_block_number_and_index(block_number, index)
681    }
682
683    fn get_raw_transaction_by_hash(&self, hash: TxHash) -> ProviderCall<(TxHash,), Option<Bytes>> {
684        self.inner.get_raw_transaction_by_hash(hash)
685    }
686
687    fn get_transaction_count(
688        &self,
689        address: Address,
690    ) -> RpcWithBlock<Address, U64, u64, fn(U64) -> u64> {
691        self.inner.get_transaction_count(address)
692    }
693
694    fn get_transaction_receipt(
695        &self,
696        hash: TxHash,
697    ) -> ProviderCall<(TxHash,), Option<N::ReceiptResponse>> {
698        self.inner.get_transaction_receipt(hash)
699    }
700
701    async fn get_uncle(&self, tag: BlockId, idx: u64) -> TransportResult<Option<N::BlockResponse>> {
702        self.inner.get_uncle(tag, idx).await
703    }
704
705    async fn get_uncle_count(&self, tag: BlockId) -> TransportResult<u64> {
706        self.inner.get_uncle_count(tag).await
707    }
708
709    fn get_max_priority_fee_per_gas(&self) -> ProviderCall<NoParams, U128, u128> {
710        self.inner.get_max_priority_fee_per_gas()
711    }
712
713    async fn new_block_filter(&self) -> TransportResult<U256> {
714        self.inner.new_block_filter().await
715    }
716
717    async fn new_filter(&self, filter: &Filter) -> TransportResult<U256> {
718        self.inner.new_filter(filter).await
719    }
720
721    async fn new_pending_transactions_filter(&self, full: bool) -> TransportResult<U256> {
722        self.inner.new_pending_transactions_filter(full).await
723    }
724
725    async fn send_raw_transaction(
726        &self,
727        encoded_tx: &[u8],
728    ) -> TransportResult<PendingTransactionBuilder<N>> {
729        self.inner.send_raw_transaction(encoded_tx).await
730    }
731
732    async fn send_raw_transaction_conditional(
733        &self,
734        encoded_tx: &[u8],
735        conditional: TransactionConditional,
736    ) -> TransportResult<PendingTransactionBuilder<N>> {
737        self.inner.send_raw_transaction_conditional(encoded_tx, conditional).await
738    }
739
740    async fn send_transaction_internal(
741        &self,
742        mut tx: SendableTx<N>,
743    ) -> TransportResult<PendingTransactionBuilder<N>> {
744        tx = self.fill_inner(tx).await?;
745
746        if let Some(builder) = tx.as_builder() {
747            if let FillerControlFlow::Missing(missing) = self.filler.status(builder) {
748                // TODO: improve this.
749                // blocked by #431
750                let message = format!("missing properties: {missing:?}");
751                return Err(RpcError::local_usage_str(&message));
752            }
753        }
754
755        // Errors in tx building happen further down the stack.
756        self.inner.send_transaction_internal(tx).await
757    }
758
759    async fn send_transaction_sync_internal(
760        &self,
761        mut tx: SendableTx<N>,
762    ) -> TransportResult<N::ReceiptResponse> {
763        tx = self.fill_inner(tx).await?;
764
765        if let Some(builder) = tx.as_builder() {
766            if let FillerControlFlow::Missing(missing) = self.filler.status(builder) {
767                let message = format!("missing properties: {missing:?}");
768                return Err(RpcError::local_usage_str(&message));
769            }
770        }
771
772        // Errors in tx building happen further down the stack.
773        self.inner.send_transaction_sync_internal(tx).await
774    }
775
776    async fn sign_transaction(&self, tx: N::TransactionRequest) -> TransportResult<Bytes> {
777        let tx = self.fill(tx).await?;
778        let tx = tx.try_into_request().map_err(TransportError::local_usage)?;
779        self.inner.sign_transaction(tx).await
780    }
781
782    #[cfg(feature = "pubsub")]
783    fn subscribe_blocks(&self) -> GetSubscription<(SubscriptionKind,), N::HeaderResponse> {
784        self.inner.subscribe_blocks()
785    }
786
787    #[cfg(feature = "pubsub")]
788    fn subscribe_pending_transactions(&self) -> GetSubscription<(SubscriptionKind,), B256> {
789        self.inner.subscribe_pending_transactions()
790    }
791
792    #[cfg(feature = "pubsub")]
793    fn subscribe_full_pending_transactions(
794        &self,
795    ) -> GetSubscription<(SubscriptionKind, Params), N::TransactionResponse> {
796        self.inner.subscribe_full_pending_transactions()
797    }
798
799    #[cfg(feature = "pubsub")]
800    fn subscribe_logs(&self, filter: &Filter) -> GetSubscription<(SubscriptionKind, Params), Log> {
801        self.inner.subscribe_logs(filter)
802    }
803
804    #[cfg(feature = "pubsub")]
805    async fn unsubscribe(&self, id: B256) -> TransportResult<()> {
806        self.inner.unsubscribe(id).await
807    }
808
809    fn syncing(&self) -> ProviderCall<NoParams, SyncStatus> {
810        self.inner.syncing()
811    }
812
813    fn get_client_version(&self) -> ProviderCall<NoParams, String> {
814        self.inner.get_client_version()
815    }
816
817    fn get_sha3(&self, data: &[u8]) -> ProviderCall<(String,), B256> {
818        self.inner.get_sha3(data)
819    }
820
821    fn get_net_version(&self) -> ProviderCall<NoParams, U64, u64> {
822        self.inner.get_net_version()
823    }
824
825    async fn raw_request_dyn(
826        &self,
827        method: Cow<'static, str>,
828        params: &RawValue,
829    ) -> TransportResult<Box<RawValue>> {
830        self.inner.raw_request_dyn(method, params).await
831    }
832
833    fn transaction_request(&self) -> N::TransactionRequest {
834        self.inner.transaction_request()
835    }
836}
837
838/// A trait which may be used to configure default fillers for [Network] implementations.
839pub trait RecommendedFillers: Network {
840    /// Recommended fillers for this network.
841    type RecommendedFillers: TxFiller<Self>;
842
843    /// Returns the recommended filler for this provider.
844    fn recommended_fillers() -> Self::RecommendedFillers;
845}
846
847impl RecommendedFillers for Ethereum {
848    type RecommendedFillers =
849        JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>;
850
851    fn recommended_fillers() -> Self::RecommendedFillers {
852        Default::default()
853    }
854}
855
856impl RecommendedFillers for AnyNetwork {
857    type RecommendedFillers =
858        JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>;
859
860    fn recommended_fillers() -> Self::RecommendedFillers {
861        Default::default()
862    }
863}