Split into perp bids and perp asks (#322)
Separate, smaller accounts that are easy to extend if needed.
This commit is contained in:
parent
c44dc045cf
commit
947d9b2b60
|
@ -870,7 +870,8 @@ impl MangoClient {
|
|||
group: self.group(),
|
||||
account: *liqee.0,
|
||||
perp_market: perp.address,
|
||||
orderbook: perp.market.orderbook,
|
||||
bids: perp.market.bids,
|
||||
asks: perp.market.asks,
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
|
|
@ -310,7 +310,8 @@ pub async fn loop_update_funding(
|
|||
&mango_v4::accounts::PerpUpdateFunding {
|
||||
group: perp_market.group,
|
||||
perp_market: pk,
|
||||
orderbook: perp_market.orderbook,
|
||||
bids: perp_market.bids,
|
||||
asks: perp_market.asks,
|
||||
oracle: perp_market.oracle,
|
||||
},
|
||||
None,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
use crate::error::MangoError;
|
||||
use crate::state::{AccountLoaderDynamic, Group, MangoAccount, Orderbook, PerpMarket};
|
||||
use crate::state::{AccountLoaderDynamic, BookSide, Group, MangoAccount, Orderbook, PerpMarket};
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpCancelAllOrders<'info> {
|
||||
|
@ -14,11 +14,14 @@ pub struct PerpCancelAllOrders<'info> {
|
|||
#[account(
|
||||
mut,
|
||||
has_one = group,
|
||||
has_one = orderbook,
|
||||
has_one = bids,
|
||||
has_one = asks,
|
||||
)]
|
||||
pub perp_market: AccountLoader<'info, PerpMarket>,
|
||||
#[account(mut)]
|
||||
pub orderbook: AccountLoader<'info, Orderbook>,
|
||||
pub bids: AccountLoader<'info, BookSide>,
|
||||
#[account(mut)]
|
||||
pub asks: AccountLoader<'info, BookSide>,
|
||||
}
|
||||
|
||||
pub fn perp_cancel_all_orders(ctx: Context<PerpCancelAllOrders>, limit: u8) -> Result<()> {
|
||||
|
@ -29,7 +32,10 @@ pub fn perp_cancel_all_orders(ctx: Context<PerpCancelAllOrders>, limit: u8) -> R
|
|||
);
|
||||
|
||||
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
|
||||
let mut book = ctx.accounts.orderbook.load_mut()?;
|
||||
let mut book = Orderbook {
|
||||
bids: ctx.accounts.bids.load_mut()?,
|
||||
asks: ctx.accounts.asks.load_mut()?,
|
||||
};
|
||||
|
||||
book.cancel_all_orders(&mut account.borrow_mut(), &mut perp_market, limit, None)?;
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
use crate::error::MangoError;
|
||||
use crate::state::{AccountLoaderDynamic, Group, MangoAccount, Orderbook, PerpMarket, Side};
|
||||
use crate::state::{
|
||||
AccountLoaderDynamic, BookSide, Group, MangoAccount, Orderbook, PerpMarket, Side,
|
||||
};
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpCancelAllOrdersBySide<'info> {
|
||||
|
@ -14,11 +16,14 @@ pub struct PerpCancelAllOrdersBySide<'info> {
|
|||
#[account(
|
||||
mut,
|
||||
has_one = group,
|
||||
has_one = orderbook,
|
||||
has_one = bids,
|
||||
has_one = asks,
|
||||
)]
|
||||
pub perp_market: AccountLoader<'info, PerpMarket>,
|
||||
#[account(mut)]
|
||||
pub orderbook: AccountLoader<'info, Orderbook>,
|
||||
pub bids: AccountLoader<'info, BookSide>,
|
||||
#[account(mut)]
|
||||
pub asks: AccountLoader<'info, BookSide>,
|
||||
}
|
||||
|
||||
pub fn perp_cancel_all_orders_by_side(
|
||||
|
@ -34,7 +39,10 @@ pub fn perp_cancel_all_orders_by_side(
|
|||
);
|
||||
|
||||
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
|
||||
let mut book = ctx.accounts.orderbook.load_mut()?;
|
||||
let mut book = Orderbook {
|
||||
bids: ctx.accounts.bids.load_init()?,
|
||||
asks: ctx.accounts.asks.load_init()?,
|
||||
};
|
||||
|
||||
book.cancel_all_orders(
|
||||
&mut account.borrow_mut(),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::state::{AccountLoaderDynamic, Group, MangoAccount, Orderbook, PerpMarket};
|
||||
use crate::state::{AccountLoaderDynamic, BookSide, Group, MangoAccount, Orderbook, PerpMarket};
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpCancelOrder<'info> {
|
||||
|
@ -14,11 +14,14 @@ pub struct PerpCancelOrder<'info> {
|
|||
#[account(
|
||||
mut,
|
||||
has_one = group,
|
||||
has_one = orderbook,
|
||||
has_one = bids,
|
||||
has_one = asks,
|
||||
)]
|
||||
pub perp_market: AccountLoader<'info, PerpMarket>,
|
||||
#[account(mut)]
|
||||
pub orderbook: AccountLoader<'info, Orderbook>,
|
||||
pub bids: AccountLoader<'info, BookSide>,
|
||||
#[account(mut)]
|
||||
pub asks: AccountLoader<'info, BookSide>,
|
||||
}
|
||||
|
||||
pub fn perp_cancel_order(ctx: Context<PerpCancelOrder>, order_id: u128) -> Result<()> {
|
||||
|
@ -29,7 +32,10 @@ pub fn perp_cancel_order(ctx: Context<PerpCancelOrder>, order_id: u128) -> Resul
|
|||
);
|
||||
|
||||
let perp_market = ctx.accounts.perp_market.load_mut()?;
|
||||
let mut book = ctx.accounts.orderbook.load_mut()?;
|
||||
let mut book = Orderbook {
|
||||
bids: ctx.accounts.bids.load_mut()?,
|
||||
asks: ctx.accounts.asks.load_mut()?,
|
||||
};
|
||||
|
||||
let oo = account
|
||||
.perp_find_order_with_order_id(perp_market.perp_market_index, order_id)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::state::{AccountLoaderDynamic, Group, MangoAccount, Orderbook, PerpMarket};
|
||||
use crate::state::{AccountLoaderDynamic, BookSide, Group, MangoAccount, Orderbook, PerpMarket};
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpCancelOrderByClientOrderId<'info> {
|
||||
|
@ -14,11 +14,14 @@ pub struct PerpCancelOrderByClientOrderId<'info> {
|
|||
#[account(
|
||||
mut,
|
||||
has_one = group,
|
||||
has_one = orderbook,
|
||||
has_one = bids,
|
||||
has_one = asks,
|
||||
)]
|
||||
pub perp_market: AccountLoader<'info, PerpMarket>,
|
||||
#[account(mut)]
|
||||
pub orderbook: AccountLoader<'info, Orderbook>,
|
||||
pub bids: AccountLoader<'info, BookSide>,
|
||||
#[account(mut)]
|
||||
pub asks: AccountLoader<'info, BookSide>,
|
||||
}
|
||||
|
||||
pub fn perp_cancel_order_by_client_order_id(
|
||||
|
@ -32,7 +35,10 @@ pub fn perp_cancel_order_by_client_order_id(
|
|||
);
|
||||
|
||||
let perp_market = ctx.accounts.perp_market.load_mut()?;
|
||||
let mut book = ctx.accounts.orderbook.load_mut()?;
|
||||
let mut book = Orderbook {
|
||||
bids: ctx.accounts.bids.load_mut()?,
|
||||
asks: ctx.accounts.asks.load_mut()?,
|
||||
};
|
||||
|
||||
let oo = account
|
||||
.perp_find_order_with_client_order_id(perp_market.perp_market_index, client_order_id)
|
||||
|
|
|
@ -15,7 +15,8 @@ pub struct PerpCloseMarket<'info> {
|
|||
#[account(
|
||||
mut,
|
||||
has_one = group,
|
||||
has_one = orderbook,
|
||||
has_one = bids,
|
||||
has_one = asks,
|
||||
has_one = event_queue,
|
||||
close = sol_destination
|
||||
)]
|
||||
|
@ -25,7 +26,13 @@ pub struct PerpCloseMarket<'info> {
|
|||
mut,
|
||||
close = sol_destination
|
||||
)]
|
||||
pub orderbook: AccountLoader<'info, Orderbook>,
|
||||
pub bids: AccountLoader<'info, BookSide>,
|
||||
|
||||
#[account(
|
||||
mut,
|
||||
close = sol_destination
|
||||
)]
|
||||
pub asks: AccountLoader<'info, BookSide>,
|
||||
|
||||
#[account(
|
||||
mut,
|
||||
|
|
|
@ -33,7 +33,9 @@ pub struct PerpCreateMarket<'info> {
|
|||
/// Accounts are initialised by client,
|
||||
/// anchor discriminator is set first when ix exits,
|
||||
#[account(zero)]
|
||||
pub orderbook: AccountLoader<'info, Orderbook>,
|
||||
pub bids: AccountLoader<'info, BookSide>,
|
||||
#[account(zero)]
|
||||
pub asks: AccountLoader<'info, BookSide>,
|
||||
#[account(zero)]
|
||||
pub event_queue: AccountLoader<'info, EventQueue>,
|
||||
|
||||
|
@ -95,7 +97,8 @@ pub fn perp_create_market(
|
|||
bump: *ctx.bumps.get("perp_market").ok_or(MangoError::SomeError)?,
|
||||
base_decimals,
|
||||
name: fill_from_str(&name)?,
|
||||
orderbook: ctx.accounts.orderbook.key(),
|
||||
bids: ctx.accounts.bids.key(),
|
||||
asks: ctx.accounts.asks.key(),
|
||||
event_queue: ctx.accounts.event_queue.key(),
|
||||
oracle: ctx.accounts.oracle.key(),
|
||||
oracle_config: oracle_config.to_oracle_config(),
|
||||
|
@ -136,7 +139,10 @@ pub fn perp_create_market(
|
|||
.stable_price_model
|
||||
.reset_to_price(oracle_price.to_num(), now_ts);
|
||||
|
||||
let mut orderbook = ctx.accounts.orderbook.load_init()?;
|
||||
let mut orderbook = Orderbook {
|
||||
bids: ctx.accounts.bids.load_init()?,
|
||||
asks: ctx.accounts.asks.load_init()?,
|
||||
};
|
||||
orderbook.init();
|
||||
|
||||
emit!(PerpMarketMetaDataLog {
|
||||
|
|
|
@ -14,11 +14,14 @@ pub struct PerpLiqForceCancelOrders<'info> {
|
|||
#[account(
|
||||
mut,
|
||||
has_one = group,
|
||||
has_one = orderbook,
|
||||
has_one = bids,
|
||||
has_one = asks,
|
||||
)]
|
||||
pub perp_market: AccountLoader<'info, PerpMarket>,
|
||||
#[account(mut)]
|
||||
pub orderbook: AccountLoader<'info, Orderbook>,
|
||||
pub bids: AccountLoader<'info, BookSide>,
|
||||
#[account(mut)]
|
||||
pub asks: AccountLoader<'info, BookSide>,
|
||||
}
|
||||
|
||||
pub fn perp_liq_force_cancel_orders(
|
||||
|
@ -62,7 +65,10 @@ pub fn perp_liq_force_cancel_orders(
|
|||
//
|
||||
{
|
||||
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
|
||||
let mut book = ctx.accounts.orderbook.load_mut()?;
|
||||
let mut book = Orderbook {
|
||||
bids: ctx.accounts.bids.load_mut()?,
|
||||
asks: ctx.accounts.asks.load_mut()?,
|
||||
};
|
||||
|
||||
book.cancel_all_orders(&mut account.borrow_mut(), &mut perp_market, limit, None)?;
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ use crate::accounts_zerocopy::*;
|
|||
use crate::error::*;
|
||||
use crate::state::MangoAccount;
|
||||
use crate::state::{
|
||||
new_fixed_order_account_retriever, new_health_cache, AccountLoaderDynamic, EventQueue, Group,
|
||||
Order, Orderbook, PerpMarket,
|
||||
new_fixed_order_account_retriever, new_health_cache, AccountLoaderDynamic, BookSide,
|
||||
EventQueue, Group, Order, Orderbook, PerpMarket,
|
||||
};
|
||||
|
||||
#[derive(Accounts)]
|
||||
|
@ -19,13 +19,16 @@ pub struct PerpPlaceOrder<'info> {
|
|||
#[account(
|
||||
mut,
|
||||
has_one = group,
|
||||
has_one = orderbook,
|
||||
has_one = bids,
|
||||
has_one = asks,
|
||||
has_one = event_queue,
|
||||
has_one = oracle,
|
||||
)]
|
||||
pub perp_market: AccountLoader<'info, PerpMarket>,
|
||||
#[account(mut)]
|
||||
pub orderbook: AccountLoader<'info, Orderbook>,
|
||||
pub bids: AccountLoader<'info, BookSide>,
|
||||
#[account(mut)]
|
||||
pub asks: AccountLoader<'info, BookSide>,
|
||||
#[account(mut)]
|
||||
pub event_queue: AccountLoader<'info, EventQueue>,
|
||||
|
||||
|
@ -48,7 +51,10 @@ pub fn perp_place_order(ctx: Context<PerpPlaceOrder>, order: Order, limit: u8) -
|
|||
// before triggering the funding computation.
|
||||
{
|
||||
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
|
||||
let book = ctx.accounts.orderbook.load_mut()?;
|
||||
let book = Orderbook {
|
||||
bids: ctx.accounts.bids.load_mut()?,
|
||||
asks: ctx.accounts.asks.load_mut()?,
|
||||
};
|
||||
|
||||
oracle_price = perp_market.oracle_price(
|
||||
&AccountInfoRef::borrow(ctx.accounts.oracle.as_ref())?,
|
||||
|
@ -94,7 +100,10 @@ pub fn perp_place_order(ctx: Context<PerpPlaceOrder>, order: Order, limit: u8) -
|
|||
};
|
||||
|
||||
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
|
||||
let mut book = ctx.accounts.orderbook.load_mut()?;
|
||||
let mut book = Orderbook {
|
||||
bids: ctx.accounts.bids.load_mut()?,
|
||||
asks: ctx.accounts.asks.load_mut()?,
|
||||
};
|
||||
|
||||
let mut event_queue = ctx.accounts.event_queue.load_mut()?;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
use crate::accounts_zerocopy::*;
|
||||
use crate::state::{Group, Orderbook, PerpMarket};
|
||||
use crate::state::{BookSide, Group, Orderbook, PerpMarket};
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct PerpUpdateFunding<'info> {
|
||||
|
@ -9,13 +9,16 @@ pub struct PerpUpdateFunding<'info> {
|
|||
|
||||
#[account(
|
||||
mut,
|
||||
has_one = orderbook,
|
||||
has_one = bids,
|
||||
has_one = asks,
|
||||
has_one = oracle,
|
||||
constraint = perp_market.load()?.group.key() == group.key(),
|
||||
)]
|
||||
pub perp_market: AccountLoader<'info, PerpMarket>,
|
||||
#[account(mut)]
|
||||
pub orderbook: AccountLoader<'info, Orderbook>,
|
||||
pub bids: AccountLoader<'info, BookSide>,
|
||||
#[account(mut)]
|
||||
pub asks: AccountLoader<'info, BookSide>,
|
||||
|
||||
/// CHECK: The oracle can be one of several different account types and the pubkey is checked above
|
||||
pub oracle: UncheckedAccount<'info>,
|
||||
|
@ -24,7 +27,10 @@ pub fn perp_update_funding(ctx: Context<PerpUpdateFunding>) -> Result<()> {
|
|||
let now_ts: u64 = Clock::get()?.unix_timestamp.try_into().unwrap();
|
||||
|
||||
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
|
||||
let book = ctx.accounts.orderbook.load_mut()?;
|
||||
let book = Orderbook {
|
||||
bids: ctx.accounts.bids.load_mut()?,
|
||||
asks: ctx.accounts.asks.load_mut()?,
|
||||
};
|
||||
|
||||
let now_slot = Clock::get()?.slot;
|
||||
let oracle_price = perp_market.oracle_price(
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
use anchor_lang::prelude::*;
|
||||
use bytemuck::cast;
|
||||
use fixed::types::I80F48;
|
||||
use static_assertions::const_assert_eq;
|
||||
use std::cell::RefMut;
|
||||
|
||||
use super::*;
|
||||
use crate::util::checked_math as cm;
|
||||
|
@ -15,20 +15,12 @@ use crate::util::checked_math as cm;
|
|||
/// This exists as a guard against excessive compute use.
|
||||
const DROP_EXPIRED_ORDER_LIMIT: usize = 5;
|
||||
|
||||
#[account(zero_copy(safe_bytemuck_derives))]
|
||||
pub struct Orderbook {
|
||||
pub bids: BookSide,
|
||||
pub asks: BookSide,
|
||||
pub reserved: [u8; 2400],
|
||||
pub struct Orderbook<'a> {
|
||||
pub bids: RefMut<'a, BookSide>,
|
||||
pub asks: RefMut<'a, BookSide>,
|
||||
}
|
||||
const_assert_eq!(
|
||||
std::mem::size_of::<Orderbook>(),
|
||||
2 * std::mem::size_of::<BookSide>() + 2400
|
||||
);
|
||||
const_assert_eq!(std::mem::size_of::<Orderbook>(), 249824);
|
||||
const_assert_eq!(std::mem::size_of::<Orderbook>() % 8, 0);
|
||||
|
||||
impl Orderbook {
|
||||
impl<'a> Orderbook<'a> {
|
||||
pub fn init(&mut self) {
|
||||
self.bids.nodes.order_tree_type = OrderTreeType::Bids.into();
|
||||
self.asks.nodes.order_tree_type = OrderTreeType::Asks.into();
|
||||
|
|
|
@ -27,8 +27,7 @@ pub struct BookSideOrderHandle {
|
|||
pub order_tree: BookSideOrderTree,
|
||||
}
|
||||
|
||||
#[zero_copy]
|
||||
#[derive(bytemuck::Pod, bytemuck::Zeroable)]
|
||||
#[account(zero_copy(safe_bytemuck_derives))]
|
||||
pub struct BookSide {
|
||||
pub roots: [OrderTreeRoot; 2],
|
||||
pub reserved_roots: [OrderTreeRoot; 4],
|
||||
|
|
|
@ -26,6 +26,7 @@ mod tests {
|
|||
use bytemuck::Zeroable;
|
||||
use fixed::types::I80F48;
|
||||
use solana_program::pubkey::Pubkey;
|
||||
use std::cell::RefCell;
|
||||
|
||||
fn order_tree_leaf_by_key(bookside: &BookSide, key: u128) -> Option<&LeafNode> {
|
||||
for component in [BookSideOrderTree::Fixed, BookSideOrderTree::OraclePegged] {
|
||||
|
@ -53,9 +54,32 @@ mod tests {
|
|||
false
|
||||
}
|
||||
|
||||
fn test_setup(price: f64) -> (PerpMarket, I80F48, EventQueue, Box<Orderbook>) {
|
||||
let mut book = Box::new(Orderbook::zeroed());
|
||||
book.init();
|
||||
struct OrderbookAccounts {
|
||||
bids: Box<RefCell<BookSide>>,
|
||||
asks: Box<RefCell<BookSide>>,
|
||||
}
|
||||
|
||||
impl OrderbookAccounts {
|
||||
fn new() -> Self {
|
||||
let s = Self {
|
||||
bids: Box::new(RefCell::new(BookSide::zeroed())),
|
||||
asks: Box::new(RefCell::new(BookSide::zeroed())),
|
||||
};
|
||||
s.bids.borrow_mut().nodes.order_tree_type = OrderTreeType::Bids.into();
|
||||
s.asks.borrow_mut().nodes.order_tree_type = OrderTreeType::Asks.into();
|
||||
s
|
||||
}
|
||||
|
||||
fn orderbook(&self) -> Orderbook {
|
||||
Orderbook {
|
||||
bids: self.bids.borrow_mut(),
|
||||
asks: self.asks.borrow_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_setup(price: f64) -> (PerpMarket, I80F48, EventQueue, OrderbookAccounts) {
|
||||
let book = OrderbookAccounts::new();
|
||||
|
||||
let event_queue = EventQueue::zeroed();
|
||||
|
||||
|
@ -75,7 +99,8 @@ mod tests {
|
|||
// Check what happens when one side of the book fills up
|
||||
#[test]
|
||||
fn book_bids_full() {
|
||||
let (mut perp_market, oracle_price, mut event_queue, mut book) = test_setup(5000.0);
|
||||
let (mut perp_market, oracle_price, mut event_queue, book_accs) = test_setup(5000.0);
|
||||
let mut book = book_accs.orderbook();
|
||||
let settle_token_index = 0;
|
||||
|
||||
let mut new_order = |book: &mut Orderbook,
|
||||
|
@ -212,7 +237,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn book_new_order() {
|
||||
let (mut market, oracle_price, mut event_queue, mut book) = test_setup(1000.0);
|
||||
let (mut market, oracle_price, mut event_queue, book_accs) = test_setup(1000.0);
|
||||
let mut book = book_accs.orderbook();
|
||||
let settle_token_index = 0;
|
||||
|
||||
// Add lots and fees to make sure to exercise unit conversion
|
||||
|
@ -405,7 +431,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_fee_penalty_applied_only_on_limit_order() -> Result<()> {
|
||||
let (mut market, oracle_price, mut event_queue, mut book) = test_setup(1000.0);
|
||||
let (mut market, oracle_price, mut event_queue, book_accs) = test_setup(1000.0);
|
||||
let mut book = book_accs.orderbook();
|
||||
|
||||
let buffer = MangoAccount::default_for_tests().try_to_vec().unwrap();
|
||||
let mut account = MangoAccountValue::from_bytes(&buffer).unwrap();
|
||||
|
|
|
@ -39,7 +39,8 @@ pub struct PerpMarket {
|
|||
|
||||
pub name: [u8; 16],
|
||||
|
||||
pub orderbook: Pubkey,
|
||||
pub bids: Pubkey,
|
||||
pub asks: Pubkey,
|
||||
pub event_queue: Pubkey,
|
||||
|
||||
pub oracle: Pubkey,
|
||||
|
@ -116,6 +117,7 @@ const_assert_eq!(
|
|||
+ 32
|
||||
+ 32
|
||||
+ 32
|
||||
+ 32
|
||||
+ 96
|
||||
+ 288
|
||||
+ 8
|
||||
|
@ -137,7 +139,7 @@ const_assert_eq!(
|
|||
+ 8
|
||||
+ 1944
|
||||
);
|
||||
const_assert_eq!(size_of::<PerpMarket>(), 2776);
|
||||
const_assert_eq!(size_of::<PerpMarket>(), 2808);
|
||||
const_assert_eq!(size_of::<PerpMarket>() % 8, 0);
|
||||
|
||||
impl PerpMarket {
|
||||
|
@ -303,7 +305,8 @@ impl PerpMarket {
|
|||
trusted_market: 0,
|
||||
group_insurance_fund: 0,
|
||||
name: Default::default(),
|
||||
orderbook: Pubkey::new_unique(),
|
||||
bids: Pubkey::new_unique(),
|
||||
asks: Pubkey::new_unique(),
|
||||
event_queue: Pubkey::new_unique(),
|
||||
oracle: Pubkey::new_unique(),
|
||||
oracle_config: OracleConfig {
|
||||
|
|
|
@ -2410,7 +2410,8 @@ pub struct PerpCreateMarketInstruction {
|
|||
pub group: Pubkey,
|
||||
pub admin: TestKeypair,
|
||||
pub oracle: Pubkey,
|
||||
pub orderbook: Pubkey,
|
||||
pub bids: Pubkey,
|
||||
pub asks: Pubkey,
|
||||
pub event_queue: Pubkey,
|
||||
pub payer: TestKeypair,
|
||||
pub settle_token_index: TokenIndex,
|
||||
|
@ -2440,8 +2441,11 @@ impl PerpCreateMarketInstruction {
|
|||
base: &crate::mango_setup::Token,
|
||||
) -> Self {
|
||||
PerpCreateMarketInstruction {
|
||||
orderbook: solana
|
||||
.create_account_for_type::<Orderbook>(&mango_v4::id())
|
||||
bids: solana
|
||||
.create_account_for_type::<BookSide>(&mango_v4::id())
|
||||
.await,
|
||||
asks: solana
|
||||
.create_account_for_type::<BookSide>(&mango_v4::id())
|
||||
.await,
|
||||
event_queue: solana
|
||||
.create_account_for_type::<EventQueue>(&mango_v4::id())
|
||||
|
@ -2507,7 +2511,8 @@ impl ClientInstruction for PerpCreateMarketInstruction {
|
|||
admin: self.admin.pubkey(),
|
||||
oracle: self.oracle,
|
||||
perp_market,
|
||||
orderbook: self.orderbook,
|
||||
bids: self.bids,
|
||||
asks: self.asks,
|
||||
event_queue: self.event_queue,
|
||||
payer: self.payer.pubkey(),
|
||||
system_program: System::id(),
|
||||
|
@ -2604,7 +2609,8 @@ impl ClientInstruction for PerpCloseMarketInstruction {
|
|||
group: perp_market.group,
|
||||
admin: self.admin.pubkey(),
|
||||
perp_market: self.perp_market,
|
||||
orderbook: perp_market.orderbook,
|
||||
bids: perp_market.bids,
|
||||
asks: perp_market.asks,
|
||||
event_queue: perp_market.event_queue,
|
||||
token_program: Token::id(),
|
||||
sol_destination: self.sol_destination,
|
||||
|
@ -2701,7 +2707,8 @@ impl ClientInstruction for PerpPlaceOrderInstruction {
|
|||
group: account.fixed.group,
|
||||
account: self.account,
|
||||
perp_market: self.perp_market,
|
||||
orderbook: perp_market.orderbook,
|
||||
bids: perp_market.bids,
|
||||
asks: perp_market.asks,
|
||||
event_queue: perp_market.event_queue,
|
||||
oracle: perp_market.oracle,
|
||||
owner: self.owner.pubkey(),
|
||||
|
@ -2769,7 +2776,8 @@ impl ClientInstruction for PerpPlaceOrderPeggedInstruction {
|
|||
group: account.fixed.group,
|
||||
account: self.account,
|
||||
perp_market: self.perp_market,
|
||||
orderbook: perp_market.orderbook,
|
||||
bids: perp_market.bids,
|
||||
asks: perp_market.asks,
|
||||
event_queue: perp_market.event_queue,
|
||||
oracle: perp_market.oracle,
|
||||
owner: self.owner.pubkey(),
|
||||
|
@ -2808,7 +2816,8 @@ impl ClientInstruction for PerpCancelOrderInstruction {
|
|||
group: perp_market.group,
|
||||
account: self.account,
|
||||
perp_market: self.perp_market,
|
||||
orderbook: perp_market.orderbook,
|
||||
bids: perp_market.bids,
|
||||
asks: perp_market.asks,
|
||||
owner: self.owner.pubkey(),
|
||||
};
|
||||
|
||||
|
@ -2844,7 +2853,8 @@ impl ClientInstruction for PerpCancelOrderByClientOrderIdInstruction {
|
|||
group: perp_market.group,
|
||||
account: self.account,
|
||||
perp_market: self.perp_market,
|
||||
orderbook: perp_market.orderbook,
|
||||
bids: perp_market.bids,
|
||||
asks: perp_market.asks,
|
||||
owner: self.owner.pubkey(),
|
||||
};
|
||||
|
||||
|
@ -2877,7 +2887,8 @@ impl ClientInstruction for PerpCancelAllOrdersInstruction {
|
|||
group: perp_market.group,
|
||||
account: self.account,
|
||||
perp_market: self.perp_market,
|
||||
orderbook: perp_market.orderbook,
|
||||
bids: perp_market.bids,
|
||||
asks: perp_market.asks,
|
||||
owner: self.owner.pubkey(),
|
||||
};
|
||||
|
||||
|
@ -2947,7 +2958,8 @@ impl ClientInstruction for PerpUpdateFundingInstruction {
|
|||
let accounts = Self::Accounts {
|
||||
group: perp_market.group,
|
||||
perp_market: self.perp_market,
|
||||
orderbook: perp_market.orderbook,
|
||||
bids: perp_market.bids,
|
||||
asks: perp_market.asks,
|
||||
oracle: self.oracle,
|
||||
};
|
||||
|
||||
|
@ -3109,7 +3121,8 @@ impl ClientInstruction for PerpLiqForceCancelOrdersInstruction {
|
|||
group: account.fixed.group,
|
||||
perp_market: self.perp_market,
|
||||
account: self.account,
|
||||
orderbook: perp_market.orderbook,
|
||||
bids: perp_market.bids,
|
||||
asks: perp_market.asks,
|
||||
};
|
||||
let mut instruction = make_instruction(program_id, &accounts, instruction);
|
||||
instruction.accounts.extend(health_check_metas);
|
||||
|
|
|
@ -66,9 +66,7 @@ async fn test_perp_fixed() -> Result<(), TransportError> {
|
|||
// TEST: Create a perp market
|
||||
//
|
||||
let mango_v4::accounts::PerpCreateMarket {
|
||||
perp_market,
|
||||
orderbook,
|
||||
..
|
||||
perp_market, bids, ..
|
||||
} = send_tx(
|
||||
solana,
|
||||
PerpCreateMarketInstruction {
|
||||
|
@ -118,8 +116,8 @@ async fn test_perp_fixed() -> Result<(), TransportError> {
|
|||
.unwrap();
|
||||
check_prev_instruction_post_health(&solana, account_0).await;
|
||||
|
||||
let orderbook_data = solana.get_account_boxed::<Orderbook>(orderbook).await;
|
||||
assert_eq!(orderbook_data.bids.roots[0].leaf_count, 1);
|
||||
let bids_data = solana.get_account_boxed::<BookSide>(bids).await;
|
||||
assert_eq!(bids_data.roots[0].leaf_count, 1);
|
||||
let order_id_to_cancel = solana
|
||||
.get_account::<MangoAccount>(account_0)
|
||||
.await
|
||||
|
@ -504,9 +502,7 @@ async fn test_perp_oracle_peg() -> Result<(), TransportError> {
|
|||
// SETUP: Create a perp market
|
||||
//
|
||||
let mango_v4::accounts::PerpCreateMarket {
|
||||
perp_market,
|
||||
orderbook,
|
||||
..
|
||||
perp_market, bids, ..
|
||||
} = send_tx(
|
||||
solana,
|
||||
PerpCreateMarketInstruction {
|
||||
|
@ -558,8 +554,8 @@ async fn test_perp_oracle_peg() -> Result<(), TransportError> {
|
|||
.unwrap();
|
||||
check_prev_instruction_post_health(&solana, account_0).await;
|
||||
|
||||
let orderbook_data = solana.get_account_boxed::<Orderbook>(orderbook).await;
|
||||
assert_eq!(orderbook_data.bids.roots[1].leaf_count, 1);
|
||||
let bids_data = solana.get_account_boxed::<BookSide>(bids).await;
|
||||
assert_eq!(bids_data.roots[1].leaf_count, 1);
|
||||
let perp_order = solana
|
||||
.get_account::<MangoAccount>(account_0)
|
||||
.await
|
||||
|
|
|
@ -38,7 +38,8 @@ export class PerpMarket {
|
|||
private baseLotsToUiConverter: number;
|
||||
private quoteLotsToUiConverter: number;
|
||||
|
||||
private _orderbook: Orderbook;
|
||||
private _bids: BookSide;
|
||||
private _asks: BookSide;
|
||||
|
||||
static from(
|
||||
publicKey: PublicKey,
|
||||
|
@ -50,7 +51,8 @@ export class PerpMarket {
|
|||
groupInsuranceFund: number;
|
||||
baseDecimals: number;
|
||||
name: number[];
|
||||
orderbook: PublicKey;
|
||||
bids: PublicKey;
|
||||
asks: PublicKey;
|
||||
eventQueue: PublicKey;
|
||||
oracle: PublicKey;
|
||||
oracleConfig: OracleConfig;
|
||||
|
@ -92,7 +94,8 @@ export class PerpMarket {
|
|||
obj.groupInsuranceFund == 1,
|
||||
obj.baseDecimals,
|
||||
obj.name,
|
||||
obj.orderbook,
|
||||
obj.bids,
|
||||
obj.asks,
|
||||
obj.eventQueue,
|
||||
obj.oracle,
|
||||
obj.oracleConfig,
|
||||
|
@ -135,7 +138,8 @@ export class PerpMarket {
|
|||
public groupInsuranceFund: boolean,
|
||||
public baseDecimals: number,
|
||||
name: number[],
|
||||
public orderbook: PublicKey,
|
||||
public bids: PublicKey,
|
||||
public asks: PublicKey,
|
||||
public eventQueue: PublicKey,
|
||||
public oracle: PublicKey,
|
||||
oracleConfig: OracleConfig,
|
||||
|
@ -223,25 +227,26 @@ export class PerpMarket {
|
|||
return this.priceLotsToUiConverter;
|
||||
}
|
||||
|
||||
private async loadOrderbook(
|
||||
public async loadAsks(
|
||||
client: MangoClient,
|
||||
forceReload = false,
|
||||
): Promise<Orderbook> {
|
||||
if (forceReload || !this._orderbook)
|
||||
this._orderbook = await client.program.account.orderbook.fetch(
|
||||
this.orderbook,
|
||||
);
|
||||
return this._orderbook;
|
||||
): Promise<BookSide> {
|
||||
if (forceReload || !this._asks) {
|
||||
const asks = await client.program.account.bookSide.fetch(this.asks);
|
||||
this._asks = BookSide.from(client, this, BookSideType.asks, asks as any);
|
||||
}
|
||||
return this._asks;
|
||||
}
|
||||
|
||||
public async loadAsks(client: MangoClient): Promise<BookSide> {
|
||||
await this.loadOrderbook(client);
|
||||
return BookSide.from(client, this, BookSideType.asks, this._orderbook.asks);
|
||||
}
|
||||
|
||||
public async loadBids(client: MangoClient): Promise<BookSide> {
|
||||
await this.loadOrderbook(client);
|
||||
return BookSide.from(client, this, BookSideType.bids, this._orderbook.bids);
|
||||
public async loadBids(
|
||||
client: MangoClient,
|
||||
forceReload = false,
|
||||
): Promise<BookSide> {
|
||||
if (forceReload || !this._bids) {
|
||||
const bids = await client.program.account.bookSide.fetch(this.bids);
|
||||
this._bids = BookSide.from(client, this, BookSideType.bids, bids as any);
|
||||
}
|
||||
return this._bids;
|
||||
}
|
||||
|
||||
public async loadEventQueue(client: MangoClient): Promise<PerpEventQueue> {
|
||||
|
@ -452,28 +457,16 @@ export class PerpMarket {
|
|||
}
|
||||
}
|
||||
|
||||
interface Orderbook {
|
||||
bids: OrderTree;
|
||||
asks: OrderTree;
|
||||
interface OrderTreeNodes {
|
||||
bumpIndex: number;
|
||||
freeListLen: number;
|
||||
freeListHead: number;
|
||||
nodes: [any];
|
||||
}
|
||||
|
||||
interface OrderTree {
|
||||
fixed: {
|
||||
bumpIndex: number;
|
||||
freeListLen: number;
|
||||
freeListHead: number;
|
||||
rootNode: number;
|
||||
leafCount: number;
|
||||
nodes: [any];
|
||||
};
|
||||
oraclePegged: {
|
||||
bumpIndex: number;
|
||||
freeListLen: number;
|
||||
freeListHead: number;
|
||||
rootNode: number;
|
||||
leafCount: number;
|
||||
nodes: [any];
|
||||
};
|
||||
interface OrderTreeRoot {
|
||||
maybeNode: number;
|
||||
leafCount: number;
|
||||
}
|
||||
|
||||
export class BookSide {
|
||||
|
@ -486,59 +479,34 @@ export class BookSide {
|
|||
perpMarket: PerpMarket,
|
||||
bookSideType: BookSideType,
|
||||
obj: {
|
||||
fixed: {
|
||||
bumpIndex: number;
|
||||
freeListLen: number;
|
||||
freeListHead: number;
|
||||
rootNode: number;
|
||||
leafCount: number;
|
||||
nodes: [any];
|
||||
};
|
||||
oraclePegged: {
|
||||
bumpIndex: number;
|
||||
freeListLen: number;
|
||||
freeListHead: number;
|
||||
rootNode: number;
|
||||
leafCount: number;
|
||||
nodes: [any];
|
||||
};
|
||||
roots: OrderTreeRoot[];
|
||||
orderTree: OrderTreeNodes;
|
||||
},
|
||||
): BookSide {
|
||||
return new BookSide(client, perpMarket, bookSideType, obj);
|
||||
return new BookSide(
|
||||
client,
|
||||
perpMarket,
|
||||
bookSideType,
|
||||
obj.roots[0],
|
||||
obj.roots[1],
|
||||
obj.orderTree,
|
||||
);
|
||||
}
|
||||
|
||||
constructor(
|
||||
public client: MangoClient,
|
||||
public perpMarket: PerpMarket,
|
||||
public type: BookSideType,
|
||||
public orderTree: {
|
||||
fixed: {
|
||||
bumpIndex: number;
|
||||
freeListLen: number;
|
||||
freeListHead: number;
|
||||
rootNode: number;
|
||||
leafCount: number;
|
||||
nodes: [any];
|
||||
};
|
||||
oraclePegged: {
|
||||
bumpIndex: number;
|
||||
freeListLen: number;
|
||||
freeListHead: number;
|
||||
rootNode: number;
|
||||
leafCount: number;
|
||||
nodes: [any];
|
||||
};
|
||||
},
|
||||
public rootFixed: OrderTreeRoot,
|
||||
public rootOraclePegged: OrderTreeRoot,
|
||||
public orderTree: OrderTreeNodes,
|
||||
maxBookDelay?: number,
|
||||
) {
|
||||
// Determine the maxTimestamp found on the book to use for tif
|
||||
// If maxBookDelay is not provided, use 3600 as a very large number
|
||||
maxBookDelay = maxBookDelay === undefined ? 3600 : maxBookDelay;
|
||||
let maxTimestamp = new BN(new Date().getTime() / 1000 - maxBookDelay);
|
||||
for (const node of [
|
||||
...this.orderTree.fixed.nodes,
|
||||
...this.orderTree.oraclePegged.nodes,
|
||||
]) {
|
||||
for (const node of this.orderTree.nodes) {
|
||||
if (node.tag !== BookSide.LEAF_NODE_TAG) {
|
||||
continue;
|
||||
}
|
||||
|
@ -624,16 +592,16 @@ export class BookSide {
|
|||
}
|
||||
|
||||
public *fixedItems(): Generator<PerpOrder> {
|
||||
if (this.orderTree.fixed.leafCount === 0) {
|
||||
if (this.rootFixed.leafCount === 0) {
|
||||
return;
|
||||
}
|
||||
const now = this.now;
|
||||
const stack = [this.orderTree.fixed.rootNode];
|
||||
const stack = [this.rootFixed.maybeNode];
|
||||
const [left, right] = this.type === BookSideType.bids ? [1, 0] : [0, 1];
|
||||
|
||||
while (stack.length > 0) {
|
||||
const index = stack.pop()!;
|
||||
const node = this.orderTree.fixed.nodes[index];
|
||||
const node = this.orderTree.nodes[index];
|
||||
if (node.tag === BookSide.INNER_NODE_TAG) {
|
||||
const innerNode = BookSide.toInnerNode(this.client, node.data);
|
||||
stack.push(innerNode.children[right], innerNode.children[left]);
|
||||
|
@ -654,16 +622,16 @@ export class BookSide {
|
|||
}
|
||||
|
||||
public *oraclePeggedItems(): Generator<PerpOrder> {
|
||||
if (this.orderTree.oraclePegged.leafCount === 0) {
|
||||
if (this.rootOraclePegged.leafCount === 0) {
|
||||
return;
|
||||
}
|
||||
const now = this.now;
|
||||
const stack = [this.orderTree.oraclePegged.rootNode];
|
||||
const stack = [this.rootOraclePegged.maybeNode];
|
||||
const [left, right] = this.type === BookSideType.bids ? [1, 0] : [0, 1];
|
||||
|
||||
while (stack.length > 0) {
|
||||
const index = stack.pop()!;
|
||||
const node = this.orderTree.oraclePegged.nodes[index];
|
||||
const node = this.orderTree.nodes[index];
|
||||
if (node.tag === BookSide.INNER_NODE_TAG) {
|
||||
const innerNode = BookSide.toInnerNode(this.client, node.data);
|
||||
stack.push(innerNode.children[right], innerNode.children[left]);
|
||||
|
|
|
@ -1399,11 +1399,12 @@ export class MangoClient {
|
|||
settlePnlLimitFactor: number,
|
||||
settlePnlLimitWindowSize: number,
|
||||
): Promise<TransactionSignature> {
|
||||
const orderbook = new Keypair();
|
||||
const bids = new Keypair();
|
||||
const asks = new Keypair();
|
||||
const eventQueue = new Keypair();
|
||||
|
||||
const orderbookSize = (this.program as any)._coder.accounts.size(
|
||||
(this.program.account.orderbook as any)._idlAccount,
|
||||
const bookSideSize = (this.program as any)._coder.accounts.size(
|
||||
(this.program.account.bookSide as any)._idlAccount,
|
||||
);
|
||||
const eventQueueSize = (this.program as any)._coder.accounts.size(
|
||||
(this.program.account.eventQueue as any)._idlAccount,
|
||||
|
@ -1441,7 +1442,8 @@ export class MangoClient {
|
|||
group: group.publicKey,
|
||||
admin: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||
oracle: oraclePk,
|
||||
orderbook: orderbook.publicKey,
|
||||
bids: bids.publicKey,
|
||||
asks: asks.publicKey,
|
||||
eventQueue: eventQueue.publicKey,
|
||||
payer: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||
})
|
||||
|
@ -1449,14 +1451,25 @@ export class MangoClient {
|
|||
// book sides
|
||||
SystemProgram.createAccount({
|
||||
programId: this.program.programId,
|
||||
space: orderbookSize,
|
||||
space: bookSideSize,
|
||||
lamports:
|
||||
await this.program.provider.connection.getMinimumBalanceForRentExemption(
|
||||
orderbookSize,
|
||||
bookSideSize,
|
||||
),
|
||||
fromPubkey: (this.program.provider as AnchorProvider).wallet
|
||||
.publicKey,
|
||||
newAccountPubkey: orderbook.publicKey,
|
||||
newAccountPubkey: bids.publicKey,
|
||||
}),
|
||||
SystemProgram.createAccount({
|
||||
programId: this.program.programId,
|
||||
space: bookSideSize,
|
||||
lamports:
|
||||
await this.program.provider.connection.getMinimumBalanceForRentExemption(
|
||||
bookSideSize,
|
||||
),
|
||||
fromPubkey: (this.program.provider as AnchorProvider).wallet
|
||||
.publicKey,
|
||||
newAccountPubkey: asks.publicKey,
|
||||
}),
|
||||
// event queue
|
||||
SystemProgram.createAccount({
|
||||
|
@ -1471,7 +1484,7 @@ export class MangoClient {
|
|||
newAccountPubkey: eventQueue.publicKey,
|
||||
}),
|
||||
])
|
||||
.signers([orderbook, eventQueue])
|
||||
.signers([bids, asks, eventQueue])
|
||||
.rpc();
|
||||
}
|
||||
|
||||
|
@ -1555,7 +1568,8 @@ export class MangoClient {
|
|||
group: group.publicKey,
|
||||
admin: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||
perpMarket: perpMarket.publicKey,
|
||||
orderbook: perpMarket.orderbook,
|
||||
bids: perpMarket.bids,
|
||||
asks: perpMarket.asks,
|
||||
eventQueue: perpMarket.eventQueue,
|
||||
solDestination: (this.program.provider as AnchorProvider).wallet
|
||||
.publicKey,
|
||||
|
@ -1693,7 +1707,8 @@ export class MangoClient {
|
|||
group: group.publicKey,
|
||||
account: mangoAccount.publicKey,
|
||||
perpMarket: perpMarket.publicKey,
|
||||
orderbook: perpMarket.orderbook,
|
||||
bids: perpMarket.bids,
|
||||
asks: perpMarket.asks,
|
||||
eventQueue: perpMarket.eventQueue,
|
||||
oracle: perpMarket.oracle,
|
||||
owner: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||
|
@ -1793,7 +1808,8 @@ export class MangoClient {
|
|||
group: group.publicKey,
|
||||
account: mangoAccount.publicKey,
|
||||
perpMarket: perpMarket.publicKey,
|
||||
orderbook: perpMarket.orderbook,
|
||||
bids: perpMarket.bids,
|
||||
asks: perpMarket.asks,
|
||||
eventQueue: perpMarket.eventQueue,
|
||||
oracle: perpMarket.oracle,
|
||||
owner: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||
|
@ -1821,7 +1837,8 @@ export class MangoClient {
|
|||
account: mangoAccount.publicKey,
|
||||
owner: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||
perpMarket: perpMarket.publicKey,
|
||||
orderbook: perpMarket.orderbook,
|
||||
bids: perpMarket.bids,
|
||||
asks: perpMarket.asks,
|
||||
})
|
||||
.instruction();
|
||||
}
|
||||
|
@ -1885,7 +1902,8 @@ export class MangoClient {
|
|||
group: group.publicKey,
|
||||
account: mangoAccount.publicKey,
|
||||
perpMarket: perpMarket.publicKey,
|
||||
orderbook: perpMarket.orderbook,
|
||||
bids: perpMarket.bids,
|
||||
asks: perpMarket.asks,
|
||||
owner: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||
})
|
||||
.instruction();
|
||||
|
|
|
@ -2351,7 +2351,7 @@ export type MangoV4 = {
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false,
|
||||
"docs": [
|
||||
|
@ -2359,6 +2359,11 @@ export type MangoV4 = {
|
|||
"anchor discriminator is set first when ix exits,"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "eventQueue",
|
||||
"isMut": true,
|
||||
|
@ -2672,7 +2677,12 @@ export type MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
|
@ -2744,7 +2754,12 @@ export type MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
|
@ -2826,7 +2841,12 @@ export type MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
|
@ -2916,7 +2936,12 @@ export type MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
}
|
||||
|
@ -2952,7 +2977,12 @@ export type MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
}
|
||||
|
@ -2988,7 +3018,12 @@ export type MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
}
|
||||
|
@ -3024,7 +3059,12 @@ export type MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
}
|
||||
|
@ -3084,7 +3124,12 @@ export type MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
|
@ -3248,7 +3293,12 @@ export type MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
}
|
||||
|
@ -4032,20 +4082,30 @@ export type MangoV4 = {
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bookSide",
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"fields": [
|
||||
{
|
||||
"name": "bids",
|
||||
"name": "roots",
|
||||
"type": {
|
||||
"defined": "BookSide"
|
||||
"array": [
|
||||
{
|
||||
"defined": "OrderTreeRoot"
|
||||
},
|
||||
2
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"name": "reservedRoots",
|
||||
"type": {
|
||||
"defined": "BookSide"
|
||||
"array": [
|
||||
{
|
||||
"defined": "OrderTreeRoot"
|
||||
},
|
||||
4
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -4053,9 +4113,15 @@ export type MangoV4 = {
|
|||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
2400
|
||||
256
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nodes",
|
||||
"type": {
|
||||
"defined": "OrderTreeNodes"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -4149,7 +4215,11 @@ export type MangoV4 = {
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
|
@ -5077,9 +5147,7 @@ export type MangoV4 = {
|
|||
"fields": [
|
||||
{
|
||||
"name": "sideAndTree",
|
||||
"type": {
|
||||
"defined": "SideAndOrderTree"
|
||||
}
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "padding1",
|
||||
|
@ -5123,6 +5191,81 @@ export type MangoV4 = {
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "MangoAccountFixed",
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"fields": [
|
||||
{
|
||||
"name": "group",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
"name": "owner",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
32
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "delegate",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
"name": "accountNum",
|
||||
"type": "u32"
|
||||
},
|
||||
{
|
||||
"name": "beingLiquidated",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "inHealthRegion",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "bump",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "padding",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
1
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "netDeposits",
|
||||
"type": "i64"
|
||||
},
|
||||
{
|
||||
"name": "perpSpotTransfers",
|
||||
"type": "i64"
|
||||
},
|
||||
{
|
||||
"name": "healthRegionBeginInitHealth",
|
||||
"type": "i64"
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
240
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "OracleConfig",
|
||||
"type": {
|
||||
|
@ -5168,26 +5311,6 @@ export type MangoV4 = {
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "BookSide",
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"fields": [
|
||||
{
|
||||
"name": "fixed",
|
||||
"type": {
|
||||
"defined": "OrderTree"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "oraclePegged",
|
||||
"type": {
|
||||
"defined": "OrderTree"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "InnerNode",
|
||||
"docs": [
|
||||
|
@ -5376,7 +5499,7 @@ export type MangoV4 = {
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "OrderTree",
|
||||
"name": "OrderTreeNodes",
|
||||
"docs": [
|
||||
"A binary tree on AnyNode::key()",
|
||||
"",
|
||||
|
@ -5387,9 +5510,7 @@ export type MangoV4 = {
|
|||
"fields": [
|
||||
{
|
||||
"name": "orderTreeType",
|
||||
"type": {
|
||||
"defined": "OrderTreeType"
|
||||
}
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "padding",
|
||||
|
@ -5413,12 +5534,13 @@ export type MangoV4 = {
|
|||
"type": "u32"
|
||||
},
|
||||
{
|
||||
"name": "rootNode",
|
||||
"type": "u32"
|
||||
},
|
||||
{
|
||||
"name": "leafCount",
|
||||
"type": "u32"
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
512
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nodes",
|
||||
|
@ -5430,15 +5552,6 @@ export type MangoV4 = {
|
|||
1024
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
256
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -7276,6 +7389,11 @@ export type MangoV4 = {
|
|||
"code": 6027,
|
||||
"name": "BankNetBorrowsLimitReached",
|
||||
"msg": "bank net borrows has reached limit - this is an intermittent error - the limit will reset regularly"
|
||||
},
|
||||
{
|
||||
"code": 6028,
|
||||
"name": "TokenPositionDoesNotExist",
|
||||
"msg": "token position does not exist"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -9633,7 +9751,7 @@ export const IDL: MangoV4 = {
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false,
|
||||
"docs": [
|
||||
|
@ -9641,6 +9759,11 @@ export const IDL: MangoV4 = {
|
|||
"anchor discriminator is set first when ix exits,"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "eventQueue",
|
||||
"isMut": true,
|
||||
|
@ -9954,7 +10077,12 @@ export const IDL: MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
|
@ -10026,7 +10154,12 @@ export const IDL: MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
|
@ -10108,7 +10241,12 @@ export const IDL: MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
|
@ -10198,7 +10336,12 @@ export const IDL: MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
}
|
||||
|
@ -10234,7 +10377,12 @@ export const IDL: MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
}
|
||||
|
@ -10270,7 +10418,12 @@ export const IDL: MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
}
|
||||
|
@ -10306,7 +10459,12 @@ export const IDL: MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
}
|
||||
|
@ -10366,7 +10524,12 @@ export const IDL: MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
|
@ -10530,7 +10693,12 @@ export const IDL: MangoV4 = {
|
|||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
}
|
||||
|
@ -11314,20 +11482,30 @@ export const IDL: MangoV4 = {
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bookSide",
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"fields": [
|
||||
{
|
||||
"name": "bids",
|
||||
"name": "roots",
|
||||
"type": {
|
||||
"defined": "BookSide"
|
||||
"array": [
|
||||
{
|
||||
"defined": "OrderTreeRoot"
|
||||
},
|
||||
2
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"name": "reservedRoots",
|
||||
"type": {
|
||||
"defined": "BookSide"
|
||||
"array": [
|
||||
{
|
||||
"defined": "OrderTreeRoot"
|
||||
},
|
||||
4
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -11335,9 +11513,15 @@ export const IDL: MangoV4 = {
|
|||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
2400
|
||||
256
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nodes",
|
||||
"type": {
|
||||
"defined": "OrderTreeNodes"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -11431,7 +11615,11 @@ export const IDL: MangoV4 = {
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "orderbook",
|
||||
"name": "bids",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
"name": "asks",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
|
@ -12359,9 +12547,7 @@ export const IDL: MangoV4 = {
|
|||
"fields": [
|
||||
{
|
||||
"name": "sideAndTree",
|
||||
"type": {
|
||||
"defined": "SideAndOrderTree"
|
||||
}
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "padding1",
|
||||
|
@ -12405,6 +12591,81 @@ export const IDL: MangoV4 = {
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "MangoAccountFixed",
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"fields": [
|
||||
{
|
||||
"name": "group",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
"name": "owner",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
32
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "delegate",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
"name": "accountNum",
|
||||
"type": "u32"
|
||||
},
|
||||
{
|
||||
"name": "beingLiquidated",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "inHealthRegion",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "bump",
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "padding",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
1
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "netDeposits",
|
||||
"type": "i64"
|
||||
},
|
||||
{
|
||||
"name": "perpSpotTransfers",
|
||||
"type": "i64"
|
||||
},
|
||||
{
|
||||
"name": "healthRegionBeginInitHealth",
|
||||
"type": "i64"
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
240
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "OracleConfig",
|
||||
"type": {
|
||||
|
@ -12450,26 +12711,6 @@ export const IDL: MangoV4 = {
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "BookSide",
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"fields": [
|
||||
{
|
||||
"name": "fixed",
|
||||
"type": {
|
||||
"defined": "OrderTree"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "oraclePegged",
|
||||
"type": {
|
||||
"defined": "OrderTree"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "InnerNode",
|
||||
"docs": [
|
||||
|
@ -12658,7 +12899,7 @@ export const IDL: MangoV4 = {
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "OrderTree",
|
||||
"name": "OrderTreeNodes",
|
||||
"docs": [
|
||||
"A binary tree on AnyNode::key()",
|
||||
"",
|
||||
|
@ -12669,9 +12910,7 @@ export const IDL: MangoV4 = {
|
|||
"fields": [
|
||||
{
|
||||
"name": "orderTreeType",
|
||||
"type": {
|
||||
"defined": "OrderTreeType"
|
||||
}
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"name": "padding",
|
||||
|
@ -12695,12 +12934,13 @@ export const IDL: MangoV4 = {
|
|||
"type": "u32"
|
||||
},
|
||||
{
|
||||
"name": "rootNode",
|
||||
"type": "u32"
|
||||
},
|
||||
{
|
||||
"name": "leafCount",
|
||||
"type": "u32"
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
512
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nodes",
|
||||
|
@ -12712,15 +12952,6 @@ export const IDL: MangoV4 = {
|
|||
1024
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
256
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -14558,6 +14789,11 @@ export const IDL: MangoV4 = {
|
|||
"code": 6027,
|
||||
"name": "BankNetBorrowsLimitReached",
|
||||
"msg": "bank net borrows has reached limit - this is an intermittent error - the limit will reset regularly"
|
||||
},
|
||||
{
|
||||
"code": 6028,
|
||||
"name": "TokenPositionDoesNotExist",
|
||||
"msg": "token position does not exist"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
|
@ -648,7 +648,8 @@ async function createAndPopulateAlt() {
|
|||
.map((perpMarket) => [
|
||||
perpMarket.publicKey,
|
||||
perpMarket.oracle,
|
||||
perpMarket.orderbook,
|
||||
perpMarket.bids,
|
||||
perpMarket.asks,
|
||||
perpMarket.eventQueue,
|
||||
])
|
||||
.flat();
|
||||
|
|
Loading…
Reference in New Issue