percli_program/instructions/
trade.rs1use anchor_lang::prelude::*;
2
3use crate::error::{from_risk_error, PercolatorError};
4use crate::instructions::events;
5use crate::state::{engine_from_account_data, header_from_account_data, MARKET_ACCOUNT_SIZE};
6
7#[derive(Accounts)]
8pub struct Trade<'info> {
9 pub signer: Signer<'info>,
11
12 #[account(
14 mut,
15 owner = crate::ID @ PercolatorError::AccountNotFound,
16 constraint = market.data_len() >= MARKET_ACCOUNT_SIZE @ PercolatorError::AccountNotFound,
17 )]
18 pub market: UncheckedAccount<'info>,
19}
20
21pub fn handler(
22 ctx: Context<Trade>,
23 account_a: u16,
24 account_b: u16,
25 size_q: i128,
26 exec_price: u64,
27 funding_rate: i64,
28) -> Result<()> {
29 require!(account_a != account_b, PercolatorError::InvalidMatchingEngine);
30
31 let market = &ctx.accounts.market;
32 let mut data = market.try_borrow_mut_data()?;
33
34 require!(crate::state::is_v1_market(&data), PercolatorError::AccountNotFound);
35
36 let header = header_from_account_data(&data)?;
38 require!(
39 header.matcher == ctx.accounts.signer.key(),
40 PercolatorError::Unauthorized
41 );
42
43 let engine = engine_from_account_data(&mut data);
44 let oracle_price = engine.last_oracle_price;
45 let clock = Clock::get()?;
46
47 engine
48 .execute_trade_not_atomic(
49 account_a,
50 account_b,
51 oracle_price,
52 clock.slot,
53 size_q,
54 exec_price,
55 funding_rate,
56 )
57 .map_err(from_risk_error)?;
58
59 emit!(events::TradeExecuted {
60 matcher: ctx.accounts.signer.key(),
61 account_a,
62 account_b,
63 size_q,
64 exec_price,
65 });
66
67 Ok(())
68}