Skip to content

Commit 3bb3d40

Browse files
authored
lukas/per market lev (#1862)
* feat: per market max leverage * fix: max margin ratio correct naming and decoding * fix: correctly decode perp position max lev * fix: add missing metadata for drift address on idl
1 parent 177215a commit 3bb3d40

File tree

5 files changed

+112
-15
lines changed

5 files changed

+112
-15
lines changed

sdk/src/decode/user.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export function decodeUser(buffer: Buffer): UserAccount {
111111
offset += 8;
112112
const lastQuoteAssetAmountPerLp = readSignedBigInt64LE(buffer, offset);
113113
offset += 8;
114-
const remainderBaseAssetAmount = buffer.readInt32LE(offset);
114+
const maxMarginRatio = buffer.readUInt16LE(offset);
115115
offset += 4;
116116
const marketIndex = buffer.readUInt16LE(offset);
117117
offset += 3;
@@ -128,12 +128,13 @@ export function decodeUser(buffer: Buffer): UserAccount {
128128
openAsks,
129129
settledPnl,
130130
lpShares,
131+
remainderBaseAssetAmount: 0,
131132
lastBaseAssetAmountPerLp,
132133
lastQuoteAssetAmountPerLp,
133-
remainderBaseAssetAmount,
134134
marketIndex,
135135
openOrders,
136136
perLpBase,
137+
maxMarginRatio,
137138
});
138139
}
139140

sdk/src/driftClient.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,50 @@ export class DriftClient {
15381538
return ix;
15391539
}
15401540

1541+
public async getUpdateUserPerpPositionCustomMarginRatioIx(
1542+
perpMarketIndex: number,
1543+
marginRatio: number,
1544+
subAccountId = 0
1545+
): Promise<TransactionInstruction> {
1546+
const userAccountPublicKey = getUserAccountPublicKeySync(
1547+
this.program.programId,
1548+
this.wallet.publicKey,
1549+
subAccountId
1550+
);
1551+
1552+
await this.addUser(subAccountId, this.wallet.publicKey);
1553+
1554+
const ix = this.program.instruction.updateUserPerpPositionCustomMarginRatio(
1555+
subAccountId,
1556+
perpMarketIndex,
1557+
marginRatio,
1558+
{
1559+
accounts: {
1560+
user: userAccountPublicKey,
1561+
authority: this.wallet.publicKey,
1562+
},
1563+
}
1564+
);
1565+
1566+
return ix;
1567+
}
1568+
1569+
public async updateUserPerpPositionCustomMarginRatio(
1570+
perpMarketIndex: number,
1571+
marginRatio: number,
1572+
subAccountId = 0,
1573+
txParams?: TxParams
1574+
): Promise<TransactionSignature> {
1575+
const ix = await this.getUpdateUserPerpPositionCustomMarginRatioIx(
1576+
perpMarketIndex,
1577+
marginRatio,
1578+
subAccountId
1579+
);
1580+
const tx = await this.buildTransaction(ix, txParams ?? this.txParams);
1581+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
1582+
return txSig;
1583+
}
1584+
15411585
public async getUpdateUserMarginTradingEnabledIx(
15421586
marginTradingEnabled: boolean,
15431587
subAccountId = 0,

sdk/src/idl/drift.json

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,6 +1444,35 @@
14441444
}
14451445
]
14461446
},
1447+
{
1448+
"name": "updateUserPerpPositionCustomMarginRatio",
1449+
"accounts": [
1450+
{
1451+
"name": "user",
1452+
"isMut": true,
1453+
"isSigner": false
1454+
},
1455+
{
1456+
"name": "authority",
1457+
"isMut": false,
1458+
"isSigner": true
1459+
}
1460+
],
1461+
"args": [
1462+
{
1463+
"name": "subAccountId",
1464+
"type": "u16"
1465+
},
1466+
{
1467+
"name": "perpMarketIndex",
1468+
"type": "u16"
1469+
},
1470+
{
1471+
"name": "marginRatio",
1472+
"type": "u16"
1473+
}
1474+
]
1475+
},
14471476
{
14481477
"name": "updateUserMarginTradingEnabled",
14491478
"accounts": [
@@ -11484,13 +11513,17 @@
1148411513
"type": "i64"
1148511514
},
1148611515
{
11487-
"name": "remainderBaseAssetAmount",
11488-
"docs": [
11489-
"Settling LP position can lead to a small amount of base asset being left over smaller than step size",
11490-
"This records that remainder so it can be settled later on",
11491-
"precision: BASE_PRECISION"
11492-
],
11493-
"type": "i32"
11516+
"name": "padding",
11517+
"type": {
11518+
"array": [
11519+
"u8",
11520+
2
11521+
]
11522+
}
11523+
},
11524+
{
11525+
"name": "maxMarginRatio",
11526+
"type": "u16"
1149411527
},
1149511528
{
1149611529
"name": "marketIndex",

sdk/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,9 @@ export type PerpPosition = {
10421042
openAsks: BN;
10431043
settledPnl: BN;
10441044
lpShares: BN;
1045+
/** TODO: remove this field - it doesn't exist on chain */
10451046
remainderBaseAssetAmount: number;
1047+
maxMarginRatio: number;
10461048
lastBaseAssetAmountPerLp: BN;
10471049
lastQuoteAssetAmountPerLp: BN;
10481050
perLpBase: number;

sdk/src/user.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ export class User {
330330
lastBaseAssetAmountPerLp: ZERO,
331331
lastQuoteAssetAmountPerLp: ZERO,
332332
perLpBase: 0,
333+
maxMarginRatio: 0,
333334
};
334335
}
335336

@@ -471,21 +472,27 @@ export class User {
471472
marketIndex,
472473
freeCollateral,
473474
worstCaseBaseAssetAmount,
474-
enterHighLeverageMode
475+
enterHighLeverageMode,
476+
perpPosition
475477
);
476478
}
477479

478480
getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(
479481
marketIndex: number,
480482
freeCollateral: BN,
481483
baseAssetAmount: BN,
482-
enterHighLeverageMode = undefined
484+
enterHighLeverageMode = undefined,
485+
perpPosition?: PerpPosition
483486
): BN {
487+
const userCustomMargin = Math.max(
488+
perpPosition?.maxMarginRatio ?? 0,
489+
this.getUserAccount().maxMarginRatio
490+
);
484491
const marginRatio = calculateMarketMarginRatio(
485492
this.driftClient.getPerpMarketAccount(marketIndex),
486493
baseAssetAmount,
487494
'Initial',
488-
this.getUserAccount().maxMarginRatio,
495+
userCustomMargin,
489496
enterHighLeverageMode || this.isHighLeverageMode('Initial')
490497
);
491498

@@ -2162,7 +2169,10 @@ export class User {
21622169
);
21632170
}
21642171

2165-
const userCustomMargin = this.getUserAccount().maxMarginRatio;
2172+
const userCustomMargin = Math.max(
2173+
perpPosition.maxMarginRatio,
2174+
this.getUserAccount().maxMarginRatio
2175+
);
21662176
const marginRatio = calculateMarketMarginRatio(
21672177
market,
21682178
baseAssetAmount.abs(),
@@ -2212,7 +2222,10 @@ export class User {
22122222

22132223
const proposedBaseAssetAmount = baseAssetAmount.add(positionBaseSizeChange);
22142224

2215-
const userCustomMargin = this.getUserAccount().maxMarginRatio;
2225+
const userCustomMargin = Math.max(
2226+
perpPosition.maxMarginRatio,
2227+
this.getUserAccount().maxMarginRatio
2228+
);
22162229

22172230
const marginRatio = calculateMarketMarginRatio(
22182231
market,
@@ -3578,12 +3591,16 @@ export class User {
35783591
oraclePrice
35793592
);
35803593

3594+
const userCustomMargin = Math.max(
3595+
perpPosition.maxMarginRatio,
3596+
this.getUserAccount().maxMarginRatio
3597+
);
35813598
const marginRatio = new BN(
35823599
calculateMarketMarginRatio(
35833600
perpMarket,
35843601
worstCaseBaseAmount.abs(),
35853602
marginCategory,
3586-
this.getUserAccount().maxMarginRatio,
3603+
userCustomMargin,
35873604
this.isHighLeverageMode(marginCategory)
35883605
)
35893606
);

0 commit comments

Comments
 (0)