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    #[non_exhaustive]
29    enum CallMessage<Address> {
30        /// User-facing operations requiring account ownership.
31        ///
32        /// Auth: `context.sender()` or resolved delegate
33        User(UserAction<Address>) = 0,
34
35        /// Vault management operations requiring vault leadership.
36        ///
37        /// Auth: `vault.leader() == context.sender()`
38        Vault(VaultAction<Address>) = 1,
39
40        /// Keeper operations requiring specific admin privileges.
41        ///
42        /// Auth: Specific admin type (Pricing, Funding, Credits, FeeTier, Referrals)
43        Keeper(KeeperAction<Address>) = 2,
44
45        /// Permissionless operations anyone can call.
46        ///
47        /// Auth: None (permissionless)
48        Public(PublicAction<Address>) = 3,
49
50        /// Protocol admin operations.
51        ///
52        /// Auth: Protocol admin
53        Admin(AdminAction<Address>) = 4,
54    }
55}
56
57impl<Address> CallMessage<Address> {
58    pub fn msg_type(&self) -> String {
59        match self {
60            Self::User(x) => format!("User/{}", x.as_ref()),
61            Self::Vault(x) => format!("Vault/{}", x.as_ref()),
62            Self::Keeper(x) => format!("Keeper/{}", x.as_ref()),
63            Self::Public(x) => format!("Public/{}", x.as_ref()),
64            Self::Admin(x) => format!("Admin/{}", x.as_ref()),
65        }
66    }
67}
68
69impl<Address> From<UserAction<Address>> for CallMessage<Address> {
70    fn from(v: UserAction<Address>) -> Self {
71        Self::User(v)
72    }
73}
74impl<Address> From<VaultAction<Address>> for CallMessage<Address> {
75    fn from(v: VaultAction<Address>) -> Self {
76        Self::Vault(v)
77    }
78}
79impl<Address> From<KeeperAction<Address>> for CallMessage<Address> {
80    fn from(v: KeeperAction<Address>) -> Self {
81        Self::Keeper(v)
82    }
83}
84impl<Address> From<PublicAction<Address>> for CallMessage<Address> {
85    fn from(v: PublicAction<Address>) -> Self {
86        Self::Public(v)
87    }
88}
89impl<Address> From<AdminAction<Address>> for CallMessage<Address> {
90    fn from(v: AdminAction<Address>) -> Self {
91        Self::Admin(v)
92    }
93}
94
95#[test]
96fn test_msg_type() {
97    assert_eq!(
98        "User/CreateSubAccount",
99        CallMessage::<crate::address::Address>::User(UserAction::CreateSubAccount { index: 0 })
100            .msg_type()
101    );
102}