use alloc::vec::Vec;
use miden_protocol::account::{AccountComponent, AccountProcedureRoot};
use miden_protocol::asset::AssetAmount;
use thiserror::Error;
mod allow_all;
mod min_burn_amount;
mod owner_only;
pub use allow_all::BurnAllowAll;
pub use min_burn_amount::MinBurnAmount;
pub use owner_only::BurnOwnerOnly;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
pub enum BurnPolicyError {
#[error(
"custom burn policy root must match a procedure root in one of the provided components"
)]
RootNotInComponents,
}
#[derive(Debug, Clone)]
pub struct BurnPolicy {
root: AccountProcedureRoot,
components: Vec<AccountComponent>,
}
impl BurnPolicy {
pub fn allow_all() -> Self {
Self {
root: BurnAllowAll::root(),
components: vec![BurnAllowAll.into()],
}
}
pub fn owner_only() -> Self {
Self {
root: BurnOwnerOnly::root(),
components: vec![BurnOwnerOnly.into()],
}
}
pub fn min_burn_amount(min_burn_amount: AssetAmount) -> Self {
Self {
root: MinBurnAmount::root(),
components: vec![MinBurnAmount::new(min_burn_amount).into()],
}
}
pub fn custom<I>(root: AccountProcedureRoot, components: I) -> Result<Self, BurnPolicyError>
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(BurnPolicyError::RootNotInComponents);
}
Ok(Self { root, components })
}
pub fn root(&self) -> AccountProcedureRoot {
self.root
}
}
impl Default for BurnPolicy {
fn default() -> Self {
Self::allow_all()
}
}
impl IntoIterator for BurnPolicy {
type Item = AccountComponent;
type IntoIter = alloc::vec::IntoIter<AccountComponent>;
fn into_iter(self) -> Self::IntoIter {
self.components.into_iter()
}
}