Skip to main content

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