@drift-labs/sdk 2.149.1 → 2.150.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.env +4 -0
  2. package/VERSION +1 -1
  3. package/lib/browser/constants/perpMarkets.js +11 -0
  4. package/lib/browser/constants/spotMarkets.js +13 -0
  5. package/lib/browser/decode/user.js +2 -2
  6. package/lib/browser/driftClient.d.ts +20 -8
  7. package/lib/browser/driftClient.js +216 -17
  8. package/lib/browser/idl/drift.json +225 -21
  9. package/lib/browser/math/margin.js +2 -1
  10. package/lib/browser/math/position.d.ts +1 -0
  11. package/lib/browser/math/position.js +10 -2
  12. package/lib/browser/math/superStake.d.ts +3 -2
  13. package/lib/browser/types.d.ts +12 -6
  14. package/lib/browser/types.js +11 -6
  15. package/lib/browser/user.d.ts +3 -2
  16. package/lib/browser/user.js +24 -8
  17. package/lib/node/constants/perpMarkets.d.ts.map +1 -1
  18. package/lib/node/constants/perpMarkets.js +11 -0
  19. package/lib/node/constants/spotMarkets.d.ts.map +1 -1
  20. package/lib/node/constants/spotMarkets.js +13 -0
  21. package/lib/node/decode/user.d.ts.map +1 -1
  22. package/lib/node/decode/user.js +2 -2
  23. package/lib/node/driftClient.d.ts +20 -8
  24. package/lib/node/driftClient.d.ts.map +1 -1
  25. package/lib/node/driftClient.js +216 -17
  26. package/lib/node/idl/drift.json +225 -21
  27. package/lib/node/math/margin.d.ts.map +1 -1
  28. package/lib/node/math/margin.js +2 -1
  29. package/lib/node/math/position.d.ts +1 -0
  30. package/lib/node/math/position.d.ts.map +1 -1
  31. package/lib/node/math/position.js +10 -2
  32. package/lib/node/math/spotBalance.d.ts.map +1 -1
  33. package/lib/node/math/superStake.d.ts +3 -2
  34. package/lib/node/math/superStake.d.ts.map +1 -1
  35. package/lib/node/types.d.ts +12 -6
  36. package/lib/node/types.d.ts.map +1 -1
  37. package/lib/node/types.js +11 -6
  38. package/lib/node/user.d.ts +3 -2
  39. package/lib/node/user.d.ts.map +1 -1
  40. package/lib/node/user.js +24 -8
  41. package/package.json +1 -1
  42. package/scripts/deposit-isolated-positions.ts +110 -0
  43. package/scripts/single-grpc-client-test.ts +71 -21
  44. package/scripts/withdraw-isolated-positions.ts +174 -0
  45. package/src/constants/perpMarkets.ts +11 -0
  46. package/src/constants/spotMarkets.ts +14 -0
  47. package/src/decode/user.ts +2 -3
  48. package/src/driftClient.ts +464 -41
  49. package/src/idl/drift.json +226 -22
  50. package/src/margin/README.md +143 -0
  51. package/src/math/margin.ts +3 -4
  52. package/src/math/position.ts +12 -2
  53. package/src/math/spotBalance.ts +0 -1
  54. package/src/types.ts +15 -7
  55. package/src/user.ts +49 -15
  56. package/tests/amm/test.ts +1 -1
  57. package/tests/dlob/helpers.ts +1 -1
  58. package/tests/user/test.ts +0 -7
@@ -71,6 +71,7 @@ const on_demand_1 = require("@switchboard-xyz/on-demand");
71
71
  const grpcDriftClientAccountSubscriber_1 = require("./accounts/grpcDriftClientAccountSubscriber");
72
72
  const tweetnacl_1 = __importDefault(require("tweetnacl"));
73
73
  const oracleId_1 = require("./oracles/oracleId");
74
+ // BN is already imported globally in this file via other imports
74
75
  const sha256_1 = require("@noble/hashes/sha256");
75
76
  const utils_3 = require("./oracles/utils");
76
77
  const orders_1 = require("./math/orders");
@@ -85,6 +86,22 @@ class DriftClient {
85
86
  get isSubscribed() {
86
87
  return this._isSubscribed && this.accountSubscriber.isSubscribed;
87
88
  }
89
+ async getPrePlaceOrderIxs(orderParams, userAccount, options) {
90
+ var _a;
91
+ const preIxs = [];
92
+ if ((0, types_1.isVariant)(orderParams.marketType, 'perp')) {
93
+ const { positionMaxLev, isolatedPositionDepositAmount } = options !== null && options !== void 0 ? options : {};
94
+ if (((_a = isolatedPositionDepositAmount === null || isolatedPositionDepositAmount === void 0 ? void 0 : isolatedPositionDepositAmount.gt) === null || _a === void 0 ? void 0 : _a.call(isolatedPositionDepositAmount, numericConstants_1.ZERO)) &&
95
+ this.isOrderIncreasingPosition(orderParams, userAccount.subAccountId)) {
96
+ preIxs.push(await this.getTransferIsolatedPerpPositionDepositIx(isolatedPositionDepositAmount, orderParams.marketIndex, userAccount.subAccountId));
97
+ }
98
+ if (positionMaxLev) {
99
+ const marginRatio = Math.floor((1 / positionMaxLev) * numericConstants_1.MARGIN_PRECISION.toNumber());
100
+ preIxs.push(await this.getUpdateUserPerpPositionCustomMarginRatioIx(orderParams.marketIndex, marginRatio, userAccount.subAccountId));
101
+ }
102
+ }
103
+ return preIxs;
104
+ }
88
105
  set isSubscribed(val) {
89
106
  this._isSubscribed = val;
90
107
  }
@@ -1382,6 +1399,9 @@ class DriftClient {
1382
1399
  getQuoteAssetTokenAmount() {
1383
1400
  return this.getTokenAmount(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
1384
1401
  }
1402
+ getIsolatedPerpPositionTokenAmount(perpMarketIndex, subAccountId) {
1403
+ return this.getUser(subAccountId).getIsolatePerpPositionTokenAmount(perpMarketIndex);
1404
+ }
1385
1405
  /**
1386
1406
  * Returns the token amount for a given market. The spot market precision is based on the token mint decimals.
1387
1407
  * Positive if it is a deposit, negative if it is a borrow.
@@ -2139,6 +2159,129 @@ class DriftClient {
2139
2159
  remainingAccounts,
2140
2160
  });
2141
2161
  }
2162
+ async depositIntoIsolatedPerpPosition(amount, perpMarketIndex, userTokenAccount, subAccountId, txParams) {
2163
+ const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getDepositIntoIsolatedPerpPositionIx(amount, perpMarketIndex, userTokenAccount, subAccountId), txParams), [], this.opts);
2164
+ return txSig;
2165
+ }
2166
+ async getDepositIntoIsolatedPerpPositionIx(amount, perpMarketIndex, userTokenAccount, subAccountId) {
2167
+ const userAccountPublicKey = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.authority, subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId);
2168
+ const perpMarketAccount = this.getPerpMarketAccount(perpMarketIndex);
2169
+ const spotMarketIndex = perpMarketAccount.quoteSpotMarketIndex;
2170
+ const spotMarketAccount = this.getSpotMarketAccount(spotMarketIndex);
2171
+ const remainingAccounts = this.getRemainingAccounts({
2172
+ userAccounts: [],
2173
+ writableSpotMarketIndexes: [spotMarketIndex],
2174
+ readablePerpMarketIndex: [perpMarketIndex],
2175
+ });
2176
+ const tokenProgram = this.getTokenProgramForSpotMarket(spotMarketAccount);
2177
+ return await this.program.instruction.depositIntoIsolatedPerpPosition(spotMarketIndex, perpMarketIndex, amount, {
2178
+ accounts: {
2179
+ state: await this.getStatePublicKey(),
2180
+ spotMarketVault: spotMarketAccount.vault,
2181
+ user: userAccountPublicKey,
2182
+ userStats: this.getUserStatsAccountPublicKey(),
2183
+ userTokenAccount: userTokenAccount,
2184
+ authority: this.wallet.publicKey,
2185
+ tokenProgram,
2186
+ },
2187
+ remainingAccounts,
2188
+ });
2189
+ }
2190
+ async transferIsolatedPerpPositionDeposit(amount, perpMarketIndex, subAccountId, txParams, trySettle) {
2191
+ const ixs = [];
2192
+ const tokenAmountDeposited = this.getIsolatedPerpPositionTokenAmount(perpMarketIndex);
2193
+ const transferIx = await this.getTransferIsolatedPerpPositionDepositIx(amount, perpMarketIndex, subAccountId);
2194
+ const needsToSettle = amount.gt(tokenAmountDeposited) || amount.eq(numericConstants_1.MIN_I64) || trySettle;
2195
+ if (needsToSettle) {
2196
+ const settleIx = await this.settleMultiplePNLsIx(await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.authority, subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId), this.getUserAccount(subAccountId), [perpMarketIndex], types_1.SettlePnlMode.TRY_SETTLE);
2197
+ ixs.push(settleIx);
2198
+ }
2199
+ ixs.push(transferIx);
2200
+ const tx = await this.buildTransaction(ixs, txParams);
2201
+ const { txSig } = await this.sendTransaction(tx, [], {
2202
+ ...this.opts,
2203
+ skipPreflight: true,
2204
+ });
2205
+ return txSig;
2206
+ }
2207
+ async getTransferIsolatedPerpPositionDepositIx(amount, perpMarketIndex, subAccountId, noAmountBuffer) {
2208
+ const userAccountPublicKey = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.authority, subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId);
2209
+ const perpMarketAccount = this.getPerpMarketAccount(perpMarketIndex);
2210
+ const spotMarketIndex = perpMarketAccount.quoteSpotMarketIndex;
2211
+ const spotMarketAccount = this.getSpotMarketAccount(spotMarketIndex);
2212
+ const user = await this.getUserAccount(subAccountId);
2213
+ const remainingAccounts = this.getRemainingAccounts({
2214
+ userAccounts: [user],
2215
+ writableSpotMarketIndexes: [spotMarketIndex],
2216
+ readablePerpMarketIndex: [perpMarketIndex],
2217
+ });
2218
+ const amountWithBuffer = noAmountBuffer || amount.eq(numericConstants_1.MIN_I64)
2219
+ ? amount
2220
+ : amount.add(amount.div(new anchor_1.BN(200))); // .5% buffer
2221
+ return await this.program.instruction.transferIsolatedPerpPositionDeposit(spotMarketIndex, perpMarketIndex, amountWithBuffer, {
2222
+ accounts: {
2223
+ state: await this.getStatePublicKey(),
2224
+ spotMarketVault: spotMarketAccount.vault,
2225
+ user: userAccountPublicKey,
2226
+ userStats: this.getUserStatsAccountPublicKey(),
2227
+ authority: this.wallet.publicKey,
2228
+ },
2229
+ remainingAccounts,
2230
+ });
2231
+ }
2232
+ async withdrawFromIsolatedPerpPosition(amount, perpMarketIndex, userTokenAccount, subAccountId, txParams) {
2233
+ const instructions = await this.getWithdrawFromIsolatedPerpPositionIxsBundle(amount, perpMarketIndex, subAccountId, userTokenAccount);
2234
+ const { txSig } = await this.sendTransaction(await this.buildTransaction(instructions, txParams));
2235
+ return txSig;
2236
+ }
2237
+ async getWithdrawFromIsolatedPerpPositionIxsBundle(amount, perpMarketIndex, subAccountId, userTokenAccount) {
2238
+ const userAccountPublicKey = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.authority, subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId);
2239
+ const userAccount = this.getUserAccount(subAccountId);
2240
+ const tokenAmountDeposited = this.getIsolatedPerpPositionTokenAmount(perpMarketIndex);
2241
+ const isolatedPositionUnrealizedPnl = (0, position_1.calculateClaimablePnl)(this.getPerpMarketAccount(perpMarketIndex), this.getSpotMarketAccount(this.getPerpMarketAccount(perpMarketIndex).quoteSpotMarketIndex), userAccount.perpPositions.find((p) => p.marketIndex === perpMarketIndex), this.getOracleDataForSpotMarket(this.getPerpMarketAccount(perpMarketIndex).quoteSpotMarketIndex));
2242
+ const depositAmountPlusUnrealizedPnl = tokenAmountDeposited.add(isolatedPositionUnrealizedPnl);
2243
+ const amountToWithdraw = amount.gt(depositAmountPlusUnrealizedPnl)
2244
+ ? numericConstants_1.MIN_I64 // min i64
2245
+ : amount;
2246
+ let associatedTokenAccount = userTokenAccount;
2247
+ if (!associatedTokenAccount) {
2248
+ const perpMarketAccount = this.getPerpMarketAccount(perpMarketIndex);
2249
+ const quoteSpotMarketIndex = perpMarketAccount.quoteSpotMarketIndex;
2250
+ associatedTokenAccount = await this.getAssociatedTokenAccount(quoteSpotMarketIndex);
2251
+ }
2252
+ const withdrawIx = await this.getWithdrawFromIsolatedPerpPositionIx(amountToWithdraw, perpMarketIndex, associatedTokenAccount, subAccountId);
2253
+ const ixs = [withdrawIx];
2254
+ const needsToSettle = amount.gt(tokenAmountDeposited) && isolatedPositionUnrealizedPnl.gt(numericConstants_1.ZERO);
2255
+ if (needsToSettle) {
2256
+ const settleIx = await this.settleMultiplePNLsIx(userAccountPublicKey, userAccount, [perpMarketIndex], types_1.SettlePnlMode.TRY_SETTLE);
2257
+ ixs.push(settleIx);
2258
+ }
2259
+ return ixs;
2260
+ }
2261
+ async getWithdrawFromIsolatedPerpPositionIx(amount, perpMarketIndex, userTokenAccount, subAccountId) {
2262
+ const userAccountPublicKey = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.authority, subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId);
2263
+ const perpMarketAccount = this.getPerpMarketAccount(perpMarketIndex);
2264
+ const spotMarketIndex = perpMarketAccount.quoteSpotMarketIndex;
2265
+ const spotMarketAccount = this.getSpotMarketAccount(spotMarketIndex);
2266
+ const remainingAccounts = this.getRemainingAccounts({
2267
+ userAccounts: [this.getUserAccount(subAccountId)],
2268
+ writableSpotMarketIndexes: [spotMarketIndex],
2269
+ readablePerpMarketIndex: [perpMarketIndex],
2270
+ });
2271
+ return await this.program.instruction.withdrawFromIsolatedPerpPosition(spotMarketIndex, perpMarketIndex, amount, {
2272
+ accounts: {
2273
+ state: await this.getStatePublicKey(),
2274
+ spotMarketVault: spotMarketAccount.vault,
2275
+ user: userAccountPublicKey,
2276
+ userStats: this.getUserStatsAccountPublicKey(),
2277
+ authority: this.wallet.publicKey,
2278
+ userTokenAccount: userTokenAccount,
2279
+ tokenProgram: this.getTokenProgramForSpotMarket(spotMarketAccount),
2280
+ driftSigner: this.getSignerPublicKey(),
2281
+ },
2282
+ remainingAccounts,
2283
+ });
2284
+ }
2142
2285
  async updateSpotMarketCumulativeInterest(marketIndex, txParams) {
2143
2286
  const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.updateSpotMarketCumulativeInterestIx(marketIndex), txParams), [], this.opts);
2144
2287
  return txSig;
@@ -2271,7 +2414,7 @@ class DriftClient {
2271
2414
  const { txSig } = await this.sendTransaction(tx, undefined, opts !== null && opts !== void 0 ? opts : this.opts, true);
2272
2415
  return txSig;
2273
2416
  }
2274
- async prepareMarketOrderTxs(orderParams, userAccountPublicKey, userAccount, makerInfo, txParams, bracketOrdersParams = new Array(), referrerInfo, cancelExistingOrders, settlePnl, positionMaxLev) {
2417
+ async prepareMarketOrderTxs(orderParams, userAccountPublicKey, userAccount, makerInfo, txParams, bracketOrdersParams = new Array(), referrerInfo, cancelExistingOrders, settlePnl, positionMaxLev, isolatedPositionDepositAmount) {
2275
2418
  const marketIndex = orderParams.marketIndex;
2276
2419
  const orderId = userAccount.nextOrderId;
2277
2420
  const ixPromisesForTxs = {
@@ -2281,10 +2424,17 @@ class DriftClient {
2281
2424
  marketOrderTx: undefined,
2282
2425
  };
2283
2426
  const txKeys = Object.keys(ixPromisesForTxs);
2284
- const marketOrderTxIxs = positionMaxLev
2285
- ? this.getPlaceOrdersAndSetPositionMaxLevIx([orderParams, ...bracketOrdersParams], positionMaxLev, userAccount.subAccountId)
2286
- : this.getPlaceOrdersIx([orderParams, ...bracketOrdersParams], userAccount.subAccountId);
2287
- ixPromisesForTxs.marketOrderTx = marketOrderTxIxs;
2427
+ const preIxs = await this.getPrePlaceOrderIxs(orderParams, userAccount, {
2428
+ positionMaxLev,
2429
+ isolatedPositionDepositAmount,
2430
+ });
2431
+ ixPromisesForTxs.marketOrderTx = (async () => {
2432
+ const placeOrdersIx = await this.getPlaceOrdersIx([orderParams, ...bracketOrdersParams], userAccount.subAccountId);
2433
+ if (preIxs.length) {
2434
+ return [...preIxs, placeOrdersIx];
2435
+ }
2436
+ return placeOrdersIx;
2437
+ })();
2288
2438
  /* Cancel open orders in market if requested */
2289
2439
  if (cancelExistingOrders && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
2290
2440
  ixPromisesForTxs.cancelExistingOrdersTx = this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, userAccount.subAccountId);
@@ -2331,8 +2481,14 @@ class DriftClient {
2331
2481
  signedSettlePnlTx: signedTxs.settlePnlTx,
2332
2482
  };
2333
2483
  }
2334
- async placePerpOrder(orderParams, txParams, subAccountId) {
2335
- const { txSig, slot } = await this.sendTransaction(await this.buildTransaction(await this.getPlacePerpOrderIx(orderParams, subAccountId), txParams), [], this.opts);
2484
+ async placePerpOrder(orderParams, txParams, subAccountId, isolatedPositionDepositAmount) {
2485
+ var _a;
2486
+ const preIxs = [];
2487
+ if (((_a = isolatedPositionDepositAmount === null || isolatedPositionDepositAmount === void 0 ? void 0 : isolatedPositionDepositAmount.gt) === null || _a === void 0 ? void 0 : _a.call(isolatedPositionDepositAmount, numericConstants_1.ZERO)) &&
2488
+ this.isOrderIncreasingPosition(orderParams, subAccountId)) {
2489
+ preIxs.push(await this.getTransferIsolatedPerpPositionDepositIx(isolatedPositionDepositAmount, orderParams.marketIndex, subAccountId));
2490
+ }
2491
+ const { txSig, slot } = await this.sendTransaction(await this.buildTransaction(await this.getPlacePerpOrderIx(orderParams, subAccountId), txParams, undefined, undefined, undefined, undefined, preIxs), [], this.opts);
2336
2492
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
2337
2493
  return txSig;
2338
2494
  }
@@ -2438,8 +2594,19 @@ class DriftClient {
2438
2594
  },
2439
2595
  });
2440
2596
  }
2441
- async cancelOrder(orderId, txParams, subAccountId) {
2442
- const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getCancelOrderIx(orderId, subAccountId), txParams), [], this.opts);
2597
+ async cancelOrder(orderId, txParams, subAccountId, overrides) {
2598
+ const cancelIx = await this.getCancelOrderIx(orderId, subAccountId);
2599
+ const instructions = [cancelIx];
2600
+ if ((overrides === null || overrides === void 0 ? void 0 : overrides.withdrawIsolatedDepositAmount) !== undefined) {
2601
+ const order = this.getOrder(orderId, subAccountId);
2602
+ const perpMarketIndex = order === null || order === void 0 ? void 0 : order.marketIndex;
2603
+ const withdrawAmount = overrides.withdrawIsolatedDepositAmount;
2604
+ if (withdrawAmount.gt(numericConstants_1.ZERO)) {
2605
+ const withdrawIxs = await this.getWithdrawFromIsolatedPerpPositionIxsBundle(withdrawAmount, perpMarketIndex, subAccountId);
2606
+ instructions.push(...withdrawIxs);
2607
+ }
2608
+ }
2609
+ const { txSig } = await this.sendTransaction(await this.buildTransaction(instructions, txParams), [], this.opts);
2443
2610
  return txSig;
2444
2611
  }
2445
2612
  async getCancelOrderIx(orderId, subAccountId) {
@@ -2558,13 +2725,23 @@ class DriftClient {
2558
2725
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
2559
2726
  return txSig;
2560
2727
  }
2561
- async placeOrders(params, txParams, subAccountId, optionalIxs) {
2562
- const { txSig } = await this.sendTransaction((await this.preparePlaceOrdersTx(params, txParams, subAccountId, optionalIxs)).placeOrdersTx, [], this.opts, false);
2728
+ async placeOrders(params, txParams, subAccountId, optionalIxs, isolatedPositionDepositAmount) {
2729
+ const { txSig } = await this.sendTransaction((await this.preparePlaceOrdersTx(params, txParams, subAccountId, optionalIxs, isolatedPositionDepositAmount)).placeOrdersTx, [], this.opts, false);
2563
2730
  return txSig;
2564
2731
  }
2565
- async preparePlaceOrdersTx(params, txParams, subAccountId, optionalIxs) {
2732
+ async preparePlaceOrdersTx(params, txParams, subAccountId, optionalIxs, isolatedPositionDepositAmount) {
2733
+ var _a;
2566
2734
  const lookupTableAccounts = await this.fetchAllLookupTableAccounts();
2567
- const tx = await this.buildTransaction(await this.getPlaceOrdersIx(params, subAccountId), txParams, undefined, lookupTableAccounts, undefined, undefined, optionalIxs);
2735
+ const preIxs = [];
2736
+ if ((params === null || params === void 0 ? void 0 : params.length) === 1) {
2737
+ const p = params[0];
2738
+ if ((0, types_1.isVariant)(p.marketType, 'perp') &&
2739
+ ((_a = isolatedPositionDepositAmount === null || isolatedPositionDepositAmount === void 0 ? void 0 : isolatedPositionDepositAmount.gt) === null || _a === void 0 ? void 0 : _a.call(isolatedPositionDepositAmount, numericConstants_1.ZERO)) &&
2740
+ this.isOrderIncreasingPosition(p, subAccountId)) {
2741
+ preIxs.push(await this.getTransferIsolatedPerpPositionDepositIx(isolatedPositionDepositAmount, p.marketIndex, subAccountId));
2742
+ }
2743
+ }
2744
+ const tx = await this.buildTransaction(await this.getPlaceOrdersIx(params, subAccountId), txParams, undefined, lookupTableAccounts, undefined, undefined, [...preIxs, ...(optionalIxs !== null && optionalIxs !== void 0 ? optionalIxs : [])]);
2568
2745
  return {
2569
2746
  placeOrdersTx: tx,
2570
2747
  };
@@ -2653,7 +2830,7 @@ class DriftClient {
2653
2830
  remainingAccounts,
2654
2831
  });
2655
2832
  const marginRatio = Math.floor((1 / positionMaxLev) * numericConstants_1.MARGIN_PRECISION.toNumber());
2656
- // TODO: Handle multiple markets?
2833
+ // Keep existing behavior but note: prefer using getPostPlaceOrderIxs path
2657
2834
  const setPositionMaxLevIxs = await this.getUpdateUserPerpPositionCustomMarginRatioIx(readablePerpMarketIndex[0], marginRatio, subAccountId);
2658
2835
  return [placeOrdersIxs, setPositionMaxLevIxs];
2659
2836
  }
@@ -3654,7 +3831,7 @@ class DriftClient {
3654
3831
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
3655
3832
  return txSig;
3656
3833
  }
3657
- async preparePlaceAndTakePerpOrderWithAdditionalOrders(orderParams, makerInfo, referrerInfo, bracketOrdersParams = new Array(), txParams, subAccountId, cancelExistingOrders, settlePnl, exitEarlyIfSimFails, auctionDurationPercentage, optionalIxs) {
3834
+ async preparePlaceAndTakePerpOrderWithAdditionalOrders(orderParams, makerInfo, referrerInfo, bracketOrdersParams = new Array(), txParams, subAccountId, cancelExistingOrders, settlePnl, exitEarlyIfSimFails, auctionDurationPercentage, optionalIxs, isolatedPositionDepositAmount) {
3658
3835
  const placeAndTakeIxs = [];
3659
3836
  const txsToSign = {
3660
3837
  placeAndTakeTx: undefined,
@@ -3666,13 +3843,22 @@ class DriftClient {
3666
3843
  const lookupTableAccounts = await this.fetchAllLookupTableAccounts();
3667
3844
  let earlyExitFailedPlaceAndTakeSim = false;
3668
3845
  const prepPlaceAndTakeTx = async () => {
3669
- var _a;
3846
+ var _a, _b;
3670
3847
  const placeAndTakeIx = await this.getPlaceAndTakePerpOrderIx(orderParams, makerInfo, referrerInfo, undefined, auctionDurationPercentage, subAccountId);
3848
+ if ((0, types_1.isVariant)(orderParams.marketType, 'perp') &&
3849
+ ((_a = isolatedPositionDepositAmount === null || isolatedPositionDepositAmount === void 0 ? void 0 : isolatedPositionDepositAmount.gt) === null || _a === void 0 ? void 0 : _a.call(isolatedPositionDepositAmount, numericConstants_1.ZERO)) &&
3850
+ this.isOrderIncreasingPosition(orderParams, subAccountId)) {
3851
+ placeAndTakeIxs.push(await this.getTransferIsolatedPerpPositionDepositIx(isolatedPositionDepositAmount, orderParams.marketIndex, subAccountId));
3852
+ }
3671
3853
  placeAndTakeIxs.push(placeAndTakeIx);
3672
3854
  if (bracketOrdersParams.length > 0) {
3673
3855
  const bracketOrdersIx = await this.getPlaceOrdersIx(bracketOrdersParams, subAccountId);
3674
3856
  placeAndTakeIxs.push(bracketOrdersIx);
3675
3857
  }
3858
+ // Optional extra ixs can be appended at the front
3859
+ if (optionalIxs === null || optionalIxs === void 0 ? void 0 : optionalIxs.length) {
3860
+ placeAndTakeIxs.unshift(...optionalIxs);
3861
+ }
3676
3862
  const shouldUseSimulationComputeUnits = txParams === null || txParams === void 0 ? void 0 : txParams.useSimulatedComputeUnits;
3677
3863
  const shouldExitIfSimulationFails = exitEarlyIfSimFails;
3678
3864
  const txParamsWithoutImplicitSimulation = {
@@ -3681,7 +3867,7 @@ class DriftClient {
3681
3867
  };
3682
3868
  if (shouldUseSimulationComputeUnits || shouldExitIfSimulationFails) {
3683
3869
  const placeAndTakeTxToSim = (await this.buildTransaction(placeAndTakeIxs, txParams, undefined, lookupTableAccounts, true, recentBlockHash, optionalIxs));
3684
- const simulationResult = await txParamProcessor_1.TransactionParamProcessor.getTxSimComputeUnits(placeAndTakeTxToSim, this.connection, (_a = txParams.computeUnitsBufferMultiplier) !== null && _a !== void 0 ? _a : 1.2, txParams.lowerBoundCu);
3870
+ const simulationResult = await txParamProcessor_1.TransactionParamProcessor.getTxSimComputeUnits(placeAndTakeTxToSim, this.connection, (_b = txParams.computeUnitsBufferMultiplier) !== null && _b !== void 0 ? _b : 1.2, txParams.lowerBoundCu);
3685
3871
  if (shouldExitIfSimulationFails && !simulationResult.success) {
3686
3872
  earlyExitFailedPlaceAndTakeSim = true;
3687
3873
  return;
@@ -6486,5 +6672,18 @@ class DriftClient {
6486
6672
  forceVersionedTransaction,
6487
6673
  });
6488
6674
  }
6675
+ isOrderIncreasingPosition(orderParams, subAccountId) {
6676
+ const userAccount = this.getUserAccount(subAccountId);
6677
+ const perpPosition = userAccount.perpPositions.find((p) => p.marketIndex === orderParams.marketIndex);
6678
+ if (!perpPosition)
6679
+ return true;
6680
+ const currentBase = perpPosition.baseAssetAmount;
6681
+ if (currentBase.eq(numericConstants_1.ZERO))
6682
+ return true;
6683
+ const orderBaseAmount = (0, types_1.isVariant)(orderParams.direction, 'long')
6684
+ ? orderParams.baseAssetAmount
6685
+ : orderParams.baseAssetAmount.neg();
6686
+ return currentBase.add(orderBaseAmount).abs().gt(currentBase.abs());
6687
+ }
6489
6688
  }
6490
6689
  exports.DriftClient = DriftClient;