1mod 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,
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
72pub type RecommendedFiller =
75 JoinFill<JoinFill<JoinFill<Identity, GasFiller>, NonceFiller>, ChainIdFiller>;
76
77#[derive(Debug, thiserror::Error)]
79pub enum FillEnvelopeError<T> {
80 #[error("transport error during filling: {0}")]
82 Transport(TransportError),
83
84 #[error("transaction not ready: {0}")]
86 NotReady(SendableTxErr<T>),
87}
88
89#[derive(Clone, Debug, PartialEq, Eq)]
91pub enum FillerControlFlow {
92 Missing(Vec<(&'static str, Vec<&'static str>)>),
99 Ready,
101 Finished,
103}
104
105impl FillerControlFlow {
106 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 pub fn missing(name: &'static str, missing: Vec<&'static str>) -> Self {
135 Self::Missing(vec![(name, missing)])
136 }
137
138 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 pub const fn is_missing(&self) -> bool {
149 matches!(self, Self::Missing(_))
150 }
151
152 pub const fn is_ready(&self) -> bool {
155 matches!(self, Self::Ready)
156 }
157
158 pub const fn is_finished(&self) -> bool {
161 matches!(self, Self::Finished)
162 }
163}
164
165#[doc(alias = "TransactionFiller")]
179pub trait TxFiller<N: Network = Ethereum>: Clone + Send + Sync + std::fmt::Debug {
180 type Fillable: Send + Sync + 'static;
183
184 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 fn status(&self, tx: &N::TransactionRequest) -> FillerControlFlow;
196
197 fn continue_filling(&self, tx: &SendableTx<N>) -> bool {
199 tx.as_builder().is_some_and(|tx| self.status(tx).is_ready())
200 }
201
202 fn ready(&self, tx: &N::TransactionRequest) -> bool {
204 self.status(tx).is_ready()
205 }
206
207 fn finished(&self, tx: &N::TransactionRequest) -> bool {
209 self.status(tx).is_finished()
210 }
211
212 fn fill_sync(&self, tx: &mut SendableTx<N>);
216
217 fn prepare<P: Provider<N>>(
219 &self,
220 provider: &P,
221 tx: &N::TransactionRequest,
222 ) -> impl_future!(<Output = TransportResult<Self::Fillable>>);
223
224 fn fill(
226 &self,
227 fillable: Self::Fillable,
228 tx: SendableTx<N>,
229 ) -> impl_future!(<Output = TransportResult<SendableTx<N>>>);
230
231 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 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 fn prepare_call(
269 &self,
270 tx: &mut N::TransactionRequest,
271 ) -> impl_future!(<Output = TransportResult<()>>) {
272 let _ = tx;
273 futures::future::ready(Ok(()))
275 }
276
277 fn prepare_call_sync(&self, tx: &mut N::TransactionRequest) -> TransportResult<()> {
280 let _ = tx;
281 Ok(())
283 }
284}
285
286#[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 pub fn new(inner: P, filler: F) -> Self {
317 Self { inner, filler, _pd: PhantomData }
318 }
319
320 pub const fn filler(&self) -> &F {
322 &self.filler
323 }
324
325 pub const fn filler_mut(&mut self) -> &mut F {
327 &mut self.filler
328 }
329
330 pub const fn inner(&self) -> &P {
332 &self.inner
333 }
334
335 pub const fn inner_mut(&mut self) -> &mut P {
337 &mut self.inner
338 }
339
340 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 pub async fn fill(&self, tx: N::TransactionRequest) -> TransportResult<SendableTx<N>> {
405 self.fill_inner(SendableTx::Builder(tx)).await
406 }
407
408 pub fn prepare_call(
410 &self,
411 mut tx: N::TransactionRequest,
412 ) -> TransportResult<N::TransactionRequest> {
413 self.filler.prepare_call_sync(&mut tx)?;
414 Ok(tx)
415 }
416}
417
418#[cfg_attr(target_family = "wasm", async_trait(?Send))]
419#[cfg_attr(not(target_family = "wasm"), async_trait)]
420impl<F, P, N> Provider<N> for FillProvider<F, P, N>
421where
422 F: TxFiller<N>,
423 P: Provider<N>,
424 N: Network,
425{
426 fn root(&self) -> &RootProvider<N> {
427 self.inner.root()
428 }
429
430 fn get_accounts(&self) -> ProviderCall<NoParams, Vec<Address>> {
431 self.inner.get_accounts()
432 }
433
434 fn get_blob_base_fee(&self) -> ProviderCall<NoParams, U128, u128> {
435 self.inner.get_blob_base_fee()
436 }
437
438 fn get_block_number(&self) -> ProviderCall<NoParams, U64, BlockNumber> {
439 self.inner.get_block_number()
440 }
441
442 fn call<'req>(&self, tx: N::TransactionRequest) -> EthCall<N, Bytes> {
443 let mut tx = tx;
444 let _ = self.filler.prepare_call_sync(&mut tx);
445 self.inner.call(tx)
446 }
447
448 fn call_many<'req>(
449 &self,
450 bundles: &'req [Bundle],
451 ) -> EthCallMany<'req, N, Vec<Vec<EthCallResponse>>> {
452 self.inner.call_many(bundles)
453 }
454
455 fn simulate<'req>(
456 &self,
457 payload: &'req SimulatePayload,
458 ) -> RpcWithBlock<&'req SimulatePayload, Vec<SimulatedBlock<N::BlockResponse>>> {
459 self.inner.simulate(payload)
460 }
461
462 fn get_chain_id(&self) -> ProviderCall<NoParams, U64, u64> {
463 self.inner.get_chain_id()
464 }
465
466 fn create_access_list<'a>(
467 &self,
468 request: &'a N::TransactionRequest,
469 ) -> RpcWithBlock<&'a N::TransactionRequest, AccessListResult> {
470 self.inner.create_access_list(request)
471 }
472
473 fn estimate_gas<'req>(&self, tx: N::TransactionRequest) -> EthCall<N, U64, u64> {
474 let mut tx = tx;
475 let _ = self.filler.prepare_call_sync(&mut tx);
476 self.inner.estimate_gas(tx)
477 }
478
479 async fn get_fee_history(
480 &self,
481 block_count: u64,
482 last_block: BlockNumberOrTag,
483 reward_percentiles: &[f64],
484 ) -> TransportResult<FeeHistory> {
485 self.inner.get_fee_history(block_count, last_block, reward_percentiles).await
486 }
487
488 fn get_gas_price(&self) -> ProviderCall<NoParams, U128, u128> {
489 self.inner.get_gas_price()
490 }
491
492 fn get_account_info(
493 &self,
494 address: Address,
495 ) -> RpcWithBlock<Address, alloy_rpc_types_eth::AccountInfo> {
496 self.inner.get_account_info(address)
497 }
498
499 fn get_account(&self, address: Address) -> RpcWithBlock<Address, alloy_consensus::TrieAccount> {
500 self.inner.get_account(address)
501 }
502
503 fn get_balance(&self, address: Address) -> RpcWithBlock<Address, U256, U256> {
504 self.inner.get_balance(address)
505 }
506
507 fn get_block(&self, block: BlockId) -> EthGetBlock<N::BlockResponse> {
508 self.inner.get_block(block)
509 }
510
511 fn get_block_by_hash(&self, hash: BlockHash) -> EthGetBlock<N::BlockResponse> {
512 self.inner.get_block_by_hash(hash)
513 }
514
515 fn get_block_by_number(&self, number: BlockNumberOrTag) -> EthGetBlock<N::BlockResponse> {
516 self.inner.get_block_by_number(number)
517 }
518
519 async fn get_block_transaction_count_by_hash(
520 &self,
521 hash: BlockHash,
522 ) -> TransportResult<Option<u64>> {
523 self.inner.get_block_transaction_count_by_hash(hash).await
524 }
525
526 async fn get_block_transaction_count_by_number(
527 &self,
528 block_number: BlockNumberOrTag,
529 ) -> TransportResult<Option<u64>> {
530 self.inner.get_block_transaction_count_by_number(block_number).await
531 }
532
533 fn get_block_receipts(
534 &self,
535 block: BlockId,
536 ) -> ProviderCall<(BlockId,), Option<Vec<N::ReceiptResponse>>> {
537 self.inner.get_block_receipts(block)
538 }
539
540 fn get_code_at(&self, address: Address) -> RpcWithBlock<Address, Bytes> {
541 self.inner.get_code_at(address)
542 }
543
544 async fn watch_blocks(&self) -> TransportResult<FilterPollerBuilder<B256>> {
545 self.inner.watch_blocks().await
546 }
547
548 async fn watch_pending_transactions(&self) -> TransportResult<FilterPollerBuilder<B256>> {
549 self.inner.watch_pending_transactions().await
550 }
551
552 async fn watch_logs(&self, filter: &Filter) -> TransportResult<FilterPollerBuilder<Log>> {
553 self.inner.watch_logs(filter).await
554 }
555
556 async fn watch_full_pending_transactions(
557 &self,
558 ) -> TransportResult<FilterPollerBuilder<N::TransactionResponse>> {
559 self.inner.watch_full_pending_transactions().await
560 }
561
562 async fn get_filter_changes_dyn(&self, id: U256) -> TransportResult<FilterChanges> {
563 self.inner.get_filter_changes_dyn(id).await
564 }
565
566 async fn get_filter_logs(&self, id: U256) -> TransportResult<Vec<Log>> {
567 self.inner.get_filter_logs(id).await
568 }
569
570 async fn uninstall_filter(&self, id: U256) -> TransportResult<bool> {
571 self.inner.uninstall_filter(id).await
572 }
573
574 async fn watch_pending_transaction(
575 &self,
576 config: PendingTransactionConfig,
577 ) -> Result<PendingTransaction, PendingTransactionError> {
578 self.inner.watch_pending_transaction(config).await
579 }
580
581 async fn get_logs(&self, filter: &Filter) -> TransportResult<Vec<Log>> {
582 self.inner.get_logs(filter).await
583 }
584
585 fn get_proof(
586 &self,
587 address: Address,
588 keys: Vec<StorageKey>,
589 ) -> RpcWithBlock<(Address, Vec<StorageKey>), EIP1186AccountProofResponse> {
590 self.inner.get_proof(address, keys)
591 }
592
593 fn get_storage_at(
594 &self,
595 address: Address,
596 key: U256,
597 ) -> RpcWithBlock<(Address, U256), StorageValue> {
598 self.inner.get_storage_at(address, key)
599 }
600
601 fn get_transaction_by_hash(
602 &self,
603 hash: TxHash,
604 ) -> ProviderCall<(TxHash,), Option<N::TransactionResponse>> {
605 self.inner.get_transaction_by_hash(hash)
606 }
607
608 fn get_transaction_by_sender_nonce(
609 &self,
610 sender: Address,
611 nonce: u64,
612 ) -> ProviderCall<(Address, U64), Option<N::TransactionResponse>> {
613 self.inner.get_transaction_by_sender_nonce(sender, nonce)
614 }
615
616 fn get_transaction_by_block_hash_and_index(
617 &self,
618 block_hash: B256,
619 index: usize,
620 ) -> ProviderCall<(B256, Index), Option<N::TransactionResponse>> {
621 self.inner.get_transaction_by_block_hash_and_index(block_hash, index)
622 }
623
624 fn get_raw_transaction_by_block_hash_and_index(
625 &self,
626 block_hash: B256,
627 index: usize,
628 ) -> ProviderCall<(B256, Index), Option<Bytes>> {
629 self.inner.get_raw_transaction_by_block_hash_and_index(block_hash, index)
630 }
631
632 fn get_transaction_by_block_number_and_index(
633 &self,
634 block_number: BlockNumberOrTag,
635 index: usize,
636 ) -> ProviderCall<(BlockNumberOrTag, Index), Option<N::TransactionResponse>> {
637 self.inner.get_transaction_by_block_number_and_index(block_number, index)
638 }
639
640 fn get_raw_transaction_by_block_number_and_index(
641 &self,
642 block_number: BlockNumberOrTag,
643 index: usize,
644 ) -> ProviderCall<(BlockNumberOrTag, Index), Option<Bytes>> {
645 self.inner.get_raw_transaction_by_block_number_and_index(block_number, index)
646 }
647
648 fn get_raw_transaction_by_hash(&self, hash: TxHash) -> ProviderCall<(TxHash,), Option<Bytes>> {
649 self.inner.get_raw_transaction_by_hash(hash)
650 }
651
652 fn get_transaction_count(
653 &self,
654 address: Address,
655 ) -> RpcWithBlock<Address, U64, u64, fn(U64) -> u64> {
656 self.inner.get_transaction_count(address)
657 }
658
659 fn get_transaction_receipt(
660 &self,
661 hash: TxHash,
662 ) -> ProviderCall<(TxHash,), Option<N::ReceiptResponse>> {
663 self.inner.get_transaction_receipt(hash)
664 }
665
666 async fn get_uncle(&self, tag: BlockId, idx: u64) -> TransportResult<Option<N::BlockResponse>> {
667 self.inner.get_uncle(tag, idx).await
668 }
669
670 async fn get_uncle_count(&self, tag: BlockId) -> TransportResult<u64> {
671 self.inner.get_uncle_count(tag).await
672 }
673
674 fn get_max_priority_fee_per_gas(&self) -> ProviderCall<NoParams, U128, u128> {
675 self.inner.get_max_priority_fee_per_gas()
676 }
677
678 async fn new_block_filter(&self) -> TransportResult<U256> {
679 self.inner.new_block_filter().await
680 }
681
682 async fn new_filter(&self, filter: &Filter) -> TransportResult<U256> {
683 self.inner.new_filter(filter).await
684 }
685
686 async fn new_pending_transactions_filter(&self, full: bool) -> TransportResult<U256> {
687 self.inner.new_pending_transactions_filter(full).await
688 }
689
690 async fn send_raw_transaction(
691 &self,
692 encoded_tx: &[u8],
693 ) -> TransportResult<PendingTransactionBuilder<N>> {
694 self.inner.send_raw_transaction(encoded_tx).await
695 }
696
697 async fn send_raw_transaction_conditional(
698 &self,
699 encoded_tx: &[u8],
700 conditional: TransactionConditional,
701 ) -> TransportResult<PendingTransactionBuilder<N>> {
702 self.inner.send_raw_transaction_conditional(encoded_tx, conditional).await
703 }
704
705 async fn send_transaction_internal(
706 &self,
707 mut tx: SendableTx<N>,
708 ) -> TransportResult<PendingTransactionBuilder<N>> {
709 tx = self.fill_inner(tx).await?;
710
711 if let Some(builder) = tx.as_builder() {
712 if let FillerControlFlow::Missing(missing) = self.filler.status(builder) {
713 let message = format!("missing properties: {missing:?}");
716 return Err(RpcError::local_usage_str(&message));
717 }
718 }
719
720 self.inner.send_transaction_internal(tx).await
722 }
723
724 async fn send_transaction_sync_internal(
725 &self,
726 mut tx: SendableTx<N>,
727 ) -> TransportResult<N::ReceiptResponse> {
728 tx = self.fill_inner(tx).await?;
729
730 if let Some(builder) = tx.as_builder() {
731 if let FillerControlFlow::Missing(missing) = self.filler.status(builder) {
732 let message = format!("missing properties: {missing:?}");
733 return Err(RpcError::local_usage_str(&message));
734 }
735 }
736
737 self.inner.send_transaction_sync_internal(tx).await
739 }
740
741 async fn sign_transaction(&self, tx: N::TransactionRequest) -> TransportResult<Bytes> {
742 let tx = self.fill(tx).await?;
743 let tx = tx.try_into_request().map_err(TransportError::local_usage)?;
744 self.inner.sign_transaction(tx).await
745 }
746
747 #[cfg(feature = "pubsub")]
748 fn subscribe_blocks(&self) -> GetSubscription<(SubscriptionKind,), N::HeaderResponse> {
749 self.inner.subscribe_blocks()
750 }
751
752 #[cfg(feature = "pubsub")]
753 fn subscribe_pending_transactions(&self) -> GetSubscription<(SubscriptionKind,), B256> {
754 self.inner.subscribe_pending_transactions()
755 }
756
757 #[cfg(feature = "pubsub")]
758 fn subscribe_full_pending_transactions(
759 &self,
760 ) -> GetSubscription<(SubscriptionKind, Params), N::TransactionResponse> {
761 self.inner.subscribe_full_pending_transactions()
762 }
763
764 #[cfg(feature = "pubsub")]
765 fn subscribe_logs(&self, filter: &Filter) -> GetSubscription<(SubscriptionKind, Params), Log> {
766 self.inner.subscribe_logs(filter)
767 }
768
769 #[cfg(feature = "pubsub")]
770 async fn unsubscribe(&self, id: B256) -> TransportResult<()> {
771 self.inner.unsubscribe(id).await
772 }
773
774 fn syncing(&self) -> ProviderCall<NoParams, SyncStatus> {
775 self.inner.syncing()
776 }
777
778 fn get_client_version(&self) -> ProviderCall<NoParams, String> {
779 self.inner.get_client_version()
780 }
781
782 fn get_sha3(&self, data: &[u8]) -> ProviderCall<(String,), B256> {
783 self.inner.get_sha3(data)
784 }
785
786 fn get_net_version(&self) -> ProviderCall<NoParams, U64, u64> {
787 self.inner.get_net_version()
788 }
789
790 async fn raw_request_dyn(
791 &self,
792 method: Cow<'static, str>,
793 params: &RawValue,
794 ) -> TransportResult<Box<RawValue>> {
795 self.inner.raw_request_dyn(method, params).await
796 }
797
798 fn transaction_request(&self) -> N::TransactionRequest {
799 self.inner.transaction_request()
800 }
801}
802
803pub trait RecommendedFillers: Network {
805 type RecommendedFillers: TxFiller<Self>;
807
808 fn recommended_fillers() -> Self::RecommendedFillers;
810}
811
812impl RecommendedFillers for Ethereum {
813 type RecommendedFillers =
814 JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>;
815
816 fn recommended_fillers() -> Self::RecommendedFillers {
817 Default::default()
818 }
819}
820
821impl RecommendedFillers for AnyNetwork {
822 type RecommendedFillers =
823 JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>;
824
825 fn recommended_fillers() -> Self::RecommendedFillers {
826 Default::default()
827 }
828}