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