mango-v4/programs/mango-v4/src/instructions/consume_events.rs

100 lines
3.7 KiB
Rust
Raw Normal View History

2022-03-28 12:13:16 -07:00
use anchor_lang::prelude::*;
use bytemuck::cast_ref;
use crate::error::MangoError;
use crate::{
state::{
EventQueueHeader, EventType, FillEvent, Group, MangoAccount, OutEvent, PerpMarket, Queue,
},
util::LoadZeroCopy,
};
2022-03-28 12:13:16 -07:00
#[derive(Accounts)]
pub struct ConsumeEvents<'info> {
pub group: AccountLoader<'info, Group>,
2022-03-28 12:13:16 -07:00
#[account(
mut,
has_one = group,
)]
2022-03-28 12:13:16 -07:00
pub perp_market: AccountLoader<'info, PerpMarket>,
#[account(mut)]
2022-03-28 12:13:16 -07:00
pub event_queue: AccountLoader<'info, Queue<EventQueueHeader>>,
}
pub fn consume_events(ctx: Context<ConsumeEvents>, limit: usize) -> Result<()> {
2022-03-28 12:13:16 -07:00
let limit = std::cmp::min(limit, 8);
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
2022-03-28 12:13:16 -07:00
let mut event_queue = ctx.accounts.event_queue.load_mut()?;
let mango_account_ais = &ctx.remaining_accounts;
2022-03-28 12:13:16 -07:00
for _ in 0..limit {
let event = match event_queue.peek_front() {
None => break,
Some(e) => e,
};
match EventType::try_from(event.event_type).map_err(|_| error!(MangoError::SomeError))? {
2022-03-28 12:13:16 -07:00
EventType::Fill => {
let fill: &FillEvent = cast_ref(event);
// handle self trade separately because of rust borrow checker
if fill.maker == fill.taker {
let mut ma = match mango_account_ais.iter().find(|ai| ai.key == &fill.maker) {
None => {
msg!("Unable to find account {}", fill.maker.to_string());
return Ok(());
}
Some(account_info) => account_info.load_mut::<MangoAccount>()?,
2022-03-28 12:13:16 -07:00
};
2022-03-28 12:13:16 -07:00
ma.execute_maker(perp_market.perp_market_index, &mut perp_market, fill)?;
ma.execute_taker(perp_market.perp_market_index, &mut perp_market, fill)?;
2022-03-28 12:13:16 -07:00
} else {
let mut maker = match mango_account_ais.iter().find(|ai| ai.key == &fill.maker)
{
None => {
msg!("Unable to find maker account {}", fill.maker.to_string());
return Ok(());
}
Some(account_info) => account_info.load_mut::<MangoAccount>()?,
2022-03-28 12:13:16 -07:00
};
let mut taker = match mango_account_ais.iter().find(|ai| ai.key == &fill.taker)
{
None => {
msg!("Unable to find taker account {}", fill.taker.to_string());
return Ok(());
}
Some(account_info) => account_info.load_mut::<MangoAccount>()?,
2022-03-28 12:13:16 -07:00
};
maker.execute_maker(perp_market.perp_market_index, &mut perp_market, fill)?;
taker.execute_taker(perp_market.perp_market_index, &mut perp_market, fill)?;
}
2022-03-28 12:13:16 -07:00
}
EventType::Out => {
let out: &OutEvent = cast_ref(event);
let mut ma = match mango_account_ais.iter().find(|ai| ai.key == &out.owner) {
None => {
msg!("Unable to find account {}", out.owner.to_string());
return Ok(());
}
Some(account_info) => account_info.load_mut::<MangoAccount>()?,
2022-03-28 12:13:16 -07:00
};
ma.remove_order(out.owner_slot as usize, out.quantity)?;
}
EventType::Liquidate => {
// This is purely for record keeping. Can be removed if program logs are superior
}
}
// consume this event
event_queue.pop_front()?;
}
Ok(())
}