alloy_provider/fillers/
join_fill.rs

1use crate::{
2    fillers::{FillProvider, FillerControlFlow, TxFiller},
3    provider::SendableTx,
4    Provider, ProviderLayer,
5};
6use alloy_network::Network;
7use alloy_transport::TransportResult;
8use futures::try_join;
9
10/// A layer that can fill in a [`TransactionRequest`] with additional information by joining two
11/// [`TxFiller`]s.
12///
13/// This struct is itself a [`TxFiller`], and can be nested to compose any number of fill layers.
14///
15/// [`TransactionRequest`]: alloy_rpc_types_eth::TransactionRequest
16#[derive(Clone, Copy, Debug, Default)]
17pub struct JoinFill<L, R> {
18    left: L,
19    right: R,
20}
21
22impl<L, R> JoinFill<L, R> {
23    /// Creates a new `JoinFill` with the given layers.
24    pub const fn new(left: L, right: R) -> Self {
25        Self { left, right }
26    }
27
28    /// Get a reference to the left filler.
29    pub const fn left(&self) -> &L {
30        &self.left
31    }
32
33    /// Get a reference to the right filler.
34    pub const fn right(&self) -> &R {
35        &self.right
36    }
37
38    /// Get a mutable reference to the left filler.
39    ///
40    /// NB: this function exists to enable the [`crate::WalletProvider`] impl.
41    pub(crate) fn right_mut(&mut self) -> &mut R {
42        &mut self.right
43    }
44}
45
46impl<L, R> JoinFill<L, R> {
47    /// Get a request for the left filler, if the left filler is ready.
48    async fn prepare_left<P, N>(
49        &self,
50        provider: &P,
51        tx: &N::TransactionRequest,
52    ) -> TransportResult<Option<L::Fillable>>
53    where
54        P: Provider<N>,
55        L: TxFiller<N>,
56        N: Network,
57    {
58        if self.left.ready(tx) {
59            self.left.prepare(provider, tx).await.map(Some)
60        } else {
61            Ok(None)
62        }
63    }
64
65    /// Get a prepare for the right filler, if the right filler is ready.
66    async fn prepare_right<P, N>(
67        &self,
68        provider: &P,
69        tx: &N::TransactionRequest,
70    ) -> TransportResult<Option<R::Fillable>>
71    where
72        P: Provider<N>,
73        R: TxFiller<N>,
74        N: Network,
75    {
76        if self.right.ready(tx) {
77            self.right.prepare(provider, tx).await.map(Some)
78        } else {
79            Ok(None)
80        }
81    }
82}
83
84impl<L, R, N> TxFiller<N> for JoinFill<L, R>
85where
86    L: TxFiller<N>,
87    R: TxFiller<N>,
88    N: Network,
89{
90    type Fillable = (Option<L::Fillable>, Option<R::Fillable>);
91
92    fn status(&self, tx: &N::TransactionRequest) -> FillerControlFlow {
93        self.left.status(tx).absorb(self.right.status(tx))
94    }
95
96    fn fill_sync(&self, tx: &mut SendableTx<N>) {
97        self.left.fill_sync(tx);
98        self.right.fill_sync(tx);
99    }
100
101    async fn prepare<P>(
102        &self,
103        provider: &P,
104        tx: &N::TransactionRequest,
105    ) -> TransportResult<Self::Fillable>
106    where
107        P: Provider<N>,
108    {
109        try_join!(self.prepare_left(provider, tx), self.prepare_right(provider, tx))
110    }
111
112    async fn fill(
113        &self,
114        to_fill: Self::Fillable,
115        mut tx: SendableTx<N>,
116    ) -> TransportResult<SendableTx<N>> {
117        if let Some(to_fill) = to_fill.0 {
118            tx = self.left.fill(to_fill, tx).await?;
119        };
120        if let Some(to_fill) = to_fill.1 {
121            tx = self.right.fill(to_fill, tx).await?;
122        };
123        Ok(tx)
124    }
125
126    async fn prepare_call(
127        &self,
128        tx: &mut <N as Network>::TransactionRequest,
129    ) -> TransportResult<()> {
130        self.left.prepare_call(tx).await?;
131        self.right.prepare_call(tx).await?;
132        Ok(())
133    }
134
135    fn prepare_call_sync(
136        &self,
137        tx: &mut <N as Network>::TransactionRequest,
138    ) -> TransportResult<()> {
139        self.left.prepare_call_sync(tx)?;
140        self.right.prepare_call_sync(tx)?;
141        Ok(())
142    }
143}
144
145impl<L, R, P, N> ProviderLayer<P, N> for JoinFill<L, R>
146where
147    L: TxFiller<N>,
148    R: TxFiller<N>,
149    P: Provider<N>,
150    N: Network,
151{
152    type Provider = FillProvider<Self, P, N>;
153    fn layer(&self, inner: P) -> Self::Provider {
154        FillProvider::new(inner, self.clone())
155    }
156}