1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use js_export_macro::js_export;
use miden_client::Felt as NativeFelt;
use miden_client::account::component::FungibleFaucet as NativeFungibleFaucet;
use miden_client::account::{Account as NativeAccount, AccountStorage as NativeAccountStorage};
use super::account::Account;
use super::felt::Felt;
use super::token_symbol::TokenSymbol;
use crate::js_error_with_context;
use crate::models::account_storage::AccountStorage;
use crate::platform::JsErr;
/// Provides metadata for a fungible faucet account component.
///
/// Reads the on-chain `FungibleFaucet` component for the account, which holds the per-token
/// info (symbol, decimals, supply, and the descriptive metadata). The same component backs both
/// "basic" public faucets and network-style faucets — in the current protocol the distinction is
/// a function of the surrounding account configuration (account type, auth, access control), not
/// of the faucet component itself — so this reads metadata from either kind of faucet account.
#[js_export]
pub struct BasicFungibleFaucetComponent(NativeFungibleFaucet);
#[js_export]
impl BasicFungibleFaucetComponent {
/// Extracts faucet metadata from an account.
#[js_export(js_name = "fromAccount")]
#[allow(clippy::needless_pass_by_value)]
pub fn from_account(account: Account) -> Result<Self, JsErr> {
let native_account: NativeAccount = account.into();
let faucet = NativeFungibleFaucet::try_from(&native_account).map_err(|e| {
js_error_with_context(e, "failed to get basic fungible faucet details from account")
})?;
Ok(Self(faucet))
}
/// Extracts faucet metadata from an account's storage.
///
/// Unlike [`Self::from_account`], this reads the metadata straight from the storage slots
/// without checking that the account exposes the basic fungible faucet interface. This makes
/// it work for faucets built from custom components that reuse the standards storage layout
/// (e.g. `AggLayer` bridged-asset faucets), but it also means a non-faucet account whose
/// storage happens to use the same slot names would yield bogus metadata without an error.
#[js_export(js_name = "fromAccountStorage")]
#[allow(clippy::needless_pass_by_value)]
pub fn from_account_storage(account_storage: AccountStorage) -> Result<Self, JsErr> {
let native_account_storage: NativeAccountStorage = account_storage.into();
let faucet = NativeFungibleFaucet::try_from(&native_account_storage).map_err(|e| {
js_error_with_context(
e,
"failed to get basic fungible faucet details from account storage",
)
})?;
Ok(Self(faucet))
}
/// Returns the faucet's token symbol.
pub fn symbol(&self) -> TokenSymbol {
self.0.symbol().into()
}
/// Returns the human-readable token name.
#[js_export(js_name = "tokenName")]
pub fn token_name(&self) -> String {
self.0.token_name().as_str().to_string()
}
/// Returns the number of decimal places for the token.
pub fn decimals(&self) -> u8 {
self.0.decimals()
}
/// Returns the maximum token supply.
#[js_export(js_name = "maxSupply")]
pub fn max_supply(&self) -> Felt {
NativeFelt::from(self.0.max_supply()).into()
}
/// Returns the current token supply (the amount minted so far).
#[js_export(js_name = "tokenSupply")]
pub fn token_supply(&self) -> Felt {
NativeFelt::from(self.0.token_supply()).into()
}
/// Returns the optional free-form token description, or `undefined` when unset.
pub fn description(&self) -> Option<String> {
self.0.description().map(|d| d.as_str().to_string())
}
/// Returns the optional token logo URI, or `undefined` when unset.
#[js_export(js_name = "logoUri")]
pub fn logo_uri(&self) -> Option<String> {
self.0.logo_uri().map(|uri| uri.as_str().to_string())
}
/// Returns the optional external link (e.g. project website), or `undefined` when unset.
#[js_export(js_name = "externalLink")]
pub fn external_link(&self) -> Option<String> {
self.0.external_link().map(|link| link.as_str().to_string())
}
}