gmsol_utils/
market.rs

1use std::collections::BTreeSet;
2
3use anchor_lang::prelude::{
4    borsh::{BorshDeserialize, BorshSerialize},
5    *,
6};
7
8/// Max number of config flags.
9pub const MAX_MARKET_CONFIG_FLAGS: usize = 128;
10
11/// Max number of market flags.
12pub const MAX_MARKET_FLAGS: usize = 8;
13
14/// Max number of virtual inventory flags.
15pub const MAX_VIRTUAL_INVENTORY_FLAGS: usize = 8;
16
17/// Market error.
18#[derive(Debug, thiserror::Error)]
19pub enum MarketError {
20    /// Not a collateral token.
21    #[error("not a collateral token")]
22    NotACollateralToken,
23}
24
25type MarketResult<T> = std::result::Result<T, MarketError>;
26
27/// Market Metadata.
28#[zero_copy]
29#[derive(BorshSerialize, BorshDeserialize)]
30#[cfg_attr(feature = "debug", derive(Debug))]
31#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
32pub struct MarketMeta {
33    /// Market token.
34    pub market_token_mint: Pubkey,
35    /// Index token.
36    pub index_token_mint: Pubkey,
37    /// Long token.
38    pub long_token_mint: Pubkey,
39    /// Short token.
40    pub short_token_mint: Pubkey,
41}
42
43impl MarketMeta {
44    /// Check if the given token is a valid collateral token.
45    #[inline]
46    pub fn is_collateral_token(&self, token: &Pubkey) -> bool {
47        *token == self.long_token_mint || *token == self.short_token_mint
48    }
49
50    /// Get pnl token.
51    pub fn pnl_token(&self, is_long: bool) -> Pubkey {
52        if is_long {
53            self.long_token_mint
54        } else {
55            self.short_token_mint
56        }
57    }
58
59    /// Check if the given token is long token or short token, and return it's side.
60    pub fn to_token_side(&self, token: &Pubkey) -> MarketResult<bool> {
61        if *token == self.long_token_mint {
62            Ok(true)
63        } else if *token == self.short_token_mint {
64            Ok(false)
65        } else {
66            Err(MarketError::NotACollateralToken)
67        }
68    }
69
70    /// Get opposite token.
71    pub fn opposite_token(&self, token: &Pubkey) -> MarketResult<&Pubkey> {
72        if *token == self.long_token_mint {
73            Ok(&self.short_token_mint)
74        } else if *token == self.short_token_mint {
75            Ok(&self.long_token_mint)
76        } else {
77            Err(MarketError::NotACollateralToken)
78        }
79    }
80
81    /// Get ordered token set.
82    pub fn ordered_tokens(&self) -> BTreeSet<Pubkey> {
83        BTreeSet::from([
84            self.index_token_mint,
85            self.long_token_mint,
86            self.short_token_mint,
87        ])
88    }
89}
90
91/// Type that has market meta.
92pub trait HasMarketMeta {
93    fn market_meta(&self) -> &MarketMeta;
94
95    fn is_pure(&self) -> bool {
96        let meta = self.market_meta();
97        meta.long_token_mint == meta.short_token_mint
98    }
99}
100
101impl HasMarketMeta for MarketMeta {
102    fn market_meta(&self) -> &MarketMeta {
103        self
104    }
105}
106
107/// Get related tokens from markets in order.
108pub fn ordered_tokens(from: &impl HasMarketMeta, to: &impl HasMarketMeta) -> BTreeSet<Pubkey> {
109    let mut tokens = BTreeSet::default();
110
111    let from = from.market_meta();
112    let to = to.market_meta();
113
114    for mint in [
115        &from.index_token_mint,
116        &from.long_token_mint,
117        &from.short_token_mint,
118    ]
119    .iter()
120    .chain(&[
121        &to.index_token_mint,
122        &to.long_token_mint,
123        &to.short_token_mint,
124    ]) {
125        tokens.insert(**mint);
126    }
127    tokens
128}
129
130/// Market Config Flags.
131#[derive(
132    strum::EnumString,
133    strum::Display,
134    Clone,
135    Copy,
136    PartialEq,
137    Eq,
138    PartialOrd,
139    Ord,
140    Hash,
141    num_enum::TryFromPrimitive,
142    num_enum::IntoPrimitive,
143)]
144#[strum(serialize_all = "snake_case")]
145#[cfg_attr(feature = "debug", derive(Debug))]
146#[cfg_attr(feature = "enum-iter", derive(strum::EnumIter))]
147#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
148#[cfg_attr(feature = "clap", clap(rename_all = "snake_case"))]
149#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
150#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
151#[non_exhaustive]
152#[repr(u8)]
153pub enum MarketConfigFlag {
154    /// Skip borrowing fee for smaller side.
155    SkipBorrowingFeeForSmallerSide,
156    /// Ignore open interest for usage factor.
157    IgnoreOpenInterestForUsageFactor,
158    // CHECK: cannot have more than `MAX_CONFIG_FLAGS` flags.
159}
160
161/// Market config keys.
162#[derive(
163    strum::EnumString,
164    strum::Display,
165    Clone,
166    Copy,
167    PartialEq,
168    Eq,
169    PartialOrd,
170    Ord,
171    Hash,
172    num_enum::TryFromPrimitive,
173    num_enum::IntoPrimitive,
174)]
175#[strum(serialize_all = "snake_case")]
176#[cfg_attr(feature = "debug", derive(Debug))]
177#[cfg_attr(feature = "enum-iter", derive(strum::EnumIter))]
178#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
179#[cfg_attr(feature = "clap", clap(rename_all = "snake_case"))]
180#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
181#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
182#[non_exhaustive]
183#[repr(u16)]
184pub enum MarketConfigKey {
185    /// Swap impact exponent.
186    SwapImpactExponent,
187    /// Swap impact positive factor.
188    SwapImpactPositiveFactor,
189    /// Swap impact negative factor.
190    SwapImpactNegativeFactor,
191    /// Swap fee receiver factor.
192    SwapFeeReceiverFactor,
193    /// Swap fee factor for positive impact.
194    SwapFeeFactorForPositiveImpact,
195    /// Swap fee factor for negative impact.
196    SwapFeeFactorForNegativeImpact,
197    /// Min position size usd.
198    MinPositionSizeUsd,
199    /// Min collateral value.
200    MinCollateralValue,
201    /// Min collateral factor.
202    MinCollateralFactor,
203    /// Min collateral factor for open interest multiplier for long.
204    MinCollateralFactorForOpenInterestMultiplierForLong,
205    /// Min collateral factor for open interest multiplier for short.
206    MinCollateralFactorForOpenInterestMultiplierForShort,
207    /// Max positive position impact factor.
208    MaxPositivePositionImpactFactor,
209    /// Max negative position impact factor.
210    MaxNegativePositionImpactFactor,
211    /// Max position impact factor for liquidations.
212    MaxPositionImpactFactorForLiquidations,
213    /// Position impact exponent.
214    PositionImpactExponent,
215    /// Position impact positive factor.
216    PositionImpactPositiveFactor,
217    /// Position impact negative factor.
218    PositionImpactNegativeFactor,
219    /// Order fee receiver factor.
220    OrderFeeReceiverFactor,
221    /// Order fee factor for positive impact.
222    OrderFeeFactorForPositiveImpact,
223    /// Order fee factor for negative impact.
224    OrderFeeFactorForNegativeImpact,
225    /// Liquidation fee receiver factor.
226    LiquidationFeeReceiverFactor,
227    /// Liquidation fee factor.
228    LiquidationFeeFactor,
229    /// Position impact distribute factor.
230    PositionImpactDistributeFactor,
231    /// Min position impact pool amount.
232    MinPositionImpactPoolAmount,
233    /// Borrowing fee receiver factor.
234    BorrowingFeeReceiverFactor,
235    /// Borrowing fee factor for long.
236    BorrowingFeeFactorForLong,
237    /// Borrowing fee factor for short.
238    BorrowingFeeFactorForShort,
239    /// Borrowing fee exponent for long.
240    BorrowingFeeExponentForLong,
241    /// Borrowing fee exponent for short.
242    BorrowingFeeExponentForShort,
243    /// Borrowing fee optimal usage factor for long.
244    BorrowingFeeOptimalUsageFactorForLong,
245    /// Borrowing fee optimal usage factor for short.
246    BorrowingFeeOptimalUsageFactorForShort,
247    /// Borrowing fee base factor for long.
248    BorrowingFeeBaseFactorForLong,
249    /// Borrowing fee base factor for short.
250    BorrowingFeeBaseFactorForShort,
251    /// Borrowing fee above optimal usage factor for long.
252    BorrowingFeeAboveOptimalUsageFactorForLong,
253    /// Borrowing fee above optimal usage factor for short.
254    BorrowingFeeAboveOptimalUsageFactorForShort,
255    /// Funding fee exponent.
256    FundingFeeExponent,
257    /// Funding fee factor.
258    FundingFeeFactor,
259    /// Funding fee max factor per second.
260    FundingFeeMaxFactorPerSecond,
261    /// Funding fee min factor per second.
262    FundingFeeMinFactorPerSecond,
263    /// Funding fee increase factor per second.
264    FundingFeeIncreaseFactorPerSecond,
265    /// Funding fee decrease factor per second.
266    FundingFeeDecreaseFactorPerSecond,
267    /// Funding fee threshold for stable funding.
268    FundingFeeThresholdForStableFunding,
269    /// Funding fee threshold for decrease funding.
270    FundingFeeThresholdForDecreaseFunding,
271    /// Reserve factor.
272    ReserveFactor,
273    /// Open interest reserve factor.
274    OpenInterestReserveFactor,
275    /// Max PNL factor for long deposit.
276    MaxPnlFactorForLongDeposit,
277    /// Max PNL factor for short deposit.
278    MaxPnlFactorForShortDeposit,
279    /// Max PNL factor for long withdrawal.
280    MaxPnlFactorForLongWithdrawal,
281    /// Max PNL factor for short withdrawal.
282    MaxPnlFactorForShortWithdrawal,
283    /// Max PNL factor for long trader.
284    MaxPnlFactorForLongTrader,
285    /// Max PNL factor for short trader.
286    MaxPnlFactorForShortTrader,
287    /// Max PNL factor for long ADL.
288    MaxPnlFactorForLongAdl,
289    /// Max PNL factor for short ADL.
290    MaxPnlFactorForShortAdl,
291    /// Min PNL factor after long ADL.
292    MinPnlFactorAfterLongAdl,
293    /// Min PNL factor after short ADL.
294    MinPnlFactorAfterShortAdl,
295    /// Max pool amount for long token.
296    MaxPoolAmountForLongToken,
297    /// Max pool amount for short token.
298    MaxPoolAmountForShortToken,
299    /// Max pool value for deposit for long token.
300    MaxPoolValueForDepositForLongToken,
301    /// Max pool value for deposit for short token.
302    MaxPoolValueForDepositForShortToken,
303    /// Max open interest for long.
304    MaxOpenInterestForLong,
305    /// Max open interest for short.
306    MaxOpenInterestForShort,
307    /// Min tokens for first deposit.
308    MinTokensForFirstDeposit,
309}
310
311/// Market Flags.
312#[derive(num_enum::IntoPrimitive)]
313#[repr(u8)]
314#[non_exhaustive]
315pub enum MarketFlag {
316    /// Is enabled.
317    Enabled,
318    /// Is Pure.
319    Pure,
320    /// Is auto-deleveraging enabled for long.
321    AutoDeleveragingEnabledForLong,
322    /// Is auto-deleveraging enabled for short.
323    AutoDeleveragingEnabledForShort,
324    /// Is GT minting enabled.
325    GTEnabled,
326    // CHECK: cannot have more than `MAX_MARKET_FLAGS` flags.
327}
328
329/// Virtual Inventory Flags.
330#[derive(num_enum::IntoPrimitive)]
331#[repr(u8)]
332pub enum VirtualInventoryFlag {
333    /// Is disabled.
334    Disabled,
335    // CHECK: cannot have more than `MAX_VIRTUAL_INVENTORY_FLAGS` flags.
336}