1use std::str::FromStr;
29
30use anchor_lang::{prelude::*, Bump};
31use anchor_spl::token::Mint;
32use borsh::{BorshDeserialize, BorshSerialize};
33use config::MarketConfigFlag;
34use gmsol_model::{price::Prices, ClockKind, PoolKind};
35use gmsol_utils::market::MarketError;
36use revertible::RevertibleBuffer;
37
38use crate::{
39 utils::fixed_str::{bytes_to_fixed_str, fixed_str_to_bytes},
40 CoreError,
41};
42
43use super::{Factor, InitSpace, Oracle, Seed};
44
45use self::{
46 config::{MarketConfig, MarketConfigBuffer, MarketConfigKey},
47 pool::{Pool, Pools},
48};
49
50pub use gmsol_utils::market::{HasMarketMeta, MarketMeta};
51pub use model::AsLiquidityMarket;
52
53pub mod utils;
55
56pub mod clock;
58
59pub mod config;
61
62pub mod revertible;
64
65pub mod pool;
67
68pub mod status;
70
71mod model;
72
73pub const MAX_FLAGS: usize = 8;
75
76const MAX_NAME_LEN: usize = 64;
77
78#[account(zero_copy)]
80#[cfg_attr(feature = "debug", derive(Debug))]
81#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
82pub struct Market {
83 version: u8,
84 pub(crate) bump: u8,
86 flags: MarketFlagContainer,
87 padding: [u8; 13],
88 #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
89 name: [u8; MAX_NAME_LEN],
90 pub(crate) meta: MarketMeta,
91 pub store: Pubkey,
93 config: MarketConfig,
94 indexer: Indexer,
95 state: State,
96 buffer: RevertibleBuffer,
97 #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
98 reserved: [u8; 256],
99}
100
101#[zero_copy]
102#[cfg_attr(feature = "debug", derive(derive_more::Debug))]
103#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
104struct State {
105 pools: Pools,
106 clocks: Clocks,
107 other: OtherState,
108 #[cfg_attr(feature = "debug", debug(skip))]
109 #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
110 reserved: [u8; 1024],
111}
112
113impl Bump for Market {
114 fn seed(&self) -> u8 {
115 self.bump
116 }
117}
118
119impl Seed for Market {
120 const SEED: &'static [u8] = b"market";
121}
122
123impl InitSpace for Market {
124 const INIT_SPACE: usize = std::mem::size_of::<Self>();
125}
126
127impl Default for Market {
128 fn default() -> Self {
129 use bytemuck::Zeroable;
130 Self::zeroed()
131 }
132}
133
134impl AsRef<Market> for Market {
135 fn as_ref(&self) -> &Market {
136 self
137 }
138}
139
140impl Market {
141 pub fn find_market_address(
143 store: &Pubkey,
144 token: &Pubkey,
145 store_program_id: &Pubkey,
146 ) -> (Pubkey, u8) {
147 Pubkey::find_program_address(
148 &[Self::SEED, store.as_ref(), token.as_ref()],
149 store_program_id,
150 )
151 }
152
153 #[allow(clippy::too_many_arguments)]
155 pub fn init(
156 &mut self,
157 bump: u8,
158 store: Pubkey,
159 name: &str,
160 market_token_mint: Pubkey,
161 index_token_mint: Pubkey,
162 long_token_mint: Pubkey,
163 short_token_mint: Pubkey,
164 is_enabled: bool,
165 ) -> Result<()> {
166 self.bump = bump;
167 self.store = store;
168 self.name = fixed_str_to_bytes(name)?;
169 self.set_enabled(is_enabled);
170 self.meta.market_token_mint = market_token_mint;
171 self.meta.index_token_mint = index_token_mint;
172 self.meta.long_token_mint = long_token_mint;
173 self.meta.short_token_mint = short_token_mint;
174 let is_pure = self.meta.long_token_mint == self.meta.short_token_mint;
175 self.set_flag(MarketFlag::Pure, is_pure);
176 self.state.pools.init(is_pure);
177 self.state.clocks.init_to_current()?;
178 self.config.init();
179
180 self.buffer.init();
182 Ok(())
183 }
184
185 pub fn meta(&self) -> &MarketMeta {
187 &self.meta
188 }
189
190 pub fn validated_meta(&self, store: &Pubkey) -> Result<&MarketMeta> {
192 self.validate(store)?;
193 Ok(self.meta())
194 }
195
196 pub fn name(&self) -> Result<&str> {
198 bytes_to_fixed_str(&self.name)
199 }
200
201 pub fn description(&self) -> Result<String> {
203 let name = self.name()?;
204 Ok(format!(
205 "Market {{ name = {name}, token = {}}}",
206 self.meta.market_token_mint
207 ))
208 }
209
210 pub fn flag(&self, flag: MarketFlag) -> bool {
212 self.flags.get_flag(flag)
213 }
214
215 pub fn set_flag(&mut self, flag: MarketFlag, value: bool) -> bool {
219 self.flags.set_flag(flag, value)
220 }
221
222 pub fn is_pure(&self) -> bool {
224 self.flag(MarketFlag::Pure)
225 }
226
227 pub fn is_enabled(&self) -> bool {
229 self.flag(MarketFlag::Enabled)
230 }
231
232 pub fn set_enabled(&mut self, enabled: bool) -> bool {
236 self.set_flag(MarketFlag::Enabled, enabled)
237 }
238
239 pub fn is_adl_enabled(&self, is_long: bool) -> bool {
241 if is_long {
242 self.flag(MarketFlag::AutoDeleveragingEnabledForLong)
243 } else {
244 self.flag(MarketFlag::AutoDeleveragingEnabledForShort)
245 }
246 }
247
248 pub fn set_adl_enabled(&mut self, is_long: bool, enabled: bool) -> bool {
252 if is_long {
253 self.set_flag(MarketFlag::AutoDeleveragingEnabledForLong, enabled)
254 } else {
255 self.set_flag(MarketFlag::AutoDeleveragingEnabledForShort, enabled)
256 }
257 }
258
259 pub fn is_gt_minting_enabled(&self) -> bool {
261 self.flag(MarketFlag::GTEnabled)
262 }
263
264 pub fn set_is_gt_minting_enbaled(&mut self, enabled: bool) -> bool {
268 self.set_flag(MarketFlag::GTEnabled, enabled)
269 }
270
271 #[inline]
273 pub fn pool(&self, kind: PoolKind) -> Option<Pool> {
274 self.state.pools.get(kind).map(|s| s.pool()).copied()
275 }
276
277 pub fn try_pool(&self, kind: PoolKind) -> gmsol_model::Result<&Pool> {
279 Ok(self
280 .state
281 .pools
282 .get(kind)
283 .ok_or(gmsol_model::Error::MissingPoolKind(kind))?
284 .pool())
285 }
286
287 pub fn clock(&self, kind: ClockKind) -> Option<i64> {
289 self.state.clocks.get(kind).copied()
290 }
291
292 fn clocks(&self) -> &Clocks {
293 &self.state.clocks
294 }
295
296 pub fn validate(&self, store: &Pubkey) -> Result<()> {
298 require_keys_eq!(*store, self.store, CoreError::StoreMismatched);
299 require!(self.is_enabled(), CoreError::DisabledMarket);
300 Ok(())
301 }
302
303 pub fn get_config(&self, key: &str) -> Result<&Factor> {
305 let key = MarketConfigKey::from_str(key)
306 .map_err(|_| error!(CoreError::InvalidMarketConfigKey))?;
307 self.get_config_by_key(key)
308 .ok_or_else(|| error!(CoreError::Unimplemented))
309 }
310
311 #[inline]
313 pub fn get_config_by_key(&self, key: MarketConfigKey) -> Option<&Factor> {
314 self.config.get(key)
315 }
316
317 pub fn get_config_mut(&mut self, key: &str) -> Result<&mut Factor> {
319 let key = MarketConfigKey::from_str(key)
320 .map_err(|_| error!(CoreError::InvalidMarketConfigKey))?;
321 self.config
322 .get_mut(key)
323 .ok_or_else(|| error!(CoreError::Unimplemented))
324 }
325
326 pub fn get_config_flag(&self, key: &str) -> Result<bool> {
328 let key = MarketConfigFlag::from_str(key)
329 .map_err(|_| error!(CoreError::InvalidMarketConfigKey))?;
330 Ok(self.get_config_flag_by_key(key))
331 }
332
333 #[inline]
335 pub fn get_config_flag_by_key(&self, key: MarketConfigFlag) -> bool {
336 self.config.flag(key)
337 }
338
339 pub fn set_config_flag(&mut self, key: &str, value: bool) -> Result<bool> {
343 let key = MarketConfigFlag::from_str(key)
344 .map_err(|_| error!(CoreError::InvalidMarketConfigKey))?;
345 Ok(self.config.set_flag(key, value))
346 }
347
348 pub fn state(&self) -> &OtherState {
350 &self.state.other
351 }
352
353 pub fn indexer(&self) -> &Indexer {
355 &self.indexer
356 }
357
358 pub fn indexer_mut(&mut self) -> &mut Indexer {
360 &mut self.indexer
361 }
362
363 pub fn update_config_with_buffer(&mut self, buffer: &MarketConfigBuffer) -> Result<()> {
365 for entry in buffer.iter() {
366 let key = entry.key()?;
367 let current_value = self
368 .config
369 .get_mut(key)
370 .ok_or_else(|| error!(CoreError::Unimplemented))?;
371 let new_value = entry.value();
372 *current_value = new_value;
373 }
374 Ok(())
375 }
376
377 pub fn prices(&self, oracle: &Oracle) -> Result<Prices<u128>> {
379 oracle.market_prices(self)
380 }
381
382 pub fn max_pool_value_for_deposit(&self, is_long_token: bool) -> gmsol_model::Result<Factor> {
384 if is_long_token {
385 Ok(self.config.max_pool_value_for_deposit_for_long_token)
386 } else {
387 Ok(self.config.max_pool_value_for_deposit_for_short_token)
388 }
389 }
390
391 pub fn as_liquidity_market<'a>(
393 &'a self,
394 market_token: &'a Mint,
395 ) -> AsLiquidityMarket<'a, Self> {
396 AsLiquidityMarket::new(self, market_token)
397 }
398
399 pub fn validate_shiftable(&self, target: &Self) -> Result<()> {
401 require_keys_eq!(
408 self.meta().long_token_mint,
409 target.meta().long_token_mint,
410 CoreError::TokenMintMismatched,
411 );
412
413 require_keys_eq!(
414 self.meta().short_token_mint,
415 target.meta().short_token_mint,
416 CoreError::TokenMintMismatched,
417 );
418
419 Ok(())
420 }
421}
422
423#[derive(num_enum::IntoPrimitive)]
425#[repr(u8)]
426pub enum MarketFlag {
427 Enabled,
429 Pure,
431 AutoDeleveragingEnabledForLong,
433 AutoDeleveragingEnabledForShort,
435 GTEnabled,
437 }
439
440gmsol_utils::flags!(MarketFlag, MAX_FLAGS, u8);
441
442#[zero_copy]
444#[derive(BorshSerialize, BorshDeserialize, InitSpace)]
445#[cfg_attr(feature = "debug", derive(derive_more::Debug))]
446#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
447pub struct OtherState {
448 #[cfg_attr(feature = "debug", debug(skip))]
449 padding: [u8; 16],
450 rev: u64,
451 trade_count: u64,
452 long_token_balance: u64,
453 short_token_balance: u64,
454 funding_factor_per_second: i128,
455 #[cfg_attr(feature = "debug", debug(skip))]
456 #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
457 reserved: [u8; 256],
458}
459
460impl OtherState {
461 pub fn long_token_balance_raw(&self) -> u64 {
463 self.long_token_balance
464 }
465
466 pub fn short_token_balance_raw(&self) -> u64 {
468 self.short_token_balance
469 }
470
471 pub fn funding_factor_per_second(&self) -> i128 {
473 self.funding_factor_per_second
474 }
475
476 pub fn trade_count(&self) -> u64 {
478 self.trade_count
479 }
480
481 pub fn next_trade_id(&mut self) -> Result<u64> {
483 let next_id = self
484 .trade_count
485 .checked_add(1)
486 .ok_or_else(|| error!(CoreError::TokenAmountOverflow))?;
487 self.trade_count = next_id;
488 Ok(next_id)
489 }
490}
491
492impl HasMarketMeta for Market {
493 fn is_pure(&self) -> bool {
494 self.is_pure()
495 }
496
497 fn market_meta(&self) -> &MarketMeta {
498 &self.meta
499 }
500}
501
502#[zero_copy]
504#[derive(BorshSerialize, BorshDeserialize, InitSpace)]
505#[cfg_attr(feature = "debug", derive(derive_more::Debug))]
506#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
507pub struct Clocks {
508 #[cfg_attr(feature = "debug", debug(skip))]
509 padding: [u8; 8],
510 rev: u64,
511 price_impact_distribution: i64,
513 borrowing: i64,
515 funding: i64,
517 adl_for_long: i64,
519 adl_for_short: i64,
521 #[cfg_attr(feature = "debug", debug(skip))]
522 reserved: [i64; 3],
523}
524
525impl Clocks {
526 fn init_to_current(&mut self) -> Result<()> {
527 let current = Clock::get()?.unix_timestamp;
528 self.price_impact_distribution = current;
529 self.borrowing = current;
530 self.funding = current;
531 Ok(())
532 }
533
534 fn get(&self, kind: ClockKind) -> Option<&i64> {
535 let clock = match kind {
536 ClockKind::PriceImpactDistribution => &self.price_impact_distribution,
537 ClockKind::Borrowing => &self.borrowing,
538 ClockKind::Funding => &self.funding,
539 ClockKind::AdlForLong => &self.adl_for_long,
540 ClockKind::AdlForShort => &self.adl_for_short,
541 _ => return None,
542 };
543 Some(clock)
544 }
545
546 fn get_mut(&mut self, kind: ClockKind) -> Option<&mut i64> {
547 let clock = match kind {
548 ClockKind::PriceImpactDistribution => &mut self.price_impact_distribution,
549 ClockKind::Borrowing => &mut self.borrowing,
550 ClockKind::Funding => &mut self.funding,
551 ClockKind::AdlForLong => &mut self.adl_for_long,
552 ClockKind::AdlForShort => &mut self.adl_for_short,
553 _ => return None,
554 };
555 Some(clock)
556 }
557}
558
559#[zero_copy]
561#[cfg_attr(feature = "debug", derive(derive_more::Debug))]
562#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
563pub struct Indexer {
564 trade_count: u64,
565 deposit_count: u64,
566 withdrawal_count: u64,
567 order_count: u64,
568 shift_count: u64,
569 glv_deposit_count: u64,
570 glv_withdrawal_count: u64,
571 #[cfg_attr(feature = "debug", debug(skip))]
572 padding_0: [u8; 8],
573 #[cfg_attr(feature = "debug", debug(skip))]
574 #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
575 reserved: [u8; 128],
576}
577
578impl Indexer {
579 pub fn deposit_count(&self) -> u64 {
581 self.deposit_count
582 }
583
584 pub fn withdrawal_count(&self) -> u64 {
586 self.withdrawal_count
587 }
588
589 pub fn order_count(&self) -> u64 {
591 self.order_count
592 }
593
594 pub fn shift_count(&self) -> u64 {
596 self.shift_count
597 }
598
599 pub fn glv_deposit_count(&self) -> u64 {
601 self.glv_deposit_count
602 }
603
604 pub fn glv_withdrawal_count(&self) -> u64 {
606 self.glv_withdrawal_count
607 }
608
609 pub fn next_deposit_id(&mut self) -> Result<u64> {
611 let next_id = self
612 .deposit_count
613 .checked_add(1)
614 .ok_or_else(|| error!(CoreError::TokenAmountOverflow))?;
615 self.deposit_count = next_id;
616 Ok(next_id)
617 }
618
619 pub fn next_withdrawal_id(&mut self) -> Result<u64> {
621 let next_id = self
622 .withdrawal_count
623 .checked_add(1)
624 .ok_or_else(|| error!(CoreError::TokenAmountOverflow))?;
625 self.withdrawal_count = next_id;
626 Ok(next_id)
627 }
628
629 pub fn next_order_id(&mut self) -> Result<u64> {
631 let next_id = self
632 .order_count
633 .checked_add(1)
634 .ok_or_else(|| error!(CoreError::TokenAmountOverflow))?;
635 self.order_count = next_id;
636 Ok(next_id)
637 }
638
639 pub fn next_shift_id(&mut self) -> Result<u64> {
641 let next_id = self
642 .shift_count
643 .checked_add(1)
644 .ok_or_else(|| error!(CoreError::TokenAmountOverflow))?;
645 self.shift_count = next_id;
646 Ok(next_id)
647 }
648
649 pub fn next_glv_deposit_id(&mut self) -> Result<u64> {
651 let next_id = self
652 .glv_deposit_count
653 .checked_add(1)
654 .ok_or_else(|| error!(CoreError::TokenAmountOverflow))?;
655 self.glv_deposit_count = next_id;
656 Ok(next_id)
657 }
658
659 pub fn next_glv_withdrawal_id(&mut self) -> Result<u64> {
661 let next_id = self
662 .glv_withdrawal_count
663 .checked_add(1)
664 .ok_or_else(|| error!(CoreError::TokenAmountOverflow))?;
665 self.glv_withdrawal_count = next_id;
666 Ok(next_id)
667 }
668}
669
670impl From<MarketError> for CoreError {
671 fn from(err: MarketError) -> Self {
672 msg!("Market Error: {}", err);
673 match err {
674 MarketError::NotACollateralToken => Self::InvalidArgument,
675 }
676 }
677}
678
679#[cfg(test)]
680mod tests {
681 use super::*;
682 use crate::events::{EventClocks, EventOtherState};
683
684 #[test]
685 fn test_event_clocks() {
686 let clocks = Clocks {
687 padding: Default::default(),
688 rev: u64::MAX,
689 price_impact_distribution: i64::MAX,
690 borrowing: i64::MAX,
691 funding: i64::MAX,
692 adl_for_long: i64::MAX,
693 adl_for_short: i64::MAX,
694 reserved: Default::default(),
695 };
696
697 let event_clocks = EventClocks {
698 padding: clocks.padding,
699 rev: clocks.rev,
700 price_impact_distribution: clocks.price_impact_distribution,
701 borrowing: clocks.borrowing,
702 funding: clocks.funding,
703 adl_for_long: clocks.adl_for_long,
704 adl_for_short: clocks.adl_for_short,
705 reserved: clocks.reserved,
706 };
707
708 let mut data = Vec::with_capacity(Pool::INIT_SPACE);
709 clocks
710 .serialize(&mut data)
711 .expect("failed to serialize `Clocks`");
712
713 let mut event_data = Vec::with_capacity(Pool::INIT_SPACE);
714 event_clocks
715 .serialize(&mut event_data)
716 .expect("failed to serialize `EventClocks`");
717
718 assert_eq!(data, event_data);
719 }
720
721 #[test]
722 fn test_event_other_state() {
723 let clocks = OtherState {
724 padding: Default::default(),
725 rev: u64::MAX,
726 trade_count: u64::MAX,
727 long_token_balance: u64::MAX,
728 short_token_balance: u64::MAX,
729 funding_factor_per_second: i128::MAX,
730 reserved: [0; 256],
731 };
732
733 let event_clocks = EventOtherState {
734 padding: clocks.padding,
735 rev: clocks.rev,
736 trade_count: clocks.trade_count,
737 long_token_balance: clocks.long_token_balance,
738 short_token_balance: clocks.short_token_balance,
739 funding_factor_per_second: clocks.funding_factor_per_second,
740 reserved: clocks.reserved,
741 };
742
743 let mut data = Vec::with_capacity(Pool::INIT_SPACE);
744 clocks
745 .serialize(&mut data)
746 .expect("failed to serialize `OtherState`");
747
748 let mut event_data = Vec::with_capacity(Pool::INIT_SPACE);
749 event_clocks
750 .serialize(&mut event_data)
751 .expect("failed to serialize `EventOtherState`");
752
753 assert_eq!(data, event_data);
754 }
755}