diff --git a/crates/src/lib.rs b/crates/src/lib.rs index 84d881f..267ae84 100644 --- a/crates/src/lib.rs +++ b/crates/src/lib.rs @@ -1705,7 +1705,9 @@ impl<'a> TransactionBuilder<'a> { self.force_markets.writeable.iter(), ); - if orders.iter().any(|x| x.high_leverage_mode()) { + if self.account_data.margin_mode == MarginMode::HighLeverage + || orders.iter().any(|x| x.high_leverage_mode()) + { accounts.push(AccountMeta::new(*high_leverage_mode_account(), false)); } @@ -1935,7 +1937,7 @@ impl<'a> TransactionBuilder<'a> { .chain(self.force_markets.writeable.iter()), ); - if order.high_leverage_mode() { + if order.high_leverage_mode() || taker_info.1.margin_mode == MarginMode::HighLeverage { accounts.push(AccountMeta::new(*high_leverage_mode_account(), false)); } @@ -2013,7 +2015,9 @@ impl<'a> TransactionBuilder<'a> { .chain(self.force_markets.writeable.iter()), ); - if order.high_leverage_mode() { + if order.high_leverage_mode() + || maker_info.is_some_and(|(_, m)| m.margin_mode == MarginMode::HighLeverage) + { accounts.push(AccountMeta::new(*high_leverage_mode_account(), false)); } @@ -2153,7 +2157,9 @@ impl<'a> TransactionBuilder<'a> { self.force_markets.writeable.iter(), ); - if signed_order_info.order_params().high_leverage_mode() { + if signed_order_info.order_params().high_leverage_mode() + || taker_account.margin_mode == MarginMode::HighLeverage + { accounts.push(AccountMeta::new(*high_leverage_mode_account(), false)); } @@ -2781,4 +2787,59 @@ mod tests { assert_eq!(spot.len(), 1); assert_eq!(perp.len(), 1); } + + #[tokio::test] + async fn test_place_orders_high_leverage() { + // Create a test user with high leverage mode + let mut user = User::default(); + user.margin_mode = MarginMode::HighLeverage; + let user = Cow::Owned(user); + + // Create program data + let program_data = ProgramData::new( + vec![SpotMarket::default()], + vec![PerpMarket::default()], + vec![], + State::default(), + ); + let sub_account = Pubkey::new_unique(); + + // Create transaction builder + let builder = TransactionBuilder::new(&program_data, sub_account, user, false); + + // Test case 1: Place orders with high leverage mode account included due to user margin mode + let orders = vec![OrderParams { + market_index: 0, + market_type: MarketType::Perp, + direction: PositionDirection::Long, + order_type: OrderType::Limit, + ..Default::default() + }]; + + let tx = builder.place_orders(orders).build(); + + // Check that high leverage mode account is included + let high_leverage_account = *high_leverage_mode_account(); + assert!(tx.static_account_keys().contains(&high_leverage_account)); + + // Test case 2: Place orders with high leverage mode account included due to order params + let mut user = User::default(); + user.margin_mode = MarginMode::Default; // Not high leverage + let user = Cow::Owned(user); + let builder = TransactionBuilder::new(&program_data, sub_account, user, false); + + let orders = vec![OrderParams { + market_index: 0, + market_type: MarketType::Perp, + direction: PositionDirection::Long, + order_type: OrderType::Limit, + bit_flags: OrderParams::HIGH_LEVERAGE_MODE_FLAG, + ..Default::default() + }]; + + let tx = builder.place_orders(orders).build(); + + // Check that high leverage mode account is included + assert!(tx.static_account_keys().contains(&high_leverage_account)); + } } diff --git a/crates/src/math/account_list_builder.rs b/crates/src/math/account_list_builder.rs index 3371612..c312697 100644 --- a/crates/src/math/account_list_builder.rs +++ b/crates/src/math/account_list_builder.rs @@ -22,7 +22,7 @@ pub struct AccountsListBuilder { /// placeholder account values populated with real market & oracle account data perp_accounts: ArrayVec, spot_accounts: ArrayVec, - oracle_accounts: ArrayVec, + oracle_accounts: ArrayVec, } impl AccountsListBuilder { diff --git a/crates/src/types.rs b/crates/src/types.rs index a614c31..270900c 100644 --- a/crates/src/types.rs +++ b/crates/src/types.rs @@ -549,13 +549,15 @@ impl ReferrerInfo { } impl OrderParams { + pub const IMMEDIATE_OR_CANCEL_FLAG: u8 = 0b0000_0001; + pub const HIGH_LEVERAGE_MODE_FLAG: u8 = 0b0000_0010; /// true if 'immediate or cancel' bit is set pub fn immediate_or_cancel(&self) -> bool { - (self.bit_flags & 0b0000_00001) > 0 + (self.bit_flags & Self::IMMEDIATE_OR_CANCEL_FLAG) > 0 } /// true if HLM bit is set pub fn high_leverage_mode(&self) -> bool { - (self.bit_flags & 0b0000_00010) > 0 + (self.bit_flags & Self::HIGH_LEVERAGE_MODE_FLAG) > 0 } }