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