1
1
use std:: { borrow:: Cow , sync:: Arc } ;
2
2
3
3
use drift_sdk:: {
4
+ constants:: ProgramData ,
4
5
dlob:: DLOBClient ,
5
6
types:: { Context , MarketType , ModifyOrderParams , SdkError , SdkResult } ,
6
7
DriftClient , Pubkey , TransactionBuilder , Wallet , WsAccountProvider ,
@@ -22,8 +23,6 @@ pub type GatewayResult<T> = Result<T, ControllerError>;
22
23
pub enum ControllerError {
23
24
#[ error( "internal error: {0}" ) ]
24
25
Sdk ( #[ from] SdkError ) ,
25
- #[ error( "order id not found: {0}" ) ]
26
- UnknownOrderId ( u32 ) ,
27
26
#[ error( "{0}" ) ]
28
27
BadRequest ( String ) ,
29
28
#[ error( "tx failed ({code}): {reason}" ) ]
@@ -215,7 +214,8 @@ impl AppState {
215
214
)
216
215
. payer ( self . wallet . signer ( ) ) ;
217
216
218
- let tx = build_cancel_ix ( builder, req. cancel ) ?
217
+ let builder = build_cancel_ix ( builder, req. cancel ) ?;
218
+ let tx = build_modify_ix ( builder, req. modify , self . client . program_data ( ) ) ?
219
219
. place_orders ( orders)
220
220
. build ( ) ;
221
221
@@ -265,51 +265,14 @@ impl AppState {
265
265
) -> GatewayResult < TxResponse > {
266
266
let sub_account = self . wallet . sub_account ( sub_account_id) ;
267
267
let account_data = & self . client . get_user_account ( & sub_account) . await ?;
268
- // NB: its possible to let the drift program sort the modifications by userOrderId
269
- // sorting it client side for simplicity
270
- let mut params = Vec :: < ( u32 , ModifyOrderParams ) > :: with_capacity ( req. orders . len ( ) ) ;
271
- for order in req. orders {
272
- if let Some ( order_id) = order. order_id {
273
- if let Some ( onchain_order) =
274
- account_data. orders . iter ( ) . find ( |x| x. order_id == order_id)
275
- {
276
- let base_decimals = get_market_decimals (
277
- self . client . program_data ( ) ,
278
- Market :: new ( onchain_order. market_index , onchain_order. market_type ) ,
279
- ) ;
280
- params. push ( ( order_id, order. to_order_params ( base_decimals) ) ) ;
281
- continue ;
282
- }
283
- } else if let Some ( user_order_id) = order. user_order_id {
284
- if let Some ( onchain_order) = account_data
285
- . orders
286
- . iter ( )
287
- . find ( |x| x. user_order_id == user_order_id)
288
- {
289
- let base_decimals = get_market_decimals (
290
- self . client . program_data ( ) ,
291
- Market :: new ( onchain_order. market_index , onchain_order. market_type ) ,
292
- ) ;
293
- params. push ( ( onchain_order. order_id , order. to_order_params ( base_decimals) ) ) ;
294
- continue ;
295
- }
296
- }
297
268
298
- return Err ( ControllerError :: UnknownOrderId (
299
- order
300
- . order_id
301
- . unwrap_or ( order. user_order_id . unwrap_or ( 0 ) as u32 ) ,
302
- ) ) ;
303
- }
304
-
305
- let tx = TransactionBuilder :: new (
269
+ let builder = TransactionBuilder :: new (
306
270
self . client . program_data ( ) ,
307
271
sub_account,
308
272
Cow :: Borrowed ( account_data) ,
309
273
)
310
- . payer ( self . wallet . signer ( ) )
311
- . modify_orders ( params. as_slice ( ) )
312
- . build ( ) ;
274
+ . payer ( self . wallet . signer ( ) ) ;
275
+ let tx = build_modify_ix ( builder, req, self . client . program_data ( ) ) ?. build ( ) ;
313
276
314
277
self . client
315
278
. sign_and_send ( & self . wallet , tx)
@@ -366,6 +329,43 @@ fn build_cancel_ix(
366
329
}
367
330
}
368
331
332
+ fn build_modify_ix < ' a > (
333
+ builder : TransactionBuilder < ' a > ,
334
+ req : ModifyOrdersRequest ,
335
+ program_data : & ProgramData ,
336
+ ) -> GatewayResult < TransactionBuilder < ' a > > {
337
+ if req. orders . is_empty ( ) {
338
+ return Ok ( builder) ;
339
+ }
340
+
341
+ let by_user_order_ids = req. orders [ 0 ] . user_order_id . is_some_and ( |x| x > 0 ) ;
342
+ if by_user_order_ids {
343
+ let mut params = Vec :: < ( u8 , ModifyOrderParams ) > :: with_capacity ( req. orders . len ( ) ) ;
344
+ for order in req. orders {
345
+ let base_decimals = get_market_decimals ( program_data, order. market ) ;
346
+ params. push ( (
347
+ order. user_order_id . ok_or ( ControllerError :: BadRequest (
348
+ "userOrderId not set" . to_string ( ) ,
349
+ ) ) ?,
350
+ order. to_order_params ( base_decimals) ,
351
+ ) ) ;
352
+ }
353
+ Ok ( builder. modify_orders_by_user_id ( params. as_slice ( ) ) )
354
+ } else {
355
+ let mut params = Vec :: < ( u32 , ModifyOrderParams ) > :: with_capacity ( req. orders . len ( ) ) ;
356
+ for order in req. orders {
357
+ let base_decimals = get_market_decimals ( program_data, order. market ) ;
358
+ params. push ( (
359
+ order
360
+ . order_id
361
+ . ok_or ( ControllerError :: BadRequest ( "orderId not set" . to_string ( ) ) ) ?,
362
+ order. to_order_params ( base_decimals) ,
363
+ ) ) ;
364
+ }
365
+ Ok ( builder. modify_orders ( params. as_slice ( ) ) )
366
+ }
367
+ }
368
+
369
369
/// Initialize a wallet for controller, possible valid configs:
370
370
///
371
371
/// 1) keypair
0 commit comments