Skip to main content

percli_program/instructions/
withdraw.rs

1use anchor_lang::prelude::*;
2
3use crate::error::{from_risk_error, PercolatorError};
4use crate::state::{engine_from_account_data, MARKET_ACCOUNT_SIZE};
5
6#[derive(Accounts)]
7pub struct Withdraw<'info> {
8    #[account(mut)]
9    pub user: Signer<'info>,
10
11    /// CHECK: Validated via discriminator, PDA seeds, and size.
12    #[account(
13        mut,
14        constraint = market.data_len() == MARKET_ACCOUNT_SIZE @ PercolatorError::AccountNotFound,
15    )]
16    pub market: UncheckedAccount<'info>,
17
18    pub system_program: Program<'info, System>,
19}
20
21pub fn handler(
22    ctx: Context<Withdraw>,
23    account_idx: u16,
24    amount: u128,
25    funding_rate: i64,
26) -> Result<()> {
27    let market = &ctx.accounts.market;
28    let mut data = market.try_borrow_mut_data()?;
29
30    require!(&data[0..8] == b"percmrkt", PercolatorError::AccountNotFound);
31
32    let engine = engine_from_account_data(&mut data);
33    let oracle_price = engine.last_oracle_price;
34    let clock = Clock::get()?;
35
36    engine
37        .withdraw(account_idx, amount, oracle_price, clock.slot, funding_rate)
38        .map_err(from_risk_error)?;
39
40    // TODO: integrate SPL token transfer from vault to user
41
42    Ok(())
43}