@drift-labs/sdk 2.42.0-beta.5 → 2.42.0-beta.7

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/VERSION CHANGED
@@ -1 +1 @@
1
- 2.42.0-beta.5
1
+ 2.42.0-beta.7
@@ -269,7 +269,7 @@ export declare class DriftClient {
269
269
  * @param bracketOrdersParams
270
270
  * @returns
271
271
  */
272
- sendMarketOrderAndGetSignedFillTx(orderParams: OptionalOrderParams, userAccountPublicKey: PublicKey, userAccount: UserAccount, makerInfo?: MakerInfo | MakerInfo[], txParams?: TxParams, bracketOrdersParams?: OptionalOrderParams[], referrerInfo?: ReferrerInfo, useVersionedTx?: boolean): Promise<{
272
+ sendMarketOrderAndGetSignedFillTx(orderParams: OptionalOrderParams, userAccountPublicKey: PublicKey, userAccount: UserAccount, makerInfo?: MakerInfo | MakerInfo[], txParams?: TxParams, bracketOrdersParams?: OptionalOrderParams[], referrerInfo?: ReferrerInfo): Promise<{
273
273
  txSig: TransactionSignature;
274
274
  signedFillTx: Transaction;
275
275
  }>;
@@ -294,6 +294,7 @@ class DriftClient {
294
294
  * @param includeDelegates
295
295
  */
296
296
  async updateWallet(newWallet, subAccountIds, activeSubAccountId, includeDelegates, authoritySubaccountMap) {
297
+ var _a, _b;
297
298
  const newProvider = new anchor_1.AnchorProvider(this.connection,
298
299
  // @ts-ignore
299
300
  newWallet, this.opts);
@@ -308,6 +309,10 @@ class DriftClient {
308
309
  this.activeSubAccountId = activeSubAccountId;
309
310
  this.userStatsAccountPublicKey = undefined;
310
311
  this.includeDelegates = includeDelegates !== null && includeDelegates !== void 0 ? includeDelegates : false;
312
+ const walletSupportsVersionedTxns =
313
+ //@ts-ignore
314
+ (_b = (_a = this.wallet.supportedTransactionVersions) === null || _a === void 0 ? void 0 : _a.size) !== null && _b !== void 0 ? _b : 0 > 1;
315
+ this.txVersion = walletSupportsVersionedTxns ? 0 : 'legacy';
311
316
  if (includeDelegates && subAccountIds) {
312
317
  throw new Error('Can only pass one of includeDelegates or subAccountIds. If you want to specify subaccount ids for multiple authorities, pass authoritySubaccountMap instead');
313
318
  }
@@ -939,28 +944,25 @@ class DriftClient {
939
944
  * @param reduceOnly
940
945
  */
941
946
  async deposit(amount, marketIndex, associatedTokenAccount, subAccountId, reduceOnly = false) {
942
- const tx = new web3_js_1.Transaction();
943
- tx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
944
- units: 600000,
945
- }));
946
947
  const additionalSigners = [];
947
948
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
948
949
  const isSolMarket = spotMarketAccount.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
949
950
  const signerAuthority = this.wallet.publicKey;
950
951
  const createWSOLTokenAccount = isSolMarket && associatedTokenAccount.equals(signerAuthority);
952
+ const instructions = [];
951
953
  if (createWSOLTokenAccount) {
952
954
  const { ixs, pubkey } = await this.getWrappedSolAccountCreationIxs(amount, true);
953
955
  associatedTokenAccount = pubkey;
954
- ixs.forEach((ix) => {
955
- tx.add(ix);
956
- });
956
+ instructions.push(...ixs);
957
957
  }
958
958
  const depositCollateralIx = await this.getDepositInstruction(amount, marketIndex, associatedTokenAccount, subAccountId, reduceOnly, true);
959
- tx.add(depositCollateralIx);
959
+ instructions.push(depositCollateralIx);
960
960
  // Close the wrapped sol account at the end of the transaction
961
961
  if (createWSOLTokenAccount) {
962
- tx.add((0, spl_token_1.createCloseAccountInstruction)(associatedTokenAccount, signerAuthority, signerAuthority, []));
962
+ instructions.push((0, spl_token_1.createCloseAccountInstruction)(associatedTokenAccount, signerAuthority, signerAuthority, []));
963
963
  }
964
+ const txParams = { ...this.txParams, computeUnits: 600000 };
965
+ const tx = await this.buildTransaction(instructions, txParams);
964
966
  const { txSig, slot } = await this.sendTransaction(tx, additionalSigners, this.opts);
965
967
  this.spotMarketLastSlotCache.set(marketIndex, slot);
966
968
  return txSig;
@@ -1363,8 +1365,7 @@ class DriftClient {
1363
1365
  * @param bracketOrdersParams
1364
1366
  * @returns
1365
1367
  */
1366
- async sendMarketOrderAndGetSignedFillTx(orderParams, userAccountPublicKey, userAccount, makerInfo, txParams, bracketOrdersParams = new Array(), referrerInfo, useVersionedTx = true) {
1367
- var _a, _b;
1368
+ async sendMarketOrderAndGetSignedFillTx(orderParams, userAccountPublicKey, userAccount, makerInfo, txParams, bracketOrdersParams = new Array(), referrerInfo) {
1368
1369
  const marketIndex = orderParams.marketIndex;
1369
1370
  const orderId = userAccount.nextOrderId;
1370
1371
  const bracketOrderIxs = [];
@@ -1377,11 +1378,8 @@ class DriftClient {
1377
1378
  orderId,
1378
1379
  marketIndex,
1379
1380
  }, makerInfo, referrerInfo);
1380
- const walletSupportsVersionedTxns =
1381
- //@ts-ignore
1382
- (_b = (_a = this.wallet.supportedTransactionVersions) === null || _a === void 0 ? void 0 : _a.size) !== null && _b !== void 0 ? _b : 0 > 1;
1383
1381
  // use versioned transactions if there is a lookup table account and wallet is compatible
1384
- if (walletSupportsVersionedTxns && useVersionedTx) {
1382
+ if (this.txVersion === 0) {
1385
1383
  const versionedMarketOrderTx = await this.buildTransaction([placePerpOrderIx].concat(bracketOrderIxs), txParams, 0);
1386
1384
  const versionedFillTx = await this.buildTransaction([fillPerpOrderIx], txParams, 0);
1387
1385
  const [signedVersionedMarketOrderTx, signedVersionedFillTx] = await this.provider.wallet.signAllTransactions([
@@ -3252,12 +3250,11 @@ class DriftClient {
3252
3250
  return undefined;
3253
3251
  }
3254
3252
  sendTransaction(tx, additionalSigners, opts, preSigned) {
3255
- // @ts-ignore
3256
- if (!tx.message) {
3257
- return this.txSender.send(tx, additionalSigners, opts, preSigned);
3253
+ if (tx instanceof web3_js_1.VersionedTransaction) {
3254
+ return this.txSender.sendVersionedTransaction(tx, additionalSigners, opts, preSigned);
3258
3255
  }
3259
3256
  else {
3260
- return this.txSender.sendVersionedTransaction(tx, additionalSigners, opts, preSigned);
3257
+ return this.txSender.send(tx, additionalSigners, opts, preSigned);
3261
3258
  }
3262
3259
  }
3263
3260
  async buildTransaction(instructions, txParams, txVersion, lookupTables) {
@@ -26,7 +26,7 @@ export declare function calculateAskPrice(market: PerpMarketAccount, oraclePrice
26
26
  export declare function calculateNewMarketAfterTrade(baseAssetAmount: BN, direction: PositionDirection, market: PerpMarketAccount): PerpMarketAccount;
27
27
  export declare function calculateOracleReserveSpread(market: PerpMarketAccount, oraclePriceData: OraclePriceData): BN;
28
28
  export declare function calculateOracleSpread(price: BN, oraclePriceData: OraclePriceData): BN;
29
- export declare function calculateMarketMarginRatio(market: PerpMarketAccount, size: BN, marginCategory: MarginCategory): number;
29
+ export declare function calculateMarketMarginRatio(market: PerpMarketAccount, size: BN, marginCategory: MarginCategory, customMarginRatio?: number): number;
30
30
  export declare function calculateUnrealizedAssetWeight(market: PerpMarketAccount, quoteSpotMarket: SpotMarketAccount, unrealizedPnl: BN, marginCategory: MarginCategory, oraclePriceData: OraclePriceData): BN;
31
31
  export declare function calculateMarketAvailablePNL(perpMarket: PerpMarketAccount, spotMarket: SpotMarketAccount): BN;
32
32
  export declare function calculateMarketMaxAvailableInsurance(perpMarket: PerpMarketAccount, spotMarket: SpotMarketAccount): BN;
@@ -60,11 +60,12 @@ function calculateOracleSpread(price, oraclePriceData) {
60
60
  return price.sub(oraclePriceData.price);
61
61
  }
62
62
  exports.calculateOracleSpread = calculateOracleSpread;
63
- function calculateMarketMarginRatio(market, size, marginCategory) {
63
+ function calculateMarketMarginRatio(market, size, marginCategory, customMarginRatio = 0) {
64
64
  let marginRatio;
65
65
  switch (marginCategory) {
66
66
  case 'Initial': {
67
- marginRatio = (0, margin_1.calculateSizePremiumLiabilityWeight)(size, new anchor_1.BN(market.imfFactor), new anchor_1.BN(market.marginRatioInitial), numericConstants_1.MARGIN_PRECISION).toNumber();
67
+ // use lowest leverage between max allowed and optional user custom max
68
+ marginRatio = Math.max((0, margin_1.calculateSizePremiumLiabilityWeight)(size, new anchor_1.BN(market.imfFactor), new anchor_1.BN(market.marginRatioInitial), numericConstants_1.MARGIN_PRECISION).toNumber(), customMarginRatio);
68
69
  break;
69
70
  }
70
71
  case 'Maintenance': {
@@ -1,4 +1,4 @@
1
1
  import { BN } from '@coral-xyz/anchor';
2
2
  import { MarginCategory, SpotBalanceType, SpotMarketAccount } from '../types';
3
3
  export declare function castNumberToSpotPrecision(value: number | BN, spotMarket: SpotMarketAccount): BN;
4
- export declare function calculateSpotMarketMarginRatio(market: SpotMarketAccount, oraclePrice: BN, marginCategory: MarginCategory, size: BN, balanceType: SpotBalanceType): number;
4
+ export declare function calculateSpotMarketMarginRatio(market: SpotMarketAccount, oraclePrice: BN, marginCategory: MarginCategory, size: BN, balanceType: SpotBalanceType, customMarginRatio?: number): number;
@@ -14,14 +14,20 @@ function castNumberToSpotPrecision(value, spotMarket) {
14
14
  }
15
15
  }
16
16
  exports.castNumberToSpotPrecision = castNumberToSpotPrecision;
17
- function calculateSpotMarketMarginRatio(market, oraclePrice, marginCategory, size, balanceType) {
17
+ function calculateSpotMarketMarginRatio(market, oraclePrice, marginCategory, size, balanceType, customMarginRatio = 0) {
18
+ let marginRatio;
18
19
  if ((0, types_1.isVariant)(balanceType, 'deposit')) {
19
20
  const assetWeight = (0, spotBalance_1.calculateAssetWeight)(size, oraclePrice, market, marginCategory);
20
- return numericConstants_1.MARGIN_PRECISION.sub(assetWeight).toNumber();
21
+ marginRatio = numericConstants_1.MARGIN_PRECISION.sub(assetWeight).toNumber();
21
22
  }
22
23
  else {
23
24
  const liabilityWeight = (0, spotBalance_1.calculateLiabilityWeight)(size, market, marginCategory);
24
- return liabilityWeight.sub(numericConstants_1.MARGIN_PRECISION).toNumber();
25
+ marginRatio = liabilityWeight.sub(numericConstants_1.MARGIN_PRECISION).toNumber();
25
26
  }
27
+ if (marginCategory === 'Initial') {
28
+ // use lowest leverage between max allowed and optional user custom max
29
+ return Math.max(marginRatio, customMarginRatio);
30
+ }
31
+ return marginRatio;
26
32
  }
27
33
  exports.calculateSpotMarketMarginRatio = calculateSpotMarketMarginRatio;
@@ -10,9 +10,9 @@ export type OrderFillSimulation = {
10
10
  weightedTokenValue: BN;
11
11
  freeCollateralContribution: any;
12
12
  };
13
- export declare function getWorstCaseTokenAmounts(spotPosition: SpotPosition, spotMarketAccount: SpotMarketAccount, strictOraclePrice: StrictOraclePrice, marginCategory: MarginCategory): OrderFillSimulation;
14
- export declare function calculateWeightedTokenValue(tokenAmount: BN, tokenValue: BN, oraclePrice: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): {
13
+ export declare function getWorstCaseTokenAmounts(spotPosition: SpotPosition, spotMarketAccount: SpotMarketAccount, strictOraclePrice: StrictOraclePrice, marginCategory: MarginCategory, customMarginRatio?: number): OrderFillSimulation;
14
+ export declare function calculateWeightedTokenValue(tokenAmount: BN, tokenValue: BN, oraclePrice: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory, customMarginRatio?: number): {
15
15
  weight: BN;
16
16
  weightedTokenValue: BN;
17
17
  };
18
- export declare function simulateOrderFill(tokenAmount: BN, tokenValue: BN, openOrders: BN, strictOraclePrice: StrictOraclePrice, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): OrderFillSimulation;
18
+ export declare function simulateOrderFill(tokenAmount: BN, tokenValue: BN, openOrders: BN, strictOraclePrice: StrictOraclePrice, spotMarket: SpotMarketAccount, marginCategory: MarginCategory, customMarginRatio?: number): OrderFillSimulation;
@@ -2,16 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.simulateOrderFill = exports.calculateWeightedTokenValue = exports.getWorstCaseTokenAmounts = exports.isSpotPositionAvailable = void 0;
4
4
  const numericConstants_1 = require("../constants/numericConstants");
5
+ const anchor_1 = require("@coral-xyz/anchor");
5
6
  const spotBalance_1 = require("./spotBalance");
6
7
  function isSpotPositionAvailable(position) {
7
8
  return position.scaledBalance.eq(numericConstants_1.ZERO) && position.openOrders === 0;
8
9
  }
9
10
  exports.isSpotPositionAvailable = isSpotPositionAvailable;
10
- function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory) {
11
+ function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory, customMarginRatio) {
11
12
  const tokenAmount = (0, spotBalance_1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
12
13
  const tokenValue = (0, spotBalance_1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
13
14
  if (spotPosition.openBids.eq(numericConstants_1.ZERO) && spotPosition.openAsks.eq(numericConstants_1.ZERO)) {
14
- const { weight, weightedTokenValue } = calculateWeightedTokenValue(tokenAmount, tokenValue, strictOraclePrice.current, spotMarketAccount, marginCategory);
15
+ const { weight, weightedTokenValue } = calculateWeightedTokenValue(tokenAmount, tokenValue, strictOraclePrice.current, spotMarketAccount, marginCategory, customMarginRatio);
15
16
  return {
16
17
  tokenAmount,
17
18
  ordersValue: numericConstants_1.ZERO,
@@ -21,8 +22,8 @@ function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, strictOracleP
21
22
  freeCollateralContribution: weightedTokenValue,
22
23
  };
23
24
  }
24
- const bidsSimulation = simulateOrderFill(tokenAmount, tokenValue, spotPosition.openBids, strictOraclePrice, spotMarketAccount, marginCategory);
25
- const asksSimulation = simulateOrderFill(tokenAmount, tokenValue, spotPosition.openAsks, strictOraclePrice, spotMarketAccount, marginCategory);
25
+ const bidsSimulation = simulateOrderFill(tokenAmount, tokenValue, spotPosition.openBids, strictOraclePrice, spotMarketAccount, marginCategory, customMarginRatio);
26
+ const asksSimulation = simulateOrderFill(tokenAmount, tokenValue, spotPosition.openAsks, strictOraclePrice, spotMarketAccount, marginCategory, customMarginRatio);
26
27
  if (asksSimulation.freeCollateralContribution.lt(bidsSimulation.freeCollateralContribution)) {
27
28
  return asksSimulation;
28
29
  }
@@ -31,7 +32,7 @@ function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, strictOracleP
31
32
  }
32
33
  }
33
34
  exports.getWorstCaseTokenAmounts = getWorstCaseTokenAmounts;
34
- function calculateWeightedTokenValue(tokenAmount, tokenValue, oraclePrice, spotMarket, marginCategory) {
35
+ function calculateWeightedTokenValue(tokenAmount, tokenValue, oraclePrice, spotMarket, marginCategory, customMarginRatio) {
35
36
  let weight;
36
37
  if (tokenValue.gte(numericConstants_1.ZERO)) {
37
38
  weight = (0, spotBalance_1.calculateAssetWeight)(tokenAmount, oraclePrice, spotMarket, marginCategory);
@@ -39,6 +40,16 @@ function calculateWeightedTokenValue(tokenAmount, tokenValue, oraclePrice, spotM
39
40
  else {
40
41
  weight = (0, spotBalance_1.calculateLiabilityWeight)(tokenAmount.abs(), spotMarket, marginCategory);
41
42
  }
43
+ if (marginCategory === 'Initial' &&
44
+ customMarginRatio &&
45
+ spotMarket.marketIndex !== numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
46
+ const userCustomAssetWeight = tokenValue.gte(numericConstants_1.ZERO)
47
+ ? anchor_1.BN.max(numericConstants_1.ZERO, numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION.subn(customMarginRatio))
48
+ : numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION.addn(customMarginRatio);
49
+ weight = tokenValue.gte(numericConstants_1.ZERO)
50
+ ? anchor_1.BN.min(weight, userCustomAssetWeight)
51
+ : anchor_1.BN.max(weight, userCustomAssetWeight);
52
+ }
42
53
  return {
43
54
  weight: weight,
44
55
  weightedTokenValue: tokenValue
@@ -47,13 +58,13 @@ function calculateWeightedTokenValue(tokenAmount, tokenValue, oraclePrice, spotM
47
58
  };
48
59
  }
49
60
  exports.calculateWeightedTokenValue = calculateWeightedTokenValue;
50
- function simulateOrderFill(tokenAmount, tokenValue, openOrders, strictOraclePrice, spotMarket, marginCategory) {
61
+ function simulateOrderFill(tokenAmount, tokenValue, openOrders, strictOraclePrice, spotMarket, marginCategory, customMarginRatio) {
51
62
  const ordersValue = (0, spotBalance_1.getTokenValue)(openOrders.neg(), spotMarket.decimals, {
52
63
  price: strictOraclePrice.max(),
53
64
  });
54
65
  const tokenAmountAfterFill = tokenAmount.add(openOrders);
55
66
  const tokenValueAfterFill = tokenValue.add(ordersValue.neg());
56
- const { weight, weightedTokenValue: weightedTokenValueAfterFill } = calculateWeightedTokenValue(tokenAmountAfterFill, tokenValueAfterFill, strictOraclePrice.current, spotMarket, marginCategory);
67
+ const { weight, weightedTokenValue: weightedTokenValueAfterFill } = calculateWeightedTokenValue(tokenAmountAfterFill, tokenValueAfterFill, strictOraclePrice.current, spotMarket, marginCategory, customMarginRatio);
57
68
  const freeCollateralContribution = weightedTokenValueAfterFill.add(ordersValue);
58
69
  return {
59
70
  tokenAmount: tokenAmountAfterFill,
package/lib/user.d.ts CHANGED
@@ -187,7 +187,7 @@ export declare class User {
187
187
  spotAssetValue: BN;
188
188
  spotLiabilityValue: BN;
189
189
  }): BN;
190
- getLeverageComponents(includeOpenOrders?: boolean): {
190
+ getLeverageComponents(includeOpenOrders?: boolean, marginCategory?: MarginCategory): {
191
191
  perpLiabilityValue: BN;
192
192
  perpPnl: BN;
193
193
  spotAssetValue: BN;
package/lib/user.js CHANGED
@@ -411,7 +411,7 @@ class User {
411
411
  return this.getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex, freeCollateral, worstCaseBaseAssetAmount);
412
412
  }
413
413
  getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex, freeCollateral, baseAssetAmount) {
414
- const marginRatio = (0, _1.calculateMarketMarginRatio)(this.driftClient.getPerpMarketAccount(marketIndex), baseAssetAmount, 'Initial');
414
+ const marginRatio = (0, _1.calculateMarketMarginRatio)(this.driftClient.getPerpMarketAccount(marketIndex), baseAssetAmount, 'Initial', this.getUserAccount().maxMarginRatio);
415
415
  return freeCollateral.mul(numericConstants_1.MARGIN_PRECISION).div(new _1.BN(marginRatio));
416
416
  }
417
417
  /**
@@ -577,7 +577,7 @@ class User {
577
577
  continue;
578
578
  }
579
579
  }
580
- const { tokenAmount: worstCaseTokenAmount, ordersValue: worstCaseQuoteTokenAmount, } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory !== null && marginCategory !== void 0 ? marginCategory : 'Initial');
580
+ const { tokenAmount: worstCaseTokenAmount, ordersValue: worstCaseQuoteTokenAmount, } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory, this.getUserAccount().maxMarginRatio);
581
581
  if (worstCaseTokenAmount.gt(numericConstants_1.ZERO) && countForBase) {
582
582
  const baseAssetValue = this.getSpotAssetValue(worstCaseTokenAmount, strictOraclePrice, spotMarketAccount, marginCategory);
583
583
  totalAssetValue = totalAssetValue.add(baseAssetValue);
@@ -620,8 +620,9 @@ class User {
620
620
  let liabilityValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
621
621
  if (marginCategory !== undefined) {
622
622
  let weight = (0, spotBalance_1.calculateLiabilityWeight)(tokenAmount, spotMarketAccount, marginCategory);
623
- if (marginCategory === 'Initial') {
624
- weight = _1.BN.max(weight, new _1.BN(this.getUserAccount().maxMarginRatio));
623
+ if (marginCategory === 'Initial' &&
624
+ spotMarketAccount.marketIndex !== numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
625
+ weight = _1.BN.max(weight, numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION.addn(this.getUserAccount().maxMarginRatio));
625
626
  }
626
627
  if (liquidationBuffer !== undefined) {
627
628
  weight = weight.add(liquidationBuffer);
@@ -639,7 +640,12 @@ class User {
639
640
  getSpotAssetValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory) {
640
641
  let assetValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
641
642
  if (marginCategory !== undefined) {
642
- const weight = (0, spotBalance_1.calculateAssetWeight)(tokenAmount, strictOraclePrice.current, spotMarketAccount, marginCategory);
643
+ let weight = (0, spotBalance_1.calculateAssetWeight)(tokenAmount, strictOraclePrice.current, spotMarketAccount, marginCategory);
644
+ if (marginCategory === 'Initial' &&
645
+ spotMarketAccount.marketIndex !== numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
646
+ const userCustomAssetWeight = _1.BN.max(numericConstants_1.ZERO, numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION.subn(this.getUserAccount().maxMarginRatio));
647
+ weight = _1.BN.min(weight, userCustomAssetWeight);
648
+ }
643
649
  assetValue = assetValue.mul(weight).div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
644
650
  }
645
651
  return assetValue;
@@ -702,10 +708,7 @@ class User {
702
708
  .mul(valuationPrice)
703
709
  .div(numericConstants_1.BASE_PRECISION);
704
710
  if (marginCategory) {
705
- let marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(market, baseAssetAmount.abs(), marginCategory));
706
- if (marginCategory === 'Initial') {
707
- marginRatio = _1.BN.max(marginRatio, new _1.BN(this.getUserAccount().maxMarginRatio));
708
- }
711
+ let marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(market, baseAssetAmount.abs(), marginCategory, this.getUserAccount().maxMarginRatio));
709
712
  if (liquidationBuffer !== undefined) {
710
713
  marginRatio = marginRatio.add(liquidationBuffer);
711
714
  }
@@ -834,10 +837,10 @@ class User {
834
837
  }
835
838
  return totalLiabilityValue.mul(numericConstants_1.TEN_THOUSAND).div(netAssetValue);
836
839
  }
837
- getLeverageComponents(includeOpenOrders = true) {
838
- const perpLiability = this.getTotalPerpPositionValue(undefined, undefined, includeOpenOrders);
839
- const perpPnl = this.getUnrealizedPNL(true);
840
- const { totalAssetValue: spotAssetValue, totalLiabilityValue: spotLiabilityValue, } = this.getSpotMarketAssetAndLiabilityValue(undefined, undefined, undefined, includeOpenOrders);
840
+ getLeverageComponents(includeOpenOrders = true, marginCategory = undefined) {
841
+ const perpLiability = this.getTotalPerpPositionValue(marginCategory, undefined, includeOpenOrders);
842
+ const perpPnl = this.getUnrealizedPNL(true, undefined, marginCategory);
843
+ const { totalAssetValue: spotAssetValue, totalLiabilityValue: spotLiabilityValue, } = this.getSpotMarketAssetAndLiabilityValue(undefined, marginCategory, undefined, includeOpenOrders);
841
844
  return {
842
845
  perpLiabilityValue: perpLiability,
843
846
  perpPnl,
@@ -889,7 +892,7 @@ class User {
889
892
  let rawMarginRatio;
890
893
  switch (marginCategory) {
891
894
  case 'Initial':
892
- rawMarginRatio = market.marginRatioInitial;
895
+ rawMarginRatio = Math.max(market.marginRatioInitial, this.getUserAccount().maxMarginRatio);
893
896
  break;
894
897
  case 'Maintenance':
895
898
  rawMarginRatio = market.marginRatioMaintenance;
@@ -905,7 +908,7 @@ class User {
905
908
  .mul(numericConstants_1.PRICE_PRECISION)
906
909
  .div(marketPrice));
907
910
  // margin ratio incorporting upper bound on size
908
- let marginRatio = (0, _1.calculateMarketMarginRatio)(market, maxSize, marginCategory);
911
+ let marginRatio = (0, _1.calculateMarketMarginRatio)(market, maxSize, marginCategory, this.getUserAccount().maxMarginRatio);
909
912
  // use more fesible size since imf factor activated
910
913
  let attempts = 0;
911
914
  while (marginRatio > rawMarginRatio + 1e-4 && attempts < 10) {
@@ -916,7 +919,7 @@ class User {
916
919
  .mul(numericConstants_1.PRICE_PRECISION)
917
920
  .div(marketPrice));
918
921
  // margin ratio incorporting more fesible target size
919
- marginRatio = (0, _1.calculateMarketMarginRatio)(market, targetSize, marginCategory);
922
+ marginRatio = (0, _1.calculateMarketMarginRatio)(market, targetSize, marginCategory, this.getUserAccount().maxMarginRatio);
920
923
  attempts += 1;
921
924
  }
922
925
  // how much more liabilities can be opened w remaining free collateral
@@ -1277,19 +1280,19 @@ class User {
1277
1280
  let freeCollateral = this.getFreeCollateral();
1278
1281
  const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', numericConstants_1.ZERO, (0, types_1.isVariant)(direction, 'long')
1279
1282
  ? _1.SpotBalanceType.DEPOSIT
1280
- : _1.SpotBalanceType.BORROW);
1283
+ : _1.SpotBalanceType.BORROW, this.getUserAccount().maxMarginRatio);
1281
1284
  let tradeAmount = numericConstants_1.ZERO;
1282
1285
  if (this.getUserAccount().isMarginTradingEnabled) {
1283
1286
  // if the user is buying/selling and already short/long, need to account for closing out short/long
1284
1287
  if ((0, types_1.isVariant)(direction, 'long') && currentSpotMarketNetValue.lt(numericConstants_1.ZERO)) {
1285
1288
  tradeAmount = currentSpotMarketNetValue.abs();
1286
- const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', this.getTokenAmount(targetMarketIndex).abs(), _1.SpotBalanceType.BORROW);
1289
+ const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', this.getTokenAmount(targetMarketIndex).abs(), _1.SpotBalanceType.BORROW, this.getUserAccount().maxMarginRatio);
1287
1290
  freeCollateral = freeCollateral.add(tradeAmount.mul(new _1.BN(marginRatio)).div(numericConstants_1.MARGIN_PRECISION));
1288
1291
  }
1289
1292
  else if ((0, types_1.isVariant)(direction, 'short') &&
1290
1293
  currentSpotMarketNetValue.gt(numericConstants_1.ZERO)) {
1291
1294
  tradeAmount = currentSpotMarketNetValue;
1292
- const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', this.getTokenAmount(targetMarketIndex), _1.SpotBalanceType.DEPOSIT);
1295
+ const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', this.getTokenAmount(targetMarketIndex), _1.SpotBalanceType.DEPOSIT, this.getUserAccount().maxMarginRatio);
1293
1296
  freeCollateral = freeCollateral.add(tradeAmount.mul(new _1.BN(marginRatio)).div(numericConstants_1.MARGIN_PRECISION));
1294
1297
  }
1295
1298
  tradeAmount = tradeAmount.add(freeCollateral.mul(numericConstants_1.MARGIN_PRECISION).div(new _1.BN(marginRatio)));
@@ -1332,7 +1335,7 @@ class User {
1332
1335
  const outContributionInitial = this.calculateSpotPositionFreeCollateralContribution(outSpotPosition, outStrictOraclePrice);
1333
1336
  const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outStrictOraclePrice);
1334
1337
  const initialContribution = inContributionInitial.add(outContributionInitial);
1335
- const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
1338
+ const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents(undefined, 'Initial');
1336
1339
  if (!calculateSwap) {
1337
1340
  calculateSwap = (inSwap) => {
1338
1341
  return inSwap
@@ -1440,14 +1443,14 @@ class User {
1440
1443
  calculateSpotPositionFreeCollateralContribution(spotPosition, strictOraclePrice) {
1441
1444
  const marginCategory = 'Initial';
1442
1445
  const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
1443
- const { freeCollateralContribution } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory);
1446
+ const { freeCollateralContribution } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory, this.getUserAccount().maxMarginRatio);
1444
1447
  return freeCollateralContribution;
1445
1448
  }
1446
1449
  calculateSpotPositionLeverageContribution(spotPosition, strictOraclePrice) {
1447
1450
  let totalAssetValue = numericConstants_1.ZERO;
1448
1451
  let totalLiabilityValue = numericConstants_1.ZERO;
1449
1452
  const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
1450
- const { tokenValue, ordersValue } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, 'Initial');
1453
+ const { tokenValue, ordersValue } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, 'Initial', this.getUserAccount().maxMarginRatio);
1451
1454
  if (tokenValue.gte(numericConstants_1.ZERO)) {
1452
1455
  totalAssetValue = tokenValue;
1453
1456
  }
@@ -1487,7 +1490,7 @@ class User {
1487
1490
  this.getEmptySpotPosition(outMarketIndex);
1488
1491
  const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition, inStrictOraclePrice);
1489
1492
  const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outStrictOraclePrice);
1490
- const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
1493
+ const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents(undefined, 'Initial');
1491
1494
  const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inAmount.abs().neg(), inMarket);
1492
1495
  const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outAmount.abs(), outMarket);
1493
1496
  const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter, inStrictOraclePrice);
@@ -1801,7 +1804,7 @@ class User {
1801
1804
  const oraclePriceData = this.driftClient.getOraclePriceDataAndSlot(perpMarket.amm.oracle).data;
1802
1805
  const oraclePrice = oraclePriceData.price;
1803
1806
  const worstCaseBaseAmount = (0, margin_1.calculateWorstCaseBaseAssetAmount)(perpPosition);
1804
- const marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(perpMarket, worstCaseBaseAmount.abs(), marginCategory));
1807
+ const marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(perpMarket, worstCaseBaseAmount.abs(), marginCategory, this.getUserAccount().maxMarginRatio));
1805
1808
  const quoteSpotMarket = this.driftClient.getSpotMarketAccount(perpMarket.quoteSpotMarketIndex);
1806
1809
  const quoteOraclePriceData = this.driftClient.getOraclePriceDataAndSlot(quoteSpotMarket.oracle).data;
1807
1810
  const baseAssetValue = worstCaseBaseAmount
@@ -1861,7 +1864,7 @@ class User {
1861
1864
  netQuoteValue = netQuoteValue.add(tokenAmount);
1862
1865
  continue;
1863
1866
  }
1864
- const { tokenAmount: worstCaseTokenAmount, tokenValue: tokenValue, weight, weightedTokenValue: weightedTokenValue, ordersValue: ordersValue, } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory);
1867
+ const { tokenAmount: worstCaseTokenAmount, tokenValue: tokenValue, weight, weightedTokenValue: weightedTokenValue, ordersValue: ordersValue, } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory, this.getUserAccount().maxMarginRatio);
1865
1868
  netQuoteValue = netQuoteValue.add(ordersValue);
1866
1869
  const baseAssetValue = tokenValue.abs();
1867
1870
  const weightedValue = weightedTokenValue.abs();
@@ -1888,7 +1891,7 @@ class User {
1888
1891
  const spotMarketAccount = this.driftClient.getQuoteSpotMarketAccount();
1889
1892
  const oraclePriceData = this.getOracleDataForSpotMarket(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
1890
1893
  const baseAssetValue = (0, _1.getTokenValue)(netQuoteValue, spotMarketAccount.decimals, oraclePriceData);
1891
- const { weight, weightedTokenValue } = (0, spotPosition_1.calculateWeightedTokenValue)(netQuoteValue, baseAssetValue, oraclePriceData.price, spotMarketAccount, marginCategory);
1894
+ const { weight, weightedTokenValue } = (0, spotPosition_1.calculateWeightedTokenValue)(netQuoteValue, baseAssetValue, oraclePriceData.price, spotMarketAccount, marginCategory, this.getUserAccount().maxMarginRatio);
1892
1895
  if (netQuoteValue.lt(numericConstants_1.ZERO)) {
1893
1896
  healthComponents.borrows.push({
1894
1897
  marketIndex: spotMarketAccount.marketIndex,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.42.0-beta.5",
3
+ "version": "2.42.0-beta.7",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -539,6 +539,10 @@ export class DriftClient {
539
539
  this.activeSubAccountId = activeSubAccountId;
540
540
  this.userStatsAccountPublicKey = undefined;
541
541
  this.includeDelegates = includeDelegates ?? false;
542
+ const walletSupportsVersionedTxns =
543
+ //@ts-ignore
544
+ this.wallet.supportedTransactionVersions?.size ?? 0 > 1;
545
+ this.txVersion = walletSupportsVersionedTxns ? 0 : 'legacy';
542
546
 
543
547
  if (includeDelegates && subAccountIds) {
544
548
  throw new Error(
@@ -1574,13 +1578,6 @@ export class DriftClient {
1574
1578
  subAccountId?: number,
1575
1579
  reduceOnly = false
1576
1580
  ): Promise<TransactionSignature> {
1577
- const tx = new Transaction();
1578
- tx.add(
1579
- ComputeBudgetProgram.setComputeUnitLimit({
1580
- units: 600_000,
1581
- })
1582
- );
1583
-
1584
1581
  const additionalSigners: Array<Signer> = [];
1585
1582
 
1586
1583
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
@@ -1592,6 +1589,8 @@ export class DriftClient {
1592
1589
  const createWSOLTokenAccount =
1593
1590
  isSolMarket && associatedTokenAccount.equals(signerAuthority);
1594
1591
 
1592
+ const instructions = [];
1593
+
1595
1594
  if (createWSOLTokenAccount) {
1596
1595
  const { ixs, pubkey } = await this.getWrappedSolAccountCreationIxs(
1597
1596
  amount,
@@ -1600,9 +1599,7 @@ export class DriftClient {
1600
1599
 
1601
1600
  associatedTokenAccount = pubkey;
1602
1601
 
1603
- ixs.forEach((ix) => {
1604
- tx.add(ix);
1605
- });
1602
+ instructions.push(...ixs);
1606
1603
  }
1607
1604
 
1608
1605
  const depositCollateralIx = await this.getDepositInstruction(
@@ -1614,11 +1611,11 @@ export class DriftClient {
1614
1611
  true
1615
1612
  );
1616
1613
 
1617
- tx.add(depositCollateralIx);
1614
+ instructions.push(depositCollateralIx);
1618
1615
 
1619
1616
  // Close the wrapped sol account at the end of the transaction
1620
1617
  if (createWSOLTokenAccount) {
1621
- tx.add(
1618
+ instructions.push(
1622
1619
  createCloseAccountInstruction(
1623
1620
  associatedTokenAccount,
1624
1621
  signerAuthority,
@@ -1628,6 +1625,10 @@ export class DriftClient {
1628
1625
  );
1629
1626
  }
1630
1627
 
1628
+ const txParams = { ...this.txParams, computeUnits: 600_000 };
1629
+
1630
+ const tx = await this.buildTransaction(instructions, txParams);
1631
+
1631
1632
  const { txSig, slot } = await this.sendTransaction(
1632
1633
  tx,
1633
1634
  additionalSigners,
@@ -2442,8 +2443,7 @@ export class DriftClient {
2442
2443
  makerInfo?: MakerInfo | MakerInfo[],
2443
2444
  txParams?: TxParams,
2444
2445
  bracketOrdersParams = new Array<OptionalOrderParams>(),
2445
- referrerInfo?: ReferrerInfo,
2446
- useVersionedTx = true
2446
+ referrerInfo?: ReferrerInfo
2447
2447
  ): Promise<{ txSig: TransactionSignature; signedFillTx: Transaction }> {
2448
2448
  const marketIndex = orderParams.marketIndex;
2449
2449
  const orderId = userAccount.nextOrderId;
@@ -2469,12 +2469,8 @@ export class DriftClient {
2469
2469
  referrerInfo
2470
2470
  );
2471
2471
 
2472
- const walletSupportsVersionedTxns =
2473
- //@ts-ignore
2474
- this.wallet.supportedTransactionVersions?.size ?? 0 > 1;
2475
-
2476
2472
  // use versioned transactions if there is a lookup table account and wallet is compatible
2477
- if (walletSupportsVersionedTxns && useVersionedTx) {
2473
+ if (this.txVersion === 0) {
2478
2474
  const versionedMarketOrderTx = await this.buildTransaction(
2479
2475
  [placePerpOrderIx].concat(bracketOrderIxs),
2480
2476
  txParams,
@@ -5852,17 +5848,16 @@ export class DriftClient {
5852
5848
  opts?: ConfirmOptions,
5853
5849
  preSigned?: boolean
5854
5850
  ): Promise<TxSigAndSlot> {
5855
- // @ts-ignore
5856
- if (!tx.message) {
5857
- return this.txSender.send(
5858
- tx as Transaction,
5851
+ if (tx instanceof VersionedTransaction) {
5852
+ return this.txSender.sendVersionedTransaction(
5853
+ tx as VersionedTransaction,
5859
5854
  additionalSigners,
5860
5855
  opts,
5861
5856
  preSigned
5862
5857
  );
5863
5858
  } else {
5864
- return this.txSender.sendVersionedTransaction(
5865
- tx as VersionedTransaction,
5859
+ return this.txSender.send(
5860
+ tx as Transaction,
5866
5861
  additionalSigners,
5867
5862
  opts,
5868
5863
  preSigned
@@ -129,17 +129,22 @@ export function calculateOracleSpread(
129
129
  export function calculateMarketMarginRatio(
130
130
  market: PerpMarketAccount,
131
131
  size: BN,
132
- marginCategory: MarginCategory
132
+ marginCategory: MarginCategory,
133
+ customMarginRatio = 0
133
134
  ): number {
134
135
  let marginRatio;
135
136
  switch (marginCategory) {
136
137
  case 'Initial': {
137
- marginRatio = calculateSizePremiumLiabilityWeight(
138
- size,
139
- new BN(market.imfFactor),
140
- new BN(market.marginRatioInitial),
141
- MARGIN_PRECISION
142
- ).toNumber();
138
+ // use lowest leverage between max allowed and optional user custom max
139
+ marginRatio = Math.max(
140
+ calculateSizePremiumLiabilityWeight(
141
+ size,
142
+ new BN(market.imfFactor),
143
+ new BN(market.marginRatioInitial),
144
+ MARGIN_PRECISION
145
+ ).toNumber(),
146
+ customMarginRatio
147
+ );
143
148
  break;
144
149
  }
145
150
  case 'Maintenance': {
@@ -24,8 +24,11 @@ export function calculateSpotMarketMarginRatio(
24
24
  oraclePrice: BN,
25
25
  marginCategory: MarginCategory,
26
26
  size: BN,
27
- balanceType: SpotBalanceType
27
+ balanceType: SpotBalanceType,
28
+ customMarginRatio = 0
28
29
  ): number {
30
+ let marginRatio;
31
+
29
32
  if (isVariant(balanceType, 'deposit')) {
30
33
  const assetWeight = calculateAssetWeight(
31
34
  size,
@@ -33,13 +36,20 @@ export function calculateSpotMarketMarginRatio(
33
36
  market,
34
37
  marginCategory
35
38
  );
36
- return MARGIN_PRECISION.sub(assetWeight).toNumber();
39
+ marginRatio = MARGIN_PRECISION.sub(assetWeight).toNumber();
37
40
  } else {
38
41
  const liabilityWeight = calculateLiabilityWeight(
39
42
  size,
40
43
  market,
41
44
  marginCategory
42
45
  );
43
- return liabilityWeight.sub(MARGIN_PRECISION).toNumber();
46
+ marginRatio = liabilityWeight.sub(MARGIN_PRECISION).toNumber();
47
+ }
48
+
49
+ if (marginCategory === 'Initial') {
50
+ // use lowest leverage between max allowed and optional user custom max
51
+ return Math.max(marginRatio, customMarginRatio);
44
52
  }
53
+
54
+ return marginRatio;
45
55
  }