Skip to main content

miden_standards/account/interface/
extension.rs

1use alloc::collections::BTreeSet;
2use alloc::vec::Vec;
3
4use miden_protocol::account::{Account, AccountCode, AccountId, AccountProcedureRoot};
5
6use crate::account::components::StandardAccountComponent;
7use crate::account::interface::{AccountComponentInterface, AccountInterface};
8
9// ACCOUNT INTERFACE EXTENSION TRAIT
10// ================================================================================================
11
12/// An extension for [`AccountInterface`] that allows instantiation from higher-level types.
13pub trait AccountInterfaceExt {
14    /// Creates a new [`AccountInterface`] instance from the provided account ID and account code.
15    fn from_code(account_id: AccountId, code: &AccountCode) -> Self;
16
17    /// Creates a new [`AccountInterface`] instance from the provided [`Account`].
18    fn from_account(account: &Account) -> Self;
19}
20
21impl AccountInterfaceExt for AccountInterface {
22    fn from_code(account_id: AccountId, code: &AccountCode) -> Self {
23        let components = AccountComponentInterface::from_procedures(code.procedures());
24        Self::new(account_id, components)
25    }
26
27    fn from_account(account: &Account) -> Self {
28        let components = AccountComponentInterface::from_procedures(account.code().procedures());
29        Self::new(account.id(), components)
30    }
31}
32
33/// An extension for [`AccountComponentInterface`] that allows instantiation from a set of procedure
34/// roots.
35pub trait AccountComponentInterfaceExt {
36    /// Creates a vector of [`AccountComponentInterface`] instances from the provided set of
37    /// procedures.
38    fn from_procedures(procedures: &[AccountProcedureRoot]) -> Vec<AccountComponentInterface>;
39}
40
41impl AccountComponentInterfaceExt for AccountComponentInterface {
42    fn from_procedures(procedures: &[AccountProcedureRoot]) -> Vec<Self> {
43        let mut component_interface_vec = Vec::new();
44
45        // `AccountCode` places the account's authentication procedure at index 0.
46        let auth_procedure = procedures.first().copied();
47
48        let mut procedures = BTreeSet::from_iter(procedures.iter().copied());
49
50        // Standard component interfaces
51        // ----------------------------------------------------------------------------------------
52
53        // Get all available standard components which could be constructed from the
54        // `procedures` map and push them to the `component_interface_vec`
55        StandardAccountComponent::extract_standard_components(
56            &mut procedures,
57            &mut component_interface_vec,
58        );
59
60        // Custom authentication component interface
61        // ----------------------------------------------------------------------------------------
62
63        // If no standard auth interface claimed the authentication procedure, the account
64        // authenticates through a custom component.
65        if !component_interface_vec.iter().any(|component| component.is_auth_component())
66            && let Some(auth_procedure) = auth_procedure
67        {
68            procedures.remove(&auth_procedure);
69            component_interface_vec.push(AccountComponentInterface::CustomAuth(auth_procedure));
70        }
71
72        // Custom component interfaces
73        // ----------------------------------------------------------------------------------------
74
75        // All remaining procedures are put into the custom bucket.
76        if !procedures.is_empty() {
77            component_interface_vec
78                .push(AccountComponentInterface::Custom(procedures.into_iter().collect()));
79        }
80
81        component_interface_vec
82    }
83}