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::*;