gmsol_sdk/builders/
store_program.rs

1use anchor_lang::InstructionData;
2use gmsol_programs::anchor_lang::ToAccountMetas;
3use gmsol_solana_utils::{Program, ProgramExt};
4use solana_sdk::{instruction::Instruction, pubkey::Pubkey};
5use typed_builder::TypedBuilder;
6
7use crate::{pda, serde::StringPubkey};
8
9use super::callback::{Callback, CallbackParams};
10
11/// Nonce Bytes.
12pub type NonceBytes = StringPubkey;
13
14/// A store program.
15#[cfg_attr(js, derive(tsify_next::Tsify))]
16#[cfg_attr(js, tsify(from_wasm_abi, into_wasm_abi))]
17#[cfg_attr(serde, derive(serde::Serialize, serde::Deserialize))]
18#[derive(Debug, Clone, TypedBuilder)]
19pub struct StoreProgram {
20    /// Program ID.
21    #[builder(setter(into))]
22    pub id: StringPubkey,
23    /// Store address.
24    #[builder(setter(into))]
25    pub store: StringPubkey,
26}
27
28impl anchor_lang::Id for StoreProgram {
29    fn id() -> Pubkey {
30        gmsol_programs::gmsol_store::ID
31    }
32}
33
34impl Default for StoreProgram {
35    fn default() -> Self {
36        use gmsol_programs::gmsol_store::ID;
37        Self {
38            id: ID.into(),
39            store: pda::find_store_address("", &ID).0.into(),
40        }
41    }
42}
43
44impl Program for StoreProgram {
45    fn id(&self) -> &Pubkey {
46        &self.id
47    }
48}
49
50impl StoreProgram {
51    /// Create an instruction builder.
52    #[deprecated(
53        since = "0.8.0",
54        note = "Use `ProgramExt::anchor_instruction` instead."
55    )]
56    #[allow(deprecated)]
57    pub fn instruction(&self, args: impl InstructionData) -> InstructionBuilder {
58        InstructionBuilder(self.anchor_instruction(args))
59    }
60
61    pub(crate) fn get_callback_params(&self, callback: Option<&Callback>) -> CallbackParams {
62        match callback {
63            Some(callback) => CallbackParams {
64                callback_version: Some(callback.version),
65                callback_authority: Some(self.find_callback_authority_address()),
66                callback_program: Some(callback.program.0),
67                callback_shared_data_account: Some(callback.shared_data.0),
68                callback_partitioned_data_account: Some(callback.partitioned_data.0),
69            },
70            None => CallbackParams::default(),
71        }
72    }
73
74    /// Find the event authority address.
75    pub fn find_event_authority_address(&self) -> Pubkey {
76        pda::find_event_authority_address(&self.id).0
77    }
78
79    /// Find the store wallet address.
80    pub fn find_store_wallet_address(&self) -> Pubkey {
81        pda::find_store_wallet_address(&self.store, &self.id).0
82    }
83
84    /// Find order address.
85    pub fn find_order_address(&self, owner: &Pubkey, nonce: &NonceBytes) -> Pubkey {
86        pda::find_order_address(&self.store, owner, &nonce.0.to_bytes(), &self.id).0
87    }
88
89    /// Find deposit address.
90    pub fn find_deposit_address(&self, owner: &Pubkey, nonce: &NonceBytes) -> Pubkey {
91        pda::find_deposit_address(&self.store, owner, &nonce.0.to_bytes(), &self.id).0
92    }
93
94    /// Find withdrawal address.
95    pub fn find_withdrawal_address(&self, owner: &Pubkey, nonce: &NonceBytes) -> Pubkey {
96        pda::find_withdrawal_address(&self.store, owner, &nonce.0.to_bytes(), &self.id).0
97    }
98
99    /// Find shift address.
100    pub fn find_shift_address(&self, owner: &Pubkey, nonce: &NonceBytes) -> Pubkey {
101        pda::find_shift_address(&self.store, owner, &nonce.0.to_bytes(), &self.id).0
102    }
103
104    /// Find GLV deposit address.
105    pub fn find_glv_deposit_address(&self, owner: &Pubkey, nonce: &NonceBytes) -> Pubkey {
106        pda::find_glv_deposit_address(&self.store, owner, &nonce.0.to_bytes(), &self.id).0
107    }
108
109    /// Find GLV withdrawal address.
110    pub fn find_glv_withdrawal_address(&self, owner: &Pubkey, nonce: &NonceBytes) -> Pubkey {
111        pda::find_glv_withdrawal_address(&self.store, owner, &nonce.0.to_bytes(), &self.id).0
112    }
113
114    /// Find market address.
115    pub fn find_market_address(&self, market_token: &Pubkey) -> Pubkey {
116        pda::find_market_address(&self.store, market_token, &self.id).0
117    }
118
119    /// Find user address.
120    pub fn find_user_address(&self, owner: &Pubkey) -> Pubkey {
121        pda::find_user_address(&self.store, owner, &self.id).0
122    }
123
124    /// Find position address.
125    pub fn find_position_address(
126        &self,
127        owner: &Pubkey,
128        market_token: &Pubkey,
129        collateral_token: &Pubkey,
130        is_long: bool,
131    ) -> Pubkey {
132        pda::find_position_address(
133            &self.store,
134            owner,
135            market_token,
136            collateral_token,
137            is_long,
138            &self.id,
139        )
140        .0
141    }
142
143    /// Find the PDA for callback authority.
144    pub fn find_callback_authority_address(&self) -> Pubkey {
145        crate::pda::find_callback_authority(&self.id).0
146    }
147
148    /// Find the PDA for GLV account.
149    pub fn find_glv_address(&self, glv_token: &Pubkey) -> Pubkey {
150        crate::pda::find_glv_address(glv_token, &self.id).0
151    }
152}
153
154/// Builder for [`StoreProgram`] instructions.
155pub trait StoreProgramIxBuilder {
156    /// Returns the [`StoreProgram`].
157    fn store_program(&self) -> &StoreProgram;
158}
159
160/// Builder for Store Program Instruction.
161#[deprecated(
162    since = "0.8.0",
163    note = "Use `gmsol_sdk::solana_utils::InstructionBuilder` instead."
164)]
165pub struct InstructionBuilder<'a>(gmsol_solana_utils::InstructionBuilder<'a, StoreProgram>);
166
167#[allow(deprecated)]
168impl InstructionBuilder<'_> {
169    /// Append accounts.
170    pub fn accounts(self, accounts: impl ToAccountMetas, convert_optional: bool) -> Self {
171        Self(self.0.anchor_accounts(accounts, convert_optional))
172    }
173
174    /// Build.
175    pub fn build(self) -> Instruction {
176        self.0.build()
177    }
178}
179
180#[cfg(test)]
181mod tests {
182    use super::*;
183
184    #[test]
185    fn default_store_program() {
186        let program = StoreProgram::default();
187        assert_eq!(
188            program.store.to_string(),
189            "CTDLvGGXnoxvqLyTpGzdGLg9pD6JexKxKXSV8tqqo8bN"
190        );
191    }
192
193    #[cfg(serde)]
194    #[test]
195    fn serde() {
196        let program = StoreProgram::default();
197        assert_eq!(
198            serde_json::to_string(&program).unwrap(),
199            r#"{"id":"Gmso1uvJnLbawvw7yezdfCDcPydwW2s2iqG3w6MDucLo","store":"CTDLvGGXnoxvqLyTpGzdGLg9pD6JexKxKXSV8tqqo8bN"}"#
200        );
201    }
202}