diff --git a/client/src/client.rs b/client/src/client.rs index 7bdfcb656..3c5fac667 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -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, ); diff --git a/keeper/src/crank.rs b/keeper/src/crank.rs index 20fd8ebe3..f50999a32 100644 --- a/keeper/src/crank.rs +++ b/keeper/src/crank.rs @@ -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, diff --git a/programs/mango-v4/src/instructions/perp_cancel_all_orders.rs b/programs/mango-v4/src/instructions/perp_cancel_all_orders.rs index ccd1d089d..ae442f57b 100644 --- a/programs/mango-v4/src/instructions/perp_cancel_all_orders.rs +++ b/programs/mango-v4/src/instructions/perp_cancel_all_orders.rs @@ -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, limit: u8) -> Result<()> { @@ -29,7 +32,10 @@ pub fn perp_cancel_all_orders(ctx: Context, 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)?; diff --git a/programs/mango-v4/src/instructions/perp_cancel_all_orders_by_side.rs b/programs/mango-v4/src/instructions/perp_cancel_all_orders_by_side.rs index c17a8ffd1..f983d0f6b 100644 --- a/programs/mango-v4/src/instructions/perp_cancel_all_orders_by_side.rs +++ b/programs/mango-v4/src/instructions/perp_cancel_all_orders_by_side.rs @@ -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(), diff --git a/programs/mango-v4/src/instructions/perp_cancel_order.rs b/programs/mango-v4/src/instructions/perp_cancel_order.rs index 021b0e272..c60666eb9 100644 --- a/programs/mango-v4/src/instructions/perp_cancel_order.rs +++ b/programs/mango-v4/src/instructions/perp_cancel_order.rs @@ -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, order_id: u128) -> Result<()> { @@ -29,7 +32,10 @@ pub fn perp_cancel_order(ctx: Context, 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) diff --git a/programs/mango-v4/src/instructions/perp_cancel_order_by_client_order_id.rs b/programs/mango-v4/src/instructions/perp_cancel_order_by_client_order_id.rs index 3ae2a3743..0009b607a 100644 --- a/programs/mango-v4/src/instructions/perp_cancel_order_by_client_order_id.rs +++ b/programs/mango-v4/src/instructions/perp_cancel_order_by_client_order_id.rs @@ -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) diff --git a/programs/mango-v4/src/instructions/perp_close_market.rs b/programs/mango-v4/src/instructions/perp_close_market.rs index c389dcba2..90c3bcdae 100644 --- a/programs/mango-v4/src/instructions/perp_close_market.rs +++ b/programs/mango-v4/src/instructions/perp_close_market.rs @@ -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, diff --git a/programs/mango-v4/src/instructions/perp_create_market.rs b/programs/mango-v4/src/instructions/perp_create_market.rs index 610af5bcc..a68126c89 100644 --- a/programs/mango-v4/src/instructions/perp_create_market.rs +++ b/programs/mango-v4/src/instructions/perp_create_market.rs @@ -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 { diff --git a/programs/mango-v4/src/instructions/perp_liq_force_cancel_orders.rs b/programs/mango-v4/src/instructions/perp_liq_force_cancel_orders.rs index e24ca938c..a09544c20 100644 --- a/programs/mango-v4/src/instructions/perp_liq_force_cancel_orders.rs +++ b/programs/mango-v4/src/instructions/perp_liq_force_cancel_orders.rs @@ -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)?; diff --git a/programs/mango-v4/src/instructions/perp_place_order.rs b/programs/mango-v4/src/instructions/perp_place_order.rs index a01540317..73ba43dac 100644 --- a/programs/mango-v4/src/instructions/perp_place_order.rs +++ b/programs/mango-v4/src/instructions/perp_place_order.rs @@ -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, 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, 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()?; diff --git a/programs/mango-v4/src/instructions/perp_update_funding.rs b/programs/mango-v4/src/instructions/perp_update_funding.rs index 363f8f67f..bfcd93ea1 100644 --- a/programs/mango-v4/src/instructions/perp_update_funding.rs +++ b/programs/mango-v4/src/instructions/perp_update_funding.rs @@ -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) -> 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( diff --git a/programs/mango-v4/src/state/orderbook/book.rs b/programs/mango-v4/src/state/orderbook/book.rs index e16920cd2..723d6dd49 100644 --- a/programs/mango-v4/src/state/orderbook/book.rs +++ b/programs/mango-v4/src/state/orderbook/book.rs @@ -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::(), - 2 * std::mem::size_of::() + 2400 -); -const_assert_eq!(std::mem::size_of::(), 249824); -const_assert_eq!(std::mem::size_of::() % 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(); diff --git a/programs/mango-v4/src/state/orderbook/bookside.rs b/programs/mango-v4/src/state/orderbook/bookside.rs index aed14a377..f5af2bc82 100644 --- a/programs/mango-v4/src/state/orderbook/bookside.rs +++ b/programs/mango-v4/src/state/orderbook/bookside.rs @@ -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], diff --git a/programs/mango-v4/src/state/orderbook/mod.rs b/programs/mango-v4/src/state/orderbook/mod.rs index c4f029f2f..15db0b69e 100644 --- a/programs/mango-v4/src/state/orderbook/mod.rs +++ b/programs/mango-v4/src/state/orderbook/mod.rs @@ -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) { - let mut book = Box::new(Orderbook::zeroed()); - book.init(); + struct OrderbookAccounts { + bids: Box>, + asks: Box>, + } + + 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(); diff --git a/programs/mango-v4/src/state/perp_market.rs b/programs/mango-v4/src/state/perp_market.rs index 6b043ea89..44ac5182a 100644 --- a/programs/mango-v4/src/state/perp_market.rs +++ b/programs/mango-v4/src/state/perp_market.rs @@ -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::(), 2776); +const_assert_eq!(size_of::(), 2808); const_assert_eq!(size_of::() % 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 { diff --git a/programs/mango-v4/tests/program_test/mango_client.rs b/programs/mango-v4/tests/program_test/mango_client.rs index 2a5e966f7..2e8815e21 100644 --- a/programs/mango-v4/tests/program_test/mango_client.rs +++ b/programs/mango-v4/tests/program_test/mango_client.rs @@ -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::(&mango_v4::id()) + bids: solana + .create_account_for_type::(&mango_v4::id()) + .await, + asks: solana + .create_account_for_type::(&mango_v4::id()) .await, event_queue: solana .create_account_for_type::(&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); diff --git a/programs/mango-v4/tests/test_perp.rs b/programs/mango-v4/tests/test_perp.rs index 956be44b7..4c0f18596 100644 --- a/programs/mango-v4/tests/test_perp.rs +++ b/programs/mango-v4/tests/test_perp.rs @@ -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).await; - assert_eq!(orderbook_data.bids.roots[0].leaf_count, 1); + let bids_data = solana.get_account_boxed::(bids).await; + assert_eq!(bids_data.roots[0].leaf_count, 1); let order_id_to_cancel = solana .get_account::(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).await; - assert_eq!(orderbook_data.bids.roots[1].leaf_count, 1); + let bids_data = solana.get_account_boxed::(bids).await; + assert_eq!(bids_data.roots[1].leaf_count, 1); let perp_order = solana .get_account::(account_0) .await diff --git a/ts/client/src/accounts/perp.ts b/ts/client/src/accounts/perp.ts index 7481102d7..e92b80e5d 100644 --- a/ts/client/src/accounts/perp.ts +++ b/ts/client/src/accounts/perp.ts @@ -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 { - if (forceReload || !this._orderbook) - this._orderbook = await client.program.account.orderbook.fetch( - this.orderbook, - ); - return this._orderbook; + ): Promise { + 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 { - await this.loadOrderbook(client); - return BookSide.from(client, this, BookSideType.asks, this._orderbook.asks); - } - - public async loadBids(client: MangoClient): Promise { - await this.loadOrderbook(client); - return BookSide.from(client, this, BookSideType.bids, this._orderbook.bids); + public async loadBids( + client: MangoClient, + forceReload = false, + ): Promise { + 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 { @@ -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 { - 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 { - 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]); diff --git a/ts/client/src/client.ts b/ts/client/src/client.ts index 779363f52..5d090cfaf 100644 --- a/ts/client/src/client.ts +++ b/ts/client/src/client.ts @@ -1399,11 +1399,12 @@ export class MangoClient { settlePnlLimitFactor: number, settlePnlLimitWindowSize: number, ): Promise { - 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(); diff --git a/ts/client/src/mango_v4.ts b/ts/client/src/mango_v4.ts index c6dc3b997..2fa3b5dba 100644 --- a/ts/client/src/mango_v4.ts +++ b/ts/client/src/mango_v4.ts @@ -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" } ] }; diff --git a/ts/client/src/scripts/mb-example1-admin.ts b/ts/client/src/scripts/mb-example1-admin.ts index 82bc665b8..3fa3a253f 100644 --- a/ts/client/src/scripts/mb-example1-admin.ts +++ b/ts/client/src/scripts/mb-example1-admin.ts @@ -648,7 +648,8 @@ async function createAndPopulateAlt() { .map((perpMarket) => [ perpMarket.publicKey, perpMarket.oracle, - perpMarket.orderbook, + perpMarket.bids, + perpMarket.asks, perpMarket.eventQueue, ]) .flat();