@drift-labs/sdk 2.13.0 → 2.14.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.
@@ -12,7 +12,7 @@ const amm_1 = require("./amm");
12
12
  * @param periodAdjustment
13
13
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
14
14
  */
15
- async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1)) {
15
+ async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1), now) {
16
16
  // periodAdjustment
17
17
  // 1: hourly
18
18
  // 24: daily
@@ -25,7 +25,7 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodA
25
25
  }
26
26
  const payFreq = new anchor_1.BN(market.amm.fundingPeriod);
27
27
  // todo: sufficiently differs from blockchain timestamp?
28
- const now = new anchor_1.BN((Date.now() / 1000).toFixed(0));
28
+ now = now || new anchor_1.BN((Date.now() / 1000).toFixed(0));
29
29
  const timeSinceLastUpdate = now.sub(market.amm.lastFundingRateTs);
30
30
  // calculate real-time mark twap
31
31
  const lastMarkTwapWithMantissa = market.amm.lastMarkPriceTwap;
@@ -55,8 +55,8 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodA
55
55
  .mul(numericConstants_1.PRICE_PRECISION)
56
56
  .mul(new anchor_1.BN(100))
57
57
  .div(lastOracleTwapWithMantissa);
58
- // verify pyth live input is within 10% of last twap for live update
59
- if (oracleLiveVsTwap.lte(numericConstants_1.PRICE_PRECISION.mul(new anchor_1.BN(10)))) {
58
+ // verify pyth live input is within 20% of last twap for live update
59
+ if (oracleLiveVsTwap.lte(numericConstants_1.PRICE_PRECISION.mul(new anchor_1.BN(20)))) {
60
60
  oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
61
61
  .mul(lastOracleTwapWithMantissa)
62
62
  .add(timeSinceLastMarkChange.mul(oraclePrice))
@@ -64,10 +64,10 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodA
64
64
  }
65
65
  }
66
66
  const shrunkLastOracleTwapwithMantissa = oracleTwapTimeSinceLastUpdate
67
- .mul(lastOracleTwapWithMantissa)
67
+ .mul(oracleTwapWithMantissa)
68
68
  .add(oracleInvalidDuration.mul(lastMarkTwapWithMantissa))
69
69
  .div(oracleTwapTimeSinceLastUpdate.add(oracleInvalidDuration));
70
- const twapSpread = lastMarkTwapWithMantissa.sub(shrunkLastOracleTwapwithMantissa);
70
+ const twapSpread = markTwapWithMantissa.sub(shrunkLastOracleTwapwithMantissa);
71
71
  const twapSpreadPct = twapSpread
72
72
  .mul(numericConstants_1.PRICE_PRECISION)
73
73
  .mul(new anchor_1.BN(100))
@@ -75,7 +75,7 @@ function calculateAssetWeight(balanceAmount, spotMarket, marginCategory) {
75
75
  assetWeight = margin_1.calculateSizeDiscountAssetWeight(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor), new anchor_1.BN(spotMarket.initialAssetWeight));
76
76
  break;
77
77
  case 'Maintenance':
78
- assetWeight = new anchor_1.BN(spotMarket.maintenanceAssetWeight);
78
+ assetWeight = margin_1.calculateSizeDiscountAssetWeight(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor), new anchor_1.BN(spotMarket.maintenanceAssetWeight));
79
79
  break;
80
80
  default:
81
81
  assetWeight = new anchor_1.BN(spotMarket.initialAssetWeight);
@@ -200,7 +200,7 @@ function calculateWithdrawLimit(spotMarket, now) {
200
200
  .mul(sinceStart)
201
201
  .add(marketDepositTokenAmount.mul(sinceLast))
202
202
  .div(sinceLast.add(sinceStart));
203
- const maxBorrowTokens = anchor_1.BN.min(anchor_1.BN.max(marketDepositTokenAmount.div(new anchor_1.BN(6)), borrowTokenTwapLive.add(borrowTokenTwapLive.div(new anchor_1.BN(5)))), marketDepositTokenAmount.sub(marketDepositTokenAmount.div(new anchor_1.BN(5)))); // between ~15-80% utilization with friction on twap
203
+ const maxBorrowTokens = anchor_1.BN.max(spotMarket.withdrawGuardThreshold, anchor_1.BN.min(anchor_1.BN.max(marketDepositTokenAmount.div(new anchor_1.BN(6)), borrowTokenTwapLive.add(borrowTokenTwapLive.div(new anchor_1.BN(5)))), marketDepositTokenAmount.sub(marketDepositTokenAmount.div(new anchor_1.BN(5))))); // between ~15-80% utilization with friction on twap
204
204
  const minDepositTokens = depositTokenTwapLive.sub(anchor_1.BN.min(anchor_1.BN.max(depositTokenTwapLive.div(new anchor_1.BN(5)), spotMarket.withdrawGuardThreshold), depositTokenTwapLive));
205
205
  let withdrawLimit = anchor_1.BN.max(marketDepositTokenAmount.sub(minDepositTokens), numericConstants_1.ZERO);
206
206
  let borrowLimit = anchor_1.BN.max(maxBorrowTokens.sub(marketBorrowTokenAmount), numericConstants_1.ZERO);
@@ -11,7 +11,7 @@ function parseTokenAccount(data) {
11
11
  if (accountInfo.delegateOption === 0) {
12
12
  accountInfo.delegate = null;
13
13
  // eslint-disable-next-line new-cap
14
- accountInfo.delegatedAmount = new spl_token_1.u64(0);
14
+ accountInfo.delegatedAmount = spl_token_1.u64.fromBuffer(Buffer.from('0'));
15
15
  }
16
16
  else {
17
17
  accountInfo.delegate = new web3_js_1.PublicKey(accountInfo.delegate);
package/lib/user.d.ts CHANGED
@@ -4,7 +4,7 @@ import { PublicKey } from '@solana/web3.js';
4
4
  import { EventEmitter } from 'events';
5
5
  import StrictEventEmitter from 'strict-event-emitter-types';
6
6
  import { DriftClient } from './driftClient';
7
- import { MarginCategory, Order, UserAccount, PerpPosition, SpotPosition } from './types';
7
+ import { MarginCategory, Order, UserAccount, PerpPosition, SpotPosition, PerpMarketAccount } from './types';
8
8
  import { UserAccountSubscriber, UserAccountEvents, DataAndSlot } from './accounts/types';
9
9
  import { PositionDirection, BN, SpotMarketAccount } from '.';
10
10
  import { OraclePriceData } from './oracles/types';
@@ -168,21 +168,20 @@ export declare class User {
168
168
  */
169
169
  needsToSettleFundingPayment(): boolean;
170
170
  /**
171
- * Calculate the liquidation price of a perp position, with optional parameter to calculate the liquidation price after a trade
172
- * @param PerpPosition
173
- * @param positionBaseSizeChange // change in position size to calculate liquidation price for : Precision 10^13
174
- * @param partial
171
+ * Calculate the liquidation price of a spot position
172
+ * @param marketIndex
175
173
  * @returns Precision : PRICE_PRECISION
176
174
  */
177
- spotLiquidationPrice(spotPosition: Pick<SpotPosition, 'marketIndex'>): BN;
175
+ spotLiquidationPrice(marketIndex: number): BN;
178
176
  /**
179
177
  * Calculate the liquidation price of a perp position, with optional parameter to calculate the liquidation price after a trade
180
- * @param PerpPosition
178
+ * @param marketIndex
181
179
  * @param positionBaseSizeChange // change in position size to calculate liquidation price for : Precision 10^13
182
- * @param partial
183
180
  * @returns Precision : PRICE_PRECISION
184
181
  */
185
- liquidationPrice(perpPosition: Pick<PerpPosition, 'marketIndex'>, positionBaseSizeChange?: BN): BN;
182
+ liquidationPrice(marketIndex: number, positionBaseSizeChange?: BN): BN;
183
+ calculateFreeCollateralDeltaForPerp(market: PerpMarketAccount, perpPosition: PerpPosition, positionBaseSizeChange: BN): BN | undefined;
184
+ calculateFreeCollateralDeltaForSpot(market: SpotMarketAccount, signedTokenAmount: BN): BN;
186
185
  /**
187
186
  * Calculates the estimated liquidation price for a position after closing a quote amount of the position.
188
187
  * @param positionMarketIndex
package/lib/user.js CHANGED
@@ -724,139 +724,136 @@ class User {
724
724
  return false;
725
725
  }
726
726
  /**
727
- * Calculate the liquidation price of a perp position, with optional parameter to calculate the liquidation price after a trade
728
- * @param PerpPosition
729
- * @param positionBaseSizeChange // change in position size to calculate liquidation price for : Precision 10^13
730
- * @param partial
727
+ * Calculate the liquidation price of a spot position
728
+ * @param marketIndex
731
729
  * @returns Precision : PRICE_PRECISION
732
730
  */
733
- spotLiquidationPrice(spotPosition) {
734
- const currentSpotPosition = this.getSpotPosition(spotPosition.marketIndex);
731
+ spotLiquidationPrice(marketIndex) {
732
+ const currentSpotPosition = this.getSpotPosition(marketIndex);
735
733
  if (!currentSpotPosition) {
736
734
  return new _1.BN(-1);
737
735
  }
738
- const mtc = this.getTotalCollateral('Maintenance');
739
- const mmr = this.getMaintenanceMarginRequirement();
740
- const deltaValueToLiq = mtc.sub(mmr); // QUOTE_PRECISION
741
- const currentSpotMarket = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
742
- const tokenAmount = spotBalance_1.getTokenAmount(currentSpotPosition.scaledBalance, currentSpotMarket, currentSpotPosition.balanceType);
743
- const tokenAmountQP = tokenAmount
744
- .mul(numericConstants_1.QUOTE_PRECISION)
745
- .div(new _1.BN(10 ** currentSpotMarket.decimals));
746
- if (tokenAmountQP.abs().eq(numericConstants_1.ZERO)) {
736
+ const totalCollateral = this.getTotalCollateral('Maintenance');
737
+ const maintenanceMarginRequirement = this.getMaintenanceMarginRequirement();
738
+ const freeCollateral = _1.BN.max(numericConstants_1.ZERO, totalCollateral.sub(maintenanceMarginRequirement));
739
+ const market = this.driftClient.getSpotMarketAccount(marketIndex);
740
+ const signedTokenAmount = _1.getSignedTokenAmount(spotBalance_1.getTokenAmount(currentSpotPosition.scaledBalance, market, currentSpotPosition.balanceType), currentSpotPosition.balanceType);
741
+ if (signedTokenAmount.eq(numericConstants_1.ZERO)) {
747
742
  return new _1.BN(-1);
748
743
  }
749
- let liqPriceDelta;
750
- if (types_1.isVariant(currentSpotPosition.balanceType, 'borrow')) {
751
- liqPriceDelta = deltaValueToLiq
752
- .mul(numericConstants_1.PRICE_PRECISION)
753
- .mul(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
754
- .div(tokenAmountQP)
755
- .div(new _1.BN(currentSpotMarket.maintenanceLiabilityWeight));
744
+ let freeCollateralDelta = this.calculateFreeCollateralDeltaForSpot(market, signedTokenAmount);
745
+ const oracle = market.oracle;
746
+ const perpMarketWithSameOracle = this.driftClient
747
+ .getPerpMarketAccounts()
748
+ .find((market) => market.amm.oracle.equals(oracle));
749
+ if (perpMarketWithSameOracle) {
750
+ const perpPosition = this.getPerpPosition(perpMarketWithSameOracle.marketIndex);
751
+ if (perpPosition) {
752
+ const freeCollateralDeltaForPerp = this.calculateFreeCollateralDeltaForPerp(perpMarketWithSameOracle, perpPosition, numericConstants_1.ZERO);
753
+ freeCollateralDelta = freeCollateralDelta.add(freeCollateralDeltaForPerp || numericConstants_1.ZERO);
754
+ }
756
755
  }
757
- else {
758
- liqPriceDelta = deltaValueToLiq
759
- .mul(numericConstants_1.PRICE_PRECISION)
760
- .mul(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
761
- .div(tokenAmountQP)
762
- .div(new _1.BN(currentSpotMarket.maintenanceAssetWeight))
763
- .mul(new _1.BN(-1));
756
+ if (freeCollateralDelta.eq(numericConstants_1.ZERO)) {
757
+ return new _1.BN(-1);
758
+ }
759
+ const oraclePrice = this.driftClient.getOracleDataForSpotMarket(marketIndex).price;
760
+ const liqPriceDelta = freeCollateral
761
+ .mul(numericConstants_1.QUOTE_PRECISION)
762
+ .div(freeCollateralDelta);
763
+ const liqPrice = oraclePrice.sub(liqPriceDelta);
764
+ if (liqPrice.lt(numericConstants_1.ZERO)) {
765
+ return new _1.BN(-1);
764
766
  }
765
- const currentPrice = this.driftClient.getOracleDataForSpotMarket(spotPosition.marketIndex).price;
766
- const liqPrice = currentPrice.add(liqPriceDelta);
767
767
  return liqPrice;
768
768
  }
769
769
  /**
770
770
  * Calculate the liquidation price of a perp position, with optional parameter to calculate the liquidation price after a trade
771
- * @param PerpPosition
771
+ * @param marketIndex
772
772
  * @param positionBaseSizeChange // change in position size to calculate liquidation price for : Precision 10^13
773
- * @param partial
774
773
  * @returns Precision : PRICE_PRECISION
775
774
  */
776
- liquidationPrice(perpPosition, positionBaseSizeChange = numericConstants_1.ZERO) {
777
- // solves formula for example canBeLiquidated below
778
- /* example: assume BTC price is $40k (examine 10% up/down)
779
-
780
- if 10k deposit and levered 10x short BTC => BTC up $400 means:
781
- 1. higher base_asset_value (+$4k)
782
- 2. lower collateral (-$4k)
783
- 3. (10k - 4k)/(100k + 4k) => 6k/104k => .0576
784
-
785
- for 10x long, BTC down $400:
786
- 3. (10k - 4k) / (100k - 4k) = 6k/96k => .0625 */
775
+ liquidationPrice(marketIndex, positionBaseSizeChange = numericConstants_1.ZERO) {
787
776
  const totalCollateral = this.getTotalCollateral('Maintenance');
788
- // calculate the total position value ignoring any value from the target market of the trade
789
- const totalPositionValueExcludingTargetMarket = this.getTotalPerpPositionValueExcludingMarket(perpPosition.marketIndex, undefined, undefined, true);
790
- const currentPerpPosition = this.getPerpPosition(perpPosition.marketIndex) ||
791
- this.getEmptyPosition(perpPosition.marketIndex);
792
- const currentPerpPositionBaseSize = currentPerpPosition.baseAssetAmount;
793
- const proposedBaseAssetAmount = currentPerpPositionBaseSize.add(positionBaseSizeChange);
794
- // calculate position for current market after trade
795
- const proposedPerpPosition = {
796
- marketIndex: perpPosition.marketIndex,
797
- baseAssetAmount: proposedBaseAssetAmount,
798
- remainderBaseAssetAmount: 0,
799
- quoteAssetAmount: currentPerpPosition.quoteAssetAmount,
800
- lastCumulativeFundingRate: numericConstants_1.ZERO,
801
- quoteBreakEvenAmount: new _1.BN(0),
802
- quoteEntryAmount: new _1.BN(0),
803
- openOrders: 0,
804
- openBids: currentPerpPosition.openBids,
805
- openAsks: currentPerpPosition.openAsks,
806
- settledPnl: numericConstants_1.ZERO,
807
- lpShares: numericConstants_1.ZERO,
808
- lastBaseAssetAmountPerLp: numericConstants_1.ZERO,
809
- lastQuoteAssetAmountPerLp: numericConstants_1.ZERO,
810
- };
811
- if (proposedBaseAssetAmount.eq(numericConstants_1.ZERO))
777
+ const maintenanceMarginRequirement = this.getMaintenanceMarginRequirement();
778
+ const freeCollateral = _1.BN.max(numericConstants_1.ZERO, totalCollateral.sub(maintenanceMarginRequirement));
779
+ const market = this.driftClient.getPerpMarketAccount(marketIndex);
780
+ const currentPerpPosition = this.getPerpPosition(marketIndex);
781
+ let freeCollateralDelta = this.calculateFreeCollateralDeltaForPerp(market, currentPerpPosition, positionBaseSizeChange);
782
+ if (!freeCollateralDelta) {
812
783
  return new _1.BN(-1);
813
- const market = this.driftClient.getPerpMarketAccount(proposedPerpPosition.marketIndex);
814
- const proposedPerpPositionValue = margin_1.calculateBaseAssetValueWithOracle(market, proposedPerpPosition, this.getOracleDataForPerpMarket(market.marketIndex), true);
815
- // total position value after trade
816
- const totalPositionValueAfterTrade = totalPositionValueExcludingTargetMarket.add(proposedPerpPositionValue);
817
- const marginRequirementOfAll = this.getMaintenanceMarginRequirement();
818
- const positionValue = margin_1.calculateBaseAssetValueWithOracle(market, currentPerpPosition, this.getOracleDataForPerpMarket(market.marketIndex), true);
819
- const marginRequirementOfTargetMarket = positionValue
820
- .mul(new _1.BN(_1.calculateMarketMarginRatio(market, margin_1.calculateWorstCaseBaseAssetAmount(currentPerpPosition).abs(), 'Maintenance')))
821
- .div(numericConstants_1.MARGIN_PRECISION);
822
- const marginRequirementExcludingTargetMarket = marginRequirementOfAll.sub(marginRequirementOfTargetMarket);
823
- const freeCollateralExcludingTargetMarket = totalCollateral.sub(marginRequirementExcludingTargetMarket);
824
- // if the position value after the trade is less than free collateral, there is no liq price
825
- if (totalPositionValueAfterTrade.lte(freeCollateralExcludingTargetMarket) &&
826
- proposedPerpPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
784
+ }
785
+ const oracle = this.driftClient.getPerpMarketAccount(marketIndex).amm.oracle;
786
+ const spotMarketWithSameOracle = this.driftClient
787
+ .getSpotMarketAccounts()
788
+ .find((market) => market.oracle.equals(oracle));
789
+ if (spotMarketWithSameOracle) {
790
+ const spotPosition = this.getSpotPosition(spotMarketWithSameOracle.marketIndex);
791
+ if (spotPosition) {
792
+ const signedTokenAmount = _1.getSignedTokenAmount(spotBalance_1.getTokenAmount(spotPosition.scaledBalance, spotMarketWithSameOracle, spotPosition.balanceType), spotPosition.balanceType);
793
+ const spotFreeCollateralDelta = this.calculateFreeCollateralDeltaForSpot(spotMarketWithSameOracle, signedTokenAmount);
794
+ freeCollateralDelta = freeCollateralDelta.add(spotFreeCollateralDelta || numericConstants_1.ZERO);
795
+ }
796
+ }
797
+ if (freeCollateralDelta.eq(numericConstants_1.ZERO)) {
827
798
  return new _1.BN(-1);
828
799
  }
829
- const proposedWorstCastBaseAssetAmount = margin_1.calculateWorstCaseBaseAssetAmount(proposedPerpPosition);
830
- const marginRequirementTargetMarket = proposedPerpPositionValue
831
- .mul(new _1.BN(_1.calculateMarketMarginRatio(market, proposedWorstCastBaseAssetAmount.abs(), 'Maintenance')))
800
+ const oraclePrice = this.driftClient.getOracleDataForPerpMarket(marketIndex).price;
801
+ const liqPriceDelta = freeCollateral
802
+ .mul(numericConstants_1.QUOTE_PRECISION)
803
+ .div(freeCollateralDelta);
804
+ const liqPrice = oraclePrice.sub(liqPriceDelta);
805
+ if (liqPrice.lt(numericConstants_1.ZERO)) {
806
+ return new _1.BN(-1);
807
+ }
808
+ return liqPrice;
809
+ }
810
+ calculateFreeCollateralDeltaForPerp(market, perpPosition, positionBaseSizeChange) {
811
+ const currentBaseAssetAmount = perpPosition.baseAssetAmount;
812
+ const worstCaseBaseAssetAmount = margin_1.calculateWorstCaseBaseAssetAmount(perpPosition);
813
+ const orderBaseAssetAmount = worstCaseBaseAssetAmount.sub(currentBaseAssetAmount);
814
+ const proposedBaseAssetAmount = currentBaseAssetAmount.add(positionBaseSizeChange);
815
+ const proposedWorstCaseBaseAssetAmount = worstCaseBaseAssetAmount.add(positionBaseSizeChange);
816
+ const marginRatio = _1.calculateMarketMarginRatio(market, proposedWorstCaseBaseAssetAmount.abs(), 'Maintenance');
817
+ const marginRatioQuotePrecision = new _1.BN(marginRatio)
818
+ .mul(numericConstants_1.QUOTE_PRECISION)
832
819
  .div(numericConstants_1.MARGIN_PRECISION);
833
- const marginRequirementAfterTrade = marginRequirementExcludingTargetMarket.add(marginRequirementTargetMarket);
834
- const freeCollateralAfterTrade = totalCollateral.sub(marginRequirementAfterTrade);
835
- const marketMaxMaintLeverage = new _1.BN(numericConstants_1.TEN_THOUSAND.mul(numericConstants_1.TEN_THOUSAND).toNumber() /
836
- _1.calculateMarketMarginRatio(market, proposedWorstCastBaseAssetAmount.abs(), 'Maintenance'));
837
- let priceDelta;
838
- if (proposedBaseAssetAmount.lt(numericConstants_1.ZERO)) {
839
- priceDelta = freeCollateralAfterTrade
840
- .mul(marketMaxMaintLeverage) // precision is TEN_THOUSAND
841
- .div(marketMaxMaintLeverage.add(numericConstants_1.TEN_THOUSAND))
842
- .mul(numericConstants_1.PRICE_TO_QUOTE_PRECISION)
843
- .mul(numericConstants_1.AMM_RESERVE_PRECISION)
844
- .div(proposedBaseAssetAmount);
820
+ if (proposedWorstCaseBaseAssetAmount.eq(numericConstants_1.ZERO)) {
821
+ return undefined;
822
+ }
823
+ let freeCollateralDelta = numericConstants_1.ZERO;
824
+ if (proposedBaseAssetAmount.gt(numericConstants_1.ZERO)) {
825
+ freeCollateralDelta = numericConstants_1.QUOTE_PRECISION.sub(marginRatioQuotePrecision)
826
+ .mul(proposedBaseAssetAmount)
827
+ .div(numericConstants_1.BASE_PRECISION);
845
828
  }
846
829
  else {
847
- priceDelta = freeCollateralAfterTrade
848
- .mul(marketMaxMaintLeverage) // precision is TEN_THOUSAND
849
- .div(marketMaxMaintLeverage.sub(numericConstants_1.TEN_THOUSAND))
850
- .mul(numericConstants_1.PRICE_TO_QUOTE_PRECISION)
851
- .mul(numericConstants_1.AMM_RESERVE_PRECISION)
852
- .div(proposedBaseAssetAmount);
853
- }
854
- const currentPrice = this.getOracleDataForPerpMarket(perpPosition.marketIndex).price;
855
- if (priceDelta.gt(currentPrice) &&
856
- proposedPerpPosition.baseAssetAmount.gte(numericConstants_1.ZERO)) {
857
- return new _1.BN(-1);
830
+ freeCollateralDelta = numericConstants_1.QUOTE_PRECISION.neg()
831
+ .sub(marginRatioQuotePrecision)
832
+ .mul(proposedBaseAssetAmount.abs())
833
+ .div(numericConstants_1.BASE_PRECISION);
834
+ }
835
+ if (!orderBaseAssetAmount.eq(numericConstants_1.ZERO)) {
836
+ freeCollateralDelta = freeCollateralDelta.sub(marginRatioQuotePrecision);
837
+ }
838
+ return freeCollateralDelta;
839
+ }
840
+ calculateFreeCollateralDeltaForSpot(market, signedTokenAmount) {
841
+ const tokenPrecision = new _1.BN(Math.pow(10, market.decimals));
842
+ if (signedTokenAmount.gt(numericConstants_1.ZERO)) {
843
+ const assetWeight = spotBalance_1.calculateAssetWeight(signedTokenAmount, market, 'Maintenance');
844
+ return numericConstants_1.QUOTE_PRECISION.mul(assetWeight)
845
+ .div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
846
+ .mul(signedTokenAmount)
847
+ .div(tokenPrecision);
848
+ }
849
+ else {
850
+ const liabilityWeight = spotBalance_1.calculateLiabilityWeight(signedTokenAmount.abs(), market, 'Maintenance');
851
+ return numericConstants_1.QUOTE_PRECISION.neg()
852
+ .mul(liabilityWeight)
853
+ .div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
854
+ .mul(signedTokenAmount.abs())
855
+ .div(tokenPrecision);
858
856
  }
859
- return currentPrice.sub(priceDelta);
860
857
  }
861
858
  /**
862
859
  * Calculates the estimated liquidation price for a position after closing a quote amount of the position.
@@ -874,9 +871,7 @@ class User {
874
871
  .mul(closeQuoteAmount)
875
872
  .mod(currentPosition.quoteAssetAmount.abs()))
876
873
  .neg();
877
- return this.liquidationPrice({
878
- marketIndex: positionMarketIndex,
879
- }, closeBaseAmount);
874
+ return this.liquidationPrice(positionMarketIndex, closeBaseAmount);
880
875
  }
881
876
  /**
882
877
  * Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
@@ -1073,7 +1068,7 @@ class User {
1073
1068
  return {
1074
1069
  canBypass: false,
1075
1070
  maxDepositAmount,
1076
- depositAmount: numericConstants_1.ZERO,
1071
+ depositAmount,
1077
1072
  netDeposits,
1078
1073
  };
1079
1074
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.13.0",
3
+ "version": "2.14.0",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -37,7 +37,7 @@
37
37
  "@project-serum/serum": "^0.13.38",
38
38
  "@pythnetwork/client": "2.5.3",
39
39
  "@solana/spl-token": "^0.1.6",
40
- "@solana/web3.js": "1.66.2",
40
+ "@solana/web3.js": "1.73.2",
41
41
  "strict-event-emitter-types": "^2.0.0",
42
42
  "uuid": "^8.3.2"
43
43
  },
@@ -59,4 +59,4 @@
59
59
  "engines": {
60
60
  "node": ">=12"
61
61
  }
62
- }
62
+ }
@@ -17,6 +17,7 @@ export const BN_MAX = new BN(Number.MAX_SAFE_INTEGER);
17
17
  export const TEN_MILLION = TEN_THOUSAND.mul(TEN_THOUSAND);
18
18
 
19
19
  export const MAX_LEVERAGE = new BN(5);
20
+ export const MAX_LEVERAGE_ORDER_SIZE = new BN('18446744073709551615');
20
21
 
21
22
  export const PERCENTAGE_PRECISION_EXP = new BN(6);
22
23
  export const PERCENTAGE_PRECISION = new BN(10).pow(PERCENTAGE_PRECISION_EXP);
@@ -44,6 +44,16 @@ export const DevnetPerpMarkets: PerpMarketConfig[] = [
44
44
  launchTs: 1637691133472,
45
45
  oracleSource: OracleSource.PYTH,
46
46
  },
47
+ {
48
+ fullName: 'Aptos',
49
+ category: ['L1', 'Infra'],
50
+ symbol: 'APT-PERP',
51
+ baseAssetSymbol: 'APT',
52
+ marketIndex: 3,
53
+ oracle: new PublicKey('5d2QJ6u2NveZufmJ4noHja5EHs3Bv1DUMPLG5xfasSVs'),
54
+ launchTs: 1675610186000,
55
+ oracleSource: OracleSource.PYTH,
56
+ },
47
57
  ];
48
58
 
49
59
  export const MainnetPerpMarkets: PerpMarketConfig[] = [
package/src/dlob/DLOB.ts CHANGED
@@ -951,7 +951,7 @@ export class DLOB {
951
951
  }
952
952
 
953
953
  isRestingLimitOrder(order: Order, slot: number): boolean {
954
- return order.postOnly || new BN(slot).sub(order.slot).gte(new BN(15));
954
+ return order.postOnly || new BN(slot).sub(order.slot).gte(new BN(45));
955
955
  }
956
956
 
957
957
  *getLimitBids(