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
14pub trait TokenAccountOps<C> {
16 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 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 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}