triad_protocol/instructions/stake/
request_withdraw_stake.rs

1use crate::constants::TTRIAD_MINT;
2use crate::constraints::{ is_authority_for_stake, is_mint_for_stake };
3use crate::{ StakeV2, User };
4use crate::{ errors::TriadProtocolError, StakeVault };
5use anchor_lang::prelude::*;
6use anchor_spl::token_2022::Token2022;
7use anchor_spl::token_interface::Mint;
8
9#[derive(Accounts)]
10pub struct RequestWithdrawStake<'info> {
11    #[account(mut)]
12    pub signer: Signer<'info>,
13
14    #[account(mut)]
15    pub stake_vault: Box<Account<'info, StakeVault>>,
16
17    #[account(mut, constraint = user.authority == *signer.key)]
18    pub user: Box<Account<'info, User>>,
19
20    #[account(mut, constraint = is_authority_for_stake(&stake, &signer)?)]
21    pub stake: Box<Account<'info, StakeV2>>,
22
23    #[account(mut, constraint = is_mint_for_stake(&stake, &mint.key())?)]
24    pub mint: Box<InterfaceAccount<'info, Mint>>,
25
26    pub token_program: Program<'info, Token2022>,
27    pub system_program: Program<'info, System>,
28}
29
30pub fn request_withdraw_stake(ctx: Context<RequestWithdrawStake>) -> Result<()> {
31    let stake: &mut Box<Account<StakeV2>> = &mut ctx.accounts.stake;
32    let user: &mut Box<Account<User>> = &mut ctx.accounts.user;
33    let stake_vault: &mut Box<Account<StakeVault>> = &mut ctx.accounts.stake_vault;
34
35    if stake.withdraw_ts != 0 {
36        return Err(TriadProtocolError::Unauthorized.into());
37    }
38
39    let mut days = 3;
40
41    if stake.mint.to_string() == TTRIAD_MINT {
42        days = 7;
43
44        let result = user.staked / (10u64).pow(stake_vault.token_decimals as u32) / 10000;
45
46        if result > (i16::MAX as u64) {
47            return Err(TriadProtocolError::StakeOverflow.into());
48        } else {
49            user.swaps = result as i16;
50        }
51    }
52
53    stake.withdraw_ts = Clock::get()?.unix_timestamp + days * 24 * 60 * 60;
54
55    Ok(())
56}