use alloc::collections::BTreeSet;
use alloc::vec::Vec;
use miden_processor::mast::MastNodeExt;
use miden_protocol::Word;
use miden_protocol::account::AccountProcedureRoot;
use miden_protocol::assembly::{Library, LibraryExport};
use miden_protocol::utils::serde::Deserializable;
use miden_protocol::utils::sync::LazyLock;
use crate::account::interface::AccountComponentInterface;
static BASIC_WALLET_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
let bytes = include_bytes!(concat!(
env!("OUT_DIR"),
"/assets/account_components/wallets/basic_wallet.masl"
));
Library::read_from_bytes(bytes).expect("Shipped Basic Wallet library is well-formed")
});
static OWNABLE2STEP_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
let bytes = include_bytes!(concat!(
env!("OUT_DIR"),
"/assets/account_components/access/ownable2step.masl"
));
Library::read_from_bytes(bytes).expect("Shipped Ownable2Step library is well-formed")
});
static SINGLESIG_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
let bytes =
include_bytes!(concat!(env!("OUT_DIR"), "/assets/account_components/auth/singlesig.masl"));
Library::read_from_bytes(bytes).expect("Shipped Singlesig library is well-formed")
});
static SINGLESIG_ACL_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
let bytes = include_bytes!(concat!(
env!("OUT_DIR"),
"/assets/account_components/auth/singlesig_acl.masl"
));
Library::read_from_bytes(bytes).expect("Shipped Singlesig ACL library is well-formed")
});
static MULTISIG_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
let bytes =
include_bytes!(concat!(env!("OUT_DIR"), "/assets/account_components/auth/multisig.masl"));
Library::read_from_bytes(bytes).expect("Shipped Multisig library is well-formed")
});
static MULTISIG_PSM_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
let bytes = include_bytes!(concat!(
env!("OUT_DIR"),
"/assets/account_components/auth/multisig_psm.masl"
));
Library::read_from_bytes(bytes).expect("Shipped Multisig PSM library is well-formed")
});
static NO_AUTH_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
let bytes =
include_bytes!(concat!(env!("OUT_DIR"), "/assets/account_components/auth/no_auth.masl"));
Library::read_from_bytes(bytes).expect("Shipped NoAuth library is well-formed")
});
static BASIC_FUNGIBLE_FAUCET_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
let bytes = include_bytes!(concat!(
env!("OUT_DIR"),
"/assets/account_components/faucets/basic_fungible_faucet.masl"
));
Library::read_from_bytes(bytes).expect("Shipped Basic Fungible Faucet library is well-formed")
});
static NETWORK_FUNGIBLE_FAUCET_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
let bytes = include_bytes!(concat!(
env!("OUT_DIR"),
"/assets/account_components/faucets/network_fungible_faucet.masl"
));
Library::read_from_bytes(bytes).expect("Shipped Network Fungible Faucet library is well-formed")
});
static MINT_POLICY_OWNER_CONTROLLED_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
let bytes = include_bytes!(concat!(
env!("OUT_DIR"),
"/assets/account_components/mint_policies/owner_controlled.masl"
));
Library::read_from_bytes(bytes)
.expect("Shipped Mint Policy Owner Controlled library is well-formed")
});
static MINT_POLICY_AUTH_CONTROLLED_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
let bytes = include_bytes!(concat!(
env!("OUT_DIR"),
"/assets/account_components/mint_policies/auth_controlled.masl"
));
Library::read_from_bytes(bytes)
.expect("Shipped Mint Policy Auth Controlled library is well-formed")
});
pub fn basic_wallet_library() -> Library {
BASIC_WALLET_LIBRARY.clone()
}
pub fn ownable2step_library() -> Library {
OWNABLE2STEP_LIBRARY.clone()
}
pub fn basic_fungible_faucet_library() -> Library {
BASIC_FUNGIBLE_FAUCET_LIBRARY.clone()
}
pub fn network_fungible_faucet_library() -> Library {
NETWORK_FUNGIBLE_FAUCET_LIBRARY.clone()
}
pub fn owner_controlled_library() -> Library {
MINT_POLICY_OWNER_CONTROLLED_LIBRARY.clone()
}
pub fn auth_controlled_library() -> Library {
MINT_POLICY_AUTH_CONTROLLED_LIBRARY.clone()
}
pub fn singlesig_library() -> Library {
SINGLESIG_LIBRARY.clone()
}
pub fn singlesig_acl_library() -> Library {
SINGLESIG_ACL_LIBRARY.clone()
}
pub fn multisig_library() -> Library {
MULTISIG_LIBRARY.clone()
}
pub fn multisig_psm_library() -> Library {
MULTISIG_PSM_LIBRARY.clone()
}
pub fn no_auth_library() -> Library {
NO_AUTH_LIBRARY.clone()
}
pub enum StandardAccountComponent {
BasicWallet,
BasicFungibleFaucet,
NetworkFungibleFaucet,
AuthSingleSig,
AuthSingleSigAcl,
AuthMultisig,
AuthMultisigPsm,
AuthNoAuth,
}
impl StandardAccountComponent {
pub fn procedure_digests(&self) -> impl Iterator<Item = Word> {
let library = match self {
Self::BasicWallet => BASIC_WALLET_LIBRARY.as_ref(),
Self::BasicFungibleFaucet => BASIC_FUNGIBLE_FAUCET_LIBRARY.as_ref(),
Self::NetworkFungibleFaucet => NETWORK_FUNGIBLE_FAUCET_LIBRARY.as_ref(),
Self::AuthSingleSig => SINGLESIG_LIBRARY.as_ref(),
Self::AuthSingleSigAcl => SINGLESIG_ACL_LIBRARY.as_ref(),
Self::AuthMultisig => MULTISIG_LIBRARY.as_ref(),
Self::AuthMultisigPsm => MULTISIG_PSM_LIBRARY.as_ref(),
Self::AuthNoAuth => NO_AUTH_LIBRARY.as_ref(),
};
library
.exports()
.filter(|export| matches!(export, LibraryExport::Procedure(_)))
.map(|proc_export| {
library
.mast_forest()
.get_node_by_id(proc_export.unwrap_procedure().node)
.expect("export node not in the forest")
.digest()
})
}
fn extract_component(
&self,
procedures_set: &mut BTreeSet<AccountProcedureRoot>,
component_interface_vec: &mut Vec<AccountComponentInterface>,
) {
if self.procedure_digests().all(|proc_digest| {
procedures_set.contains(&AccountProcedureRoot::from_raw(proc_digest))
}) {
self.procedure_digests().for_each(|component_procedure| {
procedures_set.remove(&AccountProcedureRoot::from_raw(component_procedure));
});
match self {
Self::BasicWallet => {
component_interface_vec.push(AccountComponentInterface::BasicWallet)
},
Self::BasicFungibleFaucet => {
component_interface_vec.push(AccountComponentInterface::BasicFungibleFaucet)
},
Self::NetworkFungibleFaucet => {
component_interface_vec.push(AccountComponentInterface::NetworkFungibleFaucet)
},
Self::AuthSingleSig => {
component_interface_vec.push(AccountComponentInterface::AuthSingleSig)
},
Self::AuthSingleSigAcl => {
component_interface_vec.push(AccountComponentInterface::AuthSingleSigAcl)
},
Self::AuthMultisig => {
component_interface_vec.push(AccountComponentInterface::AuthMultisig)
},
Self::AuthMultisigPsm => {
component_interface_vec.push(AccountComponentInterface::AuthMultisigPsm)
},
Self::AuthNoAuth => {
component_interface_vec.push(AccountComponentInterface::AuthNoAuth)
},
}
}
}
pub fn extract_standard_components(
procedures_set: &mut BTreeSet<AccountProcedureRoot>,
component_interface_vec: &mut Vec<AccountComponentInterface>,
) {
Self::BasicWallet.extract_component(procedures_set, component_interface_vec);
Self::BasicFungibleFaucet.extract_component(procedures_set, component_interface_vec);
Self::NetworkFungibleFaucet.extract_component(procedures_set, component_interface_vec);
Self::AuthSingleSig.extract_component(procedures_set, component_interface_vec);
Self::AuthSingleSigAcl.extract_component(procedures_set, component_interface_vec);
Self::AuthMultisigPsm.extract_component(procedures_set, component_interface_vec);
Self::AuthMultisig.extract_component(procedures_set, component_interface_vec);
Self::AuthNoAuth.extract_component(procedures_set, component_interface_vec);
}
}