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, 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
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>> {
408 self.fill_inner(SendableTx::Builder(tx)).await
409 }
410
411 pub fn prepare_call(
413 &self,
414 mut tx: N::TransactionRequest,
415 ) -> TransportResult<N::TransactionRequest> {
416 self.filler.prepare_call_sync(&mut tx)?;
417 Ok(tx)
418 }
419}
420
421#[cfg_attr(target_family = "wasm", async_trait(?Send))]
422#[cfg_attr(not(target_family = "wasm"), async_trait)]
423impl<F, P, N> Provider<N> for FillProvider<F, P, N>
424where
425 F: TxFiller<N>,
426 P: Provider<N>,
427 N: Network,
428{
429 fn root(&self) -> &RootProvider<N> {
430 self.inner.root()
431 }
432
433 fn get_accounts(&self) -> ProviderCall<NoParams, Vec<Address>> {
434 self.inner.get_accounts()
435 }
436
437 fn get_blob_base_fee(&self) -> ProviderCall<NoParams, U128, u128> {
438 self.inner.get_blob_base_fee()
439 }
440
441 fn get_block_number(&self) -> ProviderCall<NoParams, U64, BlockNumber> {
442 self.inner.get_block_number()
443 }
444
445 fn call<'req>(&self, tx: N::TransactionRequest) -> EthCall<N, Bytes> {
446 let mut tx = tx;
447 let _ = self.filler.prepare_call_sync(&mut tx);
448 self.inner.call(tx)
449 }
450
451 fn call_many<'req>(
452 &self,
453 bundles: &'req [Bundle],
454 ) -> EthCallMany<'req, N, Vec<Vec<EthCallResponse>>> {
455 self.inner.call_many(bundles)
456 }
457
458 fn simulate<'req>(
459 &self,
460 payload: &'req SimulatePayload,
461 ) -> RpcWithBlock<&'req SimulatePayload, Vec<SimulatedBlock<N::BlockResponse>>> {
462 self.inner.simulate(payload)
463 }
464
465 fn get_chain_id(&self) -> ProviderCall<NoParams, U64, u64> {
466 self.inner.get_chain_id()
467 }
468
469 fn create_access_list<'a>(
470 &self,
471 request: &'a N::TransactionRequest,
472 ) -> RpcWithBlock<&'a N::TransactionRequest, AccessListResult> {
473 self.inner.create_access_list(request)
474 }
475
476 fn estimate_gas<'req>(&self, tx: N::TransactionRequest) -> EthCall<N, U64, u64> {
477 let mut tx = tx;
478 let _ = self.filler.prepare_call_sync(&mut tx);
479 self.inner.estimate_gas(tx)
480 }
481
482 async fn get_fee_history(
483 &self,
484 block_count: u64,
485 last_block: BlockNumberOrTag,
486 reward_percentiles: &[f64],
487 ) -> TransportResult<FeeHistory> {
488 self.inner.get_fee_history(block_count, last_block, reward_percentiles).await
489 }
490
491 fn get_gas_price(&self) -> ProviderCall<NoParams, U128, u128> {
492 self.inner.get_gas_price()
493 }
494
495 fn get_account_info(
496 &self,
497 address: Address,
498 ) -> RpcWithBlock<Address, alloy_rpc_types_eth::AccountInfo> {
499 self.inner.get_account_info(address)
500 }
501
502 fn get_account(&self, address: Address) -> RpcWithBlock<Address, alloy_consensus::TrieAccount> {
503 self.inner.get_account(address)
504 }
505
506 fn get_balance(&self, address: Address) -> RpcWithBlock<Address, U256, U256> {
507 self.inner.get_balance(address)
508 }
509
510 fn get_block(&self, block: BlockId) -> EthGetBlock<N::BlockResponse> {
511 self.inner.get_block(block)
512 }
513
514 fn get_block_by_hash(&self, hash: BlockHash) -> EthGetBlock<N::BlockResponse> {
515 self.inner.get_block_by_hash(hash)
516 }
517
518 fn get_block_by_number(&self, number: BlockNumberOrTag) -> EthGetBlock<N::BlockResponse> {
519 self.inner.get_block_by_number(number)
520 }
521
522 async fn get_block_transaction_count_by_hash(
523 &self,
524 hash: BlockHash,
525 ) -> TransportResult<Option<u64>> {
526 self.inner.get_block_transaction_count_by_hash(hash).await
527 }
528
529 async fn get_block_transaction_count_by_number(
530 &self,
531 block_number: BlockNumberOrTag,
532 ) -> TransportResult<Option<u64>> {
533 self.inner.get_block_transaction_count_by_number(block_number).await
534 }
535
536 fn get_block_receipts(
537 &self,
538 block: BlockId,
539 ) -> ProviderCall<(BlockId,), Option<Vec<N::ReceiptResponse>>> {
540 self.inner.get_block_receipts(block)
541 }
542
543 async fn get_header(&self, block: BlockId) -> TransportResult<Option<N::HeaderResponse>> {
544 self.inner.get_header(block).await
545 }
546
547 async fn get_header_by_hash(
548 &self,
549 hash: BlockHash,
550 ) -> TransportResult<Option<N::HeaderResponse>> {
551 self.inner.get_header_by_hash(hash).await
552 }
553
554 async fn get_header_by_number(
555 &self,
556 number: BlockNumberOrTag,
557 ) -> TransportResult<Option<N::HeaderResponse>> {
558 self.inner.get_header_by_number(number).await
559 }
560
561 fn get_code_at(&self, address: Address) -> RpcWithBlock<Address, Bytes> {
562 self.inner.get_code_at(address)
563 }
564
565 async fn watch_blocks(&self) -> TransportResult<FilterPollerBuilder<B256>> {
566 self.inner.watch_blocks().await
567 }
568
569 async fn watch_pending_transactions(&self) -> TransportResult<FilterPollerBuilder<B256>> {
570 self.inner.watch_pending_transactions().await
571 }
572
573 async fn watch_logs(&self, filter: &Filter) -> TransportResult<FilterPollerBuilder<Log>> {
574 self.inner.watch_logs(filter).await
575 }
576
577 async fn watch_full_pending_transactions(
578 &self,
579 ) -> TransportResult<FilterPollerBuilder<N::TransactionResponse>> {
580 self.inner.watch_full_pending_transactions().await
581 }
582
583 async fn get_filter_changes_dyn(&self, id: U256) -> TransportResult<FilterChanges> {
584 self.inner.get_filter_changes_dyn(id).await
585 }
586
587 async fn get_filter_logs(&self, id: U256) -> TransportResult<Vec<Log>> {
588 self.inner.get_filter_logs(id).await
589 }
590
591 async fn uninstall_filter(&self, id: U256) -> TransportResult<bool> {
592 self.inner.uninstall_filter(id).await
593 }
594
595 async fn watch_pending_transaction(
596 &self,
597 config: PendingTransactionConfig,
598 ) -> Result<PendingTransaction, PendingTransactionError> {
599 self.inner.watch_pending_transaction(config).await
600 }
601
602 async fn get_logs(&self, filter: &Filter) -> TransportResult<Vec<Log>> {
603 self.inner.get_logs(filter).await
604 }
605
606 fn get_proof(
607 &self,
608 address: Address,
609 keys: Vec<StorageKey>,
610 ) -> RpcWithBlock<(Address, Vec<StorageKey>), EIP1186AccountProofResponse> {
611 self.inner.get_proof(address, keys)
612 }
613
614 fn get_storage_at(
615 &self,
616 address: Address,
617 key: U256,
618 ) -> RpcWithBlock<(Address, U256), StorageValue> {
619 self.inner.get_storage_at(address, key)
620 }
621
622 fn get_storage_values(
623 &self,
624 requests: StorageValuesRequest,
625 ) -> RpcWithBlock<(StorageValuesRequest,), StorageValuesResponse> {
626 self.inner.get_storage_values(requests)
627 }
628
629 fn get_transaction_by_hash(
630 &self,
631 hash: TxHash,
632 ) -> ProviderCall<(TxHash,), Option<N::TransactionResponse>> {
633 self.inner.get_transaction_by_hash(hash)
634 }
635
636 fn get_transaction_by_sender_nonce(
637 &self,
638 sender: Address,
639 nonce: u64,
640 ) -> ProviderCall<(Address, U64), Option<N::TransactionResponse>> {
641 self.inner.get_transaction_by_sender_nonce(sender, nonce)
642 }
643
644 fn get_transaction_by_block_hash_and_index(
645 &self,
646 block_hash: B256,
647 index: usize,
648 ) -> ProviderCall<(B256, Index), Option<N::TransactionResponse>> {
649 self.inner.get_transaction_by_block_hash_and_index(block_hash, index)
650 }
651
652 fn get_raw_transaction_by_block_hash_and_index(
653 &self,
654 block_hash: B256,
655 index: usize,
656 ) -> ProviderCall<(B256, Index), Option<Bytes>> {
657 self.inner.get_raw_transaction_by_block_hash_and_index(block_hash, index)
658 }
659
660 fn get_transaction_by_block_number_and_index(
661 &self,
662 block_number: BlockNumberOrTag,
663 index: usize,
664 ) -> ProviderCall<(BlockNumberOrTag, Index), Option<N::TransactionResponse>> {
665 self.inner.get_transaction_by_block_number_and_index(block_number, index)
666 }
667
668 fn get_raw_transaction_by_block_number_and_index(
669 &self,
670 block_number: BlockNumberOrTag,
671 index: usize,
672 ) -> ProviderCall<(BlockNumberOrTag, Index), Option<Bytes>> {
673 self.inner.get_raw_transaction_by_block_number_and_index(block_number, index)
674 }
675
676 fn get_raw_transaction_by_hash(&self, hash: TxHash) -> ProviderCall<(TxHash,), Option<Bytes>> {
677 self.inner.get_raw_transaction_by_hash(hash)
678 }
679
680 fn get_transaction_count(
681 &self,
682 address: Address,
683 ) -> RpcWithBlock<Address, U64, u64, fn(U64) -> u64> {
684 self.inner.get_transaction_count(address)
685 }
686
687 fn get_transaction_receipt(
688 &self,
689 hash: TxHash,
690 ) -> ProviderCall<(TxHash,), Option<N::ReceiptResponse>> {
691 self.inner.get_transaction_receipt(hash)
692 }
693
694 async fn get_uncle(&self, tag: BlockId, idx: u64) -> TransportResult<Option<N::BlockResponse>> {
695 self.inner.get_uncle(tag, idx).await
696 }
697
698 async fn get_uncle_count(&self, tag: BlockId) -> TransportResult<u64> {
699 self.inner.get_uncle_count(tag).await
700 }
701
702 fn get_max_priority_fee_per_gas(&self) -> ProviderCall<NoParams, U128, u128> {
703 self.inner.get_max_priority_fee_per_gas()
704 }
705
706 async fn new_block_filter(&self) -> TransportResult<U256> {
707 self.inner.new_block_filter().await
708 }
709
710 async fn new_filter(&self, filter: &Filter) -> TransportResult<U256> {
711 self.inner.new_filter(filter).await
712 }
713
714 async fn new_pending_transactions_filter(&self, full: bool) -> TransportResult<U256> {
715 self.inner.new_pending_transactions_filter(full).await
716 }
717
718 async fn send_raw_transaction(
719 &self,
720 encoded_tx: &[u8],
721 ) -> TransportResult<PendingTransactionBuilder<N>> {
722 self.inner.send_raw_transaction(encoded_tx).await
723 }
724
725 async fn send_raw_transaction_conditional(
726 &self,
727 encoded_tx: &[u8],
728 conditional: TransactionConditional,
729 ) -> TransportResult<PendingTransactionBuilder<N>> {
730 self.inner.send_raw_transaction_conditional(encoded_tx, conditional).await
731 }
732
733 async fn send_transaction_internal(
734 &self,
735 mut tx: SendableTx<N>,
736 ) -> TransportResult<PendingTransactionBuilder<N>> {
737 tx = self.fill_inner(tx).await?;
738
739 if let Some(builder) = tx.as_builder() {
740 if let FillerControlFlow::Missing(missing) = self.filler.status(builder) {
741 let message = format!("missing properties: {missing:?}");
744 return Err(RpcError::local_usage_str(&message));
745 }
746 }
747
748 self.inner.send_transaction_internal(tx).await
750 }
751
752 async fn send_transaction_sync_internal(
753 &self,
754 mut tx: SendableTx<N>,
755 ) -> TransportResult<N::ReceiptResponse> {
756 tx = self.fill_inner(tx).await?;
757
758 if let Some(builder) = tx.as_builder() {
759 if let FillerControlFlow::Missing(missing) = self.filler.status(builder) {
760 let message = format!("missing properties: {missing:?}");
761 return Err(RpcError::local_usage_str(&message));
762 }
763 }
764
765 self.inner.send_transaction_sync_internal(tx).await
767 }
768
769 async fn sign_transaction(&self, tx: N::TransactionRequest) -> TransportResult<Bytes> {
770 let tx = self.fill(tx).await?;
771 let tx = tx.try_into_request().map_err(TransportError::local_usage)?;
772 self.inner.sign_transaction(tx).await
773 }
774
775 #[cfg(feature = "pubsub")]
776 fn subscribe_blocks(&self) -> GetSubscription<(SubscriptionKind,), N::HeaderResponse> {
777 self.inner.subscribe_blocks()
778 }
779
780 #[cfg(feature = "pubsub")]
781 fn subscribe_pending_transactions(&self) -> GetSubscription<(SubscriptionKind,), B256> {
782 self.inner.subscribe_pending_transactions()
783 }
784
785 #[cfg(feature = "pubsub")]
786 fn subscribe_full_pending_transactions(
787 &self,
788 ) -> GetSubscription<(SubscriptionKind, Params), N::TransactionResponse> {
789 self.inner.subscribe_full_pending_transactions()
790 }
791
792 #[cfg(feature = "pubsub")]
793 fn subscribe_logs(&self, filter: &Filter) -> GetSubscription<(SubscriptionKind, Params), Log> {
794 self.inner.subscribe_logs(filter)
795 }
796
797 #[cfg(feature = "pubsub")]
798 async fn unsubscribe(&self, id: B256) -> TransportResult<()> {
799 self.inner.unsubscribe(id).await
800 }
801
802 fn syncing(&self) -> ProviderCall<NoParams, SyncStatus> {
803 self.inner.syncing()
804 }
805
806 fn get_client_version(&self) -> ProviderCall<NoParams, String> {
807 self.inner.get_client_version()
808 }
809
810 fn get_sha3(&self, data: &[u8]) -> ProviderCall<(String,), B256> {
811 self.inner.get_sha3(data)
812 }
813
814 fn get_net_version(&self) -> ProviderCall<NoParams, U64, u64> {
815 self.inner.get_net_version()
816 }
817
818 async fn raw_request_dyn(
819 &self,
820 method: Cow<'static, str>,
821 params: &RawValue,
822 ) -> TransportResult<Box<RawValue>> {
823 self.inner.raw_request_dyn(method, params).await
824 }
825
826 fn transaction_request(&self) -> N::TransactionRequest {
827 self.inner.transaction_request()
828 }
829}
830
831pub trait RecommendedFillers: Network {
833 type RecommendedFillers: TxFiller<Self>;
835
836 fn recommended_fillers() -> Self::RecommendedFillers;
838}
839
840impl RecommendedFillers for Ethereum {
841 type RecommendedFillers =
842 JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>;
843
844 fn recommended_fillers() -> Self::RecommendedFillers {
845 Default::default()
846 }
847}
848
849impl RecommendedFillers for AnyNetwork {
850 type RecommendedFillers =
851 JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>;
852
853 fn recommended_fillers() -> Self::RecommendedFillers {
854 Default::default()
855 }
856}