add_decimals/
transfer.rs

1use anchor_lang::prelude::*;
2use anchor_spl::token;
3
4/// Returns the program-derived-address seeds used for creating the associated
5/// account.
6#[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
18/// Creates a token instruction signed by the user.
19macro_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
27/// Creates a token instruction performed by the wrapper.
28macro_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
43/// Helper methods for interacting with the user stake.
44impl<'info> UserStake<'info> {
45    /// Transfer user's tokens to wrapper.
46    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    /// Burn user's wrapper tokens.
56    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    /// Mint wrapped tokens to user wrapped token account.
66    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    /// Transfer underlying tokens from wrapper to user.
76    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}