gmsol_store/states/
withdrawal.rs

1use anchor_lang::prelude::*;
2
3use crate::{events::WithdrawalRemoved, CoreError};
4
5use super::{
6    common::{
7        action::{Action, ActionHeader, Closable},
8        swap::SwapActionParams,
9        token::TokenAndAccount,
10    },
11    Seed,
12};
13
14/// Withdrawal.
15#[account(zero_copy)]
16#[cfg_attr(feature = "debug", derive(derive_more::Debug))]
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18pub struct Withdrawal {
19    /// Action header.
20    pub(crate) header: ActionHeader,
21    /// Token accounts.
22    pub(crate) tokens: WithdrawalTokenAccounts,
23    /// Withdrawal params.
24    pub(crate) params: WithdrawalActionParams,
25    /// Swap params.
26    pub(crate) swap: SwapActionParams,
27    #[cfg_attr(feature = "debug", debug(skip))]
28    padding_1: [u8; 4],
29    #[cfg_attr(feature = "debug", debug(skip))]
30    #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
31    reserved: [u8; 128],
32}
33
34impl Withdrawal {
35    /// Get tokens and accounts.
36    pub fn tokens(&self) -> &WithdrawalTokenAccounts {
37        &self.tokens
38    }
39
40    /// Get the swap params.
41    pub fn swap(&self) -> &SwapActionParams {
42        &self.swap
43    }
44}
45
46impl Seed for Withdrawal {
47    /// Seed.
48    const SEED: &'static [u8] = b"withdrawal";
49}
50
51impl gmsol_utils::InitSpace for Withdrawal {
52    const INIT_SPACE: usize = std::mem::size_of::<Self>();
53}
54
55impl Action for Withdrawal {
56    const MIN_EXECUTION_LAMPORTS: u64 = 200_000;
57
58    fn header(&self) -> &ActionHeader {
59        &self.header
60    }
61}
62
63impl Closable for Withdrawal {
64    type ClosedEvent = WithdrawalRemoved;
65
66    fn to_closed_event(&self, address: &Pubkey, reason: &str) -> Result<Self::ClosedEvent> {
67        WithdrawalRemoved::new(
68            self.header.id,
69            self.header.store,
70            *address,
71            self.tokens.market_token(),
72            self.header.owner,
73            self.header.action_state()?,
74            reason,
75        )
76    }
77}
78
79/// Token Accounts.
80#[zero_copy]
81#[cfg_attr(feature = "debug", derive(derive_more::Debug))]
82#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
83pub struct WithdrawalTokenAccounts {
84    /// Final long token accounts.
85    pub(crate) final_long_token: TokenAndAccount,
86    /// Final short token accounts.
87    pub(crate) final_short_token: TokenAndAccount,
88    /// Market token account.
89    pub(crate) market_token: TokenAndAccount,
90    #[cfg_attr(feature = "debug", debug(skip))]
91    #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
92    reserved: [u8; 128],
93}
94
95impl WithdrawalTokenAccounts {
96    /// Get market token.
97    pub fn market_token(&self) -> Pubkey {
98        self.market_token.token().expect("must exist")
99    }
100
101    /// Get market token account.
102    pub fn market_token_account(&self) -> Pubkey {
103        self.market_token.account().expect("must exist")
104    }
105
106    /// Get final_long token.
107    pub fn final_long_token(&self) -> Pubkey {
108        self.final_long_token.token().expect("must exist")
109    }
110
111    /// Get final_long token account.
112    pub fn final_long_token_account(&self) -> Pubkey {
113        self.final_long_token.account().expect("must exist")
114    }
115
116    /// Get final_short token.
117    pub fn final_short_token(&self) -> Pubkey {
118        self.final_short_token.token().expect("must exist")
119    }
120
121    /// Get final_short token account.
122    pub fn final_short_token_account(&self) -> Pubkey {
123        self.final_short_token.account().expect("must exist")
124    }
125}
126
127/// Withdrawal params.
128#[zero_copy]
129#[cfg_attr(feature = "debug", derive(derive_more::Debug))]
130#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
131pub struct WithdrawalActionParams {
132    /// Market token amount to burn.
133    pub market_token_amount: u64,
134    /// The minimum acceptable amount of final long tokens to receive.
135    pub min_long_token_amount: u64,
136    /// The minimum acceptable amount of final short tokens to receive.
137    pub min_short_token_amount: u64,
138    #[cfg_attr(feature = "debug", debug(skip))]
139    #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
140    reserved: [u8; 64],
141}
142
143impl Default for WithdrawalActionParams {
144    fn default() -> Self {
145        Self {
146            reserved: [0; 64],
147            market_token_amount: 0,
148            min_long_token_amount: 0,
149            min_short_token_amount: 0,
150        }
151    }
152}
153
154impl WithdrawalActionParams {
155    pub(crate) fn validate_output_amounts(
156        &self,
157        long_amount: u64,
158        short_amount: u64,
159    ) -> Result<()> {
160        require_gte!(
161            long_amount,
162            self.min_long_token_amount,
163            CoreError::InsufficientOutputAmount
164        );
165        require_gte!(
166            short_amount,
167            self.min_short_token_amount,
168            CoreError::InsufficientOutputAmount
169        );
170        Ok(())
171    }
172}