@drift-labs/sdk 2.38.1-beta.8 → 2.39.1-beta.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.
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PriorityFeeCalculator = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ /**
6
+ * This class determines whether a priority fee needs to be included in a transaction based on
7
+ * a recent history of timed out transactions.
8
+ */
9
+ class PriorityFeeCalculator {
10
+ /**
11
+ * Constructor for the PriorityFeeCalculator class.
12
+ * @param currentTimeMs - The current time in milliseconds.
13
+ * @param priorityFeeLatchDurationMs - The duration for how long to stay in triggered state before resetting. Default value is 10 seconds.
14
+ */
15
+ constructor(currentTimeMs, priorityFeeLatchDurationMs = 10 * 1000) {
16
+ this.lastTxTimeoutCount = 0;
17
+ this.priorityFeeTriggered = false;
18
+ this.lastTxTimeoutCountTriggered = currentTimeMs;
19
+ this.priorityFeeLatchDurationMs = priorityFeeLatchDurationMs;
20
+ }
21
+ /**
22
+ * Update the priority fee state based on the current time and the current timeout count.
23
+ * @param currentTimeMs current time in milliseconds
24
+ * @returns true if priority fee should be included in the next transaction
25
+ */
26
+ updatePriorityFee(currentTimeMs, txTimeoutCount) {
27
+ let triggerPriorityFee = false;
28
+ if (txTimeoutCount > this.lastTxTimeoutCount) {
29
+ this.lastTxTimeoutCount = txTimeoutCount;
30
+ this.lastTxTimeoutCountTriggered = currentTimeMs;
31
+ triggerPriorityFee = true;
32
+ }
33
+ else {
34
+ if (!this.priorityFeeTriggered) {
35
+ triggerPriorityFee = false;
36
+ }
37
+ else if (currentTimeMs - this.lastTxTimeoutCountTriggered <
38
+ this.priorityFeeLatchDurationMs) {
39
+ triggerPriorityFee = true;
40
+ }
41
+ }
42
+ this.priorityFeeTriggered = triggerPriorityFee;
43
+ return triggerPriorityFee;
44
+ }
45
+ /**
46
+ * This method returns a transaction instruction list that sets the compute limit on the ComputeBudget program.
47
+ * @param computeUnitLimit - The maximum number of compute units that can be used by the transaction.
48
+ * @returns An array of transaction instructions.
49
+ */
50
+ generateComputeBudgetIxs(computeUnitLimit) {
51
+ const ixs = [
52
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
53
+ units: computeUnitLimit,
54
+ }),
55
+ ];
56
+ return ixs;
57
+ }
58
+ /**
59
+ * Calculates the compute unit price to use based on the desired additional fee to pay and the compute unit limit.
60
+ * @param computeUnitLimit desired CU to use
61
+ * @param additionalFeeMicroLamports desired additional fee to pay, in micro lamports
62
+ * @returns the compute unit price to use, in micro lamports
63
+ */
64
+ calculateComputeUnitPrice(computeUnitLimit, additionalFeeMicroLamports) {
65
+ return additionalFeeMicroLamports / computeUnitLimit;
66
+ }
67
+ /**
68
+ * This method generates a list of transaction instructions for the ComputeBudget program, and includes a priority fee if it's required
69
+ * @param computeUnitLimit - The maximum number of compute units that can be used by the transaction.
70
+ * @param usePriorityFee - A boolean indicating whether to include a priority fee in the transaction, this should be from `this.updatePriorityFee()` or `this.priorityFeeTriggered()`.
71
+ * @param additionalFeeMicroLamports - The additional fee to be paid, in micro lamports, the actual price will be calculated.
72
+ * @returns An array of transaction instructions.
73
+ */
74
+ generateComputeBudgetWithPriorityFeeIx(computeUnitLimit, usePriorityFee, additionalFeeMicroLamports) {
75
+ const ixs = this.generateComputeBudgetIxs(computeUnitLimit);
76
+ if (usePriorityFee) {
77
+ const computeUnitPrice = this.calculateComputeUnitPrice(computeUnitLimit, additionalFeeMicroLamports);
78
+ ixs.push(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
79
+ microLamports: computeUnitPrice,
80
+ }));
81
+ }
82
+ return ixs;
83
+ }
84
+ }
85
+ exports.PriorityFeeCalculator = PriorityFeeCalculator;
package/lib/types.d.ts CHANGED
@@ -724,6 +724,7 @@ export type SpotMarketAccount = {
724
724
  maintenanceLiabilityWeight: number;
725
725
  liquidatorFee: number;
726
726
  imfFactor: number;
727
+ scaleInitialAssetWeightStart: BN;
727
728
  withdrawGuardThreshold: BN;
728
729
  depositTokenTwap: BN;
729
730
  borrowTokenTwap: BN;
package/lib/user.d.ts CHANGED
@@ -8,6 +8,7 @@ import { UserAccountSubscriber, UserAccountEvents, DataAndSlot } from './account
8
8
  import { PositionDirection, BN, SpotMarketAccount, MarketType } from '.';
9
9
  import { OraclePriceData } from './oracles/types';
10
10
  import { UserConfig } from './userConfig';
11
+ import { StrictOraclePrice } from './oracles/strictOraclePrice';
11
12
  export declare class User {
12
13
  driftClient: DriftClient;
13
14
  userAccountPublicKey: PublicKey;
@@ -138,9 +139,9 @@ export declare class User {
138
139
  totalLiabilityValue: BN;
139
140
  };
140
141
  getSpotMarketLiabilityValue(marketIndex?: number, marginCategory?: MarginCategory, liquidationBuffer?: BN, includeOpenOrders?: boolean, strict?: boolean, now?: BN): BN;
141
- getSpotLiabilityValue(tokenAmount: BN, oraclePriceData: OraclePriceData, spotMarketAccount: SpotMarketAccount, marginCategory?: MarginCategory, liquidationBuffer?: BN, strict?: boolean, now?: BN): BN;
142
+ getSpotLiabilityValue(tokenAmount: BN, strictOraclePrice: StrictOraclePrice, spotMarketAccount: SpotMarketAccount, marginCategory?: MarginCategory, liquidationBuffer?: BN): BN;
142
143
  getSpotMarketAssetValue(marketIndex?: number, marginCategory?: MarginCategory, includeOpenOrders?: boolean, strict?: boolean, now?: BN): BN;
143
- getSpotAssetValue(tokenAmount: BN, oraclePriceData: OraclePriceData, spotMarketAccount: SpotMarketAccount, marginCategory?: MarginCategory, strict?: boolean, now?: BN): BN;
144
+ getSpotAssetValue(tokenAmount: BN, strictOraclePrice: StrictOraclePrice, spotMarketAccount: SpotMarketAccount, marginCategory?: MarginCategory): BN;
144
145
  getSpotPositionValue(marketIndex: number, marginCategory?: MarginCategory, includeOpenOrders?: boolean, strict?: boolean, now?: BN): BN;
145
146
  getNetSpotMarketValue(withWeightMarginCategory?: MarginCategory): BN;
146
147
  /**
@@ -306,8 +307,8 @@ export declare class User {
306
307
  leverage: BN;
307
308
  };
308
309
  cloneAndUpdateSpotPosition(position: SpotPosition, tokenAmount: BN, market: SpotMarketAccount): SpotPosition;
309
- calculateSpotPositionFreeCollateralContribution(spotPosition: SpotPosition): BN;
310
- calculateSpotPositionLeverageContribution(spotPosition: SpotPosition): {
310
+ calculateSpotPositionFreeCollateralContribution(spotPosition: SpotPosition, strictOraclePrice: StrictOraclePrice): BN;
311
+ calculateSpotPositionLeverageContribution(spotPosition: SpotPosition, strictOraclePrice: StrictOraclePrice): {
311
312
  totalAssetValue: BN;
312
313
  totalLiabilityValue: BN;
313
314
  };
package/lib/user.js CHANGED
@@ -13,6 +13,7 @@ const webSocketUserAccountSubscriber_1 = require("./accounts/webSocketUserAccoun
13
13
  const spotPosition_1 = require("./math/spotPosition");
14
14
  const oracles_1 = require("./math/oracles");
15
15
  const tiers_1 = require("./math/tiers");
16
+ const strictOraclePrice_1 = require("./oracles/strictOraclePrice");
16
17
  class User {
17
18
  get isSubscribed() {
18
19
  return this._isSubscribed && this.accountSubscriber.isSubscribed;
@@ -543,15 +544,21 @@ class User {
543
544
  }
544
545
  const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
545
546
  const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
547
+ let twap5min;
548
+ if (strict) {
549
+ twap5min = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
550
+ );
551
+ }
552
+ const strictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(oraclePriceData.price, twap5min);
546
553
  if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX &&
547
554
  countForQuote) {
548
555
  const tokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
549
556
  if ((0, types_1.isVariant)(spotPosition.balanceType, 'borrow')) {
550
- const weightedTokenValue = this.getSpotLiabilityValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory, liquidationBuffer, strict, now).abs();
557
+ const weightedTokenValue = this.getSpotLiabilityValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory, liquidationBuffer).abs();
551
558
  netQuoteValue = netQuoteValue.sub(weightedTokenValue);
552
559
  }
553
560
  else {
554
- const weightedTokenValue = this.getSpotAssetValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory, strict, now);
561
+ const weightedTokenValue = this.getSpotAssetValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory);
555
562
  netQuoteValue = netQuoteValue.add(weightedTokenValue);
556
563
  }
557
564
  continue;
@@ -559,24 +566,24 @@ class User {
559
566
  if (!includeOpenOrders && countForBase) {
560
567
  if ((0, types_1.isVariant)(spotPosition.balanceType, 'borrow')) {
561
568
  const tokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), _1.SpotBalanceType.BORROW);
562
- const liabilityValue = this.getSpotLiabilityValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory, liquidationBuffer, strict, now).abs();
569
+ const liabilityValue = this.getSpotLiabilityValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory, liquidationBuffer).abs();
563
570
  totalLiabilityValue = totalLiabilityValue.add(liabilityValue);
564
571
  continue;
565
572
  }
566
573
  else {
567
574
  const tokenAmount = (0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
568
- const assetValue = this.getSpotAssetValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory, strict, now);
575
+ const assetValue = this.getSpotAssetValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory);
569
576
  totalAssetValue = totalAssetValue.add(assetValue);
570
577
  continue;
571
578
  }
572
579
  }
573
- const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, this.getOracleDataForSpotMarket(spotPosition.marketIndex));
580
+ const { tokenAmount: worstCaseTokenAmount, ordersValue: worstCaseQuoteTokenAmount, } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory !== null && marginCategory !== void 0 ? marginCategory : 'Initial');
574
581
  if (worstCaseTokenAmount.gt(numericConstants_1.ZERO) && countForBase) {
575
- const baseAssetValue = this.getSpotAssetValue(worstCaseTokenAmount, oraclePriceData, spotMarketAccount, marginCategory, strict, now);
582
+ const baseAssetValue = this.getSpotAssetValue(worstCaseTokenAmount, strictOraclePrice, spotMarketAccount, marginCategory);
576
583
  totalAssetValue = totalAssetValue.add(baseAssetValue);
577
584
  }
578
585
  if (worstCaseTokenAmount.lt(numericConstants_1.ZERO) && countForBase) {
579
- const baseLiabilityValue = this.getSpotLiabilityValue(worstCaseTokenAmount, oraclePriceData, spotMarketAccount, marginCategory, liquidationBuffer, strict, now).abs();
586
+ const baseLiabilityValue = this.getSpotLiabilityValue(worstCaseTokenAmount, strictOraclePrice, spotMarketAccount, marginCategory, liquidationBuffer).abs();
580
587
  totalLiabilityValue = totalLiabilityValue.add(baseLiabilityValue);
581
588
  }
582
589
  if (worstCaseQuoteTokenAmount.gt(numericConstants_1.ZERO) && countForQuote) {
@@ -609,16 +616,8 @@ class User {
609
616
  const { totalLiabilityValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict, now);
610
617
  return totalLiabilityValue;
611
618
  }
612
- getSpotLiabilityValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory, liquidationBuffer, strict = false, now) {
613
- let liabilityValue = null;
614
- if (strict) {
615
- const estOracleTwap = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
616
- );
617
- liabilityValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, oraclePriceData, estOracleTwap);
618
- }
619
- else {
620
- liabilityValue = (0, _1.getTokenValue)(tokenAmount, spotMarketAccount.decimals, oraclePriceData);
621
- }
619
+ getSpotLiabilityValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory, liquidationBuffer) {
620
+ let liabilityValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
622
621
  if (marginCategory !== undefined) {
623
622
  let weight = (0, spotBalance_1.calculateLiabilityWeight)(tokenAmount, spotMarketAccount, marginCategory);
624
623
  if (marginCategory === 'Initial') {
@@ -637,18 +636,10 @@ class User {
637
636
  const { totalAssetValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, undefined, includeOpenOrders, strict, now);
638
637
  return totalAssetValue;
639
638
  }
640
- getSpotAssetValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory, strict = false, now) {
641
- let assetValue = null;
642
- if (strict) {
643
- const estOracleTwap = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
644
- );
645
- assetValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, oraclePriceData, estOracleTwap);
646
- }
647
- else {
648
- assetValue = (0, _1.getTokenValue)(tokenAmount, spotMarketAccount.decimals, oraclePriceData);
649
- }
639
+ getSpotAssetValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory) {
640
+ let assetValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
650
641
  if (marginCategory !== undefined) {
651
- const weight = (0, spotBalance_1.calculateAssetWeight)(tokenAmount, spotMarketAccount, marginCategory);
642
+ const weight = (0, spotBalance_1.calculateAssetWeight)(tokenAmount, strictOraclePrice.current, spotMarketAccount, marginCategory);
652
643
  assetValue = assetValue.mul(weight).div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
653
644
  }
654
645
  return assetValue;
@@ -1157,7 +1148,7 @@ class User {
1157
1148
  calculateFreeCollateralDeltaForSpot(market, signedTokenAmount) {
1158
1149
  const tokenPrecision = new _1.BN(Math.pow(10, market.decimals));
1159
1150
  if (signedTokenAmount.gt(numericConstants_1.ZERO)) {
1160
- const assetWeight = (0, spotBalance_1.calculateAssetWeight)(signedTokenAmount, market, 'Maintenance');
1151
+ const assetWeight = (0, spotBalance_1.calculateAssetWeight)(signedTokenAmount, this.driftClient.getOraclePriceDataAndSlot(market.oracle).data.price, market, 'Maintenance');
1161
1152
  return numericConstants_1.QUOTE_PRECISION.mul(assetWeight)
1162
1153
  .div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
1163
1154
  .mul(signedTokenAmount)
@@ -1279,11 +1270,12 @@ class User {
1279
1270
  */
1280
1271
  getMaxTradeSizeUSDCForSpot(targetMarketIndex, direction, currentQuoteAssetValue, currentSpotMarketNetValue) {
1281
1272
  const market = this.driftClient.getSpotMarketAccount(targetMarketIndex);
1273
+ const oraclePrice = this.driftClient.getOraclePriceDataAndSlot(market.oracle).data.price;
1282
1274
  currentQuoteAssetValue = this.getSpotMarketAssetValue(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
1283
1275
  currentSpotMarketNetValue =
1284
1276
  currentSpotMarketNetValue !== null && currentSpotMarketNetValue !== void 0 ? currentSpotMarketNetValue : this.getSpotPositionValue(targetMarketIndex);
1285
1277
  let freeCollateral = this.getFreeCollateral();
1286
- const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, 'Initial', numericConstants_1.ZERO, (0, types_1.isVariant)(direction, 'long')
1278
+ const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', numericConstants_1.ZERO, (0, types_1.isVariant)(direction, 'long')
1287
1279
  ? _1.SpotBalanceType.DEPOSIT
1288
1280
  : _1.SpotBalanceType.BORROW);
1289
1281
  let tradeAmount = numericConstants_1.ZERO;
@@ -1291,13 +1283,13 @@ class User {
1291
1283
  // if the user is buying/selling and already short/long, need to account for closing out short/long
1292
1284
  if ((0, types_1.isVariant)(direction, 'long') && currentSpotMarketNetValue.lt(numericConstants_1.ZERO)) {
1293
1285
  tradeAmount = currentSpotMarketNetValue.abs();
1294
- const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, 'Initial', this.getTokenAmount(targetMarketIndex).abs(), _1.SpotBalanceType.BORROW);
1286
+ const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', this.getTokenAmount(targetMarketIndex).abs(), _1.SpotBalanceType.BORROW);
1295
1287
  freeCollateral = freeCollateral.add(tradeAmount.mul(new _1.BN(marginRatio)).div(numericConstants_1.MARGIN_PRECISION));
1296
1288
  }
1297
1289
  else if ((0, types_1.isVariant)(direction, 'short') &&
1298
1290
  currentSpotMarketNetValue.gt(numericConstants_1.ZERO)) {
1299
1291
  tradeAmount = currentSpotMarketNetValue;
1300
- const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, 'Initial', this.getTokenAmount(targetMarketIndex), _1.SpotBalanceType.DEPOSIT);
1292
+ const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', this.getTokenAmount(targetMarketIndex), _1.SpotBalanceType.DEPOSIT);
1301
1293
  freeCollateral = freeCollateral.add(tradeAmount.mul(new _1.BN(marginRatio)).div(numericConstants_1.MARGIN_PRECISION));
1302
1294
  }
1303
1295
  tradeAmount = tradeAmount.add(freeCollateral.mul(numericConstants_1.MARGIN_PRECISION).div(new _1.BN(marginRatio)));
@@ -1322,8 +1314,12 @@ class User {
1322
1314
  getMaxSwapAmount({ inMarketIndex, outMarketIndex, calculateSwap, iterationLimit = 1000, }) {
1323
1315
  const inMarket = this.driftClient.getSpotMarketAccount(inMarketIndex);
1324
1316
  const outMarket = this.driftClient.getSpotMarketAccount(outMarketIndex);
1325
- const inOraclePrice = this.getOracleDataForSpotMarket(inMarketIndex).price;
1326
- const outOraclePrice = this.getOracleDataForSpotMarket(outMarketIndex).price;
1317
+ const inOraclePriceData = this.getOracleDataForSpotMarket(inMarketIndex);
1318
+ const inOraclePrice = inOraclePriceData.price;
1319
+ const outOraclePriceData = this.getOracleDataForSpotMarket(outMarketIndex);
1320
+ const outOraclePrice = outOraclePriceData.price;
1321
+ const inStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(inOraclePrice);
1322
+ const outStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(outOraclePrice);
1327
1323
  const inPrecision = new _1.BN(10 ** inMarket.decimals);
1328
1324
  const outPrecision = new _1.BN(10 ** outMarket.decimals);
1329
1325
  const inSpotPosition = this.getSpotPosition(inMarketIndex) ||
@@ -1331,10 +1327,10 @@ class User {
1331
1327
  const outSpotPosition = this.getSpotPosition(outMarketIndex) ||
1332
1328
  this.getEmptySpotPosition(outMarketIndex);
1333
1329
  const freeCollateral = this.getFreeCollateral();
1334
- const inContributionInitial = this.calculateSpotPositionFreeCollateralContribution(inSpotPosition);
1335
- const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition);
1336
- const outContributionInitial = this.calculateSpotPositionFreeCollateralContribution(outSpotPosition);
1337
- const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition);
1330
+ const inContributionInitial = this.calculateSpotPositionFreeCollateralContribution(inSpotPosition, inStrictOraclePrice);
1331
+ const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition, inStrictOraclePrice);
1332
+ const outContributionInitial = this.calculateSpotPositionFreeCollateralContribution(outSpotPosition, outStrictOraclePrice);
1333
+ const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outStrictOraclePrice);
1338
1334
  const initialContribution = inContributionInitial.add(outContributionInitial);
1339
1335
  const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
1340
1336
  if (!calculateSwap) {
@@ -1374,8 +1370,8 @@ class User {
1374
1370
  outSwap = calculateSwap(inSwap);
1375
1371
  const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inSwap.neg(), inMarket);
1376
1372
  const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outSwap, outMarket);
1377
- const inContributionAfter = this.calculateSpotPositionFreeCollateralContribution(inPositionAfter);
1378
- const outContributionAfter = this.calculateSpotPositionFreeCollateralContribution(outPositionAfter);
1373
+ const inContributionAfter = this.calculateSpotPositionFreeCollateralContribution(inPositionAfter, inStrictOraclePrice);
1374
+ const outContributionAfter = this.calculateSpotPositionFreeCollateralContribution(outPositionAfter, outStrictOraclePrice);
1379
1375
  const contributionAfter = inContributionAfter.add(outContributionAfter);
1380
1376
  const contributionDelta = contributionAfter.sub(initialContribution);
1381
1377
  freeCollateralAfter = freeCollateral.add(contributionDelta);
@@ -1395,8 +1391,8 @@ class User {
1395
1391
  }
1396
1392
  const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inSwap.neg(), inMarket);
1397
1393
  const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outSwap, outMarket);
1398
- const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter);
1399
- const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter);
1394
+ const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter, inStrictOraclePrice);
1395
+ const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter, outStrictOraclePrice);
1400
1396
  const spotAssetValueDelta = inTotalAssetValueAfter
1401
1397
  .add(outTotalAssetValueAfter)
1402
1398
  .sub(inTotalAssetValueInitial)
@@ -1441,45 +1437,28 @@ class User {
1441
1437
  }
1442
1438
  return clonedPosition;
1443
1439
  }
1444
- calculateSpotPositionFreeCollateralContribution(spotPosition) {
1445
- let freeCollateralContribution = numericConstants_1.ZERO;
1446
- const now = new _1.BN(new Date().getTime() / 1000);
1447
- const strict = true;
1440
+ calculateSpotPositionFreeCollateralContribution(spotPosition, strictOraclePrice) {
1448
1441
  const marginCategory = 'Initial';
1449
1442
  const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
1450
- const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
1451
- const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, oraclePriceData);
1452
- if (worstCaseTokenAmount.gt(numericConstants_1.ZERO)) {
1453
- const baseAssetValue = this.getSpotAssetValue(worstCaseTokenAmount, oraclePriceData, spotMarketAccount, marginCategory, strict, now);
1454
- freeCollateralContribution =
1455
- freeCollateralContribution.add(baseAssetValue);
1456
- }
1457
- else {
1458
- const baseLiabilityValue = this.getSpotLiabilityValue(worstCaseTokenAmount, oraclePriceData, spotMarketAccount, marginCategory, undefined, strict, now).abs();
1459
- freeCollateralContribution =
1460
- freeCollateralContribution.sub(baseLiabilityValue);
1461
- }
1462
- freeCollateralContribution.add(worstCaseQuoteTokenAmount);
1443
+ const { freeCollateralContribution } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory);
1463
1444
  return freeCollateralContribution;
1464
1445
  }
1465
- calculateSpotPositionLeverageContribution(spotPosition) {
1446
+ calculateSpotPositionLeverageContribution(spotPosition, strictOraclePrice) {
1466
1447
  let totalAssetValue = numericConstants_1.ZERO;
1467
1448
  let totalLiabilityValue = numericConstants_1.ZERO;
1468
- const now = new _1.BN(new Date().getTime() / 1000);
1469
1449
  const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
1470
- const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
1471
- const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, oraclePriceData);
1472
- if (worstCaseTokenAmount.gt(numericConstants_1.ZERO)) {
1473
- totalAssetValue = this.getSpotAssetValue(worstCaseTokenAmount, oraclePriceData, spotMarketAccount, undefined, false, now);
1450
+ const { tokenValue, ordersValue } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, 'Initial');
1451
+ if (tokenValue.gte(numericConstants_1.ZERO)) {
1452
+ totalAssetValue = tokenValue;
1474
1453
  }
1475
1454
  else {
1476
- totalLiabilityValue = this.getSpotLiabilityValue(worstCaseTokenAmount, oraclePriceData, spotMarketAccount, undefined, undefined, false, now).abs();
1455
+ totalLiabilityValue = tokenValue.abs();
1477
1456
  }
1478
- if (worstCaseQuoteTokenAmount.gt(numericConstants_1.ZERO)) {
1479
- totalAssetValue = totalAssetValue.add(worstCaseQuoteTokenAmount);
1457
+ if (ordersValue.gt(numericConstants_1.ZERO)) {
1458
+ totalAssetValue = totalAssetValue.add(ordersValue);
1480
1459
  }
1481
1460
  else {
1482
- totalLiabilityValue = totalLiabilityValue.add(worstCaseQuoteTokenAmount.abs());
1461
+ totalLiabilityValue = totalLiabilityValue.add(ordersValue.abs());
1483
1462
  }
1484
1463
  return {
1485
1464
  totalAssetValue,
@@ -1496,17 +1475,23 @@ class User {
1496
1475
  accountLeverageAfterSwap({ inMarketIndex, outMarketIndex, inAmount, outAmount, }) {
1497
1476
  const inMarket = this.driftClient.getSpotMarketAccount(inMarketIndex);
1498
1477
  const outMarket = this.driftClient.getSpotMarketAccount(outMarketIndex);
1478
+ const inOraclePriceData = this.getOracleDataForSpotMarket(inMarketIndex);
1479
+ const inOraclePrice = inOraclePriceData.price;
1480
+ const outOraclePriceData = this.getOracleDataForSpotMarket(outMarketIndex);
1481
+ const outOraclePrice = outOraclePriceData.price;
1482
+ const inStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(inOraclePrice);
1483
+ const outStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(outOraclePrice);
1499
1484
  const inSpotPosition = this.getSpotPosition(inMarketIndex) ||
1500
1485
  this.getEmptySpotPosition(inMarketIndex);
1501
1486
  const outSpotPosition = this.getSpotPosition(outMarketIndex) ||
1502
1487
  this.getEmptySpotPosition(outMarketIndex);
1503
- const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition);
1504
- const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition);
1488
+ const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition, inStrictOraclePrice);
1489
+ const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outStrictOraclePrice);
1505
1490
  const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
1506
1491
  const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inAmount.abs().neg(), inMarket);
1507
1492
  const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outAmount.abs(), outMarket);
1508
- const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter);
1509
- const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter);
1493
+ const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter, inStrictOraclePrice);
1494
+ const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter, outStrictOraclePrice);
1510
1495
  const spotAssetValueDelta = inTotalAssetValueAfter
1511
1496
  .add(outTotalAssetValueAfter)
1512
1497
  .sub(inTotalAssetValueInitial)
@@ -1634,7 +1619,7 @@ class User {
1634
1619
  if (canBypass) {
1635
1620
  withdrawLimit = _1.BN.max(withdrawLimit, userDepositAmount);
1636
1621
  }
1637
- const assetWeight = (0, spotBalance_1.calculateAssetWeight)(userDepositAmount, spotMarket, 'Initial');
1622
+ const assetWeight = (0, spotBalance_1.calculateAssetWeight)(userDepositAmount, oracleData.price, spotMarket, 'Initial');
1638
1623
  const amountWithdrawable = assetWeight.eq(numericConstants_1.ZERO)
1639
1624
  ? userDepositAmount
1640
1625
  : freeCollateral
@@ -1816,26 +1801,17 @@ class User {
1816
1801
  for (const spotPosition of this.getActiveSpotPositions()) {
1817
1802
  const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
1818
1803
  const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
1804
+ const strictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(oraclePriceData.price);
1819
1805
  if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
1820
1806
  const tokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
1821
1807
  netQuoteValue = netQuoteValue.add(tokenAmount);
1822
1808
  continue;
1823
1809
  }
1824
- const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, oraclePriceData);
1825
- netQuoteValue = netQuoteValue.add(worstCaseQuoteTokenAmount);
1826
- const baseAssetValue = (0, _1.getTokenValue)(worstCaseTokenAmount.abs(), spotMarketAccount.decimals, oraclePriceData);
1827
- const isLiability = (0, types_1.isVariant)(spotPosition.balanceType, 'borrow');
1828
- let weight;
1829
- if (isLiability) {
1830
- weight = (0, spotBalance_1.calculateLiabilityWeight)(worstCaseTokenAmount.abs(), spotMarketAccount, marginCategory);
1831
- }
1832
- else {
1833
- weight = (0, spotBalance_1.calculateAssetWeight)(worstCaseTokenAmount, spotMarketAccount, marginCategory);
1834
- }
1835
- const weightedValue = baseAssetValue
1836
- .mul(weight)
1837
- .div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
1838
- if (isLiability) {
1810
+ const { tokenAmount: worstCaseTokenAmount, tokenValue: tokenValue, weight, weightedTokenValue: weightedTokenValue, ordersValue: ordersValue, } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory);
1811
+ netQuoteValue = netQuoteValue.add(ordersValue);
1812
+ const baseAssetValue = tokenValue.abs();
1813
+ const weightedValue = weightedTokenValue.abs();
1814
+ if (weightedTokenValue.lt(numericConstants_1.ZERO)) {
1839
1815
  healthComponents.borrows.push({
1840
1816
  marketIndex: spotMarketAccount.marketIndex,
1841
1817
  size: worstCaseTokenAmount,
@@ -1857,25 +1833,15 @@ class User {
1857
1833
  if (!netQuoteValue.eq(numericConstants_1.ZERO)) {
1858
1834
  const spotMarketAccount = this.driftClient.getQuoteSpotMarketAccount();
1859
1835
  const oraclePriceData = this.getOracleDataForSpotMarket(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
1860
- const baseAssetValue = (0, _1.getTokenValue)(netQuoteValue.abs(), spotMarketAccount.decimals, oraclePriceData);
1861
- const isLiability = netQuoteValue.lt(numericConstants_1.ZERO);
1862
- let weight;
1863
- if (isLiability) {
1864
- weight = (0, spotBalance_1.calculateLiabilityWeight)(netQuoteValue.abs(), spotMarketAccount, marginCategory);
1865
- }
1866
- else {
1867
- weight = (0, spotBalance_1.calculateAssetWeight)(netQuoteValue, spotMarketAccount, marginCategory);
1868
- }
1869
- const weightedValue = baseAssetValue
1870
- .mul(weight)
1871
- .div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
1872
- if (isLiability) {
1836
+ const baseAssetValue = (0, _1.getTokenValue)(netQuoteValue, spotMarketAccount.decimals, oraclePriceData);
1837
+ const { weight, weightedTokenValue } = (0, spotPosition_1.calculateWeightedTokenValue)(netQuoteValue, baseAssetValue, oraclePriceData.price, spotMarketAccount, marginCategory);
1838
+ if (netQuoteValue.lt(numericConstants_1.ZERO)) {
1873
1839
  healthComponents.borrows.push({
1874
1840
  marketIndex: spotMarketAccount.marketIndex,
1875
1841
  size: netQuoteValue,
1876
- value: baseAssetValue,
1842
+ value: baseAssetValue.abs(),
1877
1843
  weight: weight,
1878
- weightedValue: weightedValue,
1844
+ weightedValue: weightedTokenValue.abs(),
1879
1845
  });
1880
1846
  }
1881
1847
  else {
@@ -1884,7 +1850,7 @@ class User {
1884
1850
  size: netQuoteValue,
1885
1851
  value: baseAssetValue,
1886
1852
  weight: weight,
1887
- weightedValue: weightedValue,
1853
+ weightedValue: weightedTokenValue,
1888
1854
  });
1889
1855
  }
1890
1856
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.38.1-beta.8",
3
+ "version": "2.39.1-beta.0",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -909,6 +909,29 @@ export class AdminClient extends DriftClient {
909
909
  return txSig;
910
910
  }
911
911
 
912
+ public async updateSpotMarketScaleInitialAssetWeightStart(
913
+ spotMarketIndex: number,
914
+ scaleInitialAssetWeightStart: BN
915
+ ): Promise<TransactionSignature> {
916
+ const tx =
917
+ this.program.transaction.updateSpotMarketScaleInitialAssetWeightStart(
918
+ scaleInitialAssetWeightStart,
919
+ {
920
+ accounts: {
921
+ admin: this.wallet.publicKey,
922
+ state: await this.getStatePublicKey(),
923
+ spotMarket: await getSpotMarketPublicKey(
924
+ this.program.programId,
925
+ spotMarketIndex
926
+ ),
927
+ },
928
+ }
929
+ );
930
+
931
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
932
+ return txSig;
933
+ }
934
+
912
935
  public async updateInsuranceFundUnstakingPeriod(
913
936
  spotMarketIndex: number,
914
937
  insuranceWithdrawEscrowPeriod: BN