Skip to content

Commit e11a2ec

Browse files
committed
feat: iso position txs cleanup + ix ordering
1 parent b2999c8 commit e11a2ec

File tree

2 files changed

+86
-85
lines changed

2 files changed

+86
-85
lines changed

sdk/src/driftClient.ts

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

sdk/src/types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ export type SpotBankruptcyRecord = {
585585
};
586586

587587
export class LiquidationBitFlag {
588-
static readonly IsolatedPosition = 1;
588+
static readonly IsolatedPosition = 1;
589589
}
590590

591591
export type SettlePnlRecord = {
@@ -1310,7 +1310,7 @@ export type OptionalOrderParams = {
13101310
} & NecessaryOrderParams;
13111311

13121312
export type PerpOrderIsolatedExtras = {
1313-
isolatedPositionDepositAmount?: BN;
1313+
isolatedPositionDepositAmount?: BN;
13141314
};
13151315

13161316
export type ModifyOrderParams = {
@@ -1350,7 +1350,7 @@ export type SignedMsgOrderParamsMessage = {
13501350
takeProfitOrderParams: SignedMsgTriggerOrderParams | null;
13511351
stopLossOrderParams: SignedMsgTriggerOrderParams | null;
13521352
maxMarginRatio?: number | null;
1353-
isolatedPositionDepositAmount?: BN | null;
1353+
isolatedPositionDeposit?: BN | null;
13541354
builderIdx?: number | null;
13551355
builderFeeTenthBps?: number | null;
13561356
};
@@ -1363,7 +1363,7 @@ export type SignedMsgOrderParamsDelegateMessage = {
13631363
takeProfitOrderParams: SignedMsgTriggerOrderParams | null;
13641364
stopLossOrderParams: SignedMsgTriggerOrderParams | null;
13651365
maxMarginRatio?: number | null;
1366-
isolatedPositionDepositAmount?: BN | null;
1366+
isolatedPositionDeposit?: BN | null;
13671367
builderIdx?: number | null;
13681368
builderFeeTenthBps?: number | null;
13691369
};

0 commit comments

Comments
 (0)