1use anchor_lang::prelude::*;
2use anchor_spl::token;
3
4#[macro_export]
7macro_rules! associated_seeds {
8 ($state:expr, $($with:expr),+) => {
9 &[
10 b"anchor".as_ref(),
11 $($with),+,
12 ]
13 };
14}
15
16use crate::UserStake;
17
18macro_rules! perform_as_user {
20 ($self:expr, $method:ident, $accounts:expr, $amount:expr) => {{
21 let cpi_program = $self.token_program.to_account_info();
22 let cpi_ctx = CpiContext::new(cpi_program, $accounts);
23 token::$method(cpi_ctx, $amount)
24 }};
25}
26
27macro_rules! perform_as_wrapper {
29 ($self:expr, $accounts:expr, $method:ident, $amount:expr) => {{
30 let seeds = $crate::associated_seeds!(
31 $self.wrapper,
32 $self.wrapper.wrapper_underlying_mint.as_ref(),
33 &[$self.wrapper.decimals],
34 &[$self.wrapper.nonce()]
35 );
36 let signer = &[&seeds[..]];
37 let cpi_program = $self.token_program.to_account_info();
38 let cpi_ctx = CpiContext::new_with_signer(cpi_program, $accounts, signer);
39 token::$method(cpi_ctx, $amount)
40 }};
41}
42
43impl<'info> UserStake<'info> {
45 pub fn deposit_underlying(&self, amount: u64) -> Result<()> {
47 let cpi_accounts = token::Transfer {
48 from: self.user_underlying_tokens.to_account_info(),
49 to: self.wrapper_underlying_tokens.to_account_info(),
50 authority: self.owner.to_account_info(),
51 };
52 perform_as_user!(self, transfer, cpi_accounts, amount)
53 }
54
55 pub fn burn_wrapped(&self, amount: u64) -> Result<()> {
57 let cpi_accounts = token::Burn {
58 mint: self.wrapper_mint.to_account_info(),
59 from: self.user_wrapped_tokens.to_account_info(),
60 authority: self.owner.to_account_info(),
61 };
62 perform_as_user!(self, burn, cpi_accounts, amount)
63 }
64
65 pub fn mint_wrapped(&self, amount: u64) -> Result<()> {
67 let cpi_accounts = token::MintTo {
68 mint: self.wrapper_mint.to_account_info(),
69 to: self.user_wrapped_tokens.to_account_info(),
70 authority: self.wrapper.to_account_info(),
71 };
72 perform_as_wrapper!(self, cpi_accounts, mint_to, amount)
73 }
74
75 pub fn withdraw_underlying(&self, amount: u64) -> Result<()> {
77 let cpi_accounts = token::Transfer {
78 from: self.wrapper_underlying_tokens.to_account_info(),
79 to: self.user_underlying_tokens.to_account_info(),
80 authority: self.wrapper.to_account_info(),
81 };
82 perform_as_wrapper!(self, cpi_accounts, transfer, amount)
83 }
84}