gmsol_store/instructions/
token.rs1use anchor_lang::prelude::*;
2use anchor_spl::{
3 associated_token::AssociatedToken,
4 token::{Mint, Token, TokenAccount},
5 token_interface,
6};
7
8use crate::{
9 constants,
10 states::Store,
11 utils::{internal, token::must_be_uninitialized},
12};
13
14#[derive(Accounts)]
18pub struct InitializeMarketVault<'info> {
19 #[account(mut)]
21 pub authority: Signer<'info>,
22 pub store: AccountLoader<'info, Store>,
24 pub mint: Account<'info, Mint>,
26 #[account(
28 init_if_needed,
29 payer = authority,
30 token::mint = mint,
31 token::authority = store,
33 seeds = [
34 constants::MARKET_VAULT_SEED,
35 store.key().as_ref(),
36 mint.key().as_ref(),
37 ],
38 bump,
39 )]
40 pub vault: Account<'info, TokenAccount>,
41 pub system_program: Program<'info, System>,
43 pub token_program: Program<'info, Token>,
45}
46
47#[allow(unused_variables)]
53pub(crate) fn unchecked_initialize_market_vault(ctx: Context<InitializeMarketVault>) -> Result<()> {
54 Ok(())
55}
56
57impl<'info> internal::Authentication<'info> for InitializeMarketVault<'info> {
58 fn authority(&self) -> &Signer<'info> {
59 &self.authority
60 }
61
62 fn store(&self) -> &AccountLoader<'info, Store> {
63 &self.store
64 }
65}
66
67#[derive(Accounts)]
71#[instruction(timestamp: i64)]
72pub struct UseClaimableAccount<'info> {
73 #[account(mut)]
75 pub authority: Signer<'info>,
76 pub store: AccountLoader<'info, Store>,
78 pub mint: Account<'info, Mint>,
80 pub owner: UncheckedAccount<'info>,
83 #[account(
85 init_if_needed,
86 payer = authority,
87 token::mint = mint,
88 token::authority = store,
90 seeds = [
91 constants::CLAIMABLE_ACCOUNT_SEED,
92 store.key().as_ref(),
93 mint.key().as_ref(),
94 owner.key().as_ref(),
95 &store.load()?.claimable_time_key(timestamp)?,
96 ],
97 bump,
98 )]
99 pub account: Account<'info, TokenAccount>,
100 pub system_program: Program<'info, System>,
102 pub token_program: Program<'info, Token>,
104}
105
106pub(crate) fn unchecked_use_claimable_account(
111 ctx: Context<UseClaimableAccount>,
112 _timestamp: i64,
113 amount: u64,
114) -> Result<()> {
115 if ctx.accounts.account.delegate.is_none() || ctx.accounts.account.delegated_amount != amount {
116 anchor_spl::token::approve(
117 CpiContext::new_with_signer(
118 ctx.accounts.token_program.to_account_info(),
119 anchor_spl::token::Approve {
120 to: ctx.accounts.account.to_account_info(),
121 delegate: ctx.accounts.owner.to_account_info(),
122 authority: ctx.accounts.store.to_account_info(),
123 },
124 &[&ctx.accounts.store.load()?.signer_seeds()],
125 ),
126 amount,
127 )?;
128 }
129 Ok(())
130}
131
132impl<'info> internal::Authentication<'info> for UseClaimableAccount<'info> {
133 fn authority(&self) -> &Signer<'info> {
134 &self.authority
135 }
136
137 fn store(&self) -> &AccountLoader<'info, Store> {
138 &self.store
139 }
140}
141
142#[derive(Accounts)]
146#[instruction(timestamp: i64)]
147pub struct CloseEmptyClaimableAccount<'info> {
148 #[account(mut)]
150 pub authority: Signer<'info>,
151 pub store: AccountLoader<'info, Store>,
152 pub mint: Account<'info, Mint>,
153 pub owner: UncheckedAccount<'info>,
155 #[account(
157 mut,
158 seeds = [
159 constants::CLAIMABLE_ACCOUNT_SEED,
160 store.key().as_ref(),
161 mint.key().as_ref(),
162 owner.key().as_ref(),
163 &store.load()?.claimable_time_key(timestamp)?,
164 ],
165 bump,
166 )]
167 pub account: UncheckedAccount<'info>,
168 pub system_program: Program<'info, System>,
169 pub token_program: Program<'info, Token>,
170}
171
172pub(crate) fn unchecked_close_empty_claimable_account(
177 ctx: Context<CloseEmptyClaimableAccount>,
178 _timestamp: i64,
179) -> Result<()> {
180 if must_be_uninitialized(&ctx.accounts.account) {
181 return Ok(());
182 }
183 let account = ctx.accounts.account.to_account_info();
184 let amount = anchor_spl::token::accessor::amount(&account)?;
185 if amount == 0 {
186 anchor_spl::token::close_account(CpiContext::new_with_signer(
187 ctx.accounts.token_program.to_account_info(),
188 anchor_spl::token::CloseAccount {
189 account: ctx.accounts.account.to_account_info(),
190 destination: ctx.accounts.authority.to_account_info(),
191 authority: ctx.accounts.store.to_account_info(),
192 },
193 &[&ctx.accounts.store.load()?.signer_seeds()],
194 ))?;
195 }
196 Ok(())
197}
198
199impl<'info> internal::Authentication<'info> for CloseEmptyClaimableAccount<'info> {
200 fn authority(&self) -> &Signer<'info> {
201 &self.authority
202 }
203
204 fn store(&self) -> &AccountLoader<'info, Store> {
205 &self.store
206 }
207}
208
209#[derive(Accounts)]
213pub struct PrepareAssociatedTokenAccount<'info> {
214 #[account(mut)]
216 pub payer: Signer<'info>,
217 pub owner: UncheckedAccount<'info>,
219 pub mint: InterfaceAccount<'info, token_interface::Mint>,
221 #[account(
223 init_if_needed,
224 payer = payer,
225 associated_token::mint = mint,
226 associated_token::authority = owner,
227 )]
228 pub account: InterfaceAccount<'info, token_interface::TokenAccount>,
229 pub system_program: Program<'info, System>,
231 pub token_program: Interface<'info, token_interface::TokenInterface>,
233 pub associated_token_program: Program<'info, AssociatedToken>,
235}
236
237pub(crate) fn prepare_associated_token_account(
238 _ctx: Context<PrepareAssociatedTokenAccount>,
239) -> Result<()> {
240 Ok(())
241}