Skip to content

Commit e834a8c

Browse files
add max margin ratio when simming (#90)
* add max margin ratio when simming * check max_margin for deposit+trade --------- Co-authored-by: jordy25519 <beauchjord@gmail.com>
1 parent 8b515b6 commit e834a8c

File tree

3 files changed

+88
-39
lines changed

3 files changed

+88
-39
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ bincode = "1"
2626
clap = { version = "4.0", features = ["derive"] }
2727
dashmap = "6.1.0"
2828
dotenv = "0.15.0"
29-
drift-rs = { git = "https://github.com/drift-labs/drift-rs.git" , rev = "cbc476e2" }
29+
drift-rs = { git = "https://github.com/drift-labs/drift-rs.git" , rev = "cd60371" }
3030
ed25519-dalek = "1.0.1"
3131
env_logger = "0.11"
3232
faster-hex = "0.10.0"

src/swift_server.rs

Lines changed: 84 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)