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