Skip to main content

miden_standards/account/faucets/
mod.rs

1use alloc::string::String;
2
3use miden_protocol::Felt;
4use miden_protocol::account::{Account, AccountStorage, AccountType, StorageSlotName};
5use miden_protocol::errors::{AccountError, TokenSymbolError};
6use miden_protocol::utils::sync::LazyLock;
7use thiserror::Error;
8
9mod basic_fungible;
10mod network_fungible;
11
12pub use basic_fungible::{BasicFungibleFaucet, create_basic_fungible_faucet};
13pub use network_fungible::{NetworkFungibleFaucet, create_network_fungible_faucet};
14
15static METADATA_SLOT_NAME: LazyLock<StorageSlotName> = LazyLock::new(|| {
16    StorageSlotName::new("miden::standards::fungible_faucets::metadata")
17        .expect("storage slot name should be valid")
18});
19
20// FUNGIBLE FAUCET
21// ================================================================================================
22
23/// Extension trait for fungible faucet accounts. Provides methods to access the fungible faucet
24/// account's reserved storage slot.
25pub trait FungibleFaucetExt {
26    const ISSUANCE_ELEMENT_INDEX: usize;
27
28    /// Returns the amount of tokens (in base units) issued from this fungible faucet.
29    ///
30    /// # Errors
31    /// Returns an error if the account is not a fungible faucet account.
32    fn get_token_issuance(&self) -> Result<Felt, FungibleFaucetError>;
33}
34
35impl FungibleFaucetExt for Account {
36    const ISSUANCE_ELEMENT_INDEX: usize = 3;
37
38    fn get_token_issuance(&self) -> Result<Felt, FungibleFaucetError> {
39        if self.account_type() != AccountType::FungibleFaucet {
40            return Err(FungibleFaucetError::NotAFungibleFaucetAccount);
41        }
42
43        let slot =
44            self.storage().get_item(AccountStorage::faucet_sysdata_slot()).map_err(|err| {
45                FungibleFaucetError::StorageLookupFailed {
46                    slot_name: AccountStorage::faucet_sysdata_slot().clone(),
47                    source: err,
48                }
49            })?;
50        Ok(slot[Self::ISSUANCE_ELEMENT_INDEX])
51    }
52}
53
54// FUNGIBLE FAUCET ERROR
55// ================================================================================================
56
57/// Basic fungible faucet related errors.
58#[derive(Debug, Error)]
59pub enum FungibleFaucetError {
60    #[error("faucet metadata decimals is {actual} which exceeds max value of {max}")]
61    TooManyDecimals { actual: u64, max: u8 },
62    #[error("faucet metadata max supply is {actual} which exceeds max value of {max}")]
63    MaxSupplyTooLarge { actual: u64, max: u64 },
64    #[error(
65        "account interface provided for faucet creation does not have basic fungible faucet component"
66    )]
67    NoAvailableInterface,
68    #[error("failed to retrieve storage slot with name {slot_name}")]
69    StorageLookupFailed {
70        slot_name: StorageSlotName,
71        source: AccountError,
72    },
73    #[error("invalid token symbol")]
74    InvalidTokenSymbol(#[source] TokenSymbolError),
75    #[error("unsupported authentication scheme: {0}")]
76    UnsupportedAuthScheme(String),
77    #[error("account creation failed")]
78    AccountError(#[source] AccountError),
79    #[error("account is not a fungible faucet account")]
80    NotAFungibleFaucetAccount,
81}