use core::fmt;
use miden_crypto::merkle::LeafIndex;
use miden_processor::SMT_DEPTH;
use crate::Word;
use crate::account::AccountType::FungibleFaucet;
use crate::account::{AccountId, AccountIdPrefix};
use crate::asset::{Asset, FungibleAsset, NonFungibleAsset};
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
pub struct AssetVaultKey(Word);
impl AssetVaultKey {
pub fn new_unchecked(value: Word) -> Self {
Self(value)
}
pub fn faucet_id_prefix(&self) -> AccountIdPrefix {
if self.is_fungible() {
AccountIdPrefix::new_unchecked(self.0[3])
} else {
AccountIdPrefix::new_unchecked(self.0[0])
}
}
pub fn faucet_id(&self) -> Option<AccountId> {
if self.is_fungible() {
Some(AccountId::new_unchecked([self.0[3], self.0[2]]))
} else {
None
}
}
pub fn to_leaf_index(&self) -> LeafIndex<SMT_DEPTH> {
LeafIndex::<SMT_DEPTH>::from(self.0)
}
pub fn from_account_id(faucet_id: AccountId) -> Option<Self> {
match faucet_id.account_type() {
FungibleFaucet => {
let mut key = Word::empty();
key[2] = faucet_id.suffix();
key[3] = faucet_id.prefix().as_felt();
Some(AssetVaultKey::new_unchecked(key))
},
_ => None,
}
}
fn is_fungible(&self) -> bool {
self.0[0].as_int() == 0 && self.0[1].as_int() == 0
}
}
impl fmt::Display for AssetVaultKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<AssetVaultKey> for Word {
fn from(vault_key: AssetVaultKey) -> Self {
vault_key.0
}
}
impl From<Asset> for AssetVaultKey {
fn from(asset: Asset) -> Self {
asset.vault_key()
}
}
impl From<FungibleAsset> for AssetVaultKey {
fn from(fungible_asset: FungibleAsset) -> Self {
fungible_asset.vault_key()
}
}
impl From<NonFungibleAsset> for AssetVaultKey {
fn from(non_fungible_asset: NonFungibleAsset) -> Self {
non_fungible_asset.vault_key()
}
}
#[cfg(test)]
mod tests {
use miden_core::Felt;
use super::*;
use crate::account::{AccountIdVersion, AccountStorageMode, AccountType};
fn make_non_fungible_key(prefix: u64) -> AssetVaultKey {
let word = [Felt::new(prefix), Felt::new(11), Felt::new(22), Felt::new(33)].into();
AssetVaultKey::new_unchecked(word)
}
#[test]
fn test_faucet_id_for_fungible_asset() {
let id = AccountId::dummy(
[0xff; 15],
AccountIdVersion::Version0,
AccountType::FungibleFaucet,
AccountStorageMode::Public,
);
let key =
AssetVaultKey::from_account_id(id).expect("Expected AssetVaultKey for FungibleFaucet");
assert_eq!(key.faucet_id_prefix(), id.prefix());
assert_eq!(key.faucet_id().unwrap(), id);
}
#[test]
fn test_faucet_id_for_non_fungible_asset() {
let id = AccountId::dummy(
[0xff; 15],
AccountIdVersion::Version0,
AccountType::NonFungibleFaucet,
AccountStorageMode::Public,
);
let prefix_value = id.prefix().as_u64();
let key = make_non_fungible_key(prefix_value);
assert_eq!(key.faucet_id_prefix(), id.prefix());
assert_eq!(key.faucet_id(), None);
}
}