Skip to main content

gmsol_utils/
order.rs

1use anchor_lang::prelude::*;
2
3/// Max number of order flags.
4pub const MAX_ORDER_FLAGS: usize = 8;
5
6/// Order Kind.
7#[derive(
8    AnchorSerialize,
9    AnchorDeserialize,
10    Clone,
11    InitSpace,
12    Copy,
13    strum::EnumString,
14    strum::Display,
15    num_enum::IntoPrimitive,
16    num_enum::TryFromPrimitive,
17    Debug,
18)]
19#[strum(serialize_all = "snake_case")]
20#[non_exhaustive]
21#[repr(u8)]
22pub enum OrderKind {
23    /// Liquidation: allows liquidation of positions if the criteria for liquidation are met.
24    Liquidation,
25    /// Auto-deleveraging Order.
26    AutoDeleveraging,
27    /// Swap token A to token B at the current market price.
28    ///
29    /// The order will be cancelled if the `min_output_amount` cannot be fulfilled.
30    MarketSwap,
31    /// Increase position at the current market price.
32    ///
33    /// The order will be cancelled if the position cannot be increased at the acceptable price.
34    MarketIncrease,
35    /// Decrease position at the current market price.
36    ///
37    /// The order will be cancelled if the position cannot be decreased at the acceptable price.
38    MarketDecrease,
39    /// Limit Swap.
40    LimitSwap,
41    /// Limit Increase.
42    LimitIncrease,
43    /// Limit Decrease.
44    LimitDecrease,
45    /// Stop-Loss Decrease.
46    StopLossDecrease,
47}
48
49impl OrderKind {
50    /// Is market order.
51    pub fn is_market(&self) -> bool {
52        matches!(
53            self,
54            Self::MarketSwap | Self::MarketIncrease | Self::MarketDecrease
55        )
56    }
57
58    /// Is swap order.
59    pub fn is_swap(&self) -> bool {
60        matches!(self, Self::MarketSwap | Self::LimitSwap)
61    }
62
63    /// Is increase position order.
64    pub fn is_increase_position(&self) -> bool {
65        matches!(self, Self::LimitIncrease | Self::MarketIncrease)
66    }
67
68    /// Is decrease position order.
69    pub fn is_decrease_position(&self) -> bool {
70        matches!(
71            self,
72            Self::LimitDecrease
73                | Self::MarketDecrease
74                | Self::Liquidation
75                | Self::AutoDeleveraging
76                | Self::StopLossDecrease
77        )
78    }
79
80    /// Is market decrease.
81    pub fn is_market_decrease(&self) -> bool {
82        matches!(self, Self::MarketDecrease)
83    }
84}
85
86/// Order side.
87#[derive(
88    Clone,
89    Copy,
90    strum::EnumString,
91    strum::Display,
92    num_enum::IntoPrimitive,
93    num_enum::TryFromPrimitive,
94)]
95#[strum(serialize_all = "snake_case")]
96#[cfg_attr(feature = "debug", derive(Debug))]
97#[non_exhaustive]
98#[repr(u8)]
99pub enum OrderSide {
100    /// Long.
101    Long,
102    /// Short.
103    Short,
104}
105
106impl OrderSide {
107    /// Return whether the side is long.
108    pub fn is_long(&self) -> bool {
109        matches!(self, Self::Long)
110    }
111}
112
113/// Position Kind.
114#[non_exhaustive]
115#[repr(u8)]
116#[derive(
117    Clone,
118    Copy,
119    num_enum::IntoPrimitive,
120    num_enum::TryFromPrimitive,
121    PartialEq,
122    Eq,
123    strum::EnumString,
124    strum::Display,
125)]
126#[strum(serialize_all = "snake_case")]
127#[cfg_attr(feature = "debug", derive(Debug))]
128#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
129#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
130pub enum PositionKind {
131    /// Uninitialized.
132    Uninitialized,
133    /// Long position.
134    Long,
135    /// Short position.
136    Short,
137}
138
139/// Position Cut Kind.
140#[derive(Clone)]
141#[cfg_attr(feature = "debug", derive(Debug))]
142pub enum PositionCutKind {
143    /// Liquidate.
144    Liquidate,
145    /// AutoDeleverage.
146    AutoDeleverage(u128),
147}
148
149impl PositionCutKind {
150    /// Get size delta.
151    pub fn size_delta_usd(&self, size_in_usd: u128) -> u128 {
152        match self {
153            Self::Liquidate => size_in_usd,
154            Self::AutoDeleverage(delta) => size_in_usd.min(*delta),
155        }
156    }
157
158    /// Convert into [`OrderKind`].
159    pub fn to_order_kind(&self) -> OrderKind {
160        match self {
161            Self::Liquidate => OrderKind::Liquidation,
162            Self::AutoDeleverage(_) => OrderKind::AutoDeleveraging,
163        }
164    }
165}
166
167/// Trade Data Flags.
168#[allow(clippy::enum_variant_names)]
169#[derive(num_enum::IntoPrimitive)]
170#[repr(u8)]
171pub enum TradeFlag {
172    /// Is long.
173    IsLong,
174    /// Is collateral long.
175    IsCollateralLong,
176    /// Is increase.
177    IsIncrease,
178    // CHECK: cannot have more than `8` flags.
179}
180
181crate::flags!(TradeFlag, 8, u8);
182
183/// Order Flags.
184#[repr(u8)]
185#[non_exhaustive]
186#[derive(num_enum::IntoPrimitive, num_enum::TryFromPrimitive)]
187pub enum OrderFlag {
188    /// Whether to keep position account when empty.
189    ShouldKeepPositionAccount,
190    // CHECK: should have no more than `MAX_ORDER_FLAGS` of flags.
191}