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>> {
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 async fn get_header(&self, block: BlockId) -> TransportResult<Option<N::HeaderResponse>> {
541 self.inner.get_header(block).await
542 }
543
544 async fn get_header_by_hash(
545 &self,
546 hash: BlockHash,
547 ) -> TransportResult<Option<N::HeaderResponse>> {
548 self.inner.get_header_by_hash(hash).await
549 }
550
551 async fn get_header_by_number(
552 &self,
553 number: BlockNumberOrTag,
554 ) -> TransportResult<Option<N::HeaderResponse>> {
555 self.inner.get_header_by_number(number).await
556 }
557
558 fn get_code_at(&self, address: Address) -> RpcWithBlock<Address, Bytes> {
559 self.inner.get_code_at(address)
560 }
561
562 async fn watch_blocks(&self) -> TransportResult<FilterPollerBuilder<B256>> {
563 self.inner.watch_blocks().await
564 }
565
566 async fn watch_pending_transactions(&self) -> TransportResult<FilterPollerBuilder<B256>> {
567 self.inner.watch_pending_transactions().await
568 }
569
570 async fn watch_logs(&self, filter: &Filter) -> TransportResult<FilterPollerBuilder<Log>> {
571 self.inner.watch_logs(filter).await
572 }
573
574 async fn watch_full_pending_transactions(
575 &self,
576 ) -> TransportResult<FilterPollerBuilder<N::TransactionResponse>> {
577 self.inner.watch_full_pending_transactions().await
578 }
579
580 async fn get_filter_changes_dyn(&self, id: U256) -> TransportResult<FilterChanges> {
581 self.inner.get_filter_changes_dyn(id).await
582 }
583
584 async fn get_filter_logs(&self, id: U256) -> TransportResult<Vec<Log>> {
585 self.inner.get_filter_logs(id).await
586 }
587
588 async fn uninstall_filter(&self, id: U256) -> TransportResult<bool> {
589 self.inner.uninstall_filter(id).await
590 }
591
592 async fn watch_pending_transaction(
593 &self,
594 config: PendingTransactionConfig,
595 ) -> Result<PendingTransaction, PendingTransactionError> {
596 self.inner.watch_pending_transaction(config).await
597 }
598
599 async fn get_logs(&self, filter: &Filter) -> TransportResult<Vec<Log>> {
600 self.inner.get_logs(filter).await
601 }
602
603 fn get_proof(
604 &self,
605 address: Address,
606 keys: Vec<StorageKey>,
607 ) -> RpcWithBlock<(Address, Vec<StorageKey>), EIP1186AccountProofResponse> {
608 self.inner.get_proof(address, keys)
609 }
610
611 fn get_storage_at(
612 &self,
613 address: Address,
614 key: U256,
615 ) -> RpcWithBlock<(Address, U256), StorageValue> {
616 self.inner.get_storage_at(address, key)
617 }
618
619 fn get_storage_values(
620 &self,
621 requests: StorageValuesRequest,
622 ) -> RpcWithBlock<(StorageValuesRequest,), StorageValuesResponse> {
623 self.inner.get_storage_values(requests)
624 }
625
626 fn get_transaction_by_hash(
627 &self,
628 hash: TxHash,
629 ) -> ProviderCall<(TxHash,), Option<N::TransactionResponse>> {
630 self.inner.get_transaction_by_hash(hash)
631 }
632
633 fn get_transaction_by_sender_nonce(
634 &self,
635 sender: Address,
636 nonce: u64,
637 ) -> ProviderCall<(Address, U64), Option<N::TransactionResponse>> {
638 self.inner.get_transaction_by_sender_nonce(sender, nonce)
639 }
640
641 fn get_transaction_by_block_hash_and_index(
642 &self,
643 block_hash: B256,
644 index: usize,
645 ) -> ProviderCall<(B256, Index), Option<N::TransactionResponse>> {
646 self.inner.get_transaction_by_block_hash_and_index(block_hash, index)
647 }
648
649 fn get_raw_transaction_by_block_hash_and_index(
650 &self,
651 block_hash: B256,
652 index: usize,
653 ) -> ProviderCall<(B256, Index), Option<Bytes>> {
654 self.inner.get_raw_transaction_by_block_hash_and_index(block_hash, index)
655 }
656
657 fn get_transaction_by_block_number_and_index(
658 &self,
659 block_number: BlockNumberOrTag,
660 index: usize,
661 ) -> ProviderCall<(BlockNumberOrTag, Index), Option<N::TransactionResponse>> {
662 self.inner.get_transaction_by_block_number_and_index(block_number, index)
663 }
664
665 fn get_raw_transaction_by_block_number_and_index(
666 &self,
667 block_number: BlockNumberOrTag,
668 index: usize,
669 ) -> ProviderCall<(BlockNumberOrTag, Index), Option<Bytes>> {
670 self.inner.get_raw_transaction_by_block_number_and_index(block_number, index)
671 }
672
673 fn get_raw_transaction_by_hash(&self, hash: TxHash) -> ProviderCall<(TxHash,), Option<Bytes>> {
674 self.inner.get_raw_transaction_by_hash(hash)
675 }
676
677 fn get_transaction_count(
678 &self,
679 address: Address,
680 ) -> RpcWithBlock<Address, U64, u64, fn(U64) -> u64> {
681 self.inner.get_transaction_count(address)
682 }
683
684 fn get_transaction_receipt(
685 &self,
686 hash: TxHash,
687 ) -> ProviderCall<(TxHash,), Option<N::ReceiptResponse>> {
688 self.inner.get_transaction_receipt(hash)
689 }
690
691 async fn get_uncle(&self, tag: BlockId, idx: u64) -> TransportResult<Option<N::BlockResponse>> {
692 self.inner.get_uncle(tag, idx).await
693 }
694
695 async fn get_uncle_count(&self, tag: BlockId) -> TransportResult<u64> {
696 self.inner.get_uncle_count(tag).await
697 }
698
699 fn get_max_priority_fee_per_gas(&self) -> ProviderCall<NoParams, U128, u128> {
700 self.inner.get_max_priority_fee_per_gas()
701 }
702
703 async fn new_block_filter(&self) -> TransportResult<U256> {
704 self.inner.new_block_filter().await
705 }
706
707 async fn new_filter(&self, filter: &Filter) -> TransportResult<U256> {
708 self.inner.new_filter(filter).await
709 }
710
711 async fn new_pending_transactions_filter(&self, full: bool) -> TransportResult<U256> {
712 self.inner.new_pending_transactions_filter(full).await
713 }
714
715 async fn send_raw_transaction(
716 &self,
717 encoded_tx: &[u8],
718 ) -> TransportResult<PendingTransactionBuilder<N>> {
719 self.inner.send_raw_transaction(encoded_tx).await
720 }
721
722 async fn send_raw_transaction_conditional(
723 &self,
724 encoded_tx: &[u8],
725 conditional: TransactionConditional,
726 ) -> TransportResult<PendingTransactionBuilder<N>> {
727 self.inner.send_raw_transaction_conditional(encoded_tx, conditional).await
728 }
729
730 async fn send_transaction_internal(
731 &self,
732 mut tx: SendableTx<N>,
733 ) -> TransportResult<PendingTransactionBuilder<N>> {
734 tx = self.fill_inner(tx).await?;
735
736 if let Some(builder) = tx.as_builder() {
737 if let FillerControlFlow::Missing(missing) = self.filler.status(builder) {
738 let message = format!("missing properties: {missing:?}");
741 return Err(RpcError::local_usage_str(&message));
742 }
743 }
744
745 self.inner.send_transaction_internal(tx).await
747 }
748
749 async fn send_transaction_sync_internal(
750 &self,
751 mut tx: SendableTx<N>,
752 ) -> TransportResult<N::ReceiptResponse> {
753 tx = self.fill_inner(tx).await?;
754
755 if let Some(builder) = tx.as_builder() {
756 if let FillerControlFlow::Missing(missing) = self.filler.status(builder) {
757 let message = format!("missing properties: {missing:?}");
758 return Err(RpcError::local_usage_str(&message));
759 }
760 }
761
762 self.inner.send_transaction_sync_internal(tx).await
764 }
765
766 async fn sign_transaction(&self, tx: N::TransactionRequest) -> TransportResult<Bytes> {
767 let tx = self.fill(tx).await?;
768 let tx = tx.try_into_request().map_err(TransportError::local_usage)?;
769 self.inner.sign_transaction(tx).await
770 }
771
772 #[cfg(feature = "pubsub")]
773 fn subscribe_blocks(&self) -> GetSubscription<(SubscriptionKind,), N::HeaderResponse> {
774 self.inner.subscribe_blocks()
775 }
776
777 #[cfg(feature = "pubsub")]
778 fn subscribe_pending_transactions(&self) -> GetSubscription<(SubscriptionKind,), B256> {
779 self.inner.subscribe_pending_transactions()
780 }
781
782 #[cfg(feature = "pubsub")]
783 fn subscribe_full_pending_transactions(
784 &self,
785 ) -> GetSubscription<(SubscriptionKind, Params), N::TransactionResponse> {
786 self.inner.subscribe_full_pending_transactions()
787 }
788
789 #[cfg(feature = "pubsub")]
790 fn subscribe_logs(&self, filter: &Filter) -> GetSubscription<(SubscriptionKind, Params), Log> {
791 self.inner.subscribe_logs(filter)
792 }
793
794 #[cfg(feature = "pubsub")]
795 async fn unsubscribe(&self, id: B256) -> TransportResult<()> {
796 self.inner.unsubscribe(id).await
797 }
798
799 fn syncing(&self) -> ProviderCall<NoParams, SyncStatus> {
800 self.inner.syncing()
801 }
802
803 fn get_client_version(&self) -> ProviderCall<NoParams, String> {
804 self.inner.get_client_version()
805 }
806
807 fn get_sha3(&self, data: &[u8]) -> ProviderCall<(String,), B256> {
808 self.inner.get_sha3(data)
809 }
810
811 fn get_net_version(&self) -> ProviderCall<NoParams, U64, u64> {
812 self.inner.get_net_version()
813 }
814
815 async fn raw_request_dyn(
816 &self,
817 method: Cow<'static, str>,
818 params: &RawValue,
819 ) -> TransportResult<Box<RawValue>> {
820 self.inner.raw_request_dyn(method, params).await
821 }
822
823 fn transaction_request(&self) -> N::TransactionRequest {
824 self.inner.transaction_request()
825 }
826}
827
828pub trait RecommendedFillers: Network {
830 type RecommendedFillers: TxFiller<Self>;
832
833 fn recommended_fillers() -> Self::RecommendedFillers;
835}
836
837impl RecommendedFillers for Ethereum {
838 type RecommendedFillers =
839 JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>;
840
841 fn recommended_fillers() -> Self::RecommendedFillers {
842 Default::default()
843 }
844}
845
846impl RecommendedFillers for AnyNetwork {
847 type RecommendedFillers =
848 JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>;
849
850 fn recommended_fillers() -> Self::RecommendedFillers {
851 Default::default()
852 }
853}