@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.
- package/.env +4 -0
- package/VERSION +1 -1
- package/lib/browser/constants/perpMarkets.js +11 -0
- package/lib/browser/constants/spotMarkets.js +13 -0
- package/lib/browser/decode/user.js +2 -2
- package/lib/browser/driftClient.d.ts +20 -8
- package/lib/browser/driftClient.js +216 -17
- package/lib/browser/idl/drift.json +225 -21
- package/lib/browser/math/margin.js +2 -1
- package/lib/browser/math/position.d.ts +1 -0
- package/lib/browser/math/position.js +10 -2
- package/lib/browser/math/superStake.d.ts +3 -2
- package/lib/browser/types.d.ts +12 -6
- package/lib/browser/types.js +11 -6
- package/lib/browser/user.d.ts +3 -2
- package/lib/browser/user.js +24 -8
- package/lib/node/constants/perpMarkets.d.ts.map +1 -1
- package/lib/node/constants/perpMarkets.js +11 -0
- package/lib/node/constants/spotMarkets.d.ts.map +1 -1
- package/lib/node/constants/spotMarkets.js +13 -0
- package/lib/node/decode/user.d.ts.map +1 -1
- package/lib/node/decode/user.js +2 -2
- package/lib/node/driftClient.d.ts +20 -8
- package/lib/node/driftClient.d.ts.map +1 -1
- package/lib/node/driftClient.js +216 -17
- package/lib/node/idl/drift.json +225 -21
- package/lib/node/math/margin.d.ts.map +1 -1
- package/lib/node/math/margin.js +2 -1
- package/lib/node/math/position.d.ts +1 -0
- package/lib/node/math/position.d.ts.map +1 -1
- package/lib/node/math/position.js +10 -2
- package/lib/node/math/spotBalance.d.ts.map +1 -1
- package/lib/node/math/superStake.d.ts +3 -2
- package/lib/node/math/superStake.d.ts.map +1 -1
- package/lib/node/types.d.ts +12 -6
- package/lib/node/types.d.ts.map +1 -1
- package/lib/node/types.js +11 -6
- package/lib/node/user.d.ts +3 -2
- package/lib/node/user.d.ts.map +1 -1
- package/lib/node/user.js +24 -8
- package/package.json +1 -1
- package/scripts/deposit-isolated-positions.ts +110 -0
- package/scripts/single-grpc-client-test.ts +71 -21
- package/scripts/withdraw-isolated-positions.ts +174 -0
- package/src/constants/perpMarkets.ts +11 -0
- package/src/constants/spotMarkets.ts +14 -0
- package/src/decode/user.ts +2 -3
- package/src/driftClient.ts +464 -41
- package/src/idl/drift.json +226 -22
- package/src/margin/README.md +143 -0
- package/src/math/margin.ts +3 -4
- package/src/math/position.ts +12 -2
- package/src/math/spotBalance.ts +0 -1
- package/src/types.ts +15 -7
- package/src/user.ts +49 -15
- package/tests/amm/test.ts +1 -1
- package/tests/dlob/helpers.ts +1 -1
- package/tests/user/test.ts +0 -7
package/src/driftClient.ts
CHANGED
|
@@ -57,7 +57,6 @@ import {
|
|
|
57
57
|
StateAccount,
|
|
58
58
|
SwapReduceOnly,
|
|
59
59
|
SignedMsgOrderParamsMessage,
|
|
60
|
-
TakerInfo,
|
|
61
60
|
TxParams,
|
|
62
61
|
UserAccount,
|
|
63
62
|
UserStatsAccount,
|
|
@@ -140,6 +139,7 @@ import {
|
|
|
140
139
|
BASE_PRECISION,
|
|
141
140
|
GOV_SPOT_MARKET_INDEX,
|
|
142
141
|
MARGIN_PRECISION,
|
|
142
|
+
MIN_I64,
|
|
143
143
|
ONE,
|
|
144
144
|
PERCENTAGE_PRECISION,
|
|
145
145
|
PRICE_PRECISION,
|
|
@@ -147,7 +147,11 @@ import {
|
|
|
147
147
|
QUOTE_SPOT_MARKET_INDEX,
|
|
148
148
|
ZERO,
|
|
149
149
|
} from './constants/numericConstants';
|
|
150
|
-
import {
|
|
150
|
+
import {
|
|
151
|
+
calculateClaimablePnl,
|
|
152
|
+
findDirectionToClose,
|
|
153
|
+
positionIsAvailable,
|
|
154
|
+
} from './math/position';
|
|
151
155
|
import { getSignedTokenAmount, getTokenAmount } from './math/spotBalance';
|
|
152
156
|
import { decodeName, DEFAULT_USER_NAME, encodeName } from './userName';
|
|
153
157
|
import { MMOraclePriceData, OraclePriceData } from './oracles/types';
|
|
@@ -210,6 +214,8 @@ import nacl from 'tweetnacl';
|
|
|
210
214
|
import { Slothash } from './slot/SlothashSubscriber';
|
|
211
215
|
import { getOracleId } from './oracles/oracleId';
|
|
212
216
|
import { SignedMsgOrderParams } from './types';
|
|
217
|
+
import { TakerInfo } from './types';
|
|
218
|
+
// BN is already imported globally in this file via other imports
|
|
213
219
|
import { sha256 } from '@noble/hashes/sha256';
|
|
214
220
|
import { getOracleConfidenceFromMMOracleData } from './oracles/utils';
|
|
215
221
|
import { ConstituentMap } from './constituentMap/constituentMap';
|
|
@@ -295,6 +301,46 @@ export class DriftClient {
|
|
|
295
301
|
return this._isSubscribed && this.accountSubscriber.isSubscribed;
|
|
296
302
|
}
|
|
297
303
|
|
|
304
|
+
private async getPrePlaceOrderIxs(
|
|
305
|
+
orderParams: OptionalOrderParams,
|
|
306
|
+
userAccount: UserAccount,
|
|
307
|
+
options?: { positionMaxLev?: number; isolatedPositionDepositAmount?: BN }
|
|
308
|
+
): Promise<TransactionInstruction[]> {
|
|
309
|
+
const preIxs: TransactionInstruction[] = [];
|
|
310
|
+
|
|
311
|
+
if (isVariant(orderParams.marketType, 'perp')) {
|
|
312
|
+
const { positionMaxLev, isolatedPositionDepositAmount } = options ?? {};
|
|
313
|
+
|
|
314
|
+
if (
|
|
315
|
+
isolatedPositionDepositAmount?.gt?.(ZERO) &&
|
|
316
|
+
this.isOrderIncreasingPosition(orderParams, userAccount.subAccountId)
|
|
317
|
+
) {
|
|
318
|
+
preIxs.push(
|
|
319
|
+
await this.getTransferIsolatedPerpPositionDepositIx(
|
|
320
|
+
isolatedPositionDepositAmount as BN,
|
|
321
|
+
orderParams.marketIndex,
|
|
322
|
+
userAccount.subAccountId
|
|
323
|
+
)
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (positionMaxLev) {
|
|
328
|
+
const marginRatio = Math.floor(
|
|
329
|
+
(1 / positionMaxLev) * MARGIN_PRECISION.toNumber()
|
|
330
|
+
);
|
|
331
|
+
preIxs.push(
|
|
332
|
+
await this.getUpdateUserPerpPositionCustomMarginRatioIx(
|
|
333
|
+
orderParams.marketIndex,
|
|
334
|
+
marginRatio,
|
|
335
|
+
userAccount.subAccountId
|
|
336
|
+
)
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return preIxs;
|
|
342
|
+
}
|
|
343
|
+
|
|
298
344
|
public set isSubscribed(val: boolean) {
|
|
299
345
|
this._isSubscribed = val;
|
|
300
346
|
}
|
|
@@ -768,7 +814,6 @@ export class DriftClient {
|
|
|
768
814
|
|
|
769
815
|
return lookupTableAccount;
|
|
770
816
|
}
|
|
771
|
-
|
|
772
817
|
public async fetchAllLookupTableAccounts(): Promise<
|
|
773
818
|
AddressLookupTableAccount[]
|
|
774
819
|
> {
|
|
@@ -1746,7 +1791,6 @@ export class DriftClient {
|
|
|
1746
1791
|
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
1747
1792
|
return txSig;
|
|
1748
1793
|
}
|
|
1749
|
-
|
|
1750
1794
|
public async getUpdateUserCustomMarginRatioIx(
|
|
1751
1795
|
marginRatio: number,
|
|
1752
1796
|
subAccountId = 0
|
|
@@ -2469,6 +2513,15 @@ export class DriftClient {
|
|
|
2469
2513
|
return this.getTokenAmount(QUOTE_SPOT_MARKET_INDEX);
|
|
2470
2514
|
}
|
|
2471
2515
|
|
|
2516
|
+
public getIsolatedPerpPositionTokenAmount(
|
|
2517
|
+
perpMarketIndex: number,
|
|
2518
|
+
subAccountId?: number
|
|
2519
|
+
): BN {
|
|
2520
|
+
return this.getUser(subAccountId).getIsolatePerpPositionTokenAmount(
|
|
2521
|
+
perpMarketIndex
|
|
2522
|
+
);
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2472
2525
|
/**
|
|
2473
2526
|
* Returns the token amount for a given market. The spot market precision is based on the token mint decimals.
|
|
2474
2527
|
* Positive if it is a deposit, negative if it is a borrow.
|
|
@@ -2546,7 +2599,6 @@ export class DriftClient {
|
|
|
2546
2599
|
this.mustIncludeSpotMarketIndexes.add(spotMarketIndex);
|
|
2547
2600
|
});
|
|
2548
2601
|
}
|
|
2549
|
-
|
|
2550
2602
|
getRemainingAccounts(params: RemainingAccountParams): AccountMeta[] {
|
|
2551
2603
|
const { oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap } =
|
|
2552
2604
|
this.getRemainingAccountMapsForUsers(params.userAccounts);
|
|
@@ -3434,7 +3486,6 @@ export class DriftClient {
|
|
|
3434
3486
|
userAccountPublicKey,
|
|
3435
3487
|
};
|
|
3436
3488
|
}
|
|
3437
|
-
|
|
3438
3489
|
public async createInitializeUserAccountAndDepositCollateral(
|
|
3439
3490
|
amount: BN,
|
|
3440
3491
|
userTokenAccount: PublicKey,
|
|
@@ -4082,6 +4133,281 @@ export class DriftClient {
|
|
|
4082
4133
|
);
|
|
4083
4134
|
}
|
|
4084
4135
|
|
|
4136
|
+
async depositIntoIsolatedPerpPosition(
|
|
4137
|
+
amount: BN,
|
|
4138
|
+
perpMarketIndex: number,
|
|
4139
|
+
userTokenAccount: PublicKey,
|
|
4140
|
+
subAccountId?: number,
|
|
4141
|
+
txParams?: TxParams
|
|
4142
|
+
): Promise<TransactionSignature> {
|
|
4143
|
+
const { txSig } = await this.sendTransaction(
|
|
4144
|
+
await this.buildTransaction(
|
|
4145
|
+
await this.getDepositIntoIsolatedPerpPositionIx(
|
|
4146
|
+
amount,
|
|
4147
|
+
perpMarketIndex,
|
|
4148
|
+
userTokenAccount,
|
|
4149
|
+
subAccountId
|
|
4150
|
+
),
|
|
4151
|
+
txParams
|
|
4152
|
+
),
|
|
4153
|
+
[],
|
|
4154
|
+
this.opts
|
|
4155
|
+
);
|
|
4156
|
+
return txSig;
|
|
4157
|
+
}
|
|
4158
|
+
|
|
4159
|
+
async getDepositIntoIsolatedPerpPositionIx(
|
|
4160
|
+
amount: BN,
|
|
4161
|
+
perpMarketIndex: number,
|
|
4162
|
+
userTokenAccount: PublicKey,
|
|
4163
|
+
subAccountId?: number
|
|
4164
|
+
): Promise<TransactionInstruction> {
|
|
4165
|
+
const userAccountPublicKey = await getUserAccountPublicKey(
|
|
4166
|
+
this.program.programId,
|
|
4167
|
+
this.authority,
|
|
4168
|
+
subAccountId ?? this.activeSubAccountId
|
|
4169
|
+
);
|
|
4170
|
+
|
|
4171
|
+
const perpMarketAccount = this.getPerpMarketAccount(perpMarketIndex);
|
|
4172
|
+
const spotMarketIndex = perpMarketAccount.quoteSpotMarketIndex;
|
|
4173
|
+
const spotMarketAccount = this.getSpotMarketAccount(spotMarketIndex);
|
|
4174
|
+
|
|
4175
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
4176
|
+
userAccounts: [],
|
|
4177
|
+
writableSpotMarketIndexes: [spotMarketIndex],
|
|
4178
|
+
readablePerpMarketIndex: [perpMarketIndex],
|
|
4179
|
+
});
|
|
4180
|
+
|
|
4181
|
+
const tokenProgram = this.getTokenProgramForSpotMarket(spotMarketAccount);
|
|
4182
|
+
return await this.program.instruction.depositIntoIsolatedPerpPosition(
|
|
4183
|
+
spotMarketIndex,
|
|
4184
|
+
perpMarketIndex,
|
|
4185
|
+
amount,
|
|
4186
|
+
{
|
|
4187
|
+
accounts: {
|
|
4188
|
+
state: await this.getStatePublicKey(),
|
|
4189
|
+
spotMarketVault: spotMarketAccount.vault,
|
|
4190
|
+
user: userAccountPublicKey,
|
|
4191
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
4192
|
+
userTokenAccount: userTokenAccount,
|
|
4193
|
+
authority: this.wallet.publicKey,
|
|
4194
|
+
tokenProgram,
|
|
4195
|
+
},
|
|
4196
|
+
remainingAccounts,
|
|
4197
|
+
}
|
|
4198
|
+
);
|
|
4199
|
+
}
|
|
4200
|
+
|
|
4201
|
+
public async transferIsolatedPerpPositionDeposit(
|
|
4202
|
+
amount: BN,
|
|
4203
|
+
perpMarketIndex: number,
|
|
4204
|
+
subAccountId?: number,
|
|
4205
|
+
txParams?: TxParams,
|
|
4206
|
+
trySettle?: boolean
|
|
4207
|
+
): Promise<TransactionSignature> {
|
|
4208
|
+
const ixs = [];
|
|
4209
|
+
const tokenAmountDeposited =
|
|
4210
|
+
this.getIsolatedPerpPositionTokenAmount(perpMarketIndex);
|
|
4211
|
+
const transferIx = await this.getTransferIsolatedPerpPositionDepositIx(
|
|
4212
|
+
amount,
|
|
4213
|
+
perpMarketIndex,
|
|
4214
|
+
subAccountId
|
|
4215
|
+
);
|
|
4216
|
+
|
|
4217
|
+
const needsToSettle =
|
|
4218
|
+
amount.gt(tokenAmountDeposited) || amount.eq(MIN_I64) || trySettle;
|
|
4219
|
+
if (needsToSettle) {
|
|
4220
|
+
const settleIx = await this.settleMultiplePNLsIx(
|
|
4221
|
+
await getUserAccountPublicKey(
|
|
4222
|
+
this.program.programId,
|
|
4223
|
+
this.authority,
|
|
4224
|
+
subAccountId ?? this.activeSubAccountId
|
|
4225
|
+
),
|
|
4226
|
+
this.getUserAccount(subAccountId),
|
|
4227
|
+
[perpMarketIndex],
|
|
4228
|
+
SettlePnlMode.TRY_SETTLE
|
|
4229
|
+
);
|
|
4230
|
+
ixs.push(settleIx);
|
|
4231
|
+
}
|
|
4232
|
+
|
|
4233
|
+
ixs.push(transferIx);
|
|
4234
|
+
|
|
4235
|
+
const tx = await this.buildTransaction(ixs, txParams);
|
|
4236
|
+
const { txSig } = await this.sendTransaction(tx, [], {
|
|
4237
|
+
...this.opts,
|
|
4238
|
+
skipPreflight: true,
|
|
4239
|
+
});
|
|
4240
|
+
return txSig;
|
|
4241
|
+
}
|
|
4242
|
+
|
|
4243
|
+
public async getTransferIsolatedPerpPositionDepositIx(
|
|
4244
|
+
amount: BN,
|
|
4245
|
+
perpMarketIndex: number,
|
|
4246
|
+
subAccountId?: number,
|
|
4247
|
+
noAmountBuffer?: boolean
|
|
4248
|
+
): Promise<TransactionInstruction> {
|
|
4249
|
+
const userAccountPublicKey = await getUserAccountPublicKey(
|
|
4250
|
+
this.program.programId,
|
|
4251
|
+
this.authority,
|
|
4252
|
+
subAccountId ?? this.activeSubAccountId
|
|
4253
|
+
);
|
|
4254
|
+
|
|
4255
|
+
const perpMarketAccount = this.getPerpMarketAccount(perpMarketIndex);
|
|
4256
|
+
const spotMarketIndex = perpMarketAccount.quoteSpotMarketIndex;
|
|
4257
|
+
const spotMarketAccount = this.getSpotMarketAccount(spotMarketIndex);
|
|
4258
|
+
const user = await this.getUserAccount(subAccountId);
|
|
4259
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
4260
|
+
userAccounts: [user],
|
|
4261
|
+
writableSpotMarketIndexes: [spotMarketIndex],
|
|
4262
|
+
readablePerpMarketIndex: [perpMarketIndex],
|
|
4263
|
+
});
|
|
4264
|
+
|
|
4265
|
+
const amountWithBuffer =
|
|
4266
|
+
noAmountBuffer || amount.eq(MIN_I64)
|
|
4267
|
+
? amount
|
|
4268
|
+
: amount.add(amount.div(new BN(200))); // .5% buffer
|
|
4269
|
+
|
|
4270
|
+
return await this.program.instruction.transferIsolatedPerpPositionDeposit(
|
|
4271
|
+
spotMarketIndex,
|
|
4272
|
+
perpMarketIndex,
|
|
4273
|
+
amountWithBuffer,
|
|
4274
|
+
{
|
|
4275
|
+
accounts: {
|
|
4276
|
+
state: await this.getStatePublicKey(),
|
|
4277
|
+
spotMarketVault: spotMarketAccount.vault,
|
|
4278
|
+
user: userAccountPublicKey,
|
|
4279
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
4280
|
+
authority: this.wallet.publicKey,
|
|
4281
|
+
},
|
|
4282
|
+
remainingAccounts,
|
|
4283
|
+
}
|
|
4284
|
+
);
|
|
4285
|
+
}
|
|
4286
|
+
|
|
4287
|
+
public async withdrawFromIsolatedPerpPosition(
|
|
4288
|
+
amount: BN,
|
|
4289
|
+
perpMarketIndex: number,
|
|
4290
|
+
userTokenAccount: PublicKey,
|
|
4291
|
+
subAccountId?: number,
|
|
4292
|
+
txParams?: TxParams
|
|
4293
|
+
): Promise<TransactionSignature> {
|
|
4294
|
+
const instructions =
|
|
4295
|
+
await this.getWithdrawFromIsolatedPerpPositionIxsBundle(
|
|
4296
|
+
amount,
|
|
4297
|
+
perpMarketIndex,
|
|
4298
|
+
subAccountId,
|
|
4299
|
+
userTokenAccount
|
|
4300
|
+
);
|
|
4301
|
+
const { txSig } = await this.sendTransaction(
|
|
4302
|
+
await this.buildTransaction(instructions, txParams)
|
|
4303
|
+
);
|
|
4304
|
+
return txSig;
|
|
4305
|
+
}
|
|
4306
|
+
|
|
4307
|
+
public async getWithdrawFromIsolatedPerpPositionIxsBundle(
|
|
4308
|
+
amount: BN,
|
|
4309
|
+
perpMarketIndex: number,
|
|
4310
|
+
subAccountId?: number,
|
|
4311
|
+
userTokenAccount?: PublicKey
|
|
4312
|
+
): Promise<TransactionInstruction[]> {
|
|
4313
|
+
const userAccountPublicKey = await getUserAccountPublicKey(
|
|
4314
|
+
this.program.programId,
|
|
4315
|
+
this.authority,
|
|
4316
|
+
subAccountId ?? this.activeSubAccountId
|
|
4317
|
+
);
|
|
4318
|
+
const userAccount = this.getUserAccount(subAccountId);
|
|
4319
|
+
|
|
4320
|
+
const tokenAmountDeposited =
|
|
4321
|
+
this.getIsolatedPerpPositionTokenAmount(perpMarketIndex);
|
|
4322
|
+
const isolatedPositionUnrealizedPnl = calculateClaimablePnl(
|
|
4323
|
+
this.getPerpMarketAccount(perpMarketIndex),
|
|
4324
|
+
this.getSpotMarketAccount(
|
|
4325
|
+
this.getPerpMarketAccount(perpMarketIndex).quoteSpotMarketIndex
|
|
4326
|
+
),
|
|
4327
|
+
userAccount.perpPositions.find((p) => p.marketIndex === perpMarketIndex),
|
|
4328
|
+
this.getOracleDataForSpotMarket(
|
|
4329
|
+
this.getPerpMarketAccount(perpMarketIndex).quoteSpotMarketIndex
|
|
4330
|
+
)
|
|
4331
|
+
);
|
|
4332
|
+
|
|
4333
|
+
const depositAmountPlusUnrealizedPnl = tokenAmountDeposited.add(
|
|
4334
|
+
isolatedPositionUnrealizedPnl
|
|
4335
|
+
);
|
|
4336
|
+
|
|
4337
|
+
const amountToWithdraw = amount.gt(depositAmountPlusUnrealizedPnl)
|
|
4338
|
+
? MIN_I64 // min i64
|
|
4339
|
+
: amount;
|
|
4340
|
+
let associatedTokenAccount = userTokenAccount;
|
|
4341
|
+
if (!associatedTokenAccount) {
|
|
4342
|
+
const perpMarketAccount = this.getPerpMarketAccount(perpMarketIndex);
|
|
4343
|
+
const quoteSpotMarketIndex = perpMarketAccount.quoteSpotMarketIndex;
|
|
4344
|
+
associatedTokenAccount = await this.getAssociatedTokenAccount(
|
|
4345
|
+
quoteSpotMarketIndex
|
|
4346
|
+
);
|
|
4347
|
+
}
|
|
4348
|
+
|
|
4349
|
+
const withdrawIx = await this.getWithdrawFromIsolatedPerpPositionIx(
|
|
4350
|
+
amountToWithdraw,
|
|
4351
|
+
perpMarketIndex,
|
|
4352
|
+
associatedTokenAccount,
|
|
4353
|
+
subAccountId
|
|
4354
|
+
);
|
|
4355
|
+
const ixs = [withdrawIx];
|
|
4356
|
+
|
|
4357
|
+
const needsToSettle =
|
|
4358
|
+
amount.gt(tokenAmountDeposited) && isolatedPositionUnrealizedPnl.gt(ZERO);
|
|
4359
|
+
if (needsToSettle) {
|
|
4360
|
+
const settleIx = await this.settleMultiplePNLsIx(
|
|
4361
|
+
userAccountPublicKey,
|
|
4362
|
+
userAccount,
|
|
4363
|
+
[perpMarketIndex],
|
|
4364
|
+
SettlePnlMode.TRY_SETTLE
|
|
4365
|
+
);
|
|
4366
|
+
ixs.push(settleIx);
|
|
4367
|
+
}
|
|
4368
|
+
return ixs;
|
|
4369
|
+
}
|
|
4370
|
+
|
|
4371
|
+
public async getWithdrawFromIsolatedPerpPositionIx(
|
|
4372
|
+
amount: BN,
|
|
4373
|
+
perpMarketIndex: number,
|
|
4374
|
+
userTokenAccount: PublicKey,
|
|
4375
|
+
subAccountId?: number
|
|
4376
|
+
): Promise<TransactionInstruction> {
|
|
4377
|
+
const userAccountPublicKey = await getUserAccountPublicKey(
|
|
4378
|
+
this.program.programId,
|
|
4379
|
+
this.authority,
|
|
4380
|
+
subAccountId ?? this.activeSubAccountId
|
|
4381
|
+
);
|
|
4382
|
+
const perpMarketAccount = this.getPerpMarketAccount(perpMarketIndex);
|
|
4383
|
+
const spotMarketIndex = perpMarketAccount.quoteSpotMarketIndex;
|
|
4384
|
+
const spotMarketAccount = this.getSpotMarketAccount(spotMarketIndex);
|
|
4385
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
4386
|
+
userAccounts: [this.getUserAccount(subAccountId)],
|
|
4387
|
+
writableSpotMarketIndexes: [spotMarketIndex],
|
|
4388
|
+
readablePerpMarketIndex: [perpMarketIndex],
|
|
4389
|
+
});
|
|
4390
|
+
|
|
4391
|
+
return await this.program.instruction.withdrawFromIsolatedPerpPosition(
|
|
4392
|
+
spotMarketIndex,
|
|
4393
|
+
perpMarketIndex,
|
|
4394
|
+
amount,
|
|
4395
|
+
{
|
|
4396
|
+
accounts: {
|
|
4397
|
+
state: await this.getStatePublicKey(),
|
|
4398
|
+
spotMarketVault: spotMarketAccount.vault,
|
|
4399
|
+
user: userAccountPublicKey,
|
|
4400
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
4401
|
+
authority: this.wallet.publicKey,
|
|
4402
|
+
userTokenAccount: userTokenAccount,
|
|
4403
|
+
tokenProgram: this.getTokenProgramForSpotMarket(spotMarketAccount),
|
|
4404
|
+
driftSigner: this.getSignerPublicKey(),
|
|
4405
|
+
},
|
|
4406
|
+
remainingAccounts,
|
|
4407
|
+
}
|
|
4408
|
+
);
|
|
4409
|
+
}
|
|
4410
|
+
|
|
4085
4411
|
public async updateSpotMarketCumulativeInterest(
|
|
4086
4412
|
marketIndex: number,
|
|
4087
4413
|
txParams?: TxParams
|
|
@@ -4225,7 +4551,6 @@ export class DriftClient {
|
|
|
4225
4551
|
}
|
|
4226
4552
|
);
|
|
4227
4553
|
}
|
|
4228
|
-
|
|
4229
4554
|
public async getRemovePerpLpSharesIx(
|
|
4230
4555
|
marketIndex: number,
|
|
4231
4556
|
sharesToBurn?: BN,
|
|
@@ -4382,7 +4707,8 @@ export class DriftClient {
|
|
|
4382
4707
|
referrerInfo?: ReferrerInfo,
|
|
4383
4708
|
cancelExistingOrders?: boolean,
|
|
4384
4709
|
settlePnl?: boolean,
|
|
4385
|
-
positionMaxLev?: number
|
|
4710
|
+
positionMaxLev?: number,
|
|
4711
|
+
isolatedPositionDepositAmount?: BN
|
|
4386
4712
|
): Promise<{
|
|
4387
4713
|
cancelExistingOrdersTx?: Transaction | VersionedTransaction;
|
|
4388
4714
|
settlePnlTx?: Transaction | VersionedTransaction;
|
|
@@ -4410,18 +4736,25 @@ export class DriftClient {
|
|
|
4410
4736
|
|
|
4411
4737
|
const txKeys = Object.keys(ixPromisesForTxs);
|
|
4412
4738
|
|
|
4413
|
-
const
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
userAccount.subAccountId
|
|
4422
|
-
);
|
|
4739
|
+
const preIxs: TransactionInstruction[] = await this.getPrePlaceOrderIxs(
|
|
4740
|
+
orderParams,
|
|
4741
|
+
userAccount,
|
|
4742
|
+
{
|
|
4743
|
+
positionMaxLev,
|
|
4744
|
+
isolatedPositionDepositAmount,
|
|
4745
|
+
}
|
|
4746
|
+
);
|
|
4423
4747
|
|
|
4424
|
-
ixPromisesForTxs.marketOrderTx =
|
|
4748
|
+
ixPromisesForTxs.marketOrderTx = (async () => {
|
|
4749
|
+
const placeOrdersIx = await this.getPlaceOrdersIx(
|
|
4750
|
+
[orderParams, ...bracketOrdersParams],
|
|
4751
|
+
userAccount.subAccountId
|
|
4752
|
+
);
|
|
4753
|
+
if (preIxs.length) {
|
|
4754
|
+
return [...preIxs, placeOrdersIx] as unknown as TransactionInstruction;
|
|
4755
|
+
}
|
|
4756
|
+
return placeOrdersIx;
|
|
4757
|
+
})();
|
|
4425
4758
|
|
|
4426
4759
|
/* Cancel open orders in market if requested */
|
|
4427
4760
|
if (cancelExistingOrders && isVariant(orderParams.marketType, 'perp')) {
|
|
@@ -4539,12 +4872,32 @@ export class DriftClient {
|
|
|
4539
4872
|
public async placePerpOrder(
|
|
4540
4873
|
orderParams: OptionalOrderParams,
|
|
4541
4874
|
txParams?: TxParams,
|
|
4542
|
-
subAccountId?: number
|
|
4875
|
+
subAccountId?: number,
|
|
4876
|
+
isolatedPositionDepositAmount?: BN
|
|
4543
4877
|
): Promise<TransactionSignature> {
|
|
4878
|
+
const preIxs: TransactionInstruction[] = [];
|
|
4879
|
+
if (
|
|
4880
|
+
isolatedPositionDepositAmount?.gt?.(ZERO) &&
|
|
4881
|
+
this.isOrderIncreasingPosition(orderParams, subAccountId)
|
|
4882
|
+
) {
|
|
4883
|
+
preIxs.push(
|
|
4884
|
+
await this.getTransferIsolatedPerpPositionDepositIx(
|
|
4885
|
+
isolatedPositionDepositAmount as BN,
|
|
4886
|
+
orderParams.marketIndex,
|
|
4887
|
+
subAccountId
|
|
4888
|
+
)
|
|
4889
|
+
);
|
|
4890
|
+
}
|
|
4891
|
+
|
|
4544
4892
|
const { txSig, slot } = await this.sendTransaction(
|
|
4545
4893
|
await this.buildTransaction(
|
|
4546
4894
|
await this.getPlacePerpOrderIx(orderParams, subAccountId),
|
|
4547
|
-
txParams
|
|
4895
|
+
txParams,
|
|
4896
|
+
undefined,
|
|
4897
|
+
undefined,
|
|
4898
|
+
undefined,
|
|
4899
|
+
undefined,
|
|
4900
|
+
preIxs
|
|
4548
4901
|
),
|
|
4549
4902
|
[],
|
|
4550
4903
|
this.opts
|
|
@@ -4732,13 +5085,31 @@ export class DriftClient {
|
|
|
4732
5085
|
public async cancelOrder(
|
|
4733
5086
|
orderId?: number,
|
|
4734
5087
|
txParams?: TxParams,
|
|
4735
|
-
subAccountId?: number
|
|
5088
|
+
subAccountId?: number,
|
|
5089
|
+
overrides?: { withdrawIsolatedDepositAmount?: BN }
|
|
4736
5090
|
): Promise<TransactionSignature> {
|
|
5091
|
+
const cancelIx = await this.getCancelOrderIx(orderId, subAccountId);
|
|
5092
|
+
|
|
5093
|
+
const instructions: TransactionInstruction[] = [cancelIx];
|
|
5094
|
+
|
|
5095
|
+
if (overrides?.withdrawIsolatedDepositAmount !== undefined) {
|
|
5096
|
+
const order = this.getOrder(orderId, subAccountId);
|
|
5097
|
+
const perpMarketIndex = order?.marketIndex;
|
|
5098
|
+
const withdrawAmount = overrides.withdrawIsolatedDepositAmount;
|
|
5099
|
+
|
|
5100
|
+
if (withdrawAmount.gt(ZERO)) {
|
|
5101
|
+
const withdrawIxs =
|
|
5102
|
+
await this.getWithdrawFromIsolatedPerpPositionIxsBundle(
|
|
5103
|
+
withdrawAmount,
|
|
5104
|
+
perpMarketIndex,
|
|
5105
|
+
subAccountId
|
|
5106
|
+
);
|
|
5107
|
+
instructions.push(...withdrawIxs);
|
|
5108
|
+
}
|
|
5109
|
+
}
|
|
5110
|
+
|
|
4737
5111
|
const { txSig } = await this.sendTransaction(
|
|
4738
|
-
await this.buildTransaction(
|
|
4739
|
-
await this.getCancelOrderIx(orderId, subAccountId),
|
|
4740
|
-
txParams
|
|
4741
|
-
),
|
|
5112
|
+
await this.buildTransaction(instructions, txParams),
|
|
4742
5113
|
[],
|
|
4743
5114
|
this.opts
|
|
4744
5115
|
);
|
|
@@ -4972,7 +5343,8 @@ export class DriftClient {
|
|
|
4972
5343
|
params: OrderParams[],
|
|
4973
5344
|
txParams?: TxParams,
|
|
4974
5345
|
subAccountId?: number,
|
|
4975
|
-
optionalIxs?: TransactionInstruction[]
|
|
5346
|
+
optionalIxs?: TransactionInstruction[],
|
|
5347
|
+
isolatedPositionDepositAmount?: BN
|
|
4976
5348
|
): Promise<TransactionSignature> {
|
|
4977
5349
|
const { txSig } = await this.sendTransaction(
|
|
4978
5350
|
(
|
|
@@ -4980,7 +5352,8 @@ export class DriftClient {
|
|
|
4980
5352
|
params,
|
|
4981
5353
|
txParams,
|
|
4982
5354
|
subAccountId,
|
|
4983
|
-
optionalIxs
|
|
5355
|
+
optionalIxs,
|
|
5356
|
+
isolatedPositionDepositAmount
|
|
4984
5357
|
)
|
|
4985
5358
|
).placeOrdersTx,
|
|
4986
5359
|
[],
|
|
@@ -4994,10 +5367,29 @@ export class DriftClient {
|
|
|
4994
5367
|
params: OrderParams[],
|
|
4995
5368
|
txParams?: TxParams,
|
|
4996
5369
|
subAccountId?: number,
|
|
4997
|
-
optionalIxs?: TransactionInstruction[]
|
|
5370
|
+
optionalIxs?: TransactionInstruction[],
|
|
5371
|
+
isolatedPositionDepositAmount?: BN
|
|
4998
5372
|
) {
|
|
4999
5373
|
const lookupTableAccounts = await this.fetchAllLookupTableAccounts();
|
|
5000
5374
|
|
|
5375
|
+
const preIxs: TransactionInstruction[] = [];
|
|
5376
|
+
if (params?.length === 1) {
|
|
5377
|
+
const p = params[0];
|
|
5378
|
+
if (
|
|
5379
|
+
isVariant(p.marketType, 'perp') &&
|
|
5380
|
+
isolatedPositionDepositAmount?.gt?.(ZERO) &&
|
|
5381
|
+
this.isOrderIncreasingPosition(p, subAccountId)
|
|
5382
|
+
) {
|
|
5383
|
+
preIxs.push(
|
|
5384
|
+
await this.getTransferIsolatedPerpPositionDepositIx(
|
|
5385
|
+
isolatedPositionDepositAmount as BN,
|
|
5386
|
+
p.marketIndex,
|
|
5387
|
+
subAccountId
|
|
5388
|
+
)
|
|
5389
|
+
);
|
|
5390
|
+
}
|
|
5391
|
+
}
|
|
5392
|
+
|
|
5001
5393
|
const tx = await this.buildTransaction(
|
|
5002
5394
|
await this.getPlaceOrdersIx(params, subAccountId),
|
|
5003
5395
|
txParams,
|
|
@@ -5005,14 +5397,13 @@ export class DriftClient {
|
|
|
5005
5397
|
lookupTableAccounts,
|
|
5006
5398
|
undefined,
|
|
5007
5399
|
undefined,
|
|
5008
|
-
optionalIxs
|
|
5400
|
+
[...preIxs, ...(optionalIxs ?? [])]
|
|
5009
5401
|
);
|
|
5010
5402
|
|
|
5011
5403
|
return {
|
|
5012
5404
|
placeOrdersTx: tx,
|
|
5013
5405
|
};
|
|
5014
5406
|
}
|
|
5015
|
-
|
|
5016
5407
|
public async getPlaceOrdersIx(
|
|
5017
5408
|
params: OptionalOrderParams[],
|
|
5018
5409
|
subAccountId?: number,
|
|
@@ -5121,8 +5512,7 @@ export class DriftClient {
|
|
|
5121
5512
|
const marginRatio = Math.floor(
|
|
5122
5513
|
(1 / positionMaxLev) * MARGIN_PRECISION.toNumber()
|
|
5123
5514
|
);
|
|
5124
|
-
|
|
5125
|
-
// TODO: Handle multiple markets?
|
|
5515
|
+
// Keep existing behavior but note: prefer using getPostPlaceOrderIxs path
|
|
5126
5516
|
const setPositionMaxLevIxs =
|
|
5127
5517
|
await this.getUpdateUserPerpPositionCustomMarginRatioIx(
|
|
5128
5518
|
readablePerpMarketIndex[0],
|
|
@@ -6840,7 +7230,6 @@ export class DriftClient {
|
|
|
6840
7230
|
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
6841
7231
|
return txSig;
|
|
6842
7232
|
}
|
|
6843
|
-
|
|
6844
7233
|
public async preparePlaceAndTakePerpOrderWithAdditionalOrders(
|
|
6845
7234
|
orderParams: OptionalOrderParams,
|
|
6846
7235
|
makerInfo?: MakerInfo | MakerInfo[],
|
|
@@ -6852,7 +7241,8 @@ export class DriftClient {
|
|
|
6852
7241
|
settlePnl?: boolean,
|
|
6853
7242
|
exitEarlyIfSimFails?: boolean,
|
|
6854
7243
|
auctionDurationPercentage?: number,
|
|
6855
|
-
optionalIxs?: TransactionInstruction[]
|
|
7244
|
+
optionalIxs?: TransactionInstruction[],
|
|
7245
|
+
isolatedPositionDepositAmount?: BN
|
|
6856
7246
|
): Promise<{
|
|
6857
7247
|
placeAndTakeTx: Transaction | VersionedTransaction;
|
|
6858
7248
|
cancelExistingOrdersTx: Transaction | VersionedTransaction;
|
|
@@ -6886,6 +7276,20 @@ export class DriftClient {
|
|
|
6886
7276
|
subAccountId
|
|
6887
7277
|
);
|
|
6888
7278
|
|
|
7279
|
+
if (
|
|
7280
|
+
isVariant(orderParams.marketType, 'perp') &&
|
|
7281
|
+
isolatedPositionDepositAmount?.gt?.(ZERO) &&
|
|
7282
|
+
this.isOrderIncreasingPosition(orderParams, subAccountId)
|
|
7283
|
+
) {
|
|
7284
|
+
placeAndTakeIxs.push(
|
|
7285
|
+
await this.getTransferIsolatedPerpPositionDepositIx(
|
|
7286
|
+
isolatedPositionDepositAmount as BN,
|
|
7287
|
+
orderParams.marketIndex,
|
|
7288
|
+
subAccountId
|
|
7289
|
+
)
|
|
7290
|
+
);
|
|
7291
|
+
}
|
|
7292
|
+
|
|
6889
7293
|
placeAndTakeIxs.push(placeAndTakeIx);
|
|
6890
7294
|
|
|
6891
7295
|
if (bracketOrdersParams.length > 0) {
|
|
@@ -6896,6 +7300,11 @@ export class DriftClient {
|
|
|
6896
7300
|
placeAndTakeIxs.push(bracketOrdersIx);
|
|
6897
7301
|
}
|
|
6898
7302
|
|
|
7303
|
+
// Optional extra ixs can be appended at the front
|
|
7304
|
+
if (optionalIxs?.length) {
|
|
7305
|
+
placeAndTakeIxs.unshift(...optionalIxs);
|
|
7306
|
+
}
|
|
7307
|
+
|
|
6899
7308
|
const shouldUseSimulationComputeUnits =
|
|
6900
7309
|
txParams?.useSimulatedComputeUnits;
|
|
6901
7310
|
const shouldExitIfSimulationFails = exitEarlyIfSimFails;
|
|
@@ -7703,7 +8112,6 @@ export class DriftClient {
|
|
|
7703
8112
|
this.spotMarketLastSlotCache.set(QUOTE_SPOT_MARKET_INDEX, slot);
|
|
7704
8113
|
return txSig;
|
|
7705
8114
|
}
|
|
7706
|
-
|
|
7707
8115
|
public async getPlaceAndTakeSpotOrderIx(
|
|
7708
8116
|
orderParams: OptionalOrderParams,
|
|
7709
8117
|
fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
|
|
@@ -8166,7 +8574,6 @@ export class DriftClient {
|
|
|
8166
8574
|
bitFlags?: number;
|
|
8167
8575
|
policy?: ModifyOrderPolicy;
|
|
8168
8576
|
maxTs?: BN;
|
|
8169
|
-
txParams?: TxParams;
|
|
8170
8577
|
},
|
|
8171
8578
|
subAccountId?: number
|
|
8172
8579
|
): Promise<TransactionInstruction> {
|
|
@@ -8692,7 +9099,6 @@ export class DriftClient {
|
|
|
8692
9099
|
this.perpMarketLastSlotCache.set(marketIndex, slot);
|
|
8693
9100
|
return txSig;
|
|
8694
9101
|
}
|
|
8695
|
-
|
|
8696
9102
|
public async getLiquidatePerpIx(
|
|
8697
9103
|
userAccountPublicKey: PublicKey,
|
|
8698
9104
|
userAccount: UserAccount,
|
|
@@ -9483,7 +9889,6 @@ export class DriftClient {
|
|
|
9483
9889
|
}
|
|
9484
9890
|
);
|
|
9485
9891
|
}
|
|
9486
|
-
|
|
9487
9892
|
public async resolveSpotBankruptcy(
|
|
9488
9893
|
userAccountPublicKey: PublicKey,
|
|
9489
9894
|
userAccount: UserAccount,
|
|
@@ -10320,7 +10725,6 @@ export class DriftClient {
|
|
|
10320
10725
|
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
10321
10726
|
return txSig;
|
|
10322
10727
|
}
|
|
10323
|
-
|
|
10324
10728
|
public async getSettleRevenueToInsuranceFundIx(
|
|
10325
10729
|
spotMarketIndex: number
|
|
10326
10730
|
): Promise<TransactionInstruction> {
|
|
@@ -11124,7 +11528,6 @@ export class DriftClient {
|
|
|
11124
11528
|
);
|
|
11125
11529
|
return config as ProtectedMakerModeConfig;
|
|
11126
11530
|
}
|
|
11127
|
-
|
|
11128
11531
|
public async updateUserProtectedMakerOrders(
|
|
11129
11532
|
subAccountId: number,
|
|
11130
11533
|
protectedOrders: boolean,
|
|
@@ -12518,4 +12921,24 @@ export class DriftClient {
|
|
|
12518
12921
|
forceVersionedTransaction,
|
|
12519
12922
|
});
|
|
12520
12923
|
}
|
|
12924
|
+
|
|
12925
|
+
isOrderIncreasingPosition(
|
|
12926
|
+
orderParams: OptionalOrderParams,
|
|
12927
|
+
subAccountId: number
|
|
12928
|
+
): boolean {
|
|
12929
|
+
const userAccount = this.getUserAccount(subAccountId);
|
|
12930
|
+
const perpPosition = userAccount.perpPositions.find(
|
|
12931
|
+
(p) => p.marketIndex === orderParams.marketIndex
|
|
12932
|
+
);
|
|
12933
|
+
if (!perpPosition) return true;
|
|
12934
|
+
|
|
12935
|
+
const currentBase = perpPosition.baseAssetAmount;
|
|
12936
|
+
if (currentBase.eq(ZERO)) return true;
|
|
12937
|
+
|
|
12938
|
+
const orderBaseAmount = isVariant(orderParams.direction, 'long')
|
|
12939
|
+
? orderParams.baseAssetAmount
|
|
12940
|
+
: orderParams.baseAssetAmount.neg();
|
|
12941
|
+
|
|
12942
|
+
return currentBase.add(orderBaseAmount).abs().gt(currentBase.abs());
|
|
12943
|
+
}
|
|
12521
12944
|
}
|