@@ -236,12 +236,15 @@ pub async fn process_order(
236236 } ;
237237
238238 let current_slot = server_params. slot_subscriber . current_slot ( ) ;
239- let SignedMessageInfo {
240- slot : _taker_slot,
241- order_params,
242- taker_pubkey,
243- uuid,
244- } = extract_signed_message_info ( signed_msg, & taker_authority, current_slot) ?;
239+ let (
240+ SignedMessageInfo {
241+ slot : _taker_slot,
242+ order_params,
243+ taker_pubkey,
244+ uuid,
245+ } ,
246+ max_margin_ratio,
247+ ) = extract_signed_message_info ( signed_msg, & taker_authority, current_slot) ?;
245248
246249 // check the order is valid for execution by program
247250 let market = server_params
@@ -267,7 +270,13 @@ pub async fn process_order(
267270
268271 if !skip_sim {
269272 match server_params
270- . simulate_taker_order_rpc ( & taker_pubkey, & order_params, delegate_signer, current_slot)
273+ . simulate_taker_order_rpc (
274+ & taker_pubkey,
275+ & order_params,
276+ delegate_signer,
277+ current_slot,
278+ max_margin_ratio,
279+ )
271280 . await
272281 {
273282 Ok ( sim_res) => {
@@ -387,6 +396,16 @@ pub async fn deposit_trade(
387396 . swift_order
388397 . order ( )
389398 . info ( & req. swift_order . taker_authority ) ;
399+ let current_slot = server_params. slot_subscriber . current_slot ( ) ;
400+
401+ let max_margin_ratio = match extract_signed_message_info (
402+ & req. swift_order . order ( ) ,
403+ & req. swift_order . taker_authority ,
404+ current_slot,
405+ ) {
406+ Ok ( ( _info, max_margin_ratio) ) => max_margin_ratio,
407+ Err ( ( _status, err) ) => return ( StatusCode :: BAD_REQUEST , Json ( err) ) ,
408+ } ;
390409
391410 let uuid = core:: str:: from_utf8 ( & signed_order_info. uuid ) . unwrap_or ( "<bad uuid>" ) ;
392411 log:: info!(
@@ -458,8 +477,12 @@ pub async fn deposit_trade(
458477 }
459478 }
460479
461- if let Some ( user) = user_after_deposit {
462- if !server_params. simulate_taker_order_local ( & signed_order_info. order_params , & user) {
480+ if let Some ( mut user) = user_after_deposit {
481+ if !server_params. simulate_taker_order_local (
482+ & signed_order_info. order_params ,
483+ & mut user,
484+ max_margin_ratio,
485+ ) {
463486 log:: info!( target: "server" , "[{uuid}] local order sim failed" ) ;
464487 return (
465488 StatusCode :: BAD_REQUEST ,
@@ -879,7 +902,8 @@ impl ServerParams {
879902 fn simulate_taker_order_local (
880903 & self ,
881904 order_params : & OrderParams ,
882- user : & drift_rs:: types:: accounts:: User ,
905+ user : & mut drift_rs:: types:: accounts:: User ,
906+ max_margin_ratio : Option < u16 > ,
883907 ) -> bool {
884908 let state = match self . drift . state_account ( ) {
885909 Ok ( s) => s,
@@ -917,6 +941,7 @@ impl ServerParams {
917941 & state,
918942 order_params,
919943 Some ( & mut hlm) ,
944+ max_margin_ratio,
920945 ) {
921946 Ok ( _) => true ,
922947 Err ( err) => {
@@ -932,6 +957,7 @@ impl ServerParams {
932957 taker_order_params : & OrderParams ,
933958 delegate_signer : Option < & Pubkey > ,
934959 slot : Slot ,
960+ max_margin_ratio : Option < u16 > ,
935961 ) -> Result < SimulationStatus , ( axum:: http:: StatusCode , String , Option < Vec < String > > ) > {
936962 let mut sim_result = SimulationStatus :: Disabled ;
937963
@@ -951,7 +977,7 @@ impl ServerParams {
951977 }
952978
953979 let user_result = user_with_timeout. unwrap ( ) ;
954- let user = user_result. map_err ( |err| {
980+ let mut user = user_result. map_err ( |err| {
955981 (
956982 axum:: http:: StatusCode :: NOT_FOUND ,
957983 format ! ( "unable to fetch user: {err:?}" ) ,
@@ -983,22 +1009,27 @@ impl ServerParams {
9831009 let t1 = SystemTime :: now ( ) ;
9841010 log:: info!( target: "sim" , "fetch user: {:?}" , SystemTime :: now( ) . duration_since( t0) ) ;
9851011
986- if self . simulate_taker_order_local ( taker_order_params, & user) {
1012+ if self . simulate_taker_order_local ( taker_order_params, & mut user, max_margin_ratio ) {
9871013 sim_result = SimulationStatus :: Success ;
9881014 log:: info!( target: "sim" , "simulate tx (local): {:?}" , SystemTime :: now( ) . duration_since( t1) ) ;
9891015 return Ok ( sim_result) ;
9901016 }
9911017
9921018 // fallback to network sim
993- let message = TransactionBuilder :: new (
1019+ let mut tx = TransactionBuilder :: new (
9941020 self . drift . program_data ( ) ,
9951021 * taker_subaccount_pubkey,
9961022 std:: borrow:: Cow :: Owned ( user) ,
9971023 false ,
9981024 )
999- . with_priority_fee ( 5_000 , Some ( 1_400_000 ) )
1000- . place_orders ( vec ! [ * taker_order_params] )
1001- . build ( ) ;
1025+ . with_priority_fee ( 5_000 , Some ( 1_400_000 ) ) ;
1026+ if let Some ( margin_ratio) = max_margin_ratio {
1027+ tx = tx. update_user_perp_position_custom_margin_ratio (
1028+ taker_order_params. market_index ,
1029+ margin_ratio,
1030+ ) ;
1031+ }
1032+ let message = tx. place_orders ( vec ! [ * taker_order_params] ) . build ( ) ;
10021033
10031034 let simulate_result_with_timeout = tokio:: time:: timeout (
10041035 self . config . simulation_timeout ,
@@ -1309,7 +1340,7 @@ fn extract_signed_message_info(
13091340 signed_msg : & SignedOrderType ,
13101341 taker_authority : & Pubkey ,
13111342 current_slot : Slot ,
1312- ) -> Result < SignedMessageInfo , ( axum:: http:: StatusCode , ProcessOrderResponse ) > {
1343+ ) -> Result < ( SignedMessageInfo , Option < u16 > ) , ( axum:: http:: StatusCode , ProcessOrderResponse ) > {
13131344 match signed_msg {
13141345 SignedOrderType :: Delegated ( x) => {
13151346 validate_order (
@@ -1318,12 +1349,15 @@ fn extract_signed_message_info(
13181349 x. slot ,
13191350 current_slot,
13201351 ) ?;
1321- Ok ( SignedMessageInfo {
1322- taker_pubkey : x. taker_pubkey ,
1323- order_params : x. signed_msg_order_params ,
1324- uuid : x. uuid ,
1325- slot : x. slot ,
1326- } )
1352+ Ok ( (
1353+ SignedMessageInfo {
1354+ taker_pubkey : x. taker_pubkey ,
1355+ order_params : x. signed_msg_order_params ,
1356+ uuid : x. uuid ,
1357+ slot : x. slot ,
1358+ } ,
1359+ x. max_margin_ratio ,
1360+ ) )
13271361 }
13281362 SignedOrderType :: Authority ( x) => {
13291363 validate_order (
@@ -1332,12 +1366,15 @@ fn extract_signed_message_info(
13321366 x. slot ,
13331367 current_slot,
13341368 ) ?;
1335- Ok ( SignedMessageInfo {
1336- taker_pubkey : Wallet :: derive_user_account ( taker_authority, x. sub_account_id ) ,
1337- order_params : x. signed_msg_order_params ,
1338- uuid : x. uuid ,
1339- slot : x. slot ,
1340- } )
1369+ Ok ( (
1370+ SignedMessageInfo {
1371+ taker_pubkey : Wallet :: derive_user_account ( taker_authority, x. sub_account_id ) ,
1372+ order_params : x. signed_msg_order_params ,
1373+ uuid : x. uuid ,
1374+ slot : x. slot ,
1375+ } ,
1376+ x. max_margin_ratio ,
1377+ ) )
13411378 }
13421379 }
13431380}
@@ -1642,7 +1679,7 @@ mod tests {
16421679 } ) ;
16431680
16441681 let result = extract_signed_message_info ( & delegated_msg, & taker_authority, current_slot) ;
1645- assert ! ( result. is_ok_and( |info| {
1682+ assert ! ( result. is_ok_and( |( info, _ ) | {
16461683 info. slot == current_slot
16471684 && info. order_params. base_asset_amount == LAMPORTS_PER_SOL
16481685 && info. order_params. order_type == OrderType :: Market
@@ -1704,7 +1741,7 @@ mod tests {
17041741 } ) ;
17051742
17061743 let result = extract_signed_message_info ( & authority_msg, & taker_authority, current_slot) ;
1707- assert ! ( result. is_ok_and( |info| {
1744+ assert ! ( result. is_ok_and( |( info, _margin_ratio ) | {
17081745 info. slot == current_slot
17091746 && info. order_params. base_asset_amount == LAMPORTS_PER_SOL
17101747 && info. order_params. order_type == OrderType :: Market
@@ -1789,8 +1826,8 @@ mod tests {
17891826 . await
17901827 . unwrap ( ) ;
17911828
1792- let taker_pubkey = Keypair :: new ( ) . pubkey ( ) ;
1793- let taker_pubkey2 = Keypair :: new ( ) . pubkey ( ) ;
1829+ let mut taker_pubkey = Keypair :: new ( ) . pubkey ( ) ;
1830+ let mut taker_pubkey2 = Keypair :: new ( ) . pubkey ( ) ;
17941831 let delegate_pubkey = Keypair :: new ( ) . pubkey ( ) ;
17951832 let users: HashMap < Pubkey , User > = [
17961833 (
@@ -1839,7 +1876,13 @@ mod tests {
18391876
18401877 // Test
18411878 let result = server_params
1842- . simulate_taker_order_rpc ( & taker_pubkey, & order_params, Some ( & delegate_pubkey) , 1_000 )
1879+ . simulate_taker_order_rpc (
1880+ & mut taker_pubkey,
1881+ & order_params,
1882+ Some ( & delegate_pubkey) ,
1883+ 1_000 ,
1884+ None ,
1885+ )
18431886 . await ;
18441887 assert ! ( result. is_err_and( |( status, msg, _) | {
18451888 dbg!( & msg) ;
@@ -1848,7 +1891,13 @@ mod tests {
18481891 } ) ) ;
18491892
18501893 let result = server_params
1851- . simulate_taker_order_rpc ( & taker_pubkey2, & order_params, Some ( & delegate_pubkey) , 1_000 )
1894+ . simulate_taker_order_rpc (
1895+ & mut taker_pubkey2,
1896+ & order_params,
1897+ Some ( & delegate_pubkey) ,
1898+ 1_000 ,
1899+ None ,
1900+ )
18521901 . await ;
18531902 // it fails later at remote sim since the account is not a real drift account
18541903 assert ! ( result. is_err_and( |( status, msg, _) | {
0 commit comments