@drift-labs/sdk 2.145.0 → 2.146.0-alpha.13

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 (99) hide show
  1. package/.env +4 -0
  2. package/VERSION +1 -1
  3. package/lib/browser/accounts/grpcMultiUserAccountSubscriber.js +8 -1
  4. package/lib/browser/accounts/webSocketProgramAccountSubscriberV2.d.ts +99 -7
  5. package/lib/browser/accounts/webSocketProgramAccountSubscriberV2.js +435 -144
  6. package/lib/browser/adminClient.d.ts +5 -1
  7. package/lib/browser/adminClient.js +57 -23
  8. package/lib/browser/constants/numericConstants.d.ts +2 -0
  9. package/lib/browser/constants/numericConstants.js +5 -1
  10. package/lib/browser/constants/perpMarkets.js +0 -2
  11. package/lib/browser/decode/user.js +4 -0
  12. package/lib/browser/driftClient.d.ts +25 -10
  13. package/lib/browser/driftClient.js +238 -41
  14. package/lib/browser/driftClientConfig.d.ts +7 -2
  15. package/lib/browser/idl/drift.json +245 -22
  16. package/lib/browser/index.d.ts +4 -0
  17. package/lib/browser/index.js +9 -1
  18. package/lib/browser/marginCalculation.d.ts +86 -0
  19. package/lib/browser/marginCalculation.js +209 -0
  20. package/lib/browser/math/margin.d.ts +1 -1
  21. package/lib/browser/math/margin.js +8 -1
  22. package/lib/browser/math/position.d.ts +1 -0
  23. package/lib/browser/math/position.js +10 -2
  24. package/lib/browser/math/spotPosition.d.ts +1 -1
  25. package/lib/browser/math/spotPosition.js +3 -2
  26. package/lib/browser/math/superStake.d.ts +3 -2
  27. package/lib/browser/types.d.ts +13 -0
  28. package/lib/browser/types.js +12 -1
  29. package/lib/browser/user.d.ts +59 -11
  30. package/lib/browser/user.js +348 -43
  31. package/lib/node/accounts/grpcMultiUserAccountSubscriber.d.ts.map +1 -1
  32. package/lib/node/accounts/grpcMultiUserAccountSubscriber.js +8 -1
  33. package/lib/node/accounts/webSocketProgramAccountSubscriberV2.d.ts +99 -7
  34. package/lib/node/accounts/webSocketProgramAccountSubscriberV2.d.ts.map +1 -1
  35. package/lib/node/accounts/webSocketProgramAccountSubscriberV2.js +435 -144
  36. package/lib/node/adminClient.d.ts +5 -1
  37. package/lib/node/adminClient.d.ts.map +1 -1
  38. package/lib/node/adminClient.js +57 -23
  39. package/lib/node/constants/numericConstants.d.ts +2 -0
  40. package/lib/node/constants/numericConstants.d.ts.map +1 -1
  41. package/lib/node/constants/numericConstants.js +5 -1
  42. package/lib/node/constants/perpMarkets.d.ts.map +1 -1
  43. package/lib/node/constants/perpMarkets.js +0 -2
  44. package/lib/node/decode/user.d.ts.map +1 -1
  45. package/lib/node/decode/user.js +4 -0
  46. package/lib/node/driftClient.d.ts +25 -10
  47. package/lib/node/driftClient.d.ts.map +1 -1
  48. package/lib/node/driftClient.js +238 -41
  49. package/lib/node/driftClientConfig.d.ts +7 -2
  50. package/lib/node/driftClientConfig.d.ts.map +1 -1
  51. package/lib/node/idl/drift.json +245 -22
  52. package/lib/node/index.d.ts +4 -0
  53. package/lib/node/index.d.ts.map +1 -1
  54. package/lib/node/index.js +9 -1
  55. package/lib/node/marginCalculation.d.ts +87 -0
  56. package/lib/node/marginCalculation.d.ts.map +1 -0
  57. package/lib/node/marginCalculation.js +209 -0
  58. package/lib/node/math/margin.d.ts +1 -1
  59. package/lib/node/math/margin.d.ts.map +1 -1
  60. package/lib/node/math/margin.js +8 -1
  61. package/lib/node/math/position.d.ts +1 -0
  62. package/lib/node/math/position.d.ts.map +1 -1
  63. package/lib/node/math/position.js +10 -2
  64. package/lib/node/math/spotPosition.d.ts +1 -1
  65. package/lib/node/math/spotPosition.d.ts.map +1 -1
  66. package/lib/node/math/spotPosition.js +3 -2
  67. package/lib/node/math/superStake.d.ts +3 -2
  68. package/lib/node/math/superStake.d.ts.map +1 -1
  69. package/lib/node/types.d.ts +13 -0
  70. package/lib/node/types.d.ts.map +1 -1
  71. package/lib/node/types.js +12 -1
  72. package/lib/node/user.d.ts +59 -11
  73. package/lib/node/user.d.ts.map +1 -1
  74. package/lib/node/user.js +348 -43
  75. package/package.json +1 -1
  76. package/scripts/deposit-isolated-positions.ts +110 -0
  77. package/scripts/single-grpc-client-test.ts +71 -21
  78. package/scripts/withdraw-isolated-positions.ts +174 -0
  79. package/src/accounts/grpcMultiUserAccountSubscriber.ts +8 -1
  80. package/src/accounts/webSocketProgramAccountSubscriberV2.ts +566 -167
  81. package/src/adminClient.ts +74 -25
  82. package/src/constants/numericConstants.ts +5 -0
  83. package/src/constants/perpMarkets.ts +0 -3
  84. package/src/decode/user.ts +7 -1
  85. package/src/driftClient.ts +465 -52
  86. package/src/driftClientConfig.ts +15 -8
  87. package/src/idl/drift.json +246 -23
  88. package/src/index.ts +4 -0
  89. package/src/margin/README.md +143 -0
  90. package/src/marginCalculation.ts +306 -0
  91. package/src/math/margin.ts +13 -1
  92. package/src/math/position.ts +12 -2
  93. package/src/math/spotPosition.ts +6 -2
  94. package/src/types.ts +16 -0
  95. package/src/user.ts +623 -81
  96. package/tests/amm/test.ts +1 -1
  97. package/tests/dlob/helpers.ts +6 -3
  98. package/tests/user/getMarginCalculation.ts +405 -0
  99. package/tests/user/test.ts +0 -7
@@ -71,10 +71,12 @@ 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");
77
78
  const builder_1 = require("./math/builder");
79
+ const bigNum_1 = require("./factory/bigNum");
78
80
  const titanClient_1 = require("./titan/titanClient");
79
81
  const UnifiedSwapClient_1 = require("./swap/UnifiedSwapClient");
80
82
  /**
@@ -85,11 +87,27 @@ class DriftClient {
85
87
  get isSubscribed() {
86
88
  return this._isSubscribed && this.accountSubscriber.isSubscribed;
87
89
  }
90
+ async getPrePlaceOrderIxs(orderParams, userAccount, options) {
91
+ var _a;
92
+ const preIxs = [];
93
+ if ((0, types_1.isVariant)(orderParams.marketType, 'perp')) {
94
+ const { positionMaxLev, isolatedPositionDepositAmount } = options !== null && options !== void 0 ? options : {};
95
+ if (((_a = isolatedPositionDepositAmount === null || isolatedPositionDepositAmount === void 0 ? void 0 : isolatedPositionDepositAmount.gt) === null || _a === void 0 ? void 0 : _a.call(isolatedPositionDepositAmount, numericConstants_1.ZERO)) &&
96
+ this.isOrderIncreasingPosition(orderParams, userAccount)) {
97
+ preIxs.push(await this.getTransferIsolatedPerpPositionDepositIx(isolatedPositionDepositAmount, orderParams.marketIndex, userAccount.subAccountId));
98
+ }
99
+ if (positionMaxLev) {
100
+ const marginRatio = Math.floor((1 / positionMaxLev) * numericConstants_1.MARGIN_PRECISION.toNumber());
101
+ preIxs.push(await this.getUpdateUserPerpPositionCustomMarginRatioIx(orderParams.marketIndex, marginRatio, userAccount.subAccountId));
102
+ }
103
+ }
104
+ return preIxs;
105
+ }
88
106
  set isSubscribed(val) {
89
107
  this._isSubscribed = val;
90
108
  }
91
109
  constructor(config) {
92
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25;
110
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26;
93
111
  this.users = new Map();
94
112
  this._isSubscribed = false;
95
113
  this.perpMarketLastSlotCache = new Map();
@@ -180,12 +198,13 @@ class DriftClient {
180
198
  resubTimeoutMs: (_z = config.accountSubscription) === null || _z === void 0 ? void 0 : _z.resubTimeoutMs,
181
199
  logResubMessages: (_0 = config.accountSubscription) === null || _0 === void 0 ? void 0 : _0.logResubMessages,
182
200
  commitment: (_1 = config.accountSubscription) === null || _1 === void 0 ? void 0 : _1.commitment,
201
+ programUserAccountSubscriber: (_2 = config.accountSubscription) === null || _2 === void 0 ? void 0 : _2.programUserAccountSubscriber,
183
202
  };
184
203
  this.userStatsAccountSubscriptionConfig = {
185
204
  type: 'websocket',
186
- resubTimeoutMs: (_2 = config.accountSubscription) === null || _2 === void 0 ? void 0 : _2.resubTimeoutMs,
187
- logResubMessages: (_3 = config.accountSubscription) === null || _3 === void 0 ? void 0 : _3.logResubMessages,
188
- commitment: (_4 = config.accountSubscription) === null || _4 === void 0 ? void 0 : _4.commitment,
205
+ resubTimeoutMs: (_3 = config.accountSubscription) === null || _3 === void 0 ? void 0 : _3.resubTimeoutMs,
206
+ logResubMessages: (_4 = config.accountSubscription) === null || _4 === void 0 ? void 0 : _4.logResubMessages,
207
+ commitment: (_5 = config.accountSubscription) === null || _5 === void 0 ? void 0 : _5.commitment,
189
208
  };
190
209
  }
191
210
  if (config.userStats) {
@@ -207,21 +226,22 @@ class DriftClient {
207
226
  const noMarketsAndOraclesSpecified = config.perpMarketIndexes === undefined &&
208
227
  config.spotMarketIndexes === undefined &&
209
228
  config.oracleInfos === undefined;
210
- if (((_5 = config.accountSubscription) === null || _5 === void 0 ? void 0 : _5.type) === 'polling') {
211
- this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, (_6 = config.perpMarketIndexes) !== null && _6 !== void 0 ? _6 : [], (_7 = config.spotMarketIndexes) !== null && _7 !== void 0 ? _7 : [], (_8 = config.oracleInfos) !== null && _8 !== void 0 ? _8 : [], noMarketsAndOraclesSpecified, delistedMarketSetting);
212
- }
213
- else if (((_9 = config.accountSubscription) === null || _9 === void 0 ? void 0 : _9.type) === 'grpc') {
214
- const accountSubscriberClass = (_11 = (_10 = config.accountSubscription) === null || _10 === void 0 ? void 0 : _10.driftClientAccountSubscriber) !== null && _11 !== void 0 ? _11 : grpcDriftClientAccountSubscriber_1.grpcDriftClientAccountSubscriber;
215
- this.accountSubscriber = new accountSubscriberClass(config.accountSubscription.grpcConfigs, this.program, (_12 = config.perpMarketIndexes) !== null && _12 !== void 0 ? _12 : [], (_13 = config.spotMarketIndexes) !== null && _13 !== void 0 ? _13 : [], (_14 = config.oracleInfos) !== null && _14 !== void 0 ? _14 : [], noMarketsAndOraclesSpecified, delistedMarketSetting, {
216
- resubTimeoutMs: (_15 = config.accountSubscription) === null || _15 === void 0 ? void 0 : _15.resubTimeoutMs,
217
- logResubMessages: (_16 = config.accountSubscription) === null || _16 === void 0 ? void 0 : _16.logResubMessages,
229
+ if (((_6 = config.accountSubscription) === null || _6 === void 0 ? void 0 : _6.type) === 'polling') {
230
+ this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, (_7 = config.perpMarketIndexes) !== null && _7 !== void 0 ? _7 : [], (_8 = config.spotMarketIndexes) !== null && _8 !== void 0 ? _8 : [], (_9 = config.oracleInfos) !== null && _9 !== void 0 ? _9 : [], noMarketsAndOraclesSpecified, delistedMarketSetting);
231
+ }
232
+ else if (((_10 = config.accountSubscription) === null || _10 === void 0 ? void 0 : _10.type) === 'grpc') {
233
+ const accountSubscriberClass = (_12 = (_11 = config.accountSubscription) === null || _11 === void 0 ? void 0 : _11.driftClientAccountSubscriber) !== null && _12 !== void 0 ? _12 : grpcDriftClientAccountSubscriber_1.grpcDriftClientAccountSubscriber;
234
+ this.accountSubscriber = new accountSubscriberClass(config.accountSubscription.grpcConfigs, this.program, (_13 = config.perpMarketIndexes) !== null && _13 !== void 0 ? _13 : [], (_14 = config.spotMarketIndexes) !== null && _14 !== void 0 ? _14 : [], (_15 = config.oracleInfos) !== null && _15 !== void 0 ? _15 : [], noMarketsAndOraclesSpecified, delistedMarketSetting, {
235
+ resubTimeoutMs: (_16 = config.accountSubscription) === null || _16 === void 0 ? void 0 : _16.resubTimeoutMs,
236
+ logResubMessages: (_17 = config.accountSubscription) === null || _17 === void 0 ? void 0 : _17.logResubMessages,
218
237
  });
219
238
  }
220
239
  else {
221
- this.accountSubscriber = new webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber(this.program, (_17 = config.perpMarketIndexes) !== null && _17 !== void 0 ? _17 : [], (_18 = config.spotMarketIndexes) !== null && _18 !== void 0 ? _18 : [], (_19 = config.oracleInfos) !== null && _19 !== void 0 ? _19 : [], noMarketsAndOraclesSpecified, delistedMarketSetting, {
222
- resubTimeoutMs: (_20 = config.accountSubscription) === null || _20 === void 0 ? void 0 : _20.resubTimeoutMs,
223
- logResubMessages: (_21 = config.accountSubscription) === null || _21 === void 0 ? void 0 : _21.logResubMessages,
224
- }, (_22 = config.accountSubscription) === null || _22 === void 0 ? void 0 : _22.commitment, (_23 = config.accountSubscription) === null || _23 === void 0 ? void 0 : _23.perpMarketAccountSubscriber, (_24 = config.accountSubscription) === null || _24 === void 0 ? void 0 : _24.oracleAccountSubscriber);
240
+ const accountSubscriberClass = (_19 = (_18 = config.accountSubscription) === null || _18 === void 0 ? void 0 : _18.driftClientAccountSubscriber) !== null && _19 !== void 0 ? _19 : webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber;
241
+ this.accountSubscriber = new accountSubscriberClass(this.program, (_20 = config.perpMarketIndexes) !== null && _20 !== void 0 ? _20 : [], (_21 = config.spotMarketIndexes) !== null && _21 !== void 0 ? _21 : [], (_22 = config.oracleInfos) !== null && _22 !== void 0 ? _22 : [], noMarketsAndOraclesSpecified, delistedMarketSetting, {
242
+ resubTimeoutMs: (_23 = config.accountSubscription) === null || _23 === void 0 ? void 0 : _23.resubTimeoutMs,
243
+ logResubMessages: (_24 = config.accountSubscription) === null || _24 === void 0 ? void 0 : _24.logResubMessages,
244
+ }, (_25 = config.accountSubscription) === null || _25 === void 0 ? void 0 : _25.commitment);
225
245
  }
226
246
  this.eventEmitter = this.accountSubscriber.eventEmitter;
227
247
  this.metricsEventEmitter = new events_1.EventEmitter();
@@ -229,7 +249,7 @@ class DriftClient {
229
249
  this.enableMetricsEvents = true;
230
250
  }
231
251
  this.txSender =
232
- (_25 = config.txSender) !== null && _25 !== void 0 ? _25 : new retryTxSender_1.RetryTxSender({
252
+ (_26 = config.txSender) !== null && _26 !== void 0 ? _26 : new retryTxSender_1.RetryTxSender({
233
253
  connection: this.connection,
234
254
  wallet: this.wallet,
235
255
  opts: this.opts,
@@ -1376,6 +1396,9 @@ class DriftClient {
1376
1396
  getQuoteAssetTokenAmount() {
1377
1397
  return this.getTokenAmount(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
1378
1398
  }
1399
+ getIsolatedPerpPositionTokenAmount(perpMarketIndex, subAccountId) {
1400
+ return this.getUser(subAccountId).getIsolatePerpPositionTokenAmount(perpMarketIndex);
1401
+ }
1379
1402
  /**
1380
1403
  * Returns the token amount for a given market. The spot market precision is based on the token mint decimals.
1381
1404
  * Positive if it is a deposit, negative if it is a borrow.
@@ -2130,6 +2153,122 @@ class DriftClient {
2130
2153
  remainingAccounts,
2131
2154
  });
2132
2155
  }
2156
+ async depositIntoIsolatedPerpPosition(amount, perpMarketIndex, userTokenAccount, subAccountId, txParams) {
2157
+ const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getDepositIntoIsolatedPerpPositionIx(amount, perpMarketIndex, userTokenAccount, subAccountId), txParams), [], this.opts);
2158
+ return txSig;
2159
+ }
2160
+ async getDepositIntoIsolatedPerpPositionIx(amount, perpMarketIndex, userTokenAccount, subAccountId) {
2161
+ const userAccountPublicKey = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.authority, subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId);
2162
+ const perpMarketAccount = this.getPerpMarketAccount(perpMarketIndex);
2163
+ const spotMarketIndex = perpMarketAccount.quoteSpotMarketIndex;
2164
+ const spotMarketAccount = this.getSpotMarketAccount(spotMarketIndex);
2165
+ const remainingAccounts = this.getRemainingAccounts({
2166
+ userAccounts: [],
2167
+ writableSpotMarketIndexes: [spotMarketIndex],
2168
+ readablePerpMarketIndex: [perpMarketIndex],
2169
+ });
2170
+ const tokenProgram = this.getTokenProgramForSpotMarket(spotMarketAccount);
2171
+ return await this.program.instruction.depositIntoIsolatedPerpPosition(spotMarketIndex, perpMarketIndex, amount, {
2172
+ accounts: {
2173
+ state: await this.getStatePublicKey(),
2174
+ spotMarketVault: spotMarketAccount.vault,
2175
+ user: userAccountPublicKey,
2176
+ userStats: this.getUserStatsAccountPublicKey(),
2177
+ userTokenAccount: userTokenAccount,
2178
+ authority: this.wallet.publicKey,
2179
+ tokenProgram,
2180
+ },
2181
+ remainingAccounts,
2182
+ });
2183
+ }
2184
+ async transferIsolatedPerpPositionDeposit(amount, perpMarketIndex, subAccountId, txParams) {
2185
+ const tx = await this.buildTransaction(await this.getTransferIsolatedPerpPositionDepositIx(amount, perpMarketIndex, subAccountId), txParams);
2186
+ const { txSig } = await this.sendTransaction(tx, [], {
2187
+ ...this.opts,
2188
+ skipPreflight: true,
2189
+ });
2190
+ return txSig;
2191
+ }
2192
+ async getTransferIsolatedPerpPositionDepositIx(amount, perpMarketIndex, subAccountId, noAmountBuffer) {
2193
+ const userAccountPublicKey = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.authority, subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId);
2194
+ const perpMarketAccount = this.getPerpMarketAccount(perpMarketIndex);
2195
+ const spotMarketIndex = perpMarketAccount.quoteSpotMarketIndex;
2196
+ const spotMarketAccount = this.getSpotMarketAccount(spotMarketIndex);
2197
+ const user = await this.getUserAccount(subAccountId);
2198
+ const remainingAccounts = this.getRemainingAccounts({
2199
+ userAccounts: [user],
2200
+ writableSpotMarketIndexes: [spotMarketIndex],
2201
+ readablePerpMarketIndex: [perpMarketIndex],
2202
+ });
2203
+ const amountWithBuffer = noAmountBuffer || amount.eq(bigNum_1.BigNum.fromPrint('-9223372036854775808').val)
2204
+ ? amount
2205
+ : amount.add(amount.div(new anchor_1.BN(1000))); // .1% buffer
2206
+ return await this.program.instruction.transferIsolatedPerpPositionDeposit(spotMarketIndex, perpMarketIndex, amountWithBuffer, {
2207
+ accounts: {
2208
+ state: await this.getStatePublicKey(),
2209
+ spotMarketVault: spotMarketAccount.vault,
2210
+ user: userAccountPublicKey,
2211
+ userStats: this.getUserStatsAccountPublicKey(),
2212
+ authority: this.wallet.publicKey,
2213
+ },
2214
+ remainingAccounts,
2215
+ });
2216
+ }
2217
+ async withdrawFromIsolatedPerpPosition(amount, perpMarketIndex, userTokenAccount, subAccountId, txParams) {
2218
+ const instructions = await this.getWithdrawFromIsolatedPerpPositionIxsBundle(amount, perpMarketIndex, subAccountId, userTokenAccount);
2219
+ const { txSig } = await this.sendTransaction(await this.buildTransaction(instructions, txParams));
2220
+ return txSig;
2221
+ }
2222
+ async getWithdrawFromIsolatedPerpPositionIxsBundle(amount, perpMarketIndex, subAccountId, userTokenAccount) {
2223
+ const userAccountPublicKey = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.authority, subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId);
2224
+ const userAccount = this.getUserAccount(subAccountId);
2225
+ const tokenAmountDeposited = this.getIsolatedPerpPositionTokenAmount(perpMarketIndex);
2226
+ 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));
2227
+ const depositAmountPlusUnrealizedPnl = tokenAmountDeposited.add(isolatedPositionUnrealizedPnl);
2228
+ const amountToWithdraw = amount.gt(depositAmountPlusUnrealizedPnl)
2229
+ ? bigNum_1.BigNum.fromPrint('-9223372036854775808').val // min i64
2230
+ : amount;
2231
+ console.log('amountToWithdraw', amountToWithdraw.toString());
2232
+ console.log('amount', amount.toString());
2233
+ let associatedTokenAccount = userTokenAccount;
2234
+ if (!associatedTokenAccount) {
2235
+ const perpMarketAccount = this.getPerpMarketAccount(perpMarketIndex);
2236
+ const quoteSpotMarketIndex = perpMarketAccount.quoteSpotMarketIndex;
2237
+ associatedTokenAccount = await this.getAssociatedTokenAccount(quoteSpotMarketIndex);
2238
+ }
2239
+ const withdrawIx = await this.getWithdrawFromIsolatedPerpPositionIx(amountToWithdraw, perpMarketIndex, associatedTokenAccount, subAccountId);
2240
+ const ixs = [withdrawIx];
2241
+ const needsToSettle = amount.gt(tokenAmountDeposited) && isolatedPositionUnrealizedPnl.gt(numericConstants_1.ZERO);
2242
+ if (needsToSettle) {
2243
+ const settleIx = await this.settleMultiplePNLsIx(userAccountPublicKey, userAccount, [perpMarketIndex], types_1.SettlePnlMode.TRY_SETTLE);
2244
+ ixs.push(settleIx);
2245
+ }
2246
+ return ixs;
2247
+ }
2248
+ async getWithdrawFromIsolatedPerpPositionIx(amount, perpMarketIndex, userTokenAccount, subAccountId) {
2249
+ const userAccountPublicKey = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.authority, subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId);
2250
+ const perpMarketAccount = this.getPerpMarketAccount(perpMarketIndex);
2251
+ const spotMarketIndex = perpMarketAccount.quoteSpotMarketIndex;
2252
+ const spotMarketAccount = this.getSpotMarketAccount(spotMarketIndex);
2253
+ const remainingAccounts = this.getRemainingAccounts({
2254
+ userAccounts: [this.getUserAccount(subAccountId)],
2255
+ writableSpotMarketIndexes: [spotMarketIndex],
2256
+ readablePerpMarketIndex: [perpMarketIndex],
2257
+ });
2258
+ return await this.program.instruction.withdrawFromIsolatedPerpPosition(spotMarketIndex, perpMarketIndex, amount, {
2259
+ accounts: {
2260
+ state: await this.getStatePublicKey(),
2261
+ spotMarketVault: spotMarketAccount.vault,
2262
+ user: userAccountPublicKey,
2263
+ userStats: this.getUserStatsAccountPublicKey(),
2264
+ authority: this.wallet.publicKey,
2265
+ userTokenAccount: userTokenAccount,
2266
+ tokenProgram: this.getTokenProgramForSpotMarket(spotMarketAccount),
2267
+ driftSigner: this.getSignerPublicKey(),
2268
+ },
2269
+ remainingAccounts,
2270
+ });
2271
+ }
2133
2272
  async updateSpotMarketCumulativeInterest(marketIndex, txParams) {
2134
2273
  const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.updateSpotMarketCumulativeInterestIx(marketIndex), txParams), [], this.opts);
2135
2274
  return txSig;
@@ -2262,7 +2401,7 @@ class DriftClient {
2262
2401
  const { txSig } = await this.sendTransaction(tx, undefined, opts !== null && opts !== void 0 ? opts : this.opts, true);
2263
2402
  return txSig;
2264
2403
  }
2265
- async prepareMarketOrderTxs(orderParams, userAccountPublicKey, userAccount, makerInfo, txParams, bracketOrdersParams = new Array(), referrerInfo, cancelExistingOrders, settlePnl, positionMaxLev) {
2404
+ async prepareMarketOrderTxs(orderParams, userAccountPublicKey, userAccount, makerInfo, txParams, bracketOrdersParams = new Array(), referrerInfo, cancelExistingOrders, settlePnl, positionMaxLev, isolatedPositionDepositAmount) {
2266
2405
  const marketIndex = orderParams.marketIndex;
2267
2406
  const orderId = userAccount.nextOrderId;
2268
2407
  const ixPromisesForTxs = {
@@ -2272,10 +2411,17 @@ class DriftClient {
2272
2411
  marketOrderTx: undefined,
2273
2412
  };
2274
2413
  const txKeys = Object.keys(ixPromisesForTxs);
2275
- const marketOrderTxIxs = positionMaxLev
2276
- ? this.getPlaceOrdersAndSetPositionMaxLevIx([orderParams, ...bracketOrdersParams], positionMaxLev, userAccount.subAccountId)
2277
- : this.getPlaceOrdersIx([orderParams, ...bracketOrdersParams], userAccount.subAccountId);
2278
- ixPromisesForTxs.marketOrderTx = marketOrderTxIxs;
2414
+ const preIxs = await this.getPrePlaceOrderIxs(orderParams, userAccount, {
2415
+ positionMaxLev,
2416
+ isolatedPositionDepositAmount,
2417
+ });
2418
+ ixPromisesForTxs.marketOrderTx = (async () => {
2419
+ const placeOrdersIx = await this.getPlaceOrdersIx([orderParams, ...bracketOrdersParams], userAccount.subAccountId);
2420
+ if (preIxs.length) {
2421
+ return [...preIxs, placeOrdersIx];
2422
+ }
2423
+ return placeOrdersIx;
2424
+ })();
2279
2425
  /* Cancel open orders in market if requested */
2280
2426
  if (cancelExistingOrders && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
2281
2427
  ixPromisesForTxs.cancelExistingOrdersTx = this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, userAccount.subAccountId);
@@ -2322,8 +2468,13 @@ class DriftClient {
2322
2468
  signedSettlePnlTx: signedTxs.settlePnlTx,
2323
2469
  };
2324
2470
  }
2325
- async placePerpOrder(orderParams, txParams, subAccountId) {
2326
- const { txSig, slot } = await this.sendTransaction(await this.buildTransaction(await this.getPlacePerpOrderIx(orderParams, subAccountId), txParams), [], this.opts);
2471
+ async placePerpOrder(orderParams, txParams, subAccountId, isolatedPositionDepositAmount) {
2472
+ var _a;
2473
+ const preIxs = [];
2474
+ if ((_a = isolatedPositionDepositAmount === null || isolatedPositionDepositAmount === void 0 ? void 0 : isolatedPositionDepositAmount.gt) === null || _a === void 0 ? void 0 : _a.call(isolatedPositionDepositAmount, numericConstants_1.ZERO)) {
2475
+ preIxs.push(await this.getTransferIsolatedPerpPositionDepositIx(isolatedPositionDepositAmount, orderParams.marketIndex, subAccountId));
2476
+ }
2477
+ const { txSig, slot } = await this.sendTransaction(await this.buildTransaction(await this.getPlacePerpOrderIx(orderParams, subAccountId), txParams, undefined, undefined, undefined, undefined, preIxs), [], this.opts);
2327
2478
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
2328
2479
  return txSig;
2329
2480
  }
@@ -2429,8 +2580,19 @@ class DriftClient {
2429
2580
  },
2430
2581
  });
2431
2582
  }
2432
- async cancelOrder(orderId, txParams, subAccountId) {
2433
- const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getCancelOrderIx(orderId, subAccountId), txParams), [], this.opts);
2583
+ async cancelOrder(orderId, txParams, subAccountId, overrides) {
2584
+ const cancelIx = await this.getCancelOrderIx(orderId, subAccountId);
2585
+ const instructions = [cancelIx];
2586
+ if ((overrides === null || overrides === void 0 ? void 0 : overrides.withdrawIsolatedDepositAmount) !== undefined) {
2587
+ const order = this.getOrder(orderId, subAccountId);
2588
+ const perpMarketIndex = order === null || order === void 0 ? void 0 : order.marketIndex;
2589
+ const withdrawAmount = overrides.withdrawIsolatedDepositAmount;
2590
+ if (withdrawAmount.gt(numericConstants_1.ZERO)) {
2591
+ const withdrawIxs = await this.getWithdrawFromIsolatedPerpPositionIxsBundle(withdrawAmount, perpMarketIndex, subAccountId);
2592
+ instructions.push(...withdrawIxs);
2593
+ }
2594
+ }
2595
+ const { txSig } = await this.sendTransaction(await this.buildTransaction(instructions, txParams), [], this.opts);
2434
2596
  return txSig;
2435
2597
  }
2436
2598
  async getCancelOrderIx(orderId, subAccountId) {
@@ -2549,13 +2711,22 @@ class DriftClient {
2549
2711
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
2550
2712
  return txSig;
2551
2713
  }
2552
- async placeOrders(params, txParams, subAccountId, optionalIxs) {
2553
- const { txSig } = await this.sendTransaction((await this.preparePlaceOrdersTx(params, txParams, subAccountId, optionalIxs)).placeOrdersTx, [], this.opts, false);
2714
+ async placeOrders(params, txParams, subAccountId, optionalIxs, isolatedPositionDepositAmount) {
2715
+ const { txSig } = await this.sendTransaction((await this.preparePlaceOrdersTx(params, txParams, subAccountId, optionalIxs, isolatedPositionDepositAmount)).placeOrdersTx, [], this.opts, false);
2554
2716
  return txSig;
2555
2717
  }
2556
- async preparePlaceOrdersTx(params, txParams, subAccountId, optionalIxs) {
2718
+ async preparePlaceOrdersTx(params, txParams, subAccountId, optionalIxs, isolatedPositionDepositAmount) {
2719
+ var _a;
2557
2720
  const lookupTableAccounts = await this.fetchAllLookupTableAccounts();
2558
- const tx = await this.buildTransaction(await this.getPlaceOrdersIx(params, subAccountId), txParams, undefined, lookupTableAccounts, undefined, undefined, optionalIxs);
2721
+ const preIxs = [];
2722
+ if ((params === null || params === void 0 ? void 0 : params.length) === 1) {
2723
+ const p = params[0];
2724
+ if ((0, types_1.isVariant)(p.marketType, 'perp') &&
2725
+ ((_a = isolatedPositionDepositAmount === null || isolatedPositionDepositAmount === void 0 ? void 0 : isolatedPositionDepositAmount.gt) === null || _a === void 0 ? void 0 : _a.call(isolatedPositionDepositAmount, numericConstants_1.ZERO))) {
2726
+ preIxs.push(await this.getTransferIsolatedPerpPositionDepositIx(isolatedPositionDepositAmount, p.marketIndex, subAccountId));
2727
+ }
2728
+ }
2729
+ const tx = await this.buildTransaction(await this.getPlaceOrdersIx(params, subAccountId), txParams, undefined, lookupTableAccounts, undefined, undefined, [...preIxs, ...(optionalIxs !== null && optionalIxs !== void 0 ? optionalIxs : [])]);
2559
2730
  return {
2560
2731
  placeOrdersTx: tx,
2561
2732
  };
@@ -2644,7 +2815,7 @@ class DriftClient {
2644
2815
  remainingAccounts,
2645
2816
  });
2646
2817
  const marginRatio = Math.floor((1 / positionMaxLev) * numericConstants_1.MARGIN_PRECISION.toNumber());
2647
- // TODO: Handle multiple markets?
2818
+ // Keep existing behavior but note: prefer using getPostPlaceOrderIxs path
2648
2819
  const setPositionMaxLevIxs = await this.getUpdateUserPerpPositionCustomMarginRatioIx(readablePerpMarketIndex[0], marginRatio, subAccountId);
2649
2820
  return [placeOrdersIxs, setPositionMaxLevIxs];
2650
2821
  }
@@ -3102,6 +3273,7 @@ class DriftClient {
3102
3273
  /**
3103
3274
  * Swap tokens in drift account using titan or jupiter
3104
3275
  * @param swapClient swap client to find routes and instructions (Titan or Jupiter)
3276
+ * @param jupiterClient @deprecated Use swapClient instead. Legacy parameter for backward compatibility
3105
3277
  * @param outMarketIndex the market index of the token you're buying
3106
3278
  * @param inMarketIndex the market index of the token you're selling
3107
3279
  * @param outAssociatedTokenAccount the token account to receive the token being sold on titan or jupiter
@@ -3115,12 +3287,17 @@ class DriftClient {
3115
3287
  * @param quote pass in the quote response from Jupiter quote's API
3116
3288
  * @param txParams
3117
3289
  */
3118
- async swap({ swapClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, reduceOnly, txParams, v6, quote, onlyDirectRoutes = false, }) {
3290
+ async swap({ swapClient, jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, reduceOnly, txParams, v6, quote, onlyDirectRoutes = false, }) {
3291
+ // Handle backward compatibility: use jupiterClient if swapClient is not provided
3292
+ const clientToUse = swapClient || jupiterClient;
3293
+ if (!clientToUse) {
3294
+ throw new Error('Either swapClient or jupiterClient must be provided');
3295
+ }
3119
3296
  let res;
3120
3297
  // Use unified SwapClient if available
3121
- if (swapClient instanceof UnifiedSwapClient_1.UnifiedSwapClient) {
3298
+ if (clientToUse instanceof UnifiedSwapClient_1.UnifiedSwapClient) {
3122
3299
  res = await this.getSwapIxV2({
3123
- swapClient,
3300
+ swapClient: clientToUse,
3124
3301
  outMarketIndex,
3125
3302
  inMarketIndex,
3126
3303
  outAssociatedTokenAccount,
@@ -3134,9 +3311,9 @@ class DriftClient {
3134
3311
  v6,
3135
3312
  });
3136
3313
  }
3137
- else if (swapClient instanceof titanClient_1.TitanClient) {
3314
+ else if (clientToUse instanceof titanClient_1.TitanClient) {
3138
3315
  res = await this.getTitanSwapIx({
3139
- titanClient: swapClient,
3316
+ titanClient: clientToUse,
3140
3317
  outMarketIndex,
3141
3318
  inMarketIndex,
3142
3319
  outAssociatedTokenAccount,
@@ -3148,10 +3325,10 @@ class DriftClient {
3148
3325
  reduceOnly,
3149
3326
  });
3150
3327
  }
3151
- else if (swapClient instanceof jupiterClient_1.JupiterClient) {
3328
+ else if (clientToUse instanceof jupiterClient_1.JupiterClient) {
3152
3329
  const quoteToUse = quote !== null && quote !== void 0 ? quote : v6 === null || v6 === void 0 ? void 0 : v6.quote;
3153
3330
  res = await this.getJupiterSwapIxV6({
3154
- jupiterClient: swapClient,
3331
+ jupiterClient: clientToUse,
3155
3332
  outMarketIndex,
3156
3333
  inMarketIndex,
3157
3334
  outAssociatedTokenAccount,
@@ -3623,7 +3800,7 @@ class DriftClient {
3623
3800
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
3624
3801
  return txSig;
3625
3802
  }
3626
- async preparePlaceAndTakePerpOrderWithAdditionalOrders(orderParams, makerInfo, referrerInfo, bracketOrdersParams = new Array(), txParams, subAccountId, cancelExistingOrders, settlePnl, exitEarlyIfSimFails, auctionDurationPercentage, optionalIxs) {
3803
+ async preparePlaceAndTakePerpOrderWithAdditionalOrders(orderParams, makerInfo, referrerInfo, bracketOrdersParams = new Array(), txParams, subAccountId, cancelExistingOrders, settlePnl, exitEarlyIfSimFails, auctionDurationPercentage, optionalIxs, isolatedPositionDepositAmount) {
3627
3804
  const placeAndTakeIxs = [];
3628
3805
  const txsToSign = {
3629
3806
  placeAndTakeTx: undefined,
@@ -3635,13 +3812,21 @@ class DriftClient {
3635
3812
  const lookupTableAccounts = await this.fetchAllLookupTableAccounts();
3636
3813
  let earlyExitFailedPlaceAndTakeSim = false;
3637
3814
  const prepPlaceAndTakeTx = async () => {
3638
- var _a;
3815
+ var _a, _b;
3639
3816
  const placeAndTakeIx = await this.getPlaceAndTakePerpOrderIx(orderParams, makerInfo, referrerInfo, undefined, auctionDurationPercentage, subAccountId);
3817
+ if ((0, types_1.isVariant)(orderParams.marketType, 'perp') &&
3818
+ ((_a = isolatedPositionDepositAmount === null || isolatedPositionDepositAmount === void 0 ? void 0 : isolatedPositionDepositAmount.gt) === null || _a === void 0 ? void 0 : _a.call(isolatedPositionDepositAmount, numericConstants_1.ZERO))) {
3819
+ placeAndTakeIxs.push(await this.getTransferIsolatedPerpPositionDepositIx(isolatedPositionDepositAmount, orderParams.marketIndex, subAccountId));
3820
+ }
3640
3821
  placeAndTakeIxs.push(placeAndTakeIx);
3641
3822
  if (bracketOrdersParams.length > 0) {
3642
3823
  const bracketOrdersIx = await this.getPlaceOrdersIx(bracketOrdersParams, subAccountId);
3643
3824
  placeAndTakeIxs.push(bracketOrdersIx);
3644
3825
  }
3826
+ // Optional extra ixs can be appended at the front
3827
+ if (optionalIxs === null || optionalIxs === void 0 ? void 0 : optionalIxs.length) {
3828
+ placeAndTakeIxs.unshift(...optionalIxs);
3829
+ }
3645
3830
  const shouldUseSimulationComputeUnits = txParams === null || txParams === void 0 ? void 0 : txParams.useSimulatedComputeUnits;
3646
3831
  const shouldExitIfSimulationFails = exitEarlyIfSimFails;
3647
3832
  const txParamsWithoutImplicitSimulation = {
@@ -3650,7 +3835,7 @@ class DriftClient {
3650
3835
  };
3651
3836
  if (shouldUseSimulationComputeUnits || shouldExitIfSimulationFails) {
3652
3837
  const placeAndTakeTxToSim = (await this.buildTransaction(placeAndTakeIxs, txParams, undefined, lookupTableAccounts, true, recentBlockHash, optionalIxs));
3653
- const simulationResult = await txParamProcessor_1.TransactionParamProcessor.getTxSimComputeUnits(placeAndTakeTxToSim, this.connection, (_a = txParams.computeUnitsBufferMultiplier) !== null && _a !== void 0 ? _a : 1.2, txParams.lowerBoundCu);
3838
+ const simulationResult = await txParamProcessor_1.TransactionParamProcessor.getTxSimComputeUnits(placeAndTakeTxToSim, this.connection, (_b = txParams.computeUnitsBufferMultiplier) !== null && _b !== void 0 ? _b : 1.2, txParams.lowerBoundCu);
3654
3839
  if (shouldExitIfSimulationFails && !simulationResult.success) {
3655
3840
  earlyExitFailedPlaceAndTakeSim = true;
3656
3841
  return;
@@ -6453,5 +6638,17 @@ class DriftClient {
6453
6638
  forceVersionedTransaction,
6454
6639
  });
6455
6640
  }
6641
+ isOrderIncreasingPosition(orderParams, userAccount) {
6642
+ const perpPosition = userAccount.perpPositions.find((p) => p.marketIndex === orderParams.marketIndex);
6643
+ if (!perpPosition)
6644
+ return true;
6645
+ const currentBase = perpPosition.baseAssetAmount;
6646
+ if (currentBase.eq(numericConstants_1.ZERO))
6647
+ return true;
6648
+ const orderBaseAmount = (0, types_1.isVariant)(orderParams.direction, 'long')
6649
+ ? orderParams.baseAssetAmount
6650
+ : orderParams.baseAssetAmount.neg();
6651
+ return currentBase.add(orderBaseAmount).abs().gt(currentBase.abs());
6652
+ }
6456
6653
  }
6457
6654
  exports.DriftClient = DriftClient;
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
3
  import { Commitment, ConfirmOptions, Connection, PublicKey, TransactionVersion } from '@solana/web3.js';
4
- import { IWallet, TxParams } from './types';
4
+ import { IWallet, TxParams, UserAccount } from './types';
5
5
  import { OracleInfo } from './oracles/types';
6
6
  import { BulkAccountLoader } from './accounts/bulkAccountLoader';
7
7
  import { DriftEnv } from './config';
@@ -14,6 +14,9 @@ import { WebSocketAccountSubscriberV2 } from './accounts/webSocketAccountSubscri
14
14
  import { grpcDriftClientAccountSubscriberV2 } from './accounts/grpcDriftClientAccountSubscriberV2';
15
15
  import { grpcDriftClientAccountSubscriber } from './accounts/grpcDriftClientAccountSubscriber';
16
16
  import { grpcMultiUserAccountSubscriber } from './accounts/grpcMultiUserAccountSubscriber';
17
+ import { WebSocketProgramAccountSubscriber } from './accounts/webSocketProgramAccountSubscriber';
18
+ import { WebSocketDriftClientAccountSubscriber } from './accounts/webSocketDriftClientAccountSubscriber';
19
+ import { WebSocketDriftClientAccountSubscriberV2 } from './accounts/webSocketDriftClientAccountSubscriberV2';
17
20
  export type DriftClientConfig = {
18
21
  connection: Connection;
19
22
  wallet: IWallet;
@@ -56,8 +59,10 @@ export type DriftClientSubscriptionConfig = {
56
59
  resubTimeoutMs?: number;
57
60
  logResubMessages?: boolean;
58
61
  commitment?: Commitment;
62
+ programUserAccountSubscriber?: WebSocketProgramAccountSubscriber<UserAccount>;
59
63
  perpMarketAccountSubscriber?: new (accountName: string, program: Program, accountPublicKey: PublicKey, decodeBuffer?: (buffer: Buffer) => any, resubOpts?: ResubOpts, commitment?: Commitment) => WebSocketAccountSubscriberV2<any> | WebSocketAccountSubscriber<any>;
60
- oracleAccountSubscriber?: new (accountName: string, program: Program, accountPublicKey: PublicKey, decodeBuffer?: (buffer: Buffer) => any, resubOpts?: ResubOpts, commitment?: Commitment) => WebSocketAccountSubscriberV2<any> | WebSocketAccountSubscriber<any>;
64
+ /** If you use V2 here, whatever you pass for perpMarketAccountSubscriber will be ignored and it will use v2 under the hood regardless */
65
+ driftClientAccountSubscriber?: new (program: Program, perpMarketIndexes: number[], spotMarketIndexes: number[], oracleInfos: OracleInfo[], shouldFindAllMarketsAndOracles: boolean, delistedMarketSetting: DelistedMarketSetting) => WebSocketDriftClientAccountSubscriber | WebSocketDriftClientAccountSubscriberV2;
61
66
  } | {
62
67
  type: 'polling';
63
68
  accountLoader: BulkAccountLoader;