miden_lib/account/wallets/
mod.rs1use alloc::string::String;
2
3use miden_objects::account::{
4 Account,
5 AccountBuilder,
6 AccountComponent,
7 AccountStorageMode,
8 AccountType,
9};
10use miden_objects::{AccountError, Word};
11use thiserror::Error;
12
13use super::AuthScheme;
14use crate::account::auth::{
15 AuthRpoFalcon512,
16 AuthRpoFalcon512Multisig,
17 AuthRpoFalcon512MultisigConfig,
18};
19use crate::account::components::basic_wallet_library;
20use crate::procedure_digest;
21
22procedure_digest!(
27 BASIC_WALLET_RECEIVE_ASSET,
28 BasicWallet::RECEIVE_ASSET_PROC_NAME,
29 basic_wallet_library
30);
31
32procedure_digest!(
34 BASIC_WALLET_MOVE_ASSET_TO_NOTE,
35 BasicWallet::MOVE_ASSET_TO_NOTE_PROC_NAME,
36 basic_wallet_library
37);
38
39pub struct BasicWallet;
56
57impl BasicWallet {
58 const RECEIVE_ASSET_PROC_NAME: &str = "receive_asset";
61 const MOVE_ASSET_TO_NOTE_PROC_NAME: &str = "move_asset_to_note";
62
63 pub fn receive_asset_digest() -> Word {
68 *BASIC_WALLET_RECEIVE_ASSET
69 }
70
71 pub fn move_asset_to_note_digest() -> Word {
73 *BASIC_WALLET_MOVE_ASSET_TO_NOTE
74 }
75}
76
77impl From<BasicWallet> for AccountComponent {
78 fn from(_: BasicWallet) -> Self {
79 AccountComponent::new(basic_wallet_library(), vec![])
80 .expect("basic wallet component should satisfy the requirements of a valid account component")
81 .with_supports_all_types()
82 }
83}
84
85#[derive(Debug, Error)]
90pub enum BasicWalletError {
91 #[error("unsupported authentication scheme: {0}")]
92 UnsupportedAuthScheme(String),
93 #[error("account creation failed")]
94 AccountError(#[source] AccountError),
95}
96
97pub fn create_basic_wallet(
108 init_seed: [u8; 32],
109 auth_scheme: AuthScheme,
110 account_type: AccountType,
111 account_storage_mode: AccountStorageMode,
112) -> Result<Account, BasicWalletError> {
113 if matches!(account_type, AccountType::FungibleFaucet | AccountType::NonFungibleFaucet) {
114 return Err(BasicWalletError::AccountError(AccountError::other(
115 "basic wallet accounts cannot have a faucet account type",
116 )));
117 }
118
119 let auth_component: AccountComponent = match auth_scheme {
120 AuthScheme::RpoFalcon512 { pub_key } => AuthRpoFalcon512::new(pub_key).into(),
121 AuthScheme::RpoFalcon512Multisig { threshold, pub_keys } => {
122 let config = AuthRpoFalcon512MultisigConfig::new(pub_keys, threshold)
123 .and_then(|cfg| {
124 cfg.with_proc_thresholds(vec![(BasicWallet::receive_asset_digest(), 1)])
125 })
126 .map_err(BasicWalletError::AccountError)?;
127 AuthRpoFalcon512Multisig::new(config)
128 .map_err(BasicWalletError::AccountError)?
129 .into()
130 },
131 AuthScheme::NoAuth => {
132 return Err(BasicWalletError::UnsupportedAuthScheme(
133 "basic wallets cannot be created with NoAuth authentication scheme".into(),
134 ));
135 },
136 AuthScheme::Unknown => {
137 return Err(BasicWalletError::UnsupportedAuthScheme(
138 "basic wallets cannot be created with Unknown authentication scheme".into(),
139 ));
140 },
141 };
142
143 let account = AccountBuilder::new(init_seed)
144 .account_type(account_type)
145 .storage_mode(account_storage_mode)
146 .with_auth_component(auth_component)
147 .with_component(BasicWallet)
148 .build()
149 .map_err(BasicWalletError::AccountError)?;
150
151 Ok(account)
152}
153
154#[cfg(test)]
158mod tests {
159 use miden_objects::account::auth::PublicKeyCommitment;
160 use miden_objects::{ONE, Word};
161 use miden_processor::utils::{Deserializable, Serializable};
162
163 use super::{Account, AccountStorageMode, AccountType, AuthScheme, create_basic_wallet};
164 use crate::account::wallets::BasicWallet;
165
166 #[test]
167 fn test_create_basic_wallet() {
168 let pub_key = PublicKeyCommitment::from(Word::from([ONE; 4]));
169 let wallet = create_basic_wallet(
170 [1; 32],
171 AuthScheme::RpoFalcon512 { pub_key },
172 AccountType::RegularAccountImmutableCode,
173 AccountStorageMode::Public,
174 );
175
176 wallet.unwrap_or_else(|err| {
177 panic!("{}", err);
178 });
179 }
180
181 #[test]
182 fn test_serialize_basic_wallet() {
183 let pub_key = PublicKeyCommitment::from(Word::from([ONE; 4]));
184 let wallet = create_basic_wallet(
185 [1; 32],
186 AuthScheme::RpoFalcon512 { pub_key },
187 AccountType::RegularAccountImmutableCode,
188 AccountStorageMode::Public,
189 )
190 .unwrap();
191
192 let bytes = wallet.to_bytes();
193 let deserialized_wallet = Account::read_from_bytes(&bytes).unwrap();
194 assert_eq!(wallet, deserialized_wallet);
195 }
196
197 #[test]
199 fn get_faucet_procedures() {
200 let _receive_asset_digest = BasicWallet::receive_asset_digest();
201 let _move_asset_to_note_digest = BasicWallet::move_asset_to_note_digest();
202 }
203}