use crate::account::state::Abstraction;
use crate::utils::Address;
use crate::utils::sign::{Field, L1Action, Map, NonceKey, UserAction, UserSigned};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AbstractionMode {
Disabled,
UnifiedAccount,
PortfolioMargin,
}
impl AbstractionMode {
pub const ALL: [AbstractionMode; 3] =
[AbstractionMode::Disabled, AbstractionMode::UnifiedAccount, AbstractionMode::PortfolioMargin];
#[must_use]
pub const fn wire(self) -> &'static str {
match self {
AbstractionMode::Disabled => "disabled",
AbstractionMode::UnifiedAccount => "unifiedAccount",
AbstractionMode::PortfolioMargin => "portfolioMargin",
}
}
#[must_use]
pub const fn code(self) -> &'static str {
match self {
AbstractionMode::Disabled => "i",
AbstractionMode::UnifiedAccount => "u",
AbstractionMode::PortfolioMargin => "p",
}
}
#[must_use]
pub fn from_wire(text: &str) -> Option<AbstractionMode> {
AbstractionMode::ALL.into_iter().find(|mode| mode.wire() == text)
}
#[must_use]
pub fn from_code(text: &str) -> Option<AbstractionMode> {
AbstractionMode::ALL.into_iter().find(|mode| mode.code() == text)
}
#[must_use]
pub const fn is_refused_from(self, current: &Abstraction) -> bool {
matches!((current, self), (Abstraction::UnifiedAccount, AbstractionMode::Disabled))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct UserSetAbstraction {
user: Address,
mode: AbstractionMode,
nonce: u64,
}
impl UserSetAbstraction {
#[must_use]
pub const fn new(user: Address, mode: AbstractionMode, nonce: u64) -> UserSetAbstraction {
UserSetAbstraction { user, mode, nonce }
}
}
impl UserAction for UserSetAbstraction {
fn user_signed(&self) -> UserSigned<'_> {
UserSigned::new("userSetAbstraction", "HyperliquidTransaction:UserSetAbstraction", NonceKey::Nonce, self.nonce)
.field("user", Field::Address(self.user))
.field("abstraction", Field::String(self.mode.wire()))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AgentSetAbstraction {
mode: AbstractionMode,
}
impl AgentSetAbstraction {
#[must_use]
pub const fn new(mode: AbstractionMode) -> AgentSetAbstraction {
AgentSetAbstraction { mode }
}
}
impl L1Action for AgentSetAbstraction {
fn action(&self) -> Map {
Map::new().put("type", "agentSetAbstraction").put("abstraction", self.mode.code())
}
}