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    pub const fn left_mut(&mut self) -> &mut L {
42        &mut self.left
43    }
44
45    /// Get a mutable reference to the right filler.
46    pub const fn right_mut(&mut self) -> &mut R {
47        &mut self.right
48    }
49
50    /// Maps the left filler to a new type.
51    pub fn map_left<F, T>(self, f: F) -> JoinFill<T, R>
52    where
53        F: FnOnce(L) -> T,
54    {
55        JoinFill::new(f(self.left), self.right)
56    }
57
58    /// Maps the right filler to a new type.
59    pub fn map_right<F, T>(self, f: F) -> JoinFill<L, T>
60    where
61        F: FnOnce(R) -> T,
62    {
63        JoinFill::new(self.left, f(self.right))
64    }
65}
66
67impl<L, R> JoinFill<L, R> {
68    /// Get a request for the left filler, if the left filler is ready.
69    async fn prepare_left<P, N>(
70        &self,
71        provider: &P,
72        tx: &N::TransactionRequest,
73    ) -> TransportResult<Option<L::Fillable>>
74    where
75        P: Provider<N>,
76        L: TxFiller<N>,
77        N: Network,
78    {
79        if self.left.ready(tx) {
80            self.left.prepare(provider, tx).await.map(Some)
81        } else {
82            Ok(None)
83        }
84    }
85
86    /// Get a prepare for the right filler, if the right filler is ready.
87    async fn prepare_right<P, N>(
88        &self,
89        provider: &P,
90        tx: &N::TransactionRequest,
91    ) -> TransportResult<Option<R::Fillable>>
92    where
93        P: Provider<N>,
94        R: TxFiller<N>,
95        N: Network,
96    {
97        if self.right.ready(tx) {
98            self.right.prepare(provider, tx).await.map(Some)
99        } else {
100            Ok(None)
101        }
102    }
103}
104
105impl<L, R, N> TxFiller<N> for JoinFill<L, R>
106where
107    L: TxFiller<N>,
108    R: TxFiller<N>,
109    N: Network,
110{
111    type Fillable = (Option<L::Fillable>, Option<R::Fillable>);
112
113    fn status(&self, tx: &N::TransactionRequest) -> FillerControlFlow {
114        self.left.status(tx).absorb(self.right.status(tx))
115    }
116
117    fn fill_sync(&self, tx: &mut SendableTx<N>) {
118        self.left.fill_sync(tx);
119        self.right.fill_sync(tx);
120    }
121
122    async fn prepare<P>(
123        &self,
124        provider: &P,
125        tx: &N::TransactionRequest,
126    ) -> TransportResult<Self::Fillable>
127    where
128        P: Provider<N>,
129    {
130        try_join!(self.prepare_left(provider, tx), self.prepare_right(provider, tx))
131    }
132
133    async fn fill(
134        &self,
135        to_fill: Self::Fillable,
136        mut tx: SendableTx<N>,
137    ) -> TransportResult<SendableTx<N>> {
138        if let Some(to_fill) = to_fill.0 {
139            tx = self.left.fill(to_fill, tx).await?;
140        };
141        if let Some(to_fill) = to_fill.1 {
142            tx = self.right.fill(to_fill, tx).await?;
143        };
144        Ok(tx)
145    }
146
147    async fn prepare_call(
148        &self,
149        tx: &mut <N as Network>::TransactionRequest,
150    ) -> TransportResult<()> {
151        self.left.prepare_call(tx).await?;
152        self.right.prepare_call(tx).await?;
153        Ok(())
154    }
155
156    fn prepare_call_sync(
157        &self,
158        tx: &mut <N as Network>::TransactionRequest,
159    ) -> TransportResult<()> {
160        self.left.prepare_call_sync(tx)?;
161        self.right.prepare_call_sync(tx)?;
162        Ok(())
163    }
164}
165
166impl<L, R, P, N> ProviderLayer<P, N> for JoinFill<L, R>
167where
168    L: TxFiller<N>,
169    R: TxFiller<N>,
170    P: Provider<N>,
171    N: Network,
172{
173    type Provider = FillProvider<Self, P, N>;
174
175    fn layer(&self, inner: P) -> Self::Provider {
176        FillProvider::new(inner, self.clone())
177    }
178}