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::{BlobGasFiller, GasFillable, GasFiller};
41
42mod join_fill;
43pub use join_fill::JoinFill;
44use tracing::error;
45
46#[cfg(feature = "pubsub")]
47use crate::GetSubscription;
48use crate::{
49 provider::SendableTx, EthCall, EthCallMany, EthGetBlock, FilterPollerBuilder, Identity,
50 PendingTransaction, PendingTransactionBuilder, PendingTransactionConfig,
51 PendingTransactionError, Provider, ProviderCall, ProviderLayer, RootProvider, RpcWithBlock,
52 SendableTxErr,
53};
54use alloy_json_rpc::RpcError;
55use alloy_network::{AnyNetwork, Ethereum, Network};
56use alloy_primitives::{Bytes, U64};
57use alloy_rpc_types_eth::{
58 erc4337::TransactionConditional,
59 simulate::{SimulatePayload, SimulatedBlock},
60 AccessListResult, EIP1186AccountProofResponse, EthCallResponse, FeeHistory, Filter,
61 FilterChanges, Log,
62};
63use alloy_transport::{TransportError, TransportResult};
64use async_trait::async_trait;
65use futures_utils_wasm::impl_future;
66use serde_json::value::RawValue;
67use std::marker::PhantomData;
68
69pub type RecommendedFiller =
72 JoinFill<JoinFill<JoinFill<Identity, GasFiller>, NonceFiller>, ChainIdFiller>;
73
74#[derive(Debug, thiserror::Error)]
76pub enum FillEnvelopeError<T> {
77 #[error("transport error during filling: {0}")]
79 Transport(TransportError),
80
81 #[error("transaction not ready: {0}")]
83 NotReady(SendableTxErr<T>),
84}
85
86#[derive(Clone, Debug, PartialEq, Eq)]
88pub enum FillerControlFlow {
89 Missing(Vec<(&'static str, Vec<&'static str>)>),
96 Ready,
98 Finished,
100}
101
102impl FillerControlFlow {
103 pub fn absorb(self, other: Self) -> Self {
110 if other.is_finished() {
111 return self;
112 }
113
114 if self.is_finished() {
115 return other;
116 }
117
118 if other.is_ready() || self.is_ready() {
119 return Self::Ready;
120 }
121
122 if let (Self::Missing(mut a), Self::Missing(b)) = (self, other) {
123 a.extend(b);
124 return Self::Missing(a);
125 }
126
127 unreachable!()
128 }
129
130 pub fn missing(name: &'static str, missing: Vec<&'static str>) -> Self {
132 Self::Missing(vec![(name, missing)])
133 }
134
135 pub fn as_missing(&self) -> Option<&[(&'static str, Vec<&'static str>)]> {
137 match self {
138 Self::Missing(missing) => Some(missing),
139 _ => None,
140 }
141 }
142
143 pub const fn is_missing(&self) -> bool {
146 matches!(self, Self::Missing(_))
147 }
148
149 pub const fn is_ready(&self) -> bool {
152 matches!(self, Self::Ready)
153 }
154
155 pub const fn is_finished(&self) -> bool {
158 matches!(self, Self::Finished)
159 }
160}
161
162#[doc(alias = "TransactionFiller")]
176pub trait TxFiller<N: Network = Ethereum>: Clone + Send + Sync + std::fmt::Debug {
177 type Fillable: Send + Sync + 'static;
180
181 fn join_with<T>(self, other: T) -> JoinFill<Self, T>
183 where
184 T: TxFiller<N>,
185 {
186 JoinFill::new(self, other)
187 }
188
189 fn status(&self, tx: &N::TransactionRequest) -> FillerControlFlow;
193
194 fn continue_filling(&self, tx: &SendableTx<N>) -> bool {
196 tx.as_builder().is_some_and(|tx| self.status(tx).is_ready())
197 }
198
199 fn ready(&self, tx: &N::TransactionRequest) -> bool {
201 self.status(tx).is_ready()
202 }
203
204 fn finished(&self, tx: &N::TransactionRequest) -> bool {
206 self.status(tx).is_finished()
207 }
208
209 fn fill_sync(&self, tx: &mut SendableTx<N>);
213
214 fn prepare<P: Provider<N>>(
216 &self,
217 provider: &P,
218 tx: &N::TransactionRequest,
219 ) -> impl_future!(<Output = TransportResult<Self::Fillable>>);
220
221 fn fill(
223 &self,
224 fillable: Self::Fillable,
225 tx: SendableTx<N>,
226 ) -> impl_future!(<Output = TransportResult<SendableTx<N>>>);
227
228 fn fill_envelope(
230 &self,
231 fillable: Self::Fillable,
232 tx: SendableTx<N>,
233 ) -> impl_future!(<Output = Result<N::TxEnvelope, FillEnvelopeError<N::TransactionRequest>>>)
234 {
235 async move {
236 let tx = self.fill(fillable, tx).await.map_err(FillEnvelopeError::Transport)?;
237 let envelope = tx.try_into_envelope().map_err(FillEnvelopeError::NotReady)?;
238 Ok(envelope)
239 }
240 }
241
242 fn prepare_and_fill<P>(
244 &self,
245 provider: &P,
246 tx: SendableTx<N>,
247 ) -> impl_future!(<Output = TransportResult<SendableTx<N>>>)
248 where
249 P: Provider<N>,
250 {
251 async move {
252 if tx.is_envelope() {
253 return Ok(tx);
254 }
255
256 let fillable =
257 self.prepare(provider, tx.as_builder().expect("checked by is_envelope")).await?;
258
259 self.fill(fillable, tx).await
260 }
261 }
262
263 fn prepare_call(
266 &self,
267 tx: &mut N::TransactionRequest,
268 ) -> impl_future!(<Output = TransportResult<()>>) {
269 let _ = tx;
270 futures::future::ready(Ok(()))
272 }
273
274 fn prepare_call_sync(&self, tx: &mut N::TransactionRequest) -> TransportResult<()> {
277 let _ = tx;
278 Ok(())
280 }
281}
282
283#[derive(Clone, Debug)]
295pub struct FillProvider<F, P, N = Ethereum>
296where
297 F: TxFiller<N>,
298 P: Provider<N>,
299 N: Network,
300{
301 pub(crate) inner: P,
302 pub(crate) filler: F,
303 _pd: PhantomData<fn() -> N>,
304}
305
306impl<F, P, N> FillProvider<F, P, N>
307where
308 F: TxFiller<N>,
309 P: Provider<N>,
310 N: Network,
311{
312 pub fn new(inner: P, filler: F) -> Self {
314 Self { inner, filler, _pd: PhantomData }
315 }
316
317 pub fn join_with<Other: TxFiller<N>>(
319 self,
320 other: Other,
321 ) -> FillProvider<JoinFill<F, Other>, P, N> {
322 self.filler.join_with(other).layer(self.inner)
323 }
324
325 async fn fill_inner(&self, mut tx: SendableTx<N>) -> TransportResult<SendableTx<N>> {
326 let mut count = 0;
327
328 while self.filler.continue_filling(&tx) {
329 self.filler.fill_sync(&mut tx);
330 tx = self.filler.prepare_and_fill(&self.inner, tx).await?;
331
332 count += 1;
333 if count >= 20 {
334 const ERROR: &str = "Tx filler loop detected. This indicates a bug in some filler implementation. Please file an issue containing this message.";
335 error!(
336 ?tx, ?self.filler,
337 ERROR
338 );
339 panic!("{}, {:?}, {:?}", ERROR, &tx, &self.filler);
340 }
341 }
342 Ok(tx)
343 }
344
345 pub async fn fill(&self, tx: N::TransactionRequest) -> TransportResult<SendableTx<N>> {
382 self.fill_inner(SendableTx::Builder(tx)).await
383 }
384
385 pub fn prepare_call(
387 &self,
388 mut tx: N::TransactionRequest,
389 ) -> TransportResult<N::TransactionRequest> {
390 self.filler.prepare_call_sync(&mut tx)?;
391 Ok(tx)
392 }
393}
394
395#[cfg_attr(target_family = "wasm", async_trait(?Send))]
396#[cfg_attr(not(target_family = "wasm"), async_trait)]
397impl<F, P, N> Provider<N> for FillProvider<F, P, N>
398where
399 F: TxFiller<N>,
400 P: Provider<N>,
401 N: Network,
402{
403 fn root(&self) -> &RootProvider<N> {
404 self.inner.root()
405 }
406
407 fn get_accounts(&self) -> ProviderCall<NoParams, Vec<Address>> {
408 self.inner.get_accounts()
409 }
410
411 fn get_blob_base_fee(&self) -> ProviderCall<NoParams, U128, u128> {
412 self.inner.get_blob_base_fee()
413 }
414
415 fn get_block_number(&self) -> ProviderCall<NoParams, U64, BlockNumber> {
416 self.inner.get_block_number()
417 }
418
419 fn call<'req>(&self, tx: N::TransactionRequest) -> EthCall<N, Bytes> {
420 let mut tx = tx;
421 let _ = self.filler.prepare_call_sync(&mut tx);
422 self.inner.call(tx)
423 }
424
425 fn call_many<'req>(
426 &self,
427 bundles: &'req [Bundle],
428 ) -> EthCallMany<'req, N, Vec<Vec<EthCallResponse>>> {
429 self.inner.call_many(bundles)
430 }
431
432 fn simulate<'req>(
433 &self,
434 payload: &'req SimulatePayload,
435 ) -> RpcWithBlock<&'req SimulatePayload, Vec<SimulatedBlock<N::BlockResponse>>> {
436 self.inner.simulate(payload)
437 }
438
439 fn get_chain_id(&self) -> ProviderCall<NoParams, U64, u64> {
440 self.inner.get_chain_id()
441 }
442
443 fn create_access_list<'a>(
444 &self,
445 request: &'a N::TransactionRequest,
446 ) -> RpcWithBlock<&'a N::TransactionRequest, AccessListResult> {
447 self.inner.create_access_list(request)
448 }
449
450 fn estimate_gas<'req>(&self, tx: N::TransactionRequest) -> EthCall<N, U64, u64> {
451 let mut tx = tx;
452 let _ = self.filler.prepare_call_sync(&mut tx);
453 self.inner.estimate_gas(tx)
454 }
455
456 async fn get_fee_history(
457 &self,
458 block_count: u64,
459 last_block: BlockNumberOrTag,
460 reward_percentiles: &[f64],
461 ) -> TransportResult<FeeHistory> {
462 self.inner.get_fee_history(block_count, last_block, reward_percentiles).await
463 }
464
465 fn get_gas_price(&self) -> ProviderCall<NoParams, U128, u128> {
466 self.inner.get_gas_price()
467 }
468
469 fn get_account_info(
470 &self,
471 address: Address,
472 ) -> RpcWithBlock<Address, alloy_rpc_types_eth::AccountInfo> {
473 self.inner.get_account_info(address)
474 }
475
476 fn get_account(&self, address: Address) -> RpcWithBlock<Address, alloy_consensus::TrieAccount> {
477 self.inner.get_account(address)
478 }
479
480 fn get_balance(&self, address: Address) -> RpcWithBlock<Address, U256, U256> {
481 self.inner.get_balance(address)
482 }
483
484 fn get_block(&self, block: BlockId) -> EthGetBlock<N::BlockResponse> {
485 self.inner.get_block(block)
486 }
487
488 fn get_block_by_hash(&self, hash: BlockHash) -> EthGetBlock<N::BlockResponse> {
489 self.inner.get_block_by_hash(hash)
490 }
491
492 fn get_block_by_number(&self, number: BlockNumberOrTag) -> EthGetBlock<N::BlockResponse> {
493 self.inner.get_block_by_number(number)
494 }
495
496 async fn get_block_transaction_count_by_hash(
497 &self,
498 hash: BlockHash,
499 ) -> TransportResult<Option<u64>> {
500 self.inner.get_block_transaction_count_by_hash(hash).await
501 }
502
503 async fn get_block_transaction_count_by_number(
504 &self,
505 block_number: BlockNumberOrTag,
506 ) -> TransportResult<Option<u64>> {
507 self.inner.get_block_transaction_count_by_number(block_number).await
508 }
509
510 fn get_block_receipts(
511 &self,
512 block: BlockId,
513 ) -> ProviderCall<(BlockId,), Option<Vec<N::ReceiptResponse>>> {
514 self.inner.get_block_receipts(block)
515 }
516
517 fn get_code_at(&self, address: Address) -> RpcWithBlock<Address, Bytes> {
518 self.inner.get_code_at(address)
519 }
520
521 async fn watch_blocks(&self) -> TransportResult<FilterPollerBuilder<B256>> {
522 self.inner.watch_blocks().await
523 }
524
525 async fn watch_pending_transactions(&self) -> TransportResult<FilterPollerBuilder<B256>> {
526 self.inner.watch_pending_transactions().await
527 }
528
529 async fn watch_logs(&self, filter: &Filter) -> TransportResult<FilterPollerBuilder<Log>> {
530 self.inner.watch_logs(filter).await
531 }
532
533 async fn watch_full_pending_transactions(
534 &self,
535 ) -> TransportResult<FilterPollerBuilder<N::TransactionResponse>> {
536 self.inner.watch_full_pending_transactions().await
537 }
538
539 async fn get_filter_changes_dyn(&self, id: U256) -> TransportResult<FilterChanges> {
540 self.inner.get_filter_changes_dyn(id).await
541 }
542
543 async fn get_filter_logs(&self, id: U256) -> TransportResult<Vec<Log>> {
544 self.inner.get_filter_logs(id).await
545 }
546
547 async fn uninstall_filter(&self, id: U256) -> TransportResult<bool> {
548 self.inner.uninstall_filter(id).await
549 }
550
551 async fn watch_pending_transaction(
552 &self,
553 config: PendingTransactionConfig,
554 ) -> Result<PendingTransaction, PendingTransactionError> {
555 self.inner.watch_pending_transaction(config).await
556 }
557
558 async fn get_logs(&self, filter: &Filter) -> TransportResult<Vec<Log>> {
559 self.inner.get_logs(filter).await
560 }
561
562 fn get_proof(
563 &self,
564 address: Address,
565 keys: Vec<StorageKey>,
566 ) -> RpcWithBlock<(Address, Vec<StorageKey>), EIP1186AccountProofResponse> {
567 self.inner.get_proof(address, keys)
568 }
569
570 fn get_storage_at(
571 &self,
572 address: Address,
573 key: U256,
574 ) -> RpcWithBlock<(Address, U256), StorageValue> {
575 self.inner.get_storage_at(address, key)
576 }
577
578 fn get_transaction_by_hash(
579 &self,
580 hash: TxHash,
581 ) -> ProviderCall<(TxHash,), Option<N::TransactionResponse>> {
582 self.inner.get_transaction_by_hash(hash)
583 }
584
585 fn get_transaction_by_sender_nonce(
586 &self,
587 sender: Address,
588 nonce: u64,
589 ) -> ProviderCall<(Address, U64), Option<N::TransactionResponse>> {
590 self.inner.get_transaction_by_sender_nonce(sender, nonce)
591 }
592
593 fn get_transaction_by_block_hash_and_index(
594 &self,
595 block_hash: B256,
596 index: usize,
597 ) -> ProviderCall<(B256, Index), Option<N::TransactionResponse>> {
598 self.inner.get_transaction_by_block_hash_and_index(block_hash, index)
599 }
600
601 fn get_raw_transaction_by_block_hash_and_index(
602 &self,
603 block_hash: B256,
604 index: usize,
605 ) -> ProviderCall<(B256, Index), Option<Bytes>> {
606 self.inner.get_raw_transaction_by_block_hash_and_index(block_hash, index)
607 }
608
609 fn get_transaction_by_block_number_and_index(
610 &self,
611 block_number: BlockNumberOrTag,
612 index: usize,
613 ) -> ProviderCall<(BlockNumberOrTag, Index), Option<N::TransactionResponse>> {
614 self.inner.get_transaction_by_block_number_and_index(block_number, index)
615 }
616
617 fn get_raw_transaction_by_block_number_and_index(
618 &self,
619 block_number: BlockNumberOrTag,
620 index: usize,
621 ) -> ProviderCall<(BlockNumberOrTag, Index), Option<Bytes>> {
622 self.inner.get_raw_transaction_by_block_number_and_index(block_number, index)
623 }
624
625 fn get_raw_transaction_by_hash(&self, hash: TxHash) -> ProviderCall<(TxHash,), Option<Bytes>> {
626 self.inner.get_raw_transaction_by_hash(hash)
627 }
628
629 fn get_transaction_count(
630 &self,
631 address: Address,
632 ) -> RpcWithBlock<Address, U64, u64, fn(U64) -> u64> {
633 self.inner.get_transaction_count(address)
634 }
635
636 fn get_transaction_receipt(
637 &self,
638 hash: TxHash,
639 ) -> ProviderCall<(TxHash,), Option<N::ReceiptResponse>> {
640 self.inner.get_transaction_receipt(hash)
641 }
642
643 async fn get_uncle(&self, tag: BlockId, idx: u64) -> TransportResult<Option<N::BlockResponse>> {
644 self.inner.get_uncle(tag, idx).await
645 }
646
647 async fn get_uncle_count(&self, tag: BlockId) -> TransportResult<u64> {
648 self.inner.get_uncle_count(tag).await
649 }
650
651 fn get_max_priority_fee_per_gas(&self) -> ProviderCall<NoParams, U128, u128> {
652 self.inner.get_max_priority_fee_per_gas()
653 }
654
655 async fn new_block_filter(&self) -> TransportResult<U256> {
656 self.inner.new_block_filter().await
657 }
658
659 async fn new_filter(&self, filter: &Filter) -> TransportResult<U256> {
660 self.inner.new_filter(filter).await
661 }
662
663 async fn new_pending_transactions_filter(&self, full: bool) -> TransportResult<U256> {
664 self.inner.new_pending_transactions_filter(full).await
665 }
666
667 async fn send_raw_transaction(
668 &self,
669 encoded_tx: &[u8],
670 ) -> TransportResult<PendingTransactionBuilder<N>> {
671 self.inner.send_raw_transaction(encoded_tx).await
672 }
673
674 async fn send_raw_transaction_conditional(
675 &self,
676 encoded_tx: &[u8],
677 conditional: TransactionConditional,
678 ) -> TransportResult<PendingTransactionBuilder<N>> {
679 self.inner.send_raw_transaction_conditional(encoded_tx, conditional).await
680 }
681
682 async fn send_transaction_internal(
683 &self,
684 mut tx: SendableTx<N>,
685 ) -> TransportResult<PendingTransactionBuilder<N>> {
686 tx = self.fill_inner(tx).await?;
687
688 if let Some(builder) = tx.as_builder() {
689 if let FillerControlFlow::Missing(missing) = self.filler.status(builder) {
690 let message = format!("missing properties: {missing:?}");
693 return Err(RpcError::local_usage_str(&message));
694 }
695 }
696
697 self.inner.send_transaction_internal(tx).await
699 }
700
701 async fn send_transaction_sync_internal(
702 &self,
703 mut tx: SendableTx<N>,
704 ) -> TransportResult<N::ReceiptResponse> {
705 tx = self.fill_inner(tx).await?;
706
707 if let Some(builder) = tx.as_builder() {
708 if let FillerControlFlow::Missing(missing) = self.filler.status(builder) {
709 let message = format!("missing properties: {missing:?}");
710 return Err(RpcError::local_usage_str(&message));
711 }
712 }
713
714 self.inner.send_transaction_sync_internal(tx).await
716 }
717
718 async fn sign_transaction(&self, tx: N::TransactionRequest) -> TransportResult<Bytes> {
719 let tx = self.fill(tx).await?;
720 let tx = tx.try_into_request().map_err(TransportError::local_usage)?;
721 self.inner.sign_transaction(tx).await
722 }
723
724 #[cfg(feature = "pubsub")]
725 fn subscribe_blocks(&self) -> GetSubscription<(SubscriptionKind,), N::HeaderResponse> {
726 self.inner.subscribe_blocks()
727 }
728
729 #[cfg(feature = "pubsub")]
730 fn subscribe_pending_transactions(&self) -> GetSubscription<(SubscriptionKind,), B256> {
731 self.inner.subscribe_pending_transactions()
732 }
733
734 #[cfg(feature = "pubsub")]
735 fn subscribe_full_pending_transactions(
736 &self,
737 ) -> GetSubscription<(SubscriptionKind, Params), N::TransactionResponse> {
738 self.inner.subscribe_full_pending_transactions()
739 }
740
741 #[cfg(feature = "pubsub")]
742 fn subscribe_logs(&self, filter: &Filter) -> GetSubscription<(SubscriptionKind, Params), Log> {
743 self.inner.subscribe_logs(filter)
744 }
745
746 #[cfg(feature = "pubsub")]
747 async fn unsubscribe(&self, id: B256) -> TransportResult<()> {
748 self.inner.unsubscribe(id).await
749 }
750
751 fn syncing(&self) -> ProviderCall<NoParams, SyncStatus> {
752 self.inner.syncing()
753 }
754
755 fn get_client_version(&self) -> ProviderCall<NoParams, String> {
756 self.inner.get_client_version()
757 }
758
759 fn get_sha3(&self, data: &[u8]) -> ProviderCall<(String,), B256> {
760 self.inner.get_sha3(data)
761 }
762
763 fn get_net_version(&self) -> ProviderCall<NoParams, U64, u64> {
764 self.inner.get_net_version()
765 }
766
767 async fn raw_request_dyn(
768 &self,
769 method: Cow<'static, str>,
770 params: &RawValue,
771 ) -> TransportResult<Box<RawValue>> {
772 self.inner.raw_request_dyn(method, params).await
773 }
774
775 fn transaction_request(&self) -> N::TransactionRequest {
776 self.inner.transaction_request()
777 }
778}
779
780pub trait RecommendedFillers: Network {
782 type RecommendedFillers: TxFiller<Self>;
784
785 fn recommended_fillers() -> Self::RecommendedFillers;
787}
788
789impl RecommendedFillers for Ethereum {
790 type RecommendedFillers =
791 JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>;
792
793 fn recommended_fillers() -> Self::RecommendedFillers {
794 Default::default()
795 }
796}
797
798impl RecommendedFillers for AnyNetwork {
799 type RecommendedFillers =
800 JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>;
801
802 fn recommended_fillers() -> Self::RecommendedFillers {
803 Default::default()
804 }
805}