fuels_accounts/
wallet.rs

1use crate::{provider::Provider, signers::private_key::PrivateKeySigner};
2
3#[derive(Debug, Clone)]
4pub struct Wallet<S = Unlocked<PrivateKeySigner>> {
5    state: S,
6    provider: Provider,
7}
8
9impl<S> Wallet<S> {
10    pub fn set_provider(&mut self, provider: Provider) {
11        self.provider = provider;
12    }
13
14    pub fn provider(&self) -> &Provider {
15        &self.provider
16    }
17}
18
19mod unlocked {
20    use async_trait::async_trait;
21    use fuel_tx::AssetId;
22    use fuels_core::{
23        traits::Signer,
24        types::{
25            bech32::Bech32Address, coin_type_id::CoinTypeId, errors::Result, input::Input,
26            transaction_builders::TransactionBuilder,
27        },
28    };
29    use rand::{CryptoRng, RngCore};
30
31    use crate::{
32        provider::Provider, signers::private_key::PrivateKeySigner, Account, ViewOnlyAccount,
33    };
34
35    use super::{Locked, Wallet};
36
37    #[derive(Debug, Clone)]
38    pub struct Unlocked<S> {
39        signer: S,
40    }
41
42    impl<S> Unlocked<S> {
43        fn new(signer: S) -> Self {
44            Self { signer }
45        }
46    }
47
48    impl<S> Wallet<Unlocked<S>> {
49        pub fn new(signer: S, provider: Provider) -> Self {
50            Wallet {
51                state: Unlocked::new(signer),
52                provider,
53            }
54        }
55
56        pub fn signer(&self) -> &S {
57            &self.state.signer
58        }
59    }
60
61    impl Wallet<Unlocked<PrivateKeySigner>> {
62        pub fn random(rng: &mut (impl CryptoRng + RngCore), provider: Provider) -> Self {
63            Self::new(PrivateKeySigner::random(rng), provider)
64        }
65    }
66
67    impl<S> Wallet<Unlocked<S>>
68    where
69        S: Signer,
70    {
71        pub fn lock(&self) -> Wallet<Locked> {
72            Wallet::new_locked(self.state.signer.address().clone(), self.provider.clone())
73        }
74    }
75
76    #[async_trait]
77    impl<S> ViewOnlyAccount for Wallet<Unlocked<S>>
78    where
79        S: Signer + Clone + Send + Sync + std::fmt::Debug + 'static,
80    {
81        fn address(&self) -> &Bech32Address {
82            self.state.signer.address()
83        }
84
85        fn try_provider(&self) -> Result<&Provider> {
86            Ok(&self.provider)
87        }
88
89        async fn get_asset_inputs_for_amount(
90            &self,
91            asset_id: AssetId,
92            amount: u64,
93            excluded_coins: Option<Vec<CoinTypeId>>,
94        ) -> Result<Vec<Input>> {
95            Ok(self
96                .get_spendable_resources(asset_id, amount, excluded_coins)
97                .await?
98                .into_iter()
99                .map(Input::resource_signed)
100                .collect::<Vec<Input>>())
101        }
102    }
103
104    #[async_trait]
105    impl<S> Account for Wallet<Unlocked<S>>
106    where
107        S: Signer + Clone + Send + Sync + std::fmt::Debug + 'static,
108    {
109        fn add_witnesses<Tb: TransactionBuilder>(&self, tb: &mut Tb) -> Result<()> {
110            tb.add_signer(self.state.signer.clone())?;
111
112            Ok(())
113        }
114    }
115}
116pub use unlocked::*;
117
118mod locked {
119    use async_trait::async_trait;
120    use fuel_tx::AssetId;
121    use fuels_core::types::{
122        bech32::Bech32Address, coin_type_id::CoinTypeId, errors::Result, input::Input,
123    };
124
125    use crate::{provider::Provider, ViewOnlyAccount};
126
127    use super::Wallet;
128
129    #[derive(Debug, Clone)]
130    pub struct Locked {
131        address: Bech32Address,
132    }
133
134    impl Locked {
135        fn new(address: Bech32Address) -> Self {
136            Self { address }
137        }
138    }
139
140    impl Wallet<Locked> {
141        pub fn new_locked(addr: Bech32Address, provider: Provider) -> Self {
142            Self {
143                state: Locked::new(addr),
144                provider,
145            }
146        }
147    }
148
149    #[async_trait]
150    impl ViewOnlyAccount for Wallet<Locked> {
151        fn address(&self) -> &Bech32Address {
152            &self.state.address
153        }
154
155        fn try_provider(&self) -> Result<&Provider> {
156            Ok(&self.provider)
157        }
158
159        async fn get_asset_inputs_for_amount(
160            &self,
161            asset_id: AssetId,
162            amount: u64,
163            excluded_coins: Option<Vec<CoinTypeId>>,
164        ) -> Result<Vec<Input>> {
165            Ok(self
166                .get_spendable_resources(asset_id, amount, excluded_coins)
167                .await?
168                .into_iter()
169                .map(Input::resource_signed)
170                .collect::<Vec<Input>>())
171        }
172    }
173}
174pub use locked::*;