Skip to content

Commit 89272cc

Browse files
committed
feat: deposit into iso position ixs
1 parent d527fc8 commit 89272cc

File tree

4 files changed

+156
-34
lines changed

4 files changed

+156
-34
lines changed

sdk/src/driftClient.ts

Lines changed: 150 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ import {
5757
StateAccount,
5858
SwapReduceOnly,
5959
SignedMsgOrderParamsMessage,
60-
TakerInfo,
6160
TxParams,
6261
UserAccount,
6362
UserStatsAccount,
@@ -185,6 +184,8 @@ import nacl from 'tweetnacl';
185184
import { Slothash } from './slot/SlothashSubscriber';
186185
import { getOracleId } from './oracles/oracleId';
187186
import { SignedMsgOrderParams } from './types';
187+
import { TakerInfo } from './types';
188+
// BN is already imported globally in this file via other imports
188189
import { sha256 } from '@noble/hashes/sha256';
189190

190191
type RemainingAccountParams = {
@@ -254,6 +255,69 @@ export class DriftClient {
254255
return this._isSubscribed && this.accountSubscriber.isSubscribed;
255256
}
256257

258+
public async getDepositIntoIsolatedPerpPositionIx({
259+
perpMarketIndex,
260+
amount,
261+
spotMarketIndex,
262+
subAccountId,
263+
userTokenAccount,
264+
}: {
265+
perpMarketIndex: number;
266+
amount: BN;
267+
spotMarketIndex?: number; // defaults to perp.quoteSpotMarketIndex
268+
subAccountId?: number;
269+
userTokenAccount?: PublicKey; // defaults ATA for spot market mint
270+
}): Promise<TransactionInstruction> {
271+
const user = await this.getUserAccountPublicKey(subAccountId);
272+
const userStats = this.getUserStatsAccountPublicKey();
273+
const statePk = await this.getStatePublicKey();
274+
const perp = this.getPerpMarketAccount(perpMarketIndex);
275+
const spotIndex = spotMarketIndex ?? perp.quoteSpotMarketIndex;
276+
const spot = this.getSpotMarketAccount(spotIndex);
277+
278+
const remainingAccounts = this.getRemainingAccounts({
279+
userAccounts: [this.getUserAccount(subAccountId)],
280+
readablePerpMarketIndex: perpMarketIndex,
281+
writableSpotMarketIndexes: [spotIndex],
282+
});
283+
284+
// token program and transfer hook mints need to be present for deposit
285+
this.addTokenMintToRemainingAccounts(spot, remainingAccounts);
286+
if (this.isTransferHook(spot)) {
287+
await this.addExtraAccountMetasToRemainingAccounts(
288+
spot.mint,
289+
remainingAccounts
290+
);
291+
}
292+
293+
const tokenProgram = this.getTokenProgramForSpotMarket(spot);
294+
const ata =
295+
userTokenAccount ??
296+
(await this.getAssociatedTokenAccount(
297+
spotIndex,
298+
false,
299+
tokenProgram
300+
));
301+
302+
return await this.program.instruction.depositIntoIsolatedPerpPosition(
303+
spotIndex,
304+
perpMarketIndex,
305+
amount,
306+
{
307+
accounts: {
308+
state: statePk,
309+
user,
310+
userStats,
311+
authority: this.wallet.publicKey,
312+
spotMarketVault: spot.vault,
313+
userTokenAccount: ata,
314+
tokenProgram,
315+
},
316+
remainingAccounts,
317+
}
318+
);
319+
}
320+
257321
public set isSubscribed(val: boolean) {
258322
this._isSubscribed = val;
259323
}
@@ -717,7 +781,6 @@ export class DriftClient {
717781

718782
return lookupTableAccount;
719783
}
720-
721784
public async fetchAllLookupTableAccounts(): Promise<
722785
AddressLookupTableAccount[]
723786
> {
@@ -1495,7 +1558,6 @@ export class DriftClient {
14951558
const { txSig } = await this.sendTransaction(tx, [], this.opts);
14961559
return txSig;
14971560
}
1498-
14991561
public async getUpdateUserCustomMarginRatioIx(
15001562
marginRatio: number,
15011563
subAccountId = 0
@@ -2196,7 +2258,6 @@ export class DriftClient {
21962258
this.mustIncludeSpotMarketIndexes.add(spotMarketIndex);
21972259
});
21982260
}
2199-
22002261
getRemainingAccounts(params: RemainingAccountParams): AccountMeta[] {
22012262
const { oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap } =
22022263
this.getRemainingAccountMapsForUsers(params.userAccounts);
@@ -2977,7 +3038,6 @@ export class DriftClient {
29773038
userAccountPublicKey,
29783039
};
29793040
}
2980-
29813041
public async createInitializeUserAccountAndDepositCollateral(
29823042
amount: BN,
29833043
userTokenAccount: PublicKey,
@@ -3777,7 +3837,6 @@ export class DriftClient {
37773837
}
37783838
);
37793839
}
3780-
37813840
public async getRemovePerpLpSharesIx(
37823841
marketIndex: number,
37833842
sharesToBurn?: BN,
@@ -3933,7 +3992,8 @@ export class DriftClient {
39333992
bracketOrdersParams = new Array<OptionalOrderParams>(),
39343993
referrerInfo?: ReferrerInfo,
39353994
cancelExistingOrders?: boolean,
3936-
settlePnl?: boolean
3995+
settlePnl?: boolean,
3996+
isolatedPositionDepositAmount?: BN
39373997
): Promise<{
39383998
cancelExistingOrdersTx?: Transaction | VersionedTransaction;
39393999
settlePnlTx?: Transaction | VersionedTransaction;
@@ -3958,10 +4018,32 @@ export class DriftClient {
39584018

39594019
const txKeys = Object.keys(ixPromisesForTxs);
39604020

3961-
ixPromisesForTxs.marketOrderTx = this.getPlaceOrdersIx(
3962-
[orderParams, ...bracketOrdersParams],
3963-
userAccount.subAccountId
3964-
);
4021+
4022+
const preIxs: TransactionInstruction[] = [];
4023+
if (isVariant(orderParams.marketType, 'perp') && isolatedPositionDepositAmount?.gt?.(ZERO)) {
4024+
preIxs.push(
4025+
await this.getDepositIntoIsolatedPerpPositionIx({
4026+
perpMarketIndex: orderParams.marketIndex,
4027+
amount: isolatedPositionDepositAmount as BN,
4028+
subAccountId: userAccount.subAccountId,
4029+
})
4030+
);
4031+
}
4032+
4033+
4034+
ixPromisesForTxs.marketOrderTx = (async () => {
4035+
const placeOrdersIx = await this.getPlaceOrdersIx(
4036+
[orderParams, ...bracketOrdersParams],
4037+
userAccount.subAccountId
4038+
);
4039+
if (preIxs.length) {
4040+
return [
4041+
...preIxs,
4042+
placeOrdersIx,
4043+
] as unknown as TransactionInstruction;
4044+
}
4045+
return placeOrdersIx;
4046+
})();
39654047

39664048
/* Cancel open orders in market if requested */
39674049
if (cancelExistingOrders && isVariant(orderParams.marketType, 'perp')) {
@@ -4076,12 +4158,29 @@ export class DriftClient {
40764158
public async placePerpOrder(
40774159
orderParams: OptionalOrderParams,
40784160
txParams?: TxParams,
4079-
subAccountId?: number
4161+
subAccountId?: number,
4162+
isolatedPositionDepositAmount?: BN
40804163
): Promise<TransactionSignature> {
4164+
const preIxs: TransactionInstruction[] = [];
4165+
if (isolatedPositionDepositAmount?.gt?.(ZERO)) {
4166+
preIxs.push(
4167+
await this.getDepositIntoIsolatedPerpPositionIx({
4168+
perpMarketIndex: orderParams.marketIndex,
4169+
amount: isolatedPositionDepositAmount as BN,
4170+
subAccountId,
4171+
})
4172+
);
4173+
}
4174+
40814175
const { txSig, slot } = await this.sendTransaction(
40824176
await this.buildTransaction(
40834177
await this.getPlacePerpOrderIx(orderParams, subAccountId),
4084-
txParams
4178+
txParams,
4179+
undefined,
4180+
undefined,
4181+
undefined,
4182+
undefined,
4183+
preIxs
40854184
),
40864185
[],
40874186
this.opts
@@ -4435,6 +4534,7 @@ export class DriftClient {
44354534
useMarketLastSlotCache: true,
44364535
});
44374536

4537+
44384538
return await this.program.instruction.cancelOrders(
44394539
marketType ?? null,
44404540
marketIndex ?? null,
@@ -4478,7 +4578,8 @@ export class DriftClient {
44784578
params: OrderParams[],
44794579
txParams?: TxParams,
44804580
subAccountId?: number,
4481-
optionalIxs?: TransactionInstruction[]
4581+
optionalIxs?: TransactionInstruction[],
4582+
isolatedPositionDepositAmount?: BN
44824583
): Promise<TransactionSignature> {
44834584
const { txSig } = await this.sendTransaction(
44844585
(
@@ -4500,25 +4601,39 @@ export class DriftClient {
45004601
params: OrderParams[],
45014602
txParams?: TxParams,
45024603
subAccountId?: number,
4503-
optionalIxs?: TransactionInstruction[]
4604+
optionalIxs?: TransactionInstruction[],
4605+
isolatedPositionDepositAmount?: BN
45044606
) {
45054607
const lookupTableAccounts = await this.fetchAllLookupTableAccounts();
45064608

4609+
const preIxs: TransactionInstruction[] = [];
4610+
if (params?.length === 1) {
4611+
const p = params[0];
4612+
if (isVariant(p.marketType, 'perp') && isolatedPositionDepositAmount?.gt?.(ZERO)) {
4613+
preIxs.push(
4614+
await this.getDepositIntoIsolatedPerpPositionIx({
4615+
perpMarketIndex: p.marketIndex,
4616+
amount: isolatedPositionDepositAmount as BN,
4617+
subAccountId,
4618+
})
4619+
);
4620+
}
4621+
}
4622+
45074623
const tx = await this.buildTransaction(
45084624
await this.getPlaceOrdersIx(params, subAccountId),
45094625
txParams,
45104626
undefined,
45114627
lookupTableAccounts,
45124628
undefined,
45134629
undefined,
4514-
optionalIxs
4630+
[...preIxs, ...(optionalIxs ?? [])]
45154631
);
45164632

45174633
return {
45184634
placeOrdersTx: tx,
45194635
};
45204636
}
4521-
45224637
public async getPlaceOrdersIx(
45234638
params: OptionalOrderParams[],
45244639
subAccountId?: number
@@ -5256,7 +5371,6 @@ export class DriftClient {
52565371

52575372
return txSig;
52585373
}
5259-
52605374
public async getJupiterSwapIxV6({
52615375
jupiterClient,
52625376
outMarketIndex,
@@ -5926,7 +6040,6 @@ export class DriftClient {
59266040
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
59276041
return txSig;
59286042
}
5929-
59306043
public async preparePlaceAndTakePerpOrderWithAdditionalOrders(
59316044
orderParams: OptionalOrderParams,
59326045
makerInfo?: MakerInfo | MakerInfo[],
@@ -5938,7 +6051,8 @@ export class DriftClient {
59386051
settlePnl?: boolean,
59396052
exitEarlyIfSimFails?: boolean,
59406053
auctionDurationPercentage?: number,
5941-
optionalIxs?: TransactionInstruction[]
6054+
optionalIxs?: TransactionInstruction[],
6055+
isolatedPositionDepositAmount?: BN
59426056
): Promise<{
59436057
placeAndTakeTx: Transaction | VersionedTransaction;
59446058
cancelExistingOrdersTx: Transaction | VersionedTransaction;
@@ -5972,6 +6086,16 @@ export class DriftClient {
59726086
subAccountId
59736087
);
59746088

6089+
if (isVariant(orderParams.marketType, 'perp') && isolatedPositionDepositAmount?.gt?.(ZERO)) {
6090+
placeAndTakeIxs.push(
6091+
await this.getDepositIntoIsolatedPerpPositionIx({
6092+
perpMarketIndex: orderParams.marketIndex,
6093+
amount: isolatedPositionDepositAmount as BN,
6094+
subAccountId,
6095+
})
6096+
);
6097+
}
6098+
59756099
placeAndTakeIxs.push(placeAndTakeIx);
59766100

59776101
if (bracketOrdersParams.length > 0) {
@@ -5982,6 +6106,11 @@ export class DriftClient {
59826106
placeAndTakeIxs.push(bracketOrdersIx);
59836107
}
59846108

6109+
// Optional extra ixs can be appended at the front
6110+
if (optionalIxs?.length) {
6111+
placeAndTakeIxs.unshift(...optionalIxs);
6112+
}
6113+
59856114
const shouldUseSimulationComputeUnits =
59866115
txParams?.useSimulatedComputeUnits;
59876116
const shouldExitIfSimulationFails = exitEarlyIfSimFails;
@@ -6670,7 +6799,6 @@ export class DriftClient {
66706799
this.spotMarketLastSlotCache.set(QUOTE_SPOT_MARKET_INDEX, slot);
66716800
return txSig;
66726801
}
6673-
66746802
public async getPlaceAndTakeSpotOrderIx(
66756803
orderParams: OptionalOrderParams,
66766804
fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
@@ -7115,7 +7243,6 @@ export class DriftClient {
71157243
bitFlags?: number;
71167244
policy?: ModifyOrderPolicy;
71177245
maxTs?: BN;
7118-
txParams?: TxParams;
71197246
},
71207247
subAccountId?: number
71217248
): Promise<TransactionInstruction> {
@@ -7454,7 +7581,6 @@ export class DriftClient {
74547581
this.perpMarketLastSlotCache.set(marketIndex, slot);
74557582
return txSig;
74567583
}
7457-
74587584
public async getLiquidatePerpIx(
74597585
userAccountPublicKey: PublicKey,
74607586
userAccount: UserAccount,
@@ -8245,7 +8371,6 @@ export class DriftClient {
82458371
}
82468372
);
82478373
}
8248-
82498374
public async resolveSpotBankruptcy(
82508375
userAccountPublicKey: PublicKey,
82518376
userAccount: UserAccount,
@@ -9040,7 +9165,6 @@ export class DriftClient {
90409165
const { txSig } = await this.sendTransaction(tx, [], this.opts);
90419166
return txSig;
90429167
}
9043-
90449168
public async getSettleRevenueToInsuranceFundIx(
90459169
spotMarketIndex: number
90469170
): Promise<TransactionInstruction> {
@@ -9830,7 +9954,6 @@ export class DriftClient {
98309954
);
98319955
return config as ProtectedMakerModeConfig;
98329956
}
9833-
98349957
public async updateUserProtectedMakerOrders(
98359958
subAccountId: number,
98369959
protectedOrders: boolean,
@@ -10048,4 +10171,4 @@ export class DriftClient {
1004810171
forceVersionedTransaction,
1004910172
});
1005010173
}
10051-
}
10174+
}

sdk/src/math/position.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ export function calculatePositionPNL(
119119

120120
if (withFunding) {
121121
const fundingRatePnL = calculateUnsettledFundingPnl(market, perpPosition);
122-
123122
pnl = pnl.add(fundingRatePnL);
124123
}
125124

sdk/src/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,10 @@ export type OptionalOrderParams = {
12091209
[Property in keyof OrderParams]?: OrderParams[Property];
12101210
} & NecessaryOrderParams;
12111211

1212+
export type PerpOrderIsolatedExtras = {
1213+
isolatedPositionDepositAmount?: BN;
1214+
};
1215+
12121216
export type ModifyOrderParams = {
12131217
[Property in keyof OrderParams]?: OrderParams[Property] | null;
12141218
} & { policy?: ModifyOrderPolicy };

0 commit comments

Comments
 (0)