miden_lib/account/wallets/
mod.rs

1use alloc::string::ToString;
2
3use miden_objects::{
4    AccountError, Word,
5    account::{Account, AccountBuilder, AccountComponent, AccountStorageMode, AccountType},
6};
7
8use super::AuthScheme;
9use crate::account::{
10    auth::{NoAuth, RpoFalcon512},
11    components::basic_wallet_library,
12};
13
14// BASIC WALLET
15// ================================================================================================
16
17/// An [`AccountComponent`] implementing a basic wallet.
18///
19/// It reexports the procedures from `miden::contracts::wallets::basic`. When linking against this
20/// component, the `miden` library (i.e. [`MidenLib`](crate::MidenLib)) must be available to the
21/// assembler which is the case when using [`TransactionKernel::assembler()`][kasm]. The procedures
22/// of this component are:
23/// - `receive_asset`, which can be used to add an asset to the account.
24/// - `move_asset_to_note`, which can be used to remove the specified asset from the account and add
25///   it to the output note with the specified index.
26///
27/// All methods require authentication. Thus, this component must be combined with a component
28/// providing authentication.
29///
30/// This component supports all account types.
31///
32/// [kasm]: crate::transaction::TransactionKernel::assembler
33pub struct BasicWallet;
34
35impl From<BasicWallet> for AccountComponent {
36    fn from(_: BasicWallet) -> Self {
37        AccountComponent::new(basic_wallet_library(), vec![])
38          .expect("basic wallet component should satisfy the requirements of a valid account component")
39          .with_supports_all_types()
40    }
41}
42
43/// Creates a new account with basic wallet interface, the specified authentication scheme and the
44/// account storage type. Basic wallets can be specified to have either mutable or immutable code.
45///
46/// The basic wallet interface exposes three procedures:
47/// - `receive_asset`, which can be used to add an asset to the account.
48/// - `move_asset_to_note`, which can be used to remove the specified asset from the account and add
49///   it to the output note with the specified index.
50///
51/// All methods require authentication. The authentication procedure is defined by the specified
52/// authentication scheme.
53pub fn create_basic_wallet(
54    init_seed: [u8; 32],
55    auth_scheme: AuthScheme,
56    account_type: AccountType,
57    account_storage_mode: AccountStorageMode,
58) -> Result<(Account, Word), AccountError> {
59    if matches!(account_type, AccountType::FungibleFaucet | AccountType::NonFungibleFaucet) {
60        return Err(AccountError::AssumptionViolated(
61            "basic wallet accounts cannot have a faucet account type".to_string(),
62        ));
63    }
64
65    let auth_component: AccountComponent = match auth_scheme {
66        AuthScheme::RpoFalcon512 { pub_key } => RpoFalcon512::new(pub_key).into(),
67        AuthScheme::NoAuth => NoAuth::new().into(),
68    };
69
70    let (account, account_seed) = AccountBuilder::new(init_seed)
71        .account_type(account_type)
72        .storage_mode(account_storage_mode)
73        .with_auth_component(auth_component)
74        .with_component(BasicWallet)
75        .build()?;
76
77    Ok((account, account_seed))
78}
79
80// TESTS
81// ================================================================================================
82
83#[cfg(test)]
84mod tests {
85
86    use miden_objects::{ONE, crypto::dsa::rpo_falcon512};
87    use vm_processor::utils::{Deserializable, Serializable};
88
89    use super::{Account, AccountStorageMode, AccountType, AuthScheme, create_basic_wallet};
90
91    #[test]
92    fn test_create_basic_wallet() {
93        let pub_key = rpo_falcon512::PublicKey::new([ONE; 4]);
94        let wallet = create_basic_wallet(
95            [1; 32],
96            AuthScheme::RpoFalcon512 { pub_key },
97            AccountType::RegularAccountImmutableCode,
98            AccountStorageMode::Public,
99        );
100
101        wallet.unwrap_or_else(|err| {
102            panic!("{}", err);
103        });
104    }
105
106    #[test]
107    fn test_serialize_basic_wallet() {
108        let pub_key = rpo_falcon512::PublicKey::new([ONE; 4]);
109        let wallet = create_basic_wallet(
110            [1; 32],
111            AuthScheme::RpoFalcon512 { pub_key },
112            AccountType::RegularAccountImmutableCode,
113            AccountStorageMode::Public,
114        )
115        .unwrap()
116        .0;
117
118        let bytes = wallet.to_bytes();
119        let deserialized_wallet = Account::read_from_bytes(&bytes).unwrap();
120        assert_eq!(wallet, deserialized_wallet);
121    }
122}