use alloc::vec::Vec;
use miden_protocol::account::{AccountComponent, AccountId, AccountProcedureRoot};
use thiserror::Error;
mod allow_all;
mod allowlist;
mod basic_allowlist;
mod basic_blocklist;
mod blocklist;
pub use allow_all::TransferAllowAll;
pub use allowlist::{AllowlistOwnerControlled, AllowlistStorage};
pub use basic_allowlist::BasicAllowlist;
pub use basic_blocklist::BasicBlocklist;
pub use blocklist::{BlocklistOwnerControlled, BlocklistStorage};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
pub enum TransferPolicyError {
#[error(
"custom transfer policy root must match a procedure root in one of the provided components"
)]
RootNotInComponents,
}
#[derive(Debug, Clone)]
pub struct TransferPolicy {
root: AccountProcedureRoot,
components: Vec<AccountComponent>,
}
impl TransferPolicy {
pub fn allow_all() -> Self {
Self {
root: TransferAllowAll::root(),
components: vec![TransferAllowAll.into()],
}
}
pub fn empty_basic_blocklist() -> Self {
Self {
root: BasicBlocklist::root(),
components: vec![BasicBlocklist::default().into()],
}
}
pub fn with_basic_blocklist<I>(blocked_accounts: I) -> Self
where
I: IntoIterator<Item = AccountId>,
{
Self {
root: BasicBlocklist::root(),
components: vec![BasicBlocklist::with_blocked_accounts(blocked_accounts).into()],
}
}
pub fn empty_basic_allowlist() -> Self {
Self {
root: BasicAllowlist::root(),
components: vec![BasicAllowlist::default().into()],
}
}
pub fn with_basic_allowlist(allow_list: AllowlistStorage) -> Self {
Self {
root: BasicAllowlist::root(),
components: vec![BasicAllowlist::from(allow_list).into()],
}
}
pub fn custom<I>(root: AccountProcedureRoot, components: I) -> Result<Self, TransferPolicyError>
where
I: IntoIterator,
I::Item: Into<AccountComponent>,
{
let components: Vec<AccountComponent> = components.into_iter().map(Into::into).collect();
if !components.iter().any(|component| component.has_procedure(root)) {
return Err(TransferPolicyError::RootNotInComponents);
}
Ok(Self { root, components })
}
pub fn root(&self) -> AccountProcedureRoot {
self.root
}
}
impl Default for TransferPolicy {
fn default() -> Self {
Self::allow_all()
}
}
impl IntoIterator for TransferPolicy {
type Item = AccountComponent;
type IntoIter = alloc::vec::IntoIter<AccountComponent>;
fn into_iter(self) -> Self::IntoIter {
self.components.into_iter()
}
}