@@ -274,49 +274,44 @@ export class DriftClient {
274274 return this . _isSubscribed && this . accountSubscriber . isSubscribed ;
275275 }
276276
277- private async getPostIxsForIsolatedWithdrawAfterMarketOrder (
277+ private async getPrePlaceOrderIxs (
278278 orderParams : OptionalOrderParams ,
279- userAccount : UserAccount
279+ userAccount : UserAccount ,
280+ options ?: { positionMaxLev ?: number ; isolatedPositionDepositAmount ?: BN }
280281 ) : Promise < TransactionInstruction [ ] > {
281- const postIxs : TransactionInstruction [ ] = [ ] ;
282- const perpPosition = userAccount . perpPositions . find (
283- ( p ) => p . marketIndex === orderParams . marketIndex
284- ) ;
285- if ( ! perpPosition ) return postIxs ;
286-
287- const isIsolated =
288- ( perpPosition . positionFlag & PositionFlag . IsolatedPosition ) !== 0 ;
289- if ( ! isIsolated ) return postIxs ;
290-
291- const currentBase = perpPosition . baseAssetAmount ;
292- if ( currentBase . eq ( ZERO ) ) return postIxs ;
282+ const preIxs : TransactionInstruction [ ] = [ ] ;
293283
294- const signedOrderBase =
295- orderParams . direction === PositionDirection . LONG
296- ? orderParams . baseAssetAmount
297- : ( orderParams . baseAssetAmount as BN ) . neg ( ) ;
298- const postBase = currentBase . add ( signedOrderBase as BN ) ;
299- if ( ! postBase . eq ( ZERO ) ) return postIxs ;
284+ if ( isVariant ( orderParams . marketType , 'perp' ) ) {
285+ const { positionMaxLev, isolatedPositionDepositAmount } = options ?? { } ;
300286
301- const withdrawAmount = this . getIsolatedPerpPositionTokenAmount (
302- orderParams . marketIndex ,
303- userAccount . subAccountId
304- ) ;
305- if ( withdrawAmount . lte ( ZERO ) ) return postIxs ;
287+ if (
288+ isolatedPositionDepositAmount ?. gt ?.( ZERO ) &&
289+ this . isOrderIncreasingPosition ( orderParams , userAccount )
290+ ) {
291+ preIxs . push (
292+ await this . getTransferIsolatedPerpPositionDepositIx (
293+ isolatedPositionDepositAmount as BN ,
294+ orderParams . marketIndex ,
295+ userAccount . subAccountId
296+ )
297+ ) ;
298+ }
306299
307- const userTokenAccount = await this . getAssociatedTokenAccount (
308- QUOTE_SPOT_MARKET_INDEX
309- ) ;
310- postIxs . push (
311- await this . getWithdrawFromIsolatedPerpPositionIx (
312- withdrawAmount ,
313- orderParams . marketIndex ,
314- userTokenAccount ,
315- userAccount . subAccountId
316- )
317- ) ;
300+ if ( positionMaxLev ) {
301+ const marginRatio = Math . floor (
302+ ( 1 / positionMaxLev ) * MARGIN_PRECISION . toNumber ( )
303+ ) ;
304+ preIxs . push (
305+ await this . getUpdateUserPerpPositionCustomMarginRatioIx (
306+ orderParams . marketIndex ,
307+ marginRatio ,
308+ userAccount . subAccountId
309+ )
310+ ) ;
311+ }
312+ }
318313
319- return postIxs ;
314+ return preIxs ;
320315 }
321316
322317 public set isSubscribed ( val : boolean ) {
@@ -4206,16 +4201,26 @@ export class DriftClient {
42064201 subAccountId ?: number ,
42074202 txParams ?: TxParams
42084203 ) : Promise < TransactionSignature > {
4204+ const userAccountPublicKey = await getUserAccountPublicKey (
4205+ this . program . programId ,
4206+ this . authority ,
4207+ subAccountId ?? this . activeSubAccountId
4208+ ) ;
4209+ const userAccount = this . getUserAccount ( subAccountId ) ;
4210+ const settleIx = await this . settleMultiplePNLsIx (
4211+ userAccountPublicKey ,
4212+ userAccount ,
4213+ [ perpMarketIndex ] ,
4214+ SettlePnlMode . TRY_SETTLE
4215+ ) ;
4216+ const withdrawIx = await this . getWithdrawFromIsolatedPerpPositionIx (
4217+ amount ,
4218+ perpMarketIndex ,
4219+ userTokenAccount ,
4220+ subAccountId
4221+ ) ;
42094222 const { txSig } = await this . sendTransaction (
4210- await this . buildTransaction (
4211- await this . getWithdrawFromIsolatedPerpPositionIx (
4212- amount ,
4213- perpMarketIndex ,
4214- userTokenAccount ,
4215- subAccountId
4216- ) ,
4217- txParams
4218- )
4223+ await this . buildTransaction ( [ settleIx , withdrawIx ] , txParams )
42194224 ) ;
42204225 return txSig ;
42214226 }
@@ -4588,47 +4593,25 @@ export class DriftClient {
45884593
45894594 const txKeys = Object . keys ( ixPromisesForTxs ) ;
45904595
4591- const preIxs : TransactionInstruction [ ] = [ ] ;
4592- if (
4593- isVariant ( orderParams . marketType , 'perp' ) &&
4594- isolatedPositionDepositAmount ?. gt ?.( ZERO )
4595- ) {
4596- preIxs . push (
4597- await this . getTransferIsolatedPerpPositionDepositIx (
4598- isolatedPositionDepositAmount as BN ,
4599- orderParams . marketIndex ,
4600- userAccount . subAccountId
4601- )
4602- ) ;
4603- }
4604-
4605- // Build post-order instructions for perp (e.g., withdraw isolated margin on close)
4606- const postIxs : TransactionInstruction [ ] = isVariant ( orderParams . marketType , 'perp' )
4607- ? await this . getPostIxsForIsolatedWithdrawAfterMarketOrder ( orderParams , userAccount )
4608- : [ ] ;
4596+ const preIxs : TransactionInstruction [ ] = await this . getPrePlaceOrderIxs (
4597+ orderParams ,
4598+ userAccount ,
4599+ {
4600+ positionMaxLev,
4601+ isolatedPositionDepositAmount,
4602+ }
4603+ ) ;
46094604
46104605 ixPromisesForTxs . marketOrderTx = ( async ( ) => {
46114606 const placeOrdersIx = await this . getPlaceOrdersIx (
46124607 [ orderParams , ...bracketOrdersParams ] ,
46134608 userAccount . subAccountId
46144609 ) ;
4615- if ( preIxs . length || postIxs . length ) {
4616- return [ ...preIxs , placeOrdersIx , ... postIxs ] as unknown as TransactionInstruction ;
4610+ if ( preIxs . length ) {
4611+ return [ ...preIxs , placeOrdersIx ] as unknown as TransactionInstruction ;
46174612 }
46184613 return placeOrdersIx ;
46194614 } ) ( ) ;
4620- const marketOrderTxIxs = positionMaxLev
4621- ? this . getPlaceOrdersAndSetPositionMaxLevIx (
4622- [ orderParams , ...bracketOrdersParams ] ,
4623- positionMaxLev ,
4624- userAccount . subAccountId
4625- )
4626- : this . getPlaceOrdersIx (
4627- [ orderParams , ...bracketOrdersParams ] ,
4628- userAccount . subAccountId
4629- ) ;
4630-
4631- ixPromisesForTxs . marketOrderTx = marketOrderTxIxs ;
46324615
46334616 /* Cancel open orders in market if requested */
46344617 if ( cancelExistingOrders && isVariant ( orderParams . marketType , 'perp' ) ) {
@@ -5205,7 +5188,8 @@ export class DriftClient {
52055188 params ,
52065189 txParams ,
52075190 subAccountId ,
5208- optionalIxs
5191+ optionalIxs ,
5192+ isolatedPositionDepositAmount
52095193 )
52105194 ) . placeOrdersTx ,
52115195 [ ] ,
@@ -5363,8 +5347,7 @@ export class DriftClient {
53635347 const marginRatio = Math . floor (
53645348 ( 1 / positionMaxLev ) * MARGIN_PRECISION . toNumber ( )
53655349 ) ;
5366-
5367- // TODO: Handle multiple markets?
5350+ // Keep existing behavior but note: prefer using getPostPlaceOrderIxs path
53685351 const setPositionMaxLevIxs =
53695352 await this . getUpdateUserPerpPositionCustomMarginRatioIx (
53705353 readablePerpMarketIndex [ 0 ] ,
@@ -11360,4 +11343,22 @@ export class DriftClient {
1136011343 forceVersionedTransaction,
1136111344 } ) ;
1136211345 }
11346+
11347+ isOrderIncreasingPosition (
11348+ orderParams : OptionalOrderParams ,
11349+ userAccount : UserAccount
11350+ ) : boolean {
11351+ const perpPosition = userAccount . perpPositions . find (
11352+ ( p ) => p . marketIndex === orderParams . marketIndex
11353+ ) ;
11354+ if ( ! perpPosition ) return true ;
11355+
11356+ const currentBase = perpPosition . baseAssetAmount ;
11357+ if ( currentBase . eq ( ZERO ) ) return true ;
11358+
11359+ return currentBase
11360+ . add ( orderParams . baseAssetAmount )
11361+ . abs ( )
11362+ . gt ( currentBase . abs ( ) ) ;
11363+ }
1136311364}
0 commit comments