alloy_provider/fillers/
wallet.rs1use std::fmt::Debug;
2
3use crate::{provider::SendableTx, Provider};
4use alloy_json_rpc::RpcError;
5use alloy_network::{Network, NetworkWallet, TransactionBuilder};
6use alloy_transport::TransportResult;
7
8use super::{FillerControlFlow, TxFiller};
9
10#[derive(Clone, Debug)]
32pub struct WalletFiller<W> {
33 wallet: W,
34}
35
36impl<W> AsRef<W> for WalletFiller<W> {
37 fn as_ref(&self) -> &W {
38 &self.wallet
39 }
40}
41
42impl<W> AsMut<W> for WalletFiller<W> {
43 fn as_mut(&mut self) -> &mut W {
44 &mut self.wallet
45 }
46}
47
48impl<W> WalletFiller<W> {
49 pub const fn new(wallet: W) -> Self {
51 Self { wallet }
52 }
53}
54
55impl<W, N> TxFiller<N> for WalletFiller<W>
56where
57 N: Network,
58 W: NetworkWallet<N> + Clone,
59{
60 type Fillable = ();
61
62 fn status(&self, tx: &<N as Network>::TransactionRequest) -> FillerControlFlow {
63 if tx.from().is_none() {
64 return FillerControlFlow::Ready;
65 }
66
67 match tx.complete_preferred() {
68 Ok(_) => FillerControlFlow::Ready,
69 Err(e) => FillerControlFlow::Missing(vec![("Wallet", e)]),
70 }
71 }
72
73 fn fill_sync(&self, tx: &mut SendableTx<N>) {
74 if let Some(builder) = tx.as_mut_builder() {
75 if builder.from().is_none() {
76 builder.set_from(self.wallet.default_signer_address());
77 }
78 }
79 }
80
81 async fn prepare<P>(
82 &self,
83 _provider: &P,
84 _tx: &<N as Network>::TransactionRequest,
85 ) -> TransportResult<Self::Fillable>
86 where
87 P: Provider<N>,
88 {
89 Ok(())
90 }
91
92 async fn fill(
93 &self,
94 _fillable: Self::Fillable,
95 tx: SendableTx<N>,
96 ) -> TransportResult<SendableTx<N>> {
97 let builder = match tx {
98 SendableTx::Builder(builder) => builder,
99 _ => return Ok(tx),
100 };
101
102 let envelope = builder.build(&self.wallet).await.map_err(RpcError::local_usage)?;
103
104 Ok(SendableTx::Envelope(envelope))
105 }
106
107 async fn prepare_call(&self, tx: &mut N::TransactionRequest) -> TransportResult<()> {
108 self.prepare_call_sync(tx)?;
109 Ok(())
110 }
111
112 fn prepare_call_sync(
113 &self,
114 tx: &mut <N as Network>::TransactionRequest,
115 ) -> TransportResult<()> {
116 if tx.from().is_none() {
117 tx.set_from(self.wallet.default_signer_address());
118 }
119 Ok(())
120 }
121}
122
123#[cfg(feature = "reqwest")]
124#[cfg(test)]
125mod tests {
126 use crate::{Provider, ProviderBuilder, WalletProvider};
127 use alloy_node_bindings::Anvil;
128 use alloy_primitives::{address, b256, U256};
129 use alloy_rpc_types_eth::TransactionRequest;
130 use alloy_signer_local::PrivateKeySigner;
131
132 #[tokio::test]
133 async fn poc() {
134 let provider = ProviderBuilder::new().on_anvil_with_wallet();
135
136 let tx = TransactionRequest {
137 nonce: Some(0),
138 value: Some(U256::from(100)),
139 to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
140 gas_price: Some(20e9 as u128),
141 gas: Some(21000),
142 ..Default::default()
143 };
144
145 let builder = provider.send_transaction(tx).await.unwrap();
146 let node_hash = *builder.tx_hash();
147 assert_eq!(
148 node_hash,
149 b256!("4b56f1a6bdceb76d1b843e978c70ab88e38aa19f1a67be851b10ce4eec65b7d4")
150 );
151
152 let pending = builder.register().await.unwrap();
153 let local_hash = *pending.tx_hash();
154 assert_eq!(local_hash, node_hash);
155
156 let local_hash2 = pending.await.unwrap();
157 assert_eq!(local_hash2, node_hash);
158
159 let receipt =
160 provider.get_transaction_receipt(local_hash2).await.unwrap().expect("no receipt");
161 let receipt_hash = receipt.transaction_hash;
162 assert_eq!(receipt_hash, node_hash);
163 }
164
165 #[tokio::test]
166 async fn ingest_pk_signer() {
167 let pk: PrivateKeySigner =
168 "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".parse().unwrap();
169
170 let anvil = Anvil::new().spawn();
171
172 let provider = ProviderBuilder::new().wallet(pk.clone()).on_http(anvil.endpoint_url());
173
174 let tx = TransactionRequest {
175 nonce: Some(0),
176 value: Some(U256::from(100)),
177 to: Some(address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045").into()),
178 gas_price: Some(20e9 as u128),
179 gas: Some(21000),
180 ..Default::default()
181 };
182
183 let receipt = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap();
184
185 let wallet = provider.wallet();
187
188 let default_address = wallet.default_signer().address();
189
190 assert_eq!(pk.address(), default_address);
191 assert_eq!(receipt.from, default_address);
192 }
193}