use anchor_lang::prelude::*; use crate::accounts_ix::*; use crate::error::*; use crate::health::*; use crate::state::*; use crate::util::clock_now; pub fn perp_liq_force_cancel_orders( ctx: Context, limit: u8, ) -> Result<()> { let mut account = ctx.accounts.account.load_full_mut()?; let (now_ts, now_slot) = clock_now(); let mut health_cache = { let retriever = new_fixed_order_account_retriever(ctx.remaining_accounts, &account.borrow(), now_slot)?; new_health_cache(&account.borrow(), &retriever, now_ts).context("create health cache")? }; let mut perp_market = ctx.accounts.perp_market.load_mut()?; // // Early return if if liquidation is not allowed or if market is not in force close // let liquidatable = account.check_liquidatable(&health_cache)?; let can_force_cancel = !account.fixed.is_operational() || liquidatable == CheckLiquidatable::Liquidatable || perp_market.is_force_close(); if !can_force_cancel { return Ok(()); } // // Cancel orders // { let mut book = Orderbook { bids: ctx.accounts.bids.load_mut()?, asks: ctx.accounts.asks.load_mut()?, }; book.cancel_all_orders( &mut account.borrow_mut(), ctx.accounts.account.as_ref().key, &mut perp_market, limit, None, )?; let perp_position = account.perp_position(perp_market.perp_market_index)?; health_cache.recompute_perp_info(perp_position, &perp_market)?; } // // Health check at the end // let init_health = health_cache.health(HealthType::LiquidationEnd); account .fixed .maybe_recover_from_being_liquidated(init_health); Ok(()) }