gmsol/
pda.rs

1use anchor_client::solana_sdk::pubkey::Pubkey;
2use gmsol_store::{
3    events::TradeData,
4    states::{
5        glv::GlvWithdrawal,
6        gt::{GtExchange, GtExchangeVault},
7        position::PositionKind,
8        user::{ReferralCodeBytes, ReferralCodeV2, UserHeader},
9        Deposit, GlvDeposit, NonceBytes, Order, Position, PriceFeed, PriceProviderKind, Seed,
10        Shift, Store, Withdrawal, MAX_ROLE_NAME_LEN,
11    },
12    utils::fixed_str::fixed_str_to_bytes,
13};
14use gmsol_timelock::states::{Executor, TimelockConfig};
15use gmsol_treasury::{
16    constants::RECEIVER_SEED,
17    states::{Config, GtBank, TreasuryVaultConfig},
18};
19use gmsol_utils::to_seed;
20
21use crate::utils::EVENT_AUTHORITY_SEED;
22
23pub use gmsol_timelock::states::find_executor_wallet_pda;
24
25/// Default store.
26pub fn find_default_store() -> (Pubkey, u8) {
27    find_store_address("", &gmsol_store::ID)
28}
29
30/// Find PDA for `event_authority` account.
31pub fn find_event_authority_address(program_id: &Pubkey) -> (Pubkey, u8) {
32    Pubkey::find_program_address(&[EVENT_AUTHORITY_SEED], program_id)
33}
34
35/// Find PDA for [`Store`] account.
36pub fn find_store_address(key: &str, store_program_id: &Pubkey) -> (Pubkey, u8) {
37    Pubkey::find_program_address(&[Store::SEED, &to_seed(key)], store_program_id)
38}
39
40/// Find PDA for store wallet account.
41pub fn find_store_wallet_pda(store: &Pubkey, store_program_id: &Pubkey) -> (Pubkey, u8) {
42    Pubkey::find_program_address(&[Store::WALLET_SEED, store.as_ref()], store_program_id)
43}
44
45/// Find PDA for the market vault.
46pub fn find_market_vault_address(
47    store: &Pubkey,
48    token: &Pubkey,
49    store_program_id: &Pubkey,
50) -> (Pubkey, u8) {
51    Pubkey::find_program_address(
52        &[
53            gmsol_store::constants::MARKET_VAULT_SEED,
54            store.as_ref(),
55            token.as_ref(),
56        ],
57        store_program_id,
58    )
59}
60
61/// Find PDA for Market token mint account.
62pub fn find_market_token_address(
63    store: &Pubkey,
64    index_token: &Pubkey,
65    long_token: &Pubkey,
66    short_token: &Pubkey,
67    store_program_id: &Pubkey,
68) -> (Pubkey, u8) {
69    Pubkey::find_program_address(
70        &[
71            gmsol_store::constants::MAREKT_TOKEN_MINT_SEED,
72            store.as_ref(),
73            index_token.as_ref(),
74            long_token.as_ref(),
75            short_token.as_ref(),
76        ],
77        store_program_id,
78    )
79}
80
81/// Create PDA for deposit.
82pub fn find_deposit_address(
83    store: &Pubkey,
84    user: &Pubkey,
85    nonce: &NonceBytes,
86    store_program_id: &Pubkey,
87) -> (Pubkey, u8) {
88    Pubkey::find_program_address(
89        &[Deposit::SEED, store.as_ref(), user.as_ref(), nonce],
90        store_program_id,
91    )
92}
93
94/// Create PDA for withdrawal.
95pub fn find_withdrawal_address(
96    store: &Pubkey,
97    user: &Pubkey,
98    nonce: &NonceBytes,
99    store_program_id: &Pubkey,
100) -> (Pubkey, u8) {
101    Pubkey::find_program_address(
102        &[Withdrawal::SEED, store.as_ref(), user.as_ref(), nonce],
103        store_program_id,
104    )
105}
106
107/// Create PDA for order.
108pub fn find_order_address(
109    store: &Pubkey,
110    user: &Pubkey,
111    nonce: &NonceBytes,
112    store_program_id: &Pubkey,
113) -> (Pubkey, u8) {
114    Pubkey::find_program_address(
115        &[Order::SEED, store.as_ref(), user.as_ref(), nonce],
116        store_program_id,
117    )
118}
119
120/// Create PDA for shift.
121pub fn find_shift_address(
122    store: &Pubkey,
123    owner: &Pubkey,
124    nonce: &NonceBytes,
125    store_program_id: &Pubkey,
126) -> (Pubkey, u8) {
127    Pubkey::find_program_address(
128        &[Shift::SEED, store.as_ref(), owner.as_ref(), nonce],
129        store_program_id,
130    )
131}
132
133/// Create PDA for position.
134pub fn find_position_address(
135    store: &Pubkey,
136    user: &Pubkey,
137    market_token: &Pubkey,
138    collateral_token: &Pubkey,
139    kind: PositionKind,
140    store_program_id: &Pubkey,
141) -> crate::Result<(Pubkey, u8)> {
142    if matches!(kind, PositionKind::Uninitialized) {
143        return Err(crate::Error::invalid_argument(
144            "uninitialized position kind is not allowed",
145        ));
146    }
147    Ok(Pubkey::find_program_address(
148        &[
149            Position::SEED,
150            store.as_ref(),
151            user.as_ref(),
152            market_token.as_ref(),
153            collateral_token.as_ref(),
154            &[kind as u8],
155        ],
156        store_program_id,
157    ))
158}
159
160/// Find PDA for claimable account.
161pub fn find_claimable_account_pda(
162    store: &Pubkey,
163    mint: &Pubkey,
164    user: &Pubkey,
165    time_key: &[u8],
166    store_program_id: &Pubkey,
167) -> (Pubkey, u8) {
168    Pubkey::find_program_address(
169        &[
170            gmsol_store::constants::CLAIMABLE_ACCOUNT_SEED,
171            store.as_ref(),
172            mint.as_ref(),
173            user.as_ref(),
174            time_key,
175        ],
176        store_program_id,
177    )
178}
179
180/// Find PDA for trade event buffer.
181pub fn find_trade_event_buffer_pda(
182    store: &Pubkey,
183    authority: &Pubkey,
184    index: u16,
185    store_program_id: &Pubkey,
186) -> (Pubkey, u8) {
187    Pubkey::find_program_address(
188        &[
189            TradeData::SEED,
190            store.as_ref(),
191            authority.as_ref(),
192            &index.to_le_bytes(),
193        ],
194        store_program_id,
195    )
196}
197
198/// Find PDA for user account.
199pub fn find_user_pda(store: &Pubkey, owner: &Pubkey, store_program_id: &Pubkey) -> (Pubkey, u8) {
200    Pubkey::find_program_address(
201        &[UserHeader::SEED, store.as_ref(), owner.as_ref()],
202        store_program_id,
203    )
204}
205
206/// Find PDA for referral code account.
207pub fn find_referral_code_pda(
208    store: &Pubkey,
209    code: ReferralCodeBytes,
210    store_program_id: &Pubkey,
211) -> (Pubkey, u8) {
212    Pubkey::find_program_address(
213        &[ReferralCodeV2::SEED, store.as_ref(), &code],
214        store_program_id,
215    )
216}
217
218/// Find the PDA for a GLV deposit account.
219pub fn find_glv_deposit_pda(
220    store: &Pubkey,
221    owner: &Pubkey,
222    nonce: &NonceBytes,
223    store_program_id: &Pubkey,
224) -> (Pubkey, u8) {
225    Pubkey::find_program_address(
226        &[GlvDeposit::SEED, store.as_ref(), owner.as_ref(), nonce],
227        store_program_id,
228    )
229}
230
231/// Find the PDA for a GLV withdrawal account.
232pub fn find_glv_withdrawal_pda(
233    store: &Pubkey,
234    owner: &Pubkey,
235    nonce: &NonceBytes,
236    store_program_id: &Pubkey,
237) -> (Pubkey, u8) {
238    Pubkey::find_program_address(
239        &[GlvWithdrawal::SEED, store.as_ref(), owner.as_ref(), nonce],
240        store_program_id,
241    )
242}
243
244/// Find the PDA for GT exchange vault account.
245pub fn find_gt_exchange_vault_pda(
246    store: &Pubkey,
247    time_window_index: i64,
248    time_window: u32,
249    store_program_id: &Pubkey,
250) -> (Pubkey, u8) {
251    Pubkey::find_program_address(
252        &[
253            GtExchangeVault::SEED,
254            store.as_ref(),
255            &time_window_index.to_le_bytes(),
256            &time_window.to_le_bytes(),
257        ],
258        store_program_id,
259    )
260}
261
262/// Find the PDA for GT exchange account.
263pub fn find_gt_exchange_pda(
264    vault: &Pubkey,
265    owner: &Pubkey,
266    store_program_id: &Pubkey,
267) -> (Pubkey, u8) {
268    Pubkey::find_program_address(
269        &[GtExchange::SEED, vault.as_ref(), owner.as_ref()],
270        store_program_id,
271    )
272}
273
274/// Fint the PDA for custom price feed account.
275pub fn find_price_feed_pda(
276    store: &Pubkey,
277    authority: &Pubkey,
278    index: u16,
279    provider: PriceProviderKind,
280    token: &Pubkey,
281    store_program_id: &Pubkey,
282) -> (Pubkey, u8) {
283    Pubkey::find_program_address(
284        &[
285            PriceFeed::SEED,
286            store.as_ref(),
287            authority.as_ref(),
288            &index.to_le_bytes(),
289            &[u8::from(provider)],
290            token.as_ref(),
291        ],
292        store_program_id,
293    )
294}
295
296/// Find the PDA for global treasury config.
297pub fn find_treasury_config_pda(store: &Pubkey, treasury_program_id: &Pubkey) -> (Pubkey, u8) {
298    Pubkey::find_program_address(&[Config::SEED, store.as_ref()], treasury_program_id)
299}
300
301/// Find the PDA for a treasury vault config.
302pub fn find_treasury_vault_config_pda(
303    config: &Pubkey,
304    index: u16,
305    treasury_program_id: &Pubkey,
306) -> (Pubkey, u8) {
307    Pubkey::find_program_address(
308        &[
309            TreasuryVaultConfig::SEED,
310            config.as_ref(),
311            &index.to_le_bytes(),
312        ],
313        treasury_program_id,
314    )
315}
316
317/// Find the PDA for a GT bank.
318pub fn find_gt_bank_pda(
319    treasury_vault_config: &Pubkey,
320    gt_exchange_vault: &Pubkey,
321    treasury_program_id: &Pubkey,
322) -> (Pubkey, u8) {
323    Pubkey::find_program_address(
324        &[
325            GtBank::SEED,
326            treasury_vault_config.as_ref(),
327            gt_exchange_vault.as_ref(),
328        ],
329        treasury_program_id,
330    )
331}
332
333/// Find treasury receiver PDA.
334pub fn find_treasury_receiver_pda(config: &Pubkey, treasury_program_id: &Pubkey) -> (Pubkey, u8) {
335    Pubkey::find_program_address(&[RECEIVER_SEED, config.as_ref()], treasury_program_id)
336}
337
338/// Find timelock config PDA.
339pub fn find_timelock_config_pda(store: &Pubkey, timelock_program_id: &Pubkey) -> (Pubkey, u8) {
340    Pubkey::find_program_address(&[TimelockConfig::SEED, store.as_ref()], timelock_program_id)
341}
342
343/// Find executor PDA.
344pub fn find_executor_pda(
345    store: &Pubkey,
346    role: &str,
347    timelock_program_id: &Pubkey,
348) -> crate::Result<(Pubkey, u8)> {
349    Ok(Pubkey::find_program_address(
350        &[
351            Executor::SEED,
352            store.as_ref(),
353            &fixed_str_to_bytes::<MAX_ROLE_NAME_LEN>(role)?,
354        ],
355        timelock_program_id,
356    ))
357}