Skip to main content

bullet_exchange_interface/message/
mod.rs

1//! Exchange call message types - nested enum with role-based categorization.
2//!
3//! # Adding New Operations
4//!
5//! 1. Determine the role/category: Who is authorized to call this operation?
6//!    - User? Vault leader? Specific admin? Anyone?
7//! 2. Add the variant to the appropriate *Action enum
8//! 3. Choose a NEVER used explicit discriminant: `NewOperation { ... } = N,`
9//! 4. Add handler function and update dispatch
10//! 5. NEVER change existing discriminants, reorder variants/fields, change types
11
12use crate::define_enum;
13
14mod admin;
15mod keeper;
16mod public;
17mod user;
18mod vault;
19
20pub use self::admin::*;
21pub use self::keeper::*;
22pub use self::public::*;
23pub use self::user::*;
24pub use self::vault::*;
25
26define_enum! {
27    /// Top-level call message enum organized by authorization role.
28    enum CallMessage<Address> {
29        /// User-facing operations requiring account ownership.
30        ///
31        /// Auth: `context.sender()` or resolved delegate
32        User(UserAction<Address>) = 0,
33
34        /// Vault management operations requiring vault leadership.
35        ///
36        /// Auth: `vault.leader() == context.sender()`
37        Vault(VaultAction<Address>) = 1,
38
39        /// Keeper operations requiring specific admin privileges.
40        ///
41        /// Auth: Specific admin type (Pricing, Funding, Credits, FeeTier, Referrals)
42        Keeper(KeeperAction<Address>) = 2,
43
44        /// Permissionless operations anyone can call.
45        ///
46        /// Auth: None (permissionless)
47        Public(PublicAction<Address>) = 3,
48
49        /// Protocol admin operations.
50        ///
51        /// Auth: Protocol admin
52        Admin(AdminAction<Address>) = 4,
53    }
54}
55
56impl<Address> CallMessage<Address> {
57    pub fn msg_type(&self) -> String {
58        match self {
59            Self::User(x) => format!("User/{}", x.as_ref()),
60            Self::Vault(x) => format!("Vault/{}", x.as_ref()),
61            Self::Keeper(x) => format!("Keeper/{}", x.as_ref()),
62            Self::Public(x) => format!("Public/{}", x.as_ref()),
63            Self::Admin(x) => format!("Admin/{}", x.as_ref()),
64        }
65    }
66}
67
68impl<Address> From<UserAction<Address>> for CallMessage<Address> {
69    fn from(v: UserAction<Address>) -> Self {
70        Self::User(v)
71    }
72}
73impl<Address> From<VaultAction<Address>> for CallMessage<Address> {
74    fn from(v: VaultAction<Address>) -> Self {
75        Self::Vault(v)
76    }
77}
78impl<Address> From<KeeperAction<Address>> for CallMessage<Address> {
79    fn from(v: KeeperAction<Address>) -> Self {
80        Self::Keeper(v)
81    }
82}
83impl<Address> From<PublicAction<Address>> for CallMessage<Address> {
84    fn from(v: PublicAction<Address>) -> Self {
85        Self::Public(v)
86    }
87}
88impl<Address> From<AdminAction<Address>> for CallMessage<Address> {
89    fn from(v: AdminAction<Address>) -> Self {
90        Self::Admin(v)
91    }
92}
93
94#[test]
95fn test_msg_type() {
96    assert_eq!(
97        "User/CreateSubAccount",
98        CallMessage::<crate::address::Address>::User(UserAction::CreateSubAccount { index: 0 })
99            .msg_type()
100    );
101}