gmsol_sdk/
pda.rs

1use gmsol_utils::oracle::PriceProviderKind;
2use solana_sdk::pubkey::Pubkey;
3
4#[allow(unused_imports)]
5use gmsol_programs::gmsol_store::accounts as store_accounts;
6
7#[cfg(treasury)]
8#[allow(unused_imports)]
9use gmsol_programs::gmsol_treasury::accounts as treasury_accounts;
10
11#[cfg(timelock)]
12#[allow(unused_imports)]
13use gmsol_programs::gmsol_timelock::accounts as timelock_accounts;
14
15#[cfg(liquidity_provider)]
16#[allow(unused_imports)]
17use gmsol_programs::gmsol_liquidity_provider::accounts as liquidity_provider_accounts;
18
19pub use gmsol_programs::gmsol_store::constants::{
20    VIRTUAL_INVENTORY_FOR_POSITIONS_SEED, VIRTUAL_INVENTORY_FOR_SWAPS_SEED,
21};
22
23/// Nonce bytes.
24pub type NonceBytes = [u8; 32];
25
26/// Referral code bytes.
27pub type ReferralCodeBytes = [u8; 8];
28
29/// Seed for event authority.
30pub const EVENT_AUTHORITY_SEED: &[u8] = b"__event_authority";
31
32/// Seed for [`Store`](store_accounts::Store).
33pub const STORE_SEED: &[u8] = b"data_store";
34
35/// Seed for store wallet.
36pub const STORE_WALLET_SEED: &[u8] = b"store_wallet";
37
38/// Seed for market vault.
39pub const MARKET_VAULT_SEED: &[u8] = b"market_vault";
40
41/// Seed for market token mint.
42pub const MARKET_TOKEN_MINT_SEED: &[u8] = b"market_token_mint";
43
44/// Seed for [`Market`](store_accounts::Market).
45pub const MARKET_SEED: &[u8] = b"market";
46
47/// Seed for [`Deposit`](store_accounts::Deposit).
48pub const DEPOSIT_SEED: &[u8] = b"deposit";
49
50/// Seed for first deposit receiver.
51pub const FIRST_DEPOSIT_RECEIVER_SEED: &[u8] = b"first_deposit_receiver";
52
53/// Seed for [`Withdrawal`](store_accounts::Withdrawal).
54pub const WITHDRAWAL_SEED: &[u8] = b"withdrawal";
55
56/// Seed for [`Shift`](store_accounts::Shift).
57pub const SHIFT_SEED: &[u8] = b"shift";
58
59/// Seed for [`Order`](store_accounts::Order).
60pub const ORDER_SEED: &[u8] = b"order";
61
62/// Seed for [`Position`](store_accounts::Position).
63pub const POSITION_SEED: &[u8] = b"position";
64
65/// Seed for claimable account.
66pub const CLAIMABLE_ACCOUNT_SEED: &[u8] = b"claimable_account";
67
68/// Seed for trade event buffer account.
69pub const TRADE_DATA_SEED: &[u8] = b"trade_event_data";
70
71/// Seed for [`User`](store_accounts::UserHeader).
72pub const USER_SEED: &[u8] = b"user";
73
74/// Seed for [`ReferralCodeV2`](store_accounts::ReferralCodeV2).
75pub const REFERRAL_CODE_SEED: &[u8] = b"referral_code";
76
77/// Seed for GLV token mint.
78pub const GLV_TOKEN_SEED: &[u8] = b"glv_token";
79
80/// Seed for [`Glv`](store_accounts::Glv).
81pub const GLV_SEED: &[u8] = b"glv";
82
83/// Seed for [`GlvDeposit`](store_accounts::GlvDeposit).
84pub const GLV_DEPOSIT_SEED: &[u8] = b"glv_deposit";
85
86/// Seed for [`GlvWithdrawal`](store_accounts::GlvWithdrawal).
87pub const GLV_WITHDRAWAL_SEED: &[u8] = b"glv_withdrawal";
88
89/// Seed for [`GtExchangeVault`](store_accounts::GtExchangeVault).
90pub const GT_EXCHANGE_VAULT_SEED: &[u8] = b"gt_exchange_vault";
91
92/// Seed for [`GtExchange`](store_accounts::GtExchange).
93pub const GT_EXCHANGE_SEED: &[u8] = b"gt_exchange";
94
95/// Seed for [`PriceFeed`](store_accounts::PriceFeed).
96pub const PRICE_FEED_SEED: &[u8] = b"price_feed";
97
98/// Seed for [`Config`](treasury_accounts::Config).
99#[cfg(treasury)]
100pub const TREASURY_CONFIG_SEED: &[u8] = b"config";
101
102/// Seed for [`TreasuryVaultConfig`](treasury_accounts::TreasuryVaultConfig).
103#[cfg(treasury)]
104pub const TREASURY_VAULT_CONFIG_SEED: &[u8] = b"treasury_vault_config";
105
106/// Seed for [`GtBank`](treasury_accounts::GtBank).
107#[cfg(treasury)]
108pub const GT_BANK_SEED: &[u8] = b"gt_bank";
109
110/// Seed for treasury receiver.
111#[cfg(treasury)]
112pub const TREASURY_RECEIVER_SEED: &[u8] = b"receiver";
113
114/// Seed for [`TimelockConfig`](timelock_accounts::TimelockConfig).
115#[cfg(timelock)]
116pub const TIMELOCK_CONFIG_SEED: &[u8] = b"timelock_config";
117
118/// Seed for [`Executor`](timelock_accounts::Executor).
119#[cfg(timelock)]
120pub const TIMELOCK_EXECUTOR_SEED: &[u8] = b"timelock_executor";
121
122/// Seed for the exeuctor wallet.
123#[cfg(timelock)]
124pub const TIMELOCK_EXECUTOR_WALLET_SEED: &[u8] = b"wallet";
125
126/// Seed for callback authority.
127pub const CALLBACK_AUTHORITY_SEED: &[u8] = b"callback";
128
129/// Seed for competition account.
130#[cfg(competition)]
131pub use gmsol_programs::gmsol_competition::constants::COMPETITION_SEED;
132
133/// Seed for participant account.
134#[cfg(competition)]
135pub use gmsol_programs::gmsol_competition::constants::PARTICIPANT_SEED;
136
137fn to_seed(key: &str) -> [u8; 32] {
138    use solana_sdk::hash::hash;
139    hash(key.as_bytes()).to_bytes()
140}
141
142/// Find PDA for `event_authority` account.
143pub fn find_event_authority_address(program_id: &Pubkey) -> (Pubkey, u8) {
144    Pubkey::find_program_address(&[EVENT_AUTHORITY_SEED], program_id)
145}
146
147/// Find PDA for [`Store`](store_accounts::Store) account.
148pub fn find_store_address(key: &str, store_program_id: &Pubkey) -> (Pubkey, u8) {
149    Pubkey::find_program_address(&[STORE_SEED, &to_seed(key)], store_program_id)
150}
151
152/// Find the default store address.
153pub fn find_default_store_address() -> (Pubkey, u8) {
154    find_store_address("", &gmsol_programs::gmsol_store::ID)
155}
156
157/// Find PDA for store wallet account.
158pub fn find_store_wallet_address(store: &Pubkey, store_program_id: &Pubkey) -> (Pubkey, u8) {
159    Pubkey::find_program_address(&[STORE_WALLET_SEED, store.as_ref()], store_program_id)
160}
161
162/// Find PDA for market vault.
163pub fn find_market_vault_address(
164    store: &Pubkey,
165    token: &Pubkey,
166    store_program_id: &Pubkey,
167) -> (Pubkey, u8) {
168    Pubkey::find_program_address(
169        &[MARKET_VAULT_SEED, store.as_ref(), token.as_ref()],
170        store_program_id,
171    )
172}
173
174/// Find PDA for Market token mint account.
175pub fn find_market_token_address(
176    store: &Pubkey,
177    index_token: &Pubkey,
178    long_token: &Pubkey,
179    short_token: &Pubkey,
180    store_program_id: &Pubkey,
181) -> (Pubkey, u8) {
182    Pubkey::find_program_address(
183        &[
184            MARKET_TOKEN_MINT_SEED,
185            store.as_ref(),
186            index_token.as_ref(),
187            long_token.as_ref(),
188            short_token.as_ref(),
189        ],
190        store_program_id,
191    )
192}
193
194/// Find PDA for [`Market`](store_accounts::Market) account.
195pub fn find_market_address(
196    store: &Pubkey,
197    token: &Pubkey,
198    store_program_id: &Pubkey,
199) -> (Pubkey, u8) {
200    Pubkey::find_program_address(
201        &[MARKET_SEED, store.as_ref(), token.as_ref()],
202        store_program_id,
203    )
204}
205
206/// Find PDA for deposit.
207pub fn find_deposit_address(
208    store: &Pubkey,
209    user: &Pubkey,
210    nonce: &NonceBytes,
211    store_program_id: &Pubkey,
212) -> (Pubkey, u8) {
213    Pubkey::find_program_address(
214        &[DEPOSIT_SEED, store.as_ref(), user.as_ref(), nonce],
215        store_program_id,
216    )
217}
218
219/// Find PDA for first deposit receiver.
220pub fn find_first_deposit_receiver_address(store_program_id: &Pubkey) -> (Pubkey, u8) {
221    Pubkey::find_program_address(&[FIRST_DEPOSIT_RECEIVER_SEED], store_program_id)
222}
223
224/// Find PDA for withdrawal.
225pub fn find_withdrawal_address(
226    store: &Pubkey,
227    user: &Pubkey,
228    nonce: &NonceBytes,
229    store_program_id: &Pubkey,
230) -> (Pubkey, u8) {
231    Pubkey::find_program_address(
232        &[WITHDRAWAL_SEED, store.as_ref(), user.as_ref(), nonce],
233        store_program_id,
234    )
235}
236
237/// Find PDA for shift.
238pub fn find_shift_address(
239    store: &Pubkey,
240    owner: &Pubkey,
241    nonce: &NonceBytes,
242    store_program_id: &Pubkey,
243) -> (Pubkey, u8) {
244    Pubkey::find_program_address(
245        &[SHIFT_SEED, store.as_ref(), owner.as_ref(), nonce],
246        store_program_id,
247    )
248}
249
250/// Find PDA for [`Order`](store_accounts::Order) account.
251pub fn find_order_address(
252    store: &Pubkey,
253    owner: &Pubkey,
254    nonce: &NonceBytes,
255    store_program_id: &Pubkey,
256) -> (Pubkey, u8) {
257    Pubkey::find_program_address(
258        &[ORDER_SEED, store.as_ref(), owner.as_ref(), nonce.as_ref()],
259        store_program_id,
260    )
261}
262
263/// Find PDA for position.
264pub fn find_position_address(
265    store: &Pubkey,
266    owner: &Pubkey,
267    market_token: &Pubkey,
268    collateral_token: &Pubkey,
269    is_long: bool,
270    store_program_id: &Pubkey,
271) -> (Pubkey, u8) {
272    // See the definition of `PositionKind`.
273    let kind = if is_long { 1 } else { 2 };
274    Pubkey::find_program_address(
275        &[
276            POSITION_SEED,
277            store.as_ref(),
278            owner.as_ref(),
279            market_token.as_ref(),
280            collateral_token.as_ref(),
281            &[kind],
282        ],
283        store_program_id,
284    )
285}
286
287/// Find PDA for claimable account.
288pub fn find_claimable_account_address(
289    store: &Pubkey,
290    mint: &Pubkey,
291    user: &Pubkey,
292    time_key: &[u8],
293    store_program_id: &Pubkey,
294) -> (Pubkey, u8) {
295    Pubkey::find_program_address(
296        &[
297            CLAIMABLE_ACCOUNT_SEED,
298            store.as_ref(),
299            mint.as_ref(),
300            user.as_ref(),
301            time_key,
302        ],
303        store_program_id,
304    )
305}
306
307/// Find PDA for trade event buffer.
308pub fn find_trade_event_buffer_address(
309    store: &Pubkey,
310    authority: &Pubkey,
311    index: u16,
312    store_program_id: &Pubkey,
313) -> (Pubkey, u8) {
314    Pubkey::find_program_address(
315        &[
316            TRADE_DATA_SEED,
317            store.as_ref(),
318            authority.as_ref(),
319            &index.to_le_bytes(),
320        ],
321        store_program_id,
322    )
323}
324
325/// Find PDA for [`User`](store_accounts::UserHeader) account.
326pub fn find_user_address(
327    store: &Pubkey,
328    owner: &Pubkey,
329    store_program_id: &Pubkey,
330) -> (Pubkey, u8) {
331    Pubkey::find_program_address(
332        &[USER_SEED, store.as_ref(), owner.as_ref()],
333        store_program_id,
334    )
335}
336
337/// Find PDA for referral code account.
338pub fn find_referral_code_address(
339    store: &Pubkey,
340    code: ReferralCodeBytes,
341    store_program_id: &Pubkey,
342) -> (Pubkey, u8) {
343    Pubkey::find_program_address(
344        &[REFERRAL_CODE_SEED, store.as_ref(), &code],
345        store_program_id,
346    )
347}
348
349/// Find PDA for GLV token.
350pub fn find_glv_token_address(store: &Pubkey, index: u16, program_id: &Pubkey) -> (Pubkey, u8) {
351    Pubkey::find_program_address(
352        &[GLV_TOKEN_SEED, store.as_ref(), &index.to_le_bytes()],
353        program_id,
354    )
355}
356
357/// Find PDA GLV account.
358pub fn find_glv_address(glv_token: &Pubkey, program_id: &Pubkey) -> (Pubkey, u8) {
359    Pubkey::find_program_address(&[GLV_SEED, glv_token.as_ref()], program_id)
360}
361
362/// Find PDA for a GLV deposit account.
363pub fn find_glv_deposit_address(
364    store: &Pubkey,
365    owner: &Pubkey,
366    nonce: &NonceBytes,
367    store_program_id: &Pubkey,
368) -> (Pubkey, u8) {
369    Pubkey::find_program_address(
370        &[GLV_DEPOSIT_SEED, store.as_ref(), owner.as_ref(), nonce],
371        store_program_id,
372    )
373}
374
375/// Find PDA for a GLV withdrawal account.
376pub fn find_glv_withdrawal_address(
377    store: &Pubkey,
378    owner: &Pubkey,
379    nonce: &NonceBytes,
380    store_program_id: &Pubkey,
381) -> (Pubkey, u8) {
382    Pubkey::find_program_address(
383        &[GLV_WITHDRAWAL_SEED, store.as_ref(), owner.as_ref(), nonce],
384        store_program_id,
385    )
386}
387
388/// Find PDA for GT exchange vault account.
389pub fn find_gt_exchange_vault_address(
390    store: &Pubkey,
391    time_window_index: i64,
392    time_window: u32,
393    store_program_id: &Pubkey,
394) -> (Pubkey, u8) {
395    Pubkey::find_program_address(
396        &[
397            GT_EXCHANGE_VAULT_SEED,
398            store.as_ref(),
399            &time_window_index.to_le_bytes(),
400            &time_window.to_le_bytes(),
401        ],
402        store_program_id,
403    )
404}
405
406/// Find PDA for GT exchange account.
407pub fn find_gt_exchange_address(
408    vault: &Pubkey,
409    owner: &Pubkey,
410    store_program_id: &Pubkey,
411) -> (Pubkey, u8) {
412    Pubkey::find_program_address(
413        &[GT_EXCHANGE_SEED, vault.as_ref(), owner.as_ref()],
414        store_program_id,
415    )
416}
417
418/// Fint PDA for custom price feed account.
419pub fn find_price_feed_address(
420    store: &Pubkey,
421    authority: &Pubkey,
422    index: u16,
423    provider: PriceProviderKind,
424    token: &Pubkey,
425    store_program_id: &Pubkey,
426) -> (Pubkey, u8) {
427    Pubkey::find_program_address(
428        &[
429            PRICE_FEED_SEED,
430            store.as_ref(),
431            authority.as_ref(),
432            &index.to_le_bytes(),
433            &[provider as u8],
434            token.as_ref(),
435        ],
436        store_program_id,
437    )
438}
439
440/// Find PDA for virtual inventory for swaps account.
441pub fn find_virtual_inventory_for_swaps_address(
442    store: &Pubkey,
443    index: u32,
444    store_program_id: &Pubkey,
445) -> (Pubkey, u8) {
446    Pubkey::find_program_address(
447        &[
448            VIRTUAL_INVENTORY_FOR_SWAPS_SEED,
449            store.as_ref(),
450            &index.to_le_bytes(),
451        ],
452        store_program_id,
453    )
454}
455
456/// Find PDA for virtual inventory for positions account.
457pub fn find_virtual_inventory_for_positions_address(
458    store: &Pubkey,
459    index_token: &Pubkey,
460    store_program_id: &Pubkey,
461) -> (Pubkey, u8) {
462    Pubkey::find_program_address(
463        &[
464            VIRTUAL_INVENTORY_FOR_POSITIONS_SEED,
465            store.as_ref(),
466            index_token.as_ref(),
467        ],
468        store_program_id,
469    )
470}
471
472/// Find PDA for global treasury config.
473#[cfg(treasury)]
474pub fn find_treasury_config_address(store: &Pubkey, treasury_program_id: &Pubkey) -> (Pubkey, u8) {
475    Pubkey::find_program_address(&[TREASURY_CONFIG_SEED, store.as_ref()], treasury_program_id)
476}
477
478/// Find PDA for treasury vault config.
479#[cfg(treasury)]
480pub fn find_treasury_vault_config_address(
481    config: &Pubkey,
482    index: u16,
483    treasury_program_id: &Pubkey,
484) -> (Pubkey, u8) {
485    Pubkey::find_program_address(
486        &[
487            TREASURY_VAULT_CONFIG_SEED,
488            config.as_ref(),
489            &index.to_le_bytes(),
490        ],
491        treasury_program_id,
492    )
493}
494
495/// Find PDA for GT bank.
496#[cfg(treasury)]
497pub fn find_gt_bank_address(
498    treasury_vault_config: &Pubkey,
499    gt_exchange_vault: &Pubkey,
500    treasury_program_id: &Pubkey,
501) -> (Pubkey, u8) {
502    Pubkey::find_program_address(
503        &[
504            GT_BANK_SEED,
505            treasury_vault_config.as_ref(),
506            gt_exchange_vault.as_ref(),
507        ],
508        treasury_program_id,
509    )
510}
511
512/// Find PDA for treasury receiver.
513#[cfg(treasury)]
514pub fn find_treasury_receiver_address(
515    config: &Pubkey,
516    treasury_program_id: &Pubkey,
517) -> (Pubkey, u8) {
518    Pubkey::find_program_address(
519        &[TREASURY_RECEIVER_SEED, config.as_ref()],
520        treasury_program_id,
521    )
522}
523
524/// Find PDA for timelock config.
525#[cfg(timelock)]
526pub fn find_timelock_config_address(store: &Pubkey, timelock_program_id: &Pubkey) -> (Pubkey, u8) {
527    Pubkey::find_program_address(&[TIMELOCK_CONFIG_SEED, store.as_ref()], timelock_program_id)
528}
529
530/// Find PDA for executor.
531#[cfg(timelock)]
532pub fn find_executor_address(
533    store: &Pubkey,
534    role: &str,
535    timelock_program_id: &Pubkey,
536) -> crate::Result<(Pubkey, u8)> {
537    Ok(Pubkey::find_program_address(
538        &[
539            TIMELOCK_EXECUTOR_SEED,
540            store.as_ref(),
541            &crate::utils::fixed_str::fixed_str_to_bytes::<
542                { gmsol_programs::constants::MAX_ROLE_NAME_LEN },
543            >(role)?,
544        ],
545        timelock_program_id,
546    ))
547}
548
549/// Find PDA for executor wallet.
550#[cfg(timelock)]
551pub fn find_executor_wallet_address(
552    executor: &Pubkey,
553    timelock_program_id: &Pubkey,
554) -> (Pubkey, u8) {
555    Pubkey::find_program_address(
556        &[TIMELOCK_EXECUTOR_WALLET_SEED, executor.as_ref()],
557        timelock_program_id,
558    )
559}
560
561/// Find PDA for callback authority.
562pub fn find_callback_authority(store_program_id: &Pubkey) -> (Pubkey, u8) {
563    Pubkey::find_program_address(&[CALLBACK_AUTHORITY_SEED], store_program_id)
564}
565
566/// Find PDA for competition account.
567#[cfg(competition)]
568pub fn find_competition_address(
569    authority: &Pubkey,
570    start_time: i64,
571    competition_program_id: &Pubkey,
572) -> (Pubkey, u8) {
573    Pubkey::find_program_address(
574        &[
575            COMPETITION_SEED,
576            authority.as_ref(),
577            &start_time.to_le_bytes(),
578        ],
579        competition_program_id,
580    )
581}
582
583/// Find PDA for participant account.
584#[cfg(competition)]
585pub fn find_participant_address(
586    competition: &Pubkey,
587    trader: &Pubkey,
588    competition_program_id: &Pubkey,
589) -> (Pubkey, u8) {
590    Pubkey::find_program_address(
591        &[PARTICIPANT_SEED, competition.as_ref(), trader.as_ref()],
592        competition_program_id,
593    )
594}
595
596/// Find PDA for global state account for the LP program.
597#[cfg(liquidity_provider)]
598pub fn find_lp_global_state_address(lp_program_id: &Pubkey) -> (Pubkey, u8) {
599    use gmsol_programs::gmsol_liquidity_provider::constants::GLOBAL_STATE_SEED;
600
601    Pubkey::find_program_address(&[GLOBAL_STATE_SEED], lp_program_id)
602}
603
604/// Find PDA for stake position account.
605#[cfg(liquidity_provider)]
606pub fn find_lp_stake_position_address(
607    owner: &Pubkey,
608    position_id: u64,
609    controller: &Pubkey,
610    lp_program_id: &Pubkey,
611) -> (Pubkey, u8) {
612    use gmsol_programs::gmsol_liquidity_provider::constants::POSITION_SEED;
613
614    Pubkey::find_program_address(
615        &[
616            POSITION_SEED,
617            controller.as_ref(),
618            owner.as_ref(),
619            &position_id.to_le_bytes(),
620        ],
621        lp_program_id,
622    )
623}
624
625/// Find PDA for stake position vault.
626#[cfg(liquidity_provider)]
627pub fn find_lp_stake_position_vault_address(
628    position: &Pubkey,
629    lp_program_id: &Pubkey,
630) -> (Pubkey, u8) {
631    use gmsol_programs::gmsol_liquidity_provider::constants::VAULT_SEED;
632
633    Pubkey::find_program_address(&[VAULT_SEED, position.as_ref()], lp_program_id)
634}
635
636/// Find PDA for LP token controller account.
637#[cfg(liquidity_provider)]
638pub fn find_lp_token_controller_address(
639    global_state: &Pubkey,
640    lp_token_mint: &Pubkey,
641    controller_index: u64,
642    lp_program_id: &Pubkey,
643) -> (Pubkey, u8) {
644    use gmsol_programs::gmsol_liquidity_provider::constants::LP_TOKEN_CONTROLLER_SEED;
645
646    Pubkey::find_program_address(
647        &[
648            LP_TOKEN_CONTROLLER_SEED,
649            global_state.as_ref(),
650            lp_token_mint.as_ref(),
651            &controller_index.to_le_bytes(),
652        ],
653        lp_program_id,
654    )
655}