1use std::collections::BTreeSet;
2
3use anchor_lang::prelude::{
4 borsh::{BorshDeserialize, BorshSerialize},
5 *,
6};
7
8pub const MAX_MARKET_CONFIG_FLAGS: usize = 128;
10
11#[derive(Debug, thiserror::Error)]
13pub enum MarketError {
14 #[error("not a collateral token")]
16 NotACollateralToken,
17}
18
19type MarketResult<T> = std::result::Result<T, MarketError>;
20
21#[zero_copy]
23#[derive(BorshSerialize, BorshDeserialize)]
24#[cfg_attr(feature = "debug", derive(Debug))]
25#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
26pub struct MarketMeta {
27 pub market_token_mint: Pubkey,
29 pub index_token_mint: Pubkey,
31 pub long_token_mint: Pubkey,
33 pub short_token_mint: Pubkey,
35}
36
37impl MarketMeta {
38 #[inline]
40 pub fn is_collateral_token(&self, token: &Pubkey) -> bool {
41 *token == self.long_token_mint || *token == self.short_token_mint
42 }
43
44 pub fn pnl_token(&self, is_long: bool) -> Pubkey {
46 if is_long {
47 self.long_token_mint
48 } else {
49 self.short_token_mint
50 }
51 }
52
53 pub fn to_token_side(&self, token: &Pubkey) -> MarketResult<bool> {
55 if *token == self.long_token_mint {
56 Ok(true)
57 } else if *token == self.short_token_mint {
58 Ok(false)
59 } else {
60 Err(MarketError::NotACollateralToken)
61 }
62 }
63
64 pub fn opposite_token(&self, token: &Pubkey) -> MarketResult<&Pubkey> {
66 if *token == self.long_token_mint {
67 Ok(&self.short_token_mint)
68 } else if *token == self.short_token_mint {
69 Ok(&self.long_token_mint)
70 } else {
71 Err(MarketError::NotACollateralToken)
72 }
73 }
74
75 pub fn ordered_tokens(&self) -> BTreeSet<Pubkey> {
77 BTreeSet::from([
78 self.index_token_mint,
79 self.long_token_mint,
80 self.short_token_mint,
81 ])
82 }
83}
84
85pub trait HasMarketMeta {
87 fn market_meta(&self) -> &MarketMeta;
88
89 fn is_pure(&self) -> bool {
90 let meta = self.market_meta();
91 meta.long_token_mint == meta.short_token_mint
92 }
93}
94
95impl HasMarketMeta for MarketMeta {
96 fn market_meta(&self) -> &MarketMeta {
97 self
98 }
99}
100
101pub fn ordered_tokens(from: &impl HasMarketMeta, to: &impl HasMarketMeta) -> BTreeSet<Pubkey> {
103 let mut tokens = BTreeSet::default();
104
105 let from = from.market_meta();
106 let to = to.market_meta();
107
108 for mint in [
109 &from.index_token_mint,
110 &from.long_token_mint,
111 &from.short_token_mint,
112 ]
113 .iter()
114 .chain(&[
115 &to.index_token_mint,
116 &to.long_token_mint,
117 &to.short_token_mint,
118 ]) {
119 tokens.insert(**mint);
120 }
121 tokens
122}
123
124#[derive(
126 strum::EnumString,
127 strum::Display,
128 Clone,
129 Copy,
130 PartialEq,
131 Eq,
132 PartialOrd,
133 Ord,
134 Hash,
135 num_enum::TryFromPrimitive,
136 num_enum::IntoPrimitive,
137)]
138#[strum(serialize_all = "snake_case")]
139#[cfg_attr(feature = "debug", derive(Debug))]
140#[cfg_attr(feature = "enum-iter", derive(strum::EnumIter))]
141#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
142#[cfg_attr(feature = "clap", clap(rename_all = "snake_case"))]
143#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
144#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
145#[non_exhaustive]
146#[repr(u8)]
147pub enum MarketConfigFlag {
148 SkipBorrowingFeeForSmallerSide,
150 IgnoreOpenInterestForUsageFactor,
152 }
154
155#[derive(
157 strum::EnumString,
158 strum::Display,
159 Clone,
160 Copy,
161 PartialEq,
162 Eq,
163 PartialOrd,
164 Ord,
165 Hash,
166 num_enum::TryFromPrimitive,
167 num_enum::IntoPrimitive,
168)]
169#[strum(serialize_all = "snake_case")]
170#[cfg_attr(feature = "debug", derive(Debug))]
171#[cfg_attr(feature = "enum-iter", derive(strum::EnumIter))]
172#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
173#[cfg_attr(feature = "clap", clap(rename_all = "snake_case"))]
174#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
175#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
176#[non_exhaustive]
177#[repr(u16)]
178pub enum MarketConfigKey {
179 SwapImpactExponent,
181 SwapImpactPositiveFactor,
183 SwapImpactNegativeFactor,
185 SwapFeeReceiverFactor,
187 SwapFeeFactorForPositiveImpact,
189 SwapFeeFactorForNegativeImpact,
191 MinPositionSizeUsd,
193 MinCollateralValue,
195 MinCollateralFactor,
197 MinCollateralFactorForOpenInterestMultiplierForLong,
199 MinCollateralFactorForOpenInterestMultiplierForShort,
201 MaxPositivePositionImpactFactor,
203 MaxNegativePositionImpactFactor,
205 MaxPositionImpactFactorForLiquidations,
207 PositionImpactExponent,
209 PositionImpactPositiveFactor,
211 PositionImpactNegativeFactor,
213 OrderFeeReceiverFactor,
215 OrderFeeFactorForPositiveImpact,
217 OrderFeeFactorForNegativeImpact,
219 LiquidationFeeReceiverFactor,
221 LiquidationFeeFactor,
223 PositionImpactDistributeFactor,
225 MinPositionImpactPoolAmount,
227 BorrowingFeeReceiverFactor,
229 BorrowingFeeFactorForLong,
231 BorrowingFeeFactorForShort,
233 BorrowingFeeExponentForLong,
235 BorrowingFeeExponentForShort,
237 BorrowingFeeOptimalUsageFactorForLong,
239 BorrowingFeeOptimalUsageFactorForShort,
241 BorrowingFeeBaseFactorForLong,
243 BorrowingFeeBaseFactorForShort,
245 BorrowingFeeAboveOptimalUsageFactorForLong,
247 BorrowingFeeAboveOptimalUsageFactorForShort,
249 FundingFeeExponent,
251 FundingFeeFactor,
253 FundingFeeMaxFactorPerSecond,
255 FundingFeeMinFactorPerSecond,
257 FundingFeeIncreaseFactorPerSecond,
259 FundingFeeDecreaseFactorPerSecond,
261 FundingFeeThresholdForStableFunding,
263 FundingFeeThresholdForDecreaseFunding,
265 ReserveFactor,
267 OpenInterestReserveFactor,
269 MaxPnlFactorForLongDeposit,
271 MaxPnlFactorForShortDeposit,
273 MaxPnlFactorForLongWithdrawal,
275 MaxPnlFactorForShortWithdrawal,
277 MaxPnlFactorForLongTrader,
279 MaxPnlFactorForShortTrader,
281 MaxPnlFactorForLongAdl,
283 MaxPnlFactorForShortAdl,
285 MinPnlFactorAfterLongAdl,
287 MinPnlFactorAfterShortAdl,
289 MaxPoolAmountForLongToken,
291 MaxPoolAmountForShortToken,
293 MaxPoolValueForDepositForLongToken,
295 MaxPoolValueForDepositForShortToken,
297 MaxOpenInterestForLong,
299 MaxOpenInterestForShort,
301 MinTokensForFirstDeposit,
303}