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;
15use alloy_rpc_types_eth::{Bundle, Index, SyncStatus};
16pub use chain_id::ChainIdFiller;
17use std::borrow::Cow;
18
19mod wallet;
20pub use wallet::WalletFiller;
21
22mod nonce;
23pub use nonce::{CachedNonceManager, NonceFiller, NonceManager, SimpleNonceManager};
24
25mod gas;
26pub use gas::{BlobGasFiller, GasFillable, GasFiller};
27
28mod join_fill;
29pub use join_fill::JoinFill;
30use tracing::error;
31
32use crate::{
33 provider::SendableTx, EthCall, EthCallMany, EthGetBlock, FilterPollerBuilder, Identity,
34 PendingTransaction, PendingTransactionBuilder, PendingTransactionConfig,
35 PendingTransactionError, Provider, ProviderCall, ProviderLayer, RootProvider, RpcWithBlock,
36};
37use alloy_json_rpc::RpcError;
38use alloy_network::{AnyNetwork, Ethereum, Network};
39use alloy_primitives::{Bytes, U64};
40use alloy_rpc_types_eth::{
41 erc4337::TransactionConditional,
42 simulate::{SimulatePayload, SimulatedBlock},
43 AccessListResult, EIP1186AccountProofResponse, EthCallResponse, FeeHistory, Filter,
44 FilterChanges, Log,
45};
46use alloy_transport::TransportResult;
47use async_trait::async_trait;
48use futures_utils_wasm::impl_future;
49use serde_json::value::RawValue;
50use std::marker::PhantomData;
51
52pub type RecommendedFiller =
55 JoinFill<JoinFill<JoinFill<Identity, GasFiller>, NonceFiller>, ChainIdFiller>;
56
57#[derive(Clone, Debug, PartialEq, Eq)]
59pub enum FillerControlFlow {
60 Missing(Vec<(&'static str, Vec<&'static str>)>),
67 Ready,
69 Finished,
71}
72
73impl FillerControlFlow {
74 pub fn absorb(self, other: Self) -> Self {
81 if other.is_finished() {
82 return self;
83 }
84
85 if self.is_finished() {
86 return other;
87 }
88
89 if other.is_ready() || self.is_ready() {
90 return Self::Ready;
91 }
92
93 if let (Self::Missing(mut a), Self::Missing(b)) = (self, other) {
94 a.extend(b);
95 return Self::Missing(a);
96 }
97
98 unreachable!()
99 }
100
101 pub fn missing(name: &'static str, missing: Vec<&'static str>) -> Self {
103 Self::Missing(vec![(name, missing)])
104 }
105
106 pub fn as_missing(&self) -> Option<&[(&'static str, Vec<&'static str>)]> {
108 match self {
109 Self::Missing(missing) => Some(missing),
110 _ => None,
111 }
112 }
113
114 pub const fn is_missing(&self) -> bool {
117 matches!(self, Self::Missing(_))
118 }
119
120 pub const fn is_ready(&self) -> bool {
123 matches!(self, Self::Ready)
124 }
125
126 pub const fn is_finished(&self) -> bool {
129 matches!(self, Self::Finished)
130 }
131}
132
133#[doc(alias = "TransactionFiller")]
147pub trait TxFiller<N: Network = Ethereum>: Clone + Send + Sync + std::fmt::Debug {
148 type Fillable: Send + Sync + 'static;
151
152 fn join_with<T>(self, other: T) -> JoinFill<Self, T>
154 where
155 T: TxFiller<N>,
156 {
157 JoinFill::new(self, other)
158 }
159
160 fn status(&self, tx: &N::TransactionRequest) -> FillerControlFlow;
164
165 fn continue_filling(&self, tx: &SendableTx<N>) -> bool {
167 tx.as_builder().is_some_and(|tx| self.status(tx).is_ready())
168 }
169
170 fn ready(&self, tx: &N::TransactionRequest) -> bool {
172 self.status(tx).is_ready()
173 }
174
175 fn finished(&self, tx: &N::TransactionRequest) -> bool {
177 self.status(tx).is_finished()
178 }
179
180 fn fill_sync(&self, tx: &mut SendableTx<N>);
184
185 fn prepare<P: Provider<N>>(
187 &self,
188 provider: &P,
189 tx: &N::TransactionRequest,
190 ) -> impl_future!(<Output = TransportResult<Self::Fillable>>);
191
192 fn fill(
194 &self,
195 fillable: Self::Fillable,
196 tx: SendableTx<N>,
197 ) -> impl_future!(<Output = TransportResult<SendableTx<N>>>);
198
199 fn prepare_and_fill<P>(
201 &self,
202 provider: &P,
203 tx: SendableTx<N>,
204 ) -> impl_future!(<Output = TransportResult<SendableTx<N>>>)
205 where
206 P: Provider<N>,
207 {
208 async move {
209 if tx.is_envelope() {
210 return Ok(tx);
211 }
212
213 let fillable =
214 self.prepare(provider, tx.as_builder().expect("checked by is_envelope")).await?;
215
216 self.fill(fillable, tx).await
217 }
218 }
219
220 fn prepare_call(
223 &self,
224 tx: &mut N::TransactionRequest,
225 ) -> impl_future!(<Output = TransportResult<()>>) {
226 let _ = tx;
227 futures::future::ready(Ok(()))
229 }
230
231 fn prepare_call_sync(&self, tx: &mut N::TransactionRequest) -> TransportResult<()> {
234 let _ = tx;
235 Ok(())
237 }
238}
239
240#[derive(Clone, Debug)]
252pub struct FillProvider<F, P, N = Ethereum>
253where
254 F: TxFiller<N>,
255 P: Provider<N>,
256 N: Network,
257{
258 pub(crate) inner: P,
259 pub(crate) filler: F,
260 _pd: PhantomData<fn() -> N>,
261}
262
263impl<F, P, N> FillProvider<F, P, N>
264where
265 F: TxFiller<N>,
266 P: Provider<N>,
267 N: Network,
268{
269 pub fn new(inner: P, filler: F) -> Self {
271 Self { inner, filler, _pd: PhantomData }
272 }
273
274 pub fn join_with<Other: TxFiller<N>>(
276 self,
277 other: Other,
278 ) -> FillProvider<JoinFill<F, Other>, P, N> {
279 self.filler.join_with(other).layer(self.inner)
280 }
281
282 async fn fill_inner(&self, mut tx: SendableTx<N>) -> TransportResult<SendableTx<N>> {
283 let mut count = 0;
284
285 while self.filler.continue_filling(&tx) {
286 self.filler.fill_sync(&mut tx);
287 tx = self.filler.prepare_and_fill(&self.inner, tx).await?;
288
289 count += 1;
290 if count >= 20 {
291 const ERROR: &str = "Tx filler loop detected. This indicates a bug in some filler implementation. Please file an issue containing this message.";
292 error!(
293 ?tx, ?self.filler,
294 ERROR
295 );
296 panic!("{}, {:?}, {:?}", ERROR, &tx, &self.filler);
297 }
298 }
299 Ok(tx)
300 }
301
302 pub async fn fill(&self, tx: N::TransactionRequest) -> TransportResult<SendableTx<N>> {
304 self.fill_inner(SendableTx::Builder(tx)).await
305 }
306
307 pub fn prepare_call(
309 &self,
310 mut tx: N::TransactionRequest,
311 ) -> TransportResult<N::TransactionRequest> {
312 self.filler.prepare_call_sync(&mut tx)?;
313 Ok(tx)
314 }
315}
316
317#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
318#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
319impl<F, P, N> Provider<N> for FillProvider<F, P, N>
320where
321 F: TxFiller<N>,
322 P: Provider<N>,
323 N: Network,
324{
325 fn root(&self) -> &RootProvider<N> {
326 self.inner.root()
327 }
328
329 fn get_accounts(&self) -> ProviderCall<NoParams, Vec<Address>> {
330 self.inner.get_accounts()
331 }
332
333 fn get_blob_base_fee(&self) -> ProviderCall<NoParams, U128, u128> {
334 self.inner.get_blob_base_fee()
335 }
336
337 fn get_block_number(&self) -> ProviderCall<NoParams, U64, BlockNumber> {
338 self.inner.get_block_number()
339 }
340
341 fn call<'req>(&self, tx: N::TransactionRequest) -> EthCall<N, Bytes> {
342 let mut tx = tx;
343 let _ = self.filler.prepare_call_sync(&mut tx);
344 self.inner.call(tx)
345 }
346
347 fn call_many<'req>(
348 &self,
349 bundles: &'req Vec<Bundle>,
350 ) -> EthCallMany<'req, N, Vec<Vec<EthCallResponse>>> {
351 self.inner.call_many(bundles)
352 }
353
354 fn simulate<'req>(
355 &self,
356 payload: &'req SimulatePayload,
357 ) -> RpcWithBlock<&'req SimulatePayload, Vec<SimulatedBlock<N::BlockResponse>>> {
358 self.inner.simulate(payload)
359 }
360
361 fn get_chain_id(&self) -> ProviderCall<NoParams, U64, u64> {
362 self.inner.get_chain_id()
363 }
364
365 fn create_access_list<'a>(
366 &self,
367 request: &'a N::TransactionRequest,
368 ) -> RpcWithBlock<&'a N::TransactionRequest, AccessListResult> {
369 self.inner.create_access_list(request)
370 }
371
372 fn estimate_gas<'req>(&self, tx: N::TransactionRequest) -> EthCall<N, U64, u64> {
373 let mut tx = tx;
374 let _ = self.filler.prepare_call_sync(&mut tx);
375 self.inner.estimate_gas(tx)
376 }
377
378 async fn get_fee_history(
379 &self,
380 block_count: u64,
381 last_block: BlockNumberOrTag,
382 reward_percentiles: &[f64],
383 ) -> TransportResult<FeeHistory> {
384 self.inner.get_fee_history(block_count, last_block, reward_percentiles).await
385 }
386
387 fn get_gas_price(&self) -> ProviderCall<NoParams, U128, u128> {
388 self.inner.get_gas_price()
389 }
390
391 fn get_account(&self, address: Address) -> RpcWithBlock<Address, alloy_consensus::Account> {
392 self.inner.get_account(address)
393 }
394
395 fn get_balance(&self, address: Address) -> RpcWithBlock<Address, U256, U256> {
396 self.inner.get_balance(address)
397 }
398
399 fn get_block(&self, block: BlockId) -> EthGetBlock<N::BlockResponse> {
400 self.inner.get_block(block)
401 }
402
403 fn get_block_by_hash(&self, hash: BlockHash) -> EthGetBlock<N::BlockResponse> {
404 self.inner.get_block_by_hash(hash)
405 }
406
407 fn get_block_by_number(&self, number: BlockNumberOrTag) -> EthGetBlock<N::BlockResponse> {
408 self.inner.get_block_by_number(number)
409 }
410
411 async fn get_block_transaction_count_by_hash(
412 &self,
413 hash: BlockHash,
414 ) -> TransportResult<Option<u64>> {
415 self.inner.get_block_transaction_count_by_hash(hash).await
416 }
417
418 async fn get_block_transaction_count_by_number(
419 &self,
420 block_number: BlockNumberOrTag,
421 ) -> TransportResult<Option<u64>> {
422 self.inner.get_block_transaction_count_by_number(block_number).await
423 }
424
425 fn get_block_receipts(
426 &self,
427 block: BlockId,
428 ) -> ProviderCall<(BlockId,), Option<Vec<N::ReceiptResponse>>> {
429 self.inner.get_block_receipts(block)
430 }
431
432 fn get_code_at(&self, address: Address) -> RpcWithBlock<Address, Bytes> {
433 self.inner.get_code_at(address)
434 }
435
436 async fn watch_blocks(&self) -> TransportResult<FilterPollerBuilder<B256>> {
437 self.inner.watch_blocks().await
438 }
439
440 async fn watch_pending_transactions(&self) -> TransportResult<FilterPollerBuilder<B256>> {
441 self.inner.watch_pending_transactions().await
442 }
443
444 async fn watch_logs(&self, filter: &Filter) -> TransportResult<FilterPollerBuilder<Log>> {
445 self.inner.watch_logs(filter).await
446 }
447
448 async fn watch_full_pending_transactions(
449 &self,
450 ) -> TransportResult<FilterPollerBuilder<N::TransactionResponse>> {
451 self.inner.watch_full_pending_transactions().await
452 }
453
454 async fn get_filter_changes_dyn(&self, id: U256) -> TransportResult<FilterChanges> {
455 self.inner.get_filter_changes_dyn(id).await
456 }
457
458 async fn get_filter_logs(&self, id: U256) -> TransportResult<Vec<Log>> {
459 self.inner.get_filter_logs(id).await
460 }
461
462 async fn uninstall_filter(&self, id: U256) -> TransportResult<bool> {
463 self.inner.uninstall_filter(id).await
464 }
465
466 async fn watch_pending_transaction(
467 &self,
468 config: PendingTransactionConfig,
469 ) -> Result<PendingTransaction, PendingTransactionError> {
470 self.inner.watch_pending_transaction(config).await
471 }
472
473 async fn get_logs(&self, filter: &Filter) -> TransportResult<Vec<Log>> {
474 self.inner.get_logs(filter).await
475 }
476
477 fn get_proof(
478 &self,
479 address: Address,
480 keys: Vec<StorageKey>,
481 ) -> RpcWithBlock<(Address, Vec<StorageKey>), EIP1186AccountProofResponse> {
482 self.inner.get_proof(address, keys)
483 }
484
485 fn get_storage_at(
486 &self,
487 address: Address,
488 key: U256,
489 ) -> RpcWithBlock<(Address, U256), StorageValue> {
490 self.inner.get_storage_at(address, key)
491 }
492
493 fn get_transaction_by_hash(
494 &self,
495 hash: TxHash,
496 ) -> ProviderCall<(TxHash,), Option<N::TransactionResponse>> {
497 self.inner.get_transaction_by_hash(hash)
498 }
499
500 fn get_transaction_by_block_hash_and_index(
501 &self,
502 block_hash: B256,
503 index: usize,
504 ) -> ProviderCall<(B256, Index), Option<N::TransactionResponse>> {
505 self.inner.get_transaction_by_block_hash_and_index(block_hash, index)
506 }
507
508 fn get_raw_transaction_by_block_hash_and_index(
509 &self,
510 block_hash: B256,
511 index: usize,
512 ) -> ProviderCall<(B256, Index), Option<Bytes>> {
513 self.inner.get_raw_transaction_by_block_hash_and_index(block_hash, index)
514 }
515
516 fn get_transaction_by_block_number_and_index(
517 &self,
518 block_number: BlockNumberOrTag,
519 index: usize,
520 ) -> ProviderCall<(BlockNumberOrTag, Index), Option<N::TransactionResponse>> {
521 self.inner.get_transaction_by_block_number_and_index(block_number, index)
522 }
523
524 fn get_raw_transaction_by_block_number_and_index(
525 &self,
526 block_number: BlockNumberOrTag,
527 index: usize,
528 ) -> ProviderCall<(BlockNumberOrTag, Index), Option<Bytes>> {
529 self.inner.get_raw_transaction_by_block_number_and_index(block_number, index)
530 }
531
532 fn get_raw_transaction_by_hash(&self, hash: TxHash) -> ProviderCall<(TxHash,), Option<Bytes>> {
533 self.inner.get_raw_transaction_by_hash(hash)
534 }
535
536 fn get_transaction_count(
537 &self,
538 address: Address,
539 ) -> RpcWithBlock<Address, U64, u64, fn(U64) -> u64> {
540 self.inner.get_transaction_count(address)
541 }
542
543 fn get_transaction_receipt(
544 &self,
545 hash: TxHash,
546 ) -> ProviderCall<(TxHash,), Option<N::ReceiptResponse>> {
547 self.inner.get_transaction_receipt(hash)
548 }
549
550 async fn get_uncle(&self, tag: BlockId, idx: u64) -> TransportResult<Option<N::BlockResponse>> {
551 self.inner.get_uncle(tag, idx).await
552 }
553
554 async fn get_uncle_count(&self, tag: BlockId) -> TransportResult<u64> {
555 self.inner.get_uncle_count(tag).await
556 }
557
558 fn get_max_priority_fee_per_gas(&self) -> ProviderCall<NoParams, U128, u128> {
559 self.inner.get_max_priority_fee_per_gas()
560 }
561
562 async fn new_block_filter(&self) -> TransportResult<U256> {
563 self.inner.new_block_filter().await
564 }
565
566 async fn new_filter(&self, filter: &Filter) -> TransportResult<U256> {
567 self.inner.new_filter(filter).await
568 }
569
570 async fn new_pending_transactions_filter(&self, full: bool) -> TransportResult<U256> {
571 self.inner.new_pending_transactions_filter(full).await
572 }
573
574 async fn send_raw_transaction(
575 &self,
576 encoded_tx: &[u8],
577 ) -> TransportResult<PendingTransactionBuilder<N>> {
578 self.inner.send_raw_transaction(encoded_tx).await
579 }
580
581 async fn send_raw_transaction_conditional(
582 &self,
583 encoded_tx: &[u8],
584 conditional: TransactionConditional,
585 ) -> TransportResult<PendingTransactionBuilder<N>> {
586 self.inner.send_raw_transaction_conditional(encoded_tx, conditional).await
587 }
588
589 async fn send_transaction_internal(
590 &self,
591 mut tx: SendableTx<N>,
592 ) -> TransportResult<PendingTransactionBuilder<N>> {
593 tx = self.fill_inner(tx).await?;
594
595 if let Some(builder) = tx.as_builder() {
596 if let FillerControlFlow::Missing(missing) = self.filler.status(builder) {
597 let message = format!("missing properties: {:?}", missing);
600 return Err(RpcError::local_usage_str(&message));
601 }
602 }
603
604 self.inner.send_transaction_internal(tx).await
606 }
607
608 #[cfg(feature = "pubsub")]
609 async fn subscribe_blocks(
610 &self,
611 ) -> TransportResult<alloy_pubsub::Subscription<N::HeaderResponse>> {
612 self.inner.subscribe_blocks().await
613 }
614
615 #[cfg(feature = "pubsub")]
616 async fn subscribe_pending_transactions(
617 &self,
618 ) -> TransportResult<alloy_pubsub::Subscription<B256>> {
619 self.inner.subscribe_pending_transactions().await
620 }
621
622 #[cfg(feature = "pubsub")]
623 async fn subscribe_full_pending_transactions(
624 &self,
625 ) -> TransportResult<alloy_pubsub::Subscription<N::TransactionResponse>> {
626 self.inner.subscribe_full_pending_transactions().await
627 }
628
629 #[cfg(feature = "pubsub")]
630 async fn subscribe_logs(
631 &self,
632 filter: &Filter,
633 ) -> TransportResult<alloy_pubsub::Subscription<Log>> {
634 self.inner.subscribe_logs(filter).await
635 }
636
637 #[cfg(feature = "pubsub")]
638 async fn unsubscribe(&self, id: B256) -> TransportResult<()> {
639 self.inner.unsubscribe(id).await
640 }
641
642 fn syncing(&self) -> ProviderCall<NoParams, SyncStatus> {
643 self.inner.syncing()
644 }
645
646 fn get_client_version(&self) -> ProviderCall<NoParams, String> {
647 self.inner.get_client_version()
648 }
649
650 fn get_sha3(&self, data: &[u8]) -> ProviderCall<(String,), B256> {
651 self.inner.get_sha3(data)
652 }
653
654 fn get_net_version(&self) -> ProviderCall<NoParams, U64, u64> {
655 self.inner.get_net_version()
656 }
657
658 async fn raw_request_dyn(
659 &self,
660 method: Cow<'static, str>,
661 params: &RawValue,
662 ) -> TransportResult<Box<RawValue>> {
663 self.inner.raw_request_dyn(method, params).await
664 }
665
666 fn transaction_request(&self) -> N::TransactionRequest {
667 self.inner.transaction_request()
668 }
669}
670
671pub trait RecommendedFillers: Network {
673 type RecommendedFillers: TxFiller<Self>;
675
676 fn recommended_fillers() -> Self::RecommendedFillers;
678}
679
680impl RecommendedFillers for Ethereum {
681 type RecommendedFillers =
682 JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>;
683
684 fn recommended_fillers() -> Self::RecommendedFillers {
685 Default::default()
686 }
687}
688
689impl RecommendedFillers for AnyNetwork {
690 type RecommendedFillers =
691 JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>;
692
693 fn recommended_fillers() -> Self::RecommendedFillers {
694 Default::default()
695 }
696}