gmsol/store/
token.rs

1use std::ops::Deref;
2
3use anchor_client::{
4    anchor_lang::{
5        system_program::{self, System},
6        Id,
7    },
8    solana_sdk::{pubkey::Pubkey, signer::Signer},
9};
10use anchor_spl::{associated_token::get_associated_token_address_with_program_id, token::Token};
11use gmsol_solana_utils::transaction_builder::TransactionBuilder;
12use gmsol_store::{accounts, instruction};
13
14/// Token accounts management for GMSOL.
15pub trait TokenAccountOps<C> {
16    /// Prepare a claimable account.
17    fn use_claimable_account(
18        &self,
19        store: &Pubkey,
20        mint: &Pubkey,
21        user: &Pubkey,
22        timestamp: i64,
23        account: &Pubkey,
24        amount: u64,
25    ) -> TransactionBuilder<C>;
26
27    /// Close a claimable account if it is emtpy.
28    fn close_empty_claimable_account(
29        &self,
30        store: &Pubkey,
31        mint: &Pubkey,
32        user: &Pubkey,
33        timestamp: i64,
34        account: &Pubkey,
35    ) -> TransactionBuilder<C>;
36
37    /// Prepare associated token account.
38    fn prepare_associated_token_account(
39        &self,
40        mint: &Pubkey,
41        token_program_id: &Pubkey,
42        owner: Option<&Pubkey>,
43    ) -> TransactionBuilder<C>;
44}
45
46impl<C, S> TokenAccountOps<C> for crate::Client<C>
47where
48    C: Deref<Target = S> + Clone,
49    S: Signer,
50{
51    fn use_claimable_account(
52        &self,
53        store: &Pubkey,
54        mint: &Pubkey,
55        owner: &Pubkey,
56        timestamp: i64,
57        account: &Pubkey,
58        amount: u64,
59    ) -> TransactionBuilder<C> {
60        let authority = self.payer();
61        self.store_transaction()
62            .anchor_args(instruction::UseClaimableAccount { timestamp, amount })
63            .anchor_accounts(accounts::UseClaimableAccount {
64                authority,
65                store: *store,
66                mint: *mint,
67                owner: *owner,
68                account: *account,
69                system_program: System::id(),
70                token_program: Token::id(),
71            })
72    }
73
74    fn close_empty_claimable_account(
75        &self,
76        store: &Pubkey,
77        mint: &Pubkey,
78        owner: &Pubkey,
79        timestamp: i64,
80        account: &Pubkey,
81    ) -> TransactionBuilder<C> {
82        let authority = self.payer();
83        self.store_transaction()
84            .anchor_args(instruction::CloseEmptyClaimableAccount { timestamp })
85            .anchor_accounts(accounts::CloseEmptyClaimableAccount {
86                authority,
87                store: *store,
88                mint: *mint,
89                owner: *owner,
90                account: *account,
91                system_program: System::id(),
92                token_program: Token::id(),
93            })
94    }
95
96    fn prepare_associated_token_account(
97        &self,
98        mint: &Pubkey,
99        token_program_id: &Pubkey,
100        owner: Option<&Pubkey>,
101    ) -> TransactionBuilder<C> {
102        let payer = self.payer();
103        let owner = owner.copied().unwrap_or(payer);
104        let account = get_associated_token_address_with_program_id(&owner, mint, token_program_id);
105        self.store_transaction()
106            .anchor_accounts(accounts::PrepareAssociatedTokenAccount {
107                payer,
108                owner,
109                mint: *mint,
110                account,
111                system_program: system_program::ID,
112                token_program: *token_program_id,
113                associated_token_program: anchor_spl::associated_token::ID,
114            })
115            .anchor_args(instruction::PrepareAssociatedTokenAccount {})
116    }
117}