@drift-labs/sdk 0.2.0-master.25 → 0.2.0-master.26

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.
Files changed (184) hide show
  1. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +13 -13
  2. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +27 -27
  3. package/lib/accounts/types.d.ts +8 -9
  4. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +14 -14
  5. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +35 -34
  6. package/lib/addresses/pda.d.ts +7 -6
  7. package/lib/addresses/pda.js +31 -27
  8. package/lib/admin.d.ts +9 -6
  9. package/lib/admin.js +83 -42
  10. package/lib/clearingHouse.d.ts +69 -42
  11. package/lib/clearingHouse.js +753 -277
  12. package/lib/clearingHouseConfig.d.ts +2 -2
  13. package/lib/clearingHouseUser.d.ts +16 -16
  14. package/lib/clearingHouseUser.js +139 -119
  15. package/lib/config.d.ts +7 -7
  16. package/lib/config.js +20 -20
  17. package/lib/constants/numericConstants.d.ts +12 -12
  18. package/lib/constants/numericConstants.js +13 -13
  19. package/lib/constants/{markets.d.ts → perpMarkets.d.ts} +5 -5
  20. package/{src/constants/markets.js → lib/constants/perpMarkets.js} +4 -4
  21. package/lib/constants/{banks.d.ts → spotMarkets.d.ts} +6 -6
  22. package/lib/constants/{banks.js → spotMarkets.js} +16 -16
  23. package/lib/events/types.d.ts +2 -1
  24. package/lib/events/types.js +1 -0
  25. package/lib/examples/makeTradeExample.js +7 -7
  26. package/lib/idl/clearing_house.json +1008 -279
  27. package/lib/index.d.ts +5 -3
  28. package/lib/index.js +5 -3
  29. package/lib/math/amm.d.ts +2 -2
  30. package/lib/math/amm.js +1 -1
  31. package/lib/math/funding.d.ts +6 -6
  32. package/lib/math/funding.js +2 -1
  33. package/lib/math/margin.d.ts +4 -4
  34. package/lib/math/margin.js +18 -11
  35. package/lib/math/market.d.ts +10 -9
  36. package/lib/math/market.js +29 -6
  37. package/lib/math/oracles.d.ts +2 -1
  38. package/lib/math/oracles.js +11 -1
  39. package/lib/math/orders.d.ts +5 -5
  40. package/lib/math/position.d.ts +13 -13
  41. package/lib/math/position.js +19 -19
  42. package/lib/math/spotBalance.d.ts +19 -0
  43. package/lib/math/spotBalance.js +176 -0
  44. package/lib/math/spotMarket.d.ts +4 -0
  45. package/lib/math/spotMarket.js +8 -0
  46. package/lib/math/spotPosition.d.ts +2 -0
  47. package/lib/math/spotPosition.js +8 -0
  48. package/lib/math/state.js +2 -2
  49. package/lib/math/trade.d.ts +4 -4
  50. package/lib/orderParams.d.ts +4 -4
  51. package/lib/orderParams.js +12 -4
  52. package/lib/serum/serumSubscriber.d.ts +23 -0
  53. package/lib/serum/serumSubscriber.js +41 -0
  54. package/lib/serum/types.d.ts +11 -0
  55. package/lib/serum/types.js +2 -0
  56. package/lib/tx/retryTxSender.d.ts +1 -1
  57. package/lib/tx/retryTxSender.js +4 -2
  58. package/lib/tx/types.d.ts +1 -1
  59. package/lib/types.d.ts +123 -33
  60. package/lib/types.js +31 -9
  61. package/my-script/.env +7 -0
  62. package/my-script/getUserStats.ts +106 -0
  63. package/my-script/multiConnections.ts +119 -0
  64. package/my-script/test-regex.ts +11 -0
  65. package/my-script/utils.ts +52 -0
  66. package/package.json +1 -1
  67. package/src/accounts/bulkAccountLoader.js +249 -0
  68. package/src/accounts/bulkUserStatsSubscription.js +75 -0
  69. package/src/accounts/bulkUserSubscription.js +75 -0
  70. package/src/accounts/fetch.js +92 -0
  71. package/src/accounts/pollingClearingHouseAccountSubscriber.js +465 -0
  72. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +38 -38
  73. package/src/accounts/pollingOracleSubscriber.js +156 -0
  74. package/src/accounts/pollingTokenAccountSubscriber.js +141 -0
  75. package/src/accounts/pollingUserAccountSubscriber.js +208 -0
  76. package/src/accounts/pollingUserStatsAccountSubscriber.js +208 -0
  77. package/src/accounts/types.js +28 -0
  78. package/src/accounts/types.ts +11 -9
  79. package/src/accounts/utils.js +7 -0
  80. package/src/accounts/webSocketAccountSubscriber.js +138 -0
  81. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +433 -0
  82. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +59 -52
  83. package/src/accounts/webSocketUserAccountSubscriber.js +113 -0
  84. package/src/accounts/webSocketUserStatsAccountSubsriber.js +113 -0
  85. package/src/addresses/pda.js +186 -0
  86. package/src/addresses/pda.ts +49 -44
  87. package/src/admin.js +1284 -0
  88. package/src/admin.ts +140 -47
  89. package/src/assert/assert.js +1 -1
  90. package/src/clearingHouse.js +3433 -0
  91. package/src/clearingHouse.ts +1083 -378
  92. package/src/clearingHouseConfig.js +2 -0
  93. package/src/clearingHouseConfig.ts +2 -2
  94. package/src/clearingHouseUser.js +874 -0
  95. package/src/clearingHouseUser.ts +232 -168
  96. package/src/clearingHouseUserConfig.js +2 -0
  97. package/src/clearingHouseUserStats.js +115 -0
  98. package/src/clearingHouseUserStatsConfig.js +2 -0
  99. package/src/config.js +80 -0
  100. package/src/config.ts +29 -29
  101. package/src/constants/numericConstants.js +18 -11
  102. package/src/constants/numericConstants.ts +17 -15
  103. package/{lib/constants/markets.js → src/constants/perpMarkets.js} +11 -11
  104. package/src/constants/{markets.ts → perpMarkets.ts} +5 -5
  105. package/src/constants/spotMarkets.js +51 -0
  106. package/src/constants/{banks.ts → spotMarkets.ts} +19 -19
  107. package/src/events/eventList.js +66 -23
  108. package/src/events/eventSubscriber.js +202 -0
  109. package/src/events/fetchLogs.js +117 -0
  110. package/src/events/pollingLogProvider.js +113 -0
  111. package/src/events/sort.js +41 -0
  112. package/src/events/txEventCache.js +22 -19
  113. package/src/events/types.js +25 -0
  114. package/src/events/types.ts +3 -0
  115. package/src/events/webSocketLogProvider.js +76 -0
  116. package/src/examples/makeTradeExample.ts +10 -8
  117. package/src/factory/bigNum.js +183 -180
  118. package/src/factory/oracleClient.js +9 -9
  119. package/src/idl/clearing_house.json +1008 -279
  120. package/src/index.js +75 -0
  121. package/src/index.ts +5 -3
  122. package/src/math/amm.js +422 -0
  123. package/src/math/amm.ts +6 -3
  124. package/src/math/auction.js +10 -10
  125. package/src/math/conversion.js +4 -3
  126. package/src/math/funding.js +223 -175
  127. package/src/math/funding.ts +7 -7
  128. package/src/math/insurance.js +27 -0
  129. package/src/math/margin.js +77 -0
  130. package/src/math/margin.ts +34 -23
  131. package/src/math/market.js +105 -0
  132. package/src/math/market.ts +71 -19
  133. package/src/math/oracles.js +40 -10
  134. package/src/math/oracles.ts +18 -1
  135. package/src/math/orders.js +153 -0
  136. package/src/math/orders.ts +5 -5
  137. package/src/math/position.js +172 -0
  138. package/src/math/position.ts +31 -31
  139. package/src/math/repeg.js +40 -40
  140. package/src/math/spotBalance.js +176 -0
  141. package/src/math/spotBalance.ts +290 -0
  142. package/src/math/spotMarket.js +8 -0
  143. package/src/math/spotMarket.ts +9 -0
  144. package/src/math/spotPosition.js +8 -0
  145. package/src/math/spotPosition.ts +6 -0
  146. package/src/math/state.ts +2 -2
  147. package/src/math/trade.js +81 -74
  148. package/src/math/trade.ts +4 -4
  149. package/src/math/utils.js +8 -7
  150. package/src/oracles/oracleClientCache.js +10 -9
  151. package/src/oracles/pythClient.js +52 -17
  152. package/src/oracles/quoteAssetOracleClient.js +44 -13
  153. package/src/oracles/switchboardClient.js +69 -37
  154. package/src/oracles/types.js +1 -1
  155. package/src/orderParams.js +14 -6
  156. package/src/orderParams.ts +16 -8
  157. package/src/serum/serumSubscriber.js +102 -0
  158. package/src/serum/serumSubscriber.ts +80 -0
  159. package/src/serum/types.js +2 -0
  160. package/src/serum/types.ts +13 -0
  161. package/src/slot/SlotSubscriber.js +67 -20
  162. package/src/token/index.js +4 -4
  163. package/src/tokenFaucet.js +288 -154
  164. package/src/tx/retryTxSender.js +280 -0
  165. package/src/tx/retryTxSender.ts +5 -2
  166. package/src/tx/types.js +1 -1
  167. package/src/tx/types.ts +2 -1
  168. package/src/tx/utils.js +7 -6
  169. package/src/types.js +216 -0
  170. package/src/types.ts +110 -33
  171. package/src/userName.js +5 -5
  172. package/src/util/computeUnits.js +46 -11
  173. package/src/util/promiseTimeout.js +5 -5
  174. package/src/util/tps.js +46 -12
  175. package/src/wallet.js +55 -18
  176. package/lib/math/bankBalance.d.ts +0 -15
  177. package/lib/math/bankBalance.js +0 -150
  178. package/src/addresses/marketAddresses.js +0 -26
  179. package/src/constants/banks.js +0 -42
  180. package/src/examples/makeTradeExample.js +0 -80
  181. package/src/math/bankBalance.ts +0 -258
  182. package/src/math/state.js +0 -15
  183. package/src/math/utils.js.map +0 -1
  184. package/src/util/getTokenAddress.js +0 -9
@@ -1,7 +1,7 @@
1
1
  import { squareRootBN } from './utils';
2
2
  import {
3
- BANK_WEIGHT_PRECISION,
4
- BANK_IMF_PRECISION,
3
+ SPOT_MARKET_WEIGHT_PRECISION,
4
+ SPOT_MARKET_IMF_PRECISION,
5
5
  ZERO,
6
6
  BID_ASK_SPREAD_PRECISION,
7
7
  AMM_TO_QUOTE_PRECISION_RATIO,
@@ -9,7 +9,8 @@ import {
9
9
  } from '../constants/numericConstants';
10
10
  import { BN } from '@project-serum/anchor';
11
11
  import { OraclePriceData } from '../oracles/types';
12
- import { MarketAccount, UserPosition } from '..';
12
+ import { PerpMarketAccount, PerpPosition } from '..';
13
+ import { assert } from '../assert/assert';
13
14
 
14
15
  export function calculateSizePremiumLiabilityWeight(
15
16
  size: BN, // AMM_RESERVE_PRECISION
@@ -22,14 +23,22 @@ export function calculateSizePremiumLiabilityWeight(
22
23
  }
23
24
 
24
25
  const sizeSqrt = squareRootBN(size.div(new BN(1000)).add(new BN(1))); //1e13 -> 1e10 -> 1e5
26
+
27
+ const denom0 = BN.max(new BN(1), SPOT_MARKET_IMF_PRECISION.div(imfFactor));
28
+ assert(denom0.gt(ZERO));
25
29
  const liabilityWeightNumerator = liabilityWeight.sub(
26
- liabilityWeight.div(BN.max(new BN(1), BANK_IMF_PRECISION.div(imfFactor)))
30
+ liabilityWeight.div(
31
+ BN.max(new BN(1), SPOT_MARKET_IMF_PRECISION.div(imfFactor))
32
+ )
27
33
  );
28
34
 
35
+ const denom = new BN(100_000).mul(SPOT_MARKET_IMF_PRECISION).div(precision);
36
+ assert(denom.gt(ZERO));
37
+
29
38
  const sizePremiumLiabilityWeight = liabilityWeightNumerator.add(
30
39
  sizeSqrt // 1e5
31
40
  .mul(imfFactor)
32
- .div(new BN(100_000).mul(BANK_IMF_PRECISION).div(precision)) // 1e5
41
+ .div(denom) // 1e5
33
42
  );
34
43
 
35
44
  const maxLiabilityWeight = BN.max(
@@ -49,17 +58,19 @@ export function calculateSizeDiscountAssetWeight(
49
58
  }
50
59
 
51
60
  const sizeSqrt = squareRootBN(size.div(new BN(1000)).add(new BN(1))); //1e13 -> 1e10 -> 1e5
52
- const imfNumerator = BANK_IMF_PRECISION.add(
53
- BANK_IMF_PRECISION.div(new BN(10))
61
+ const imfNumerator = SPOT_MARKET_IMF_PRECISION.add(
62
+ SPOT_MARKET_IMF_PRECISION.div(new BN(10))
54
63
  );
55
64
 
56
- const sizeDiscountAssetWeight = imfNumerator.mul(BANK_WEIGHT_PRECISION).div(
57
- BANK_IMF_PRECISION.add(
58
- sizeSqrt // 1e5
59
- .mul(imfFactor)
60
- .div(new BN(100_000)) // 1e5
61
- )
62
- );
65
+ const sizeDiscountAssetWeight = imfNumerator
66
+ .mul(SPOT_MARKET_WEIGHT_PRECISION)
67
+ .div(
68
+ SPOT_MARKET_IMF_PRECISION.add(
69
+ sizeSqrt // 1e5
70
+ .mul(imfFactor)
71
+ .div(new BN(100_000)) // 1e5
72
+ )
73
+ );
63
74
 
64
75
  const minAssetWeight = BN.min(assetWeight, sizeDiscountAssetWeight);
65
76
 
@@ -67,8 +78,8 @@ export function calculateSizeDiscountAssetWeight(
67
78
  }
68
79
 
69
80
  export function calculateOraclePriceForPerpMargin(
70
- marketPosition: UserPosition,
71
- market: MarketAccount,
81
+ perpPosition: PerpPosition,
82
+ market: PerpMarketAccount,
72
83
  oraclePriceData: OraclePriceData
73
84
  ): BN {
74
85
  const oraclePriceOffset = BN.min(
@@ -83,7 +94,7 @@ export function calculateOraclePriceForPerpMargin(
83
94
  );
84
95
 
85
96
  let marginPrice: BN;
86
- if (marketPosition.baseAssetAmount.gt(ZERO)) {
97
+ if (perpPosition.baseAssetAmount.gt(ZERO)) {
87
98
  marginPrice = oraclePriceData.price.sub(oraclePriceOffset);
88
99
  } else {
89
100
  marginPrice = oraclePriceData.price.add(oraclePriceOffset);
@@ -93,21 +104,21 @@ export function calculateOraclePriceForPerpMargin(
93
104
  }
94
105
 
95
106
  export function calculateBaseAssetValueWithOracle(
96
- market: MarketAccount,
97
- marketPosition: UserPosition,
107
+ market: PerpMarketAccount,
108
+ perpPosition: PerpPosition,
98
109
  oraclePriceData: OraclePriceData
99
110
  ): BN {
100
- return marketPosition.baseAssetAmount
111
+ return perpPosition.baseAssetAmount
101
112
  .abs()
102
113
  .mul(oraclePriceData.price)
103
114
  .div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
104
115
  }
105
116
 
106
117
  export function calculateWorstCaseBaseAssetAmount(
107
- marketPosition: UserPosition
118
+ perpPosition: PerpPosition
108
119
  ): BN {
109
- const allBids = marketPosition.baseAssetAmount.add(marketPosition.openBids);
110
- const allAsks = marketPosition.baseAssetAmount.add(marketPosition.openAsks);
120
+ const allBids = perpPosition.baseAssetAmount.add(perpPosition.openBids);
121
+ const allAsks = perpPosition.baseAssetAmount.add(perpPosition.openAsks);
111
122
 
112
123
  if (allBids.abs().gt(allAsks.abs())) {
113
124
  return allBids;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ exports.__esModule = true;
3
+ exports.calculateNetUserImbalance = exports.calculateMarketAvailablePNL = exports.calculateUnrealizedAssetWeight = exports.calculateMarketMarginRatio = exports.calculateOracleSpread = exports.calculateMarkOracleSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateMarkPrice = void 0;
4
+ var anchor_1 = require("@project-serum/anchor");
5
+ var types_1 = require("../types");
6
+ var amm_1 = require("./amm");
7
+ var margin_1 = require("./margin");
8
+ var numericConstants_1 = require("../constants/numericConstants");
9
+ var spotBalance_1 = require("./spotBalance");
10
+ /**
11
+ * Calculates market mark price
12
+ *
13
+ * @param market
14
+ * @return markPrice : Precision MARK_PRICE_PRECISION
15
+ */
16
+ function calculateMarkPrice(market, oraclePriceData) {
17
+ var newAmm = (0, amm_1.calculateUpdatedAMM)(market.amm, oraclePriceData);
18
+ return (0, amm_1.calculatePrice)(newAmm.baseAssetReserve, newAmm.quoteAssetReserve, newAmm.pegMultiplier);
19
+ }
20
+ exports.calculateMarkPrice = calculateMarkPrice;
21
+ /**
22
+ * Calculates market bid price
23
+ *
24
+ * @param market
25
+ * @return bidPrice : Precision MARK_PRICE_PRECISION
26
+ */
27
+ function calculateBidPrice(market, oraclePriceData) {
28
+ var _a = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, types_1.PositionDirection.SHORT, oraclePriceData), baseAssetReserve = _a.baseAssetReserve, quoteAssetReserve = _a.quoteAssetReserve, newPeg = _a.newPeg;
29
+ return (0, amm_1.calculatePrice)(baseAssetReserve, quoteAssetReserve, newPeg);
30
+ }
31
+ exports.calculateBidPrice = calculateBidPrice;
32
+ /**
33
+ * Calculates market ask price
34
+ *
35
+ * @param market
36
+ * @return bidPrice : Precision MARK_PRICE_PRECISION
37
+ */
38
+ function calculateAskPrice(market, oraclePriceData) {
39
+ var _a = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, types_1.PositionDirection.LONG, oraclePriceData), baseAssetReserve = _a.baseAssetReserve, quoteAssetReserve = _a.quoteAssetReserve, newPeg = _a.newPeg;
40
+ return (0, amm_1.calculatePrice)(baseAssetReserve, quoteAssetReserve, newPeg);
41
+ }
42
+ exports.calculateAskPrice = calculateAskPrice;
43
+ function calculateNewMarketAfterTrade(baseAssetAmount, direction, market) {
44
+ var _a = (0, amm_1.calculateAmmReservesAfterSwap)(market.amm, 'base', baseAssetAmount.abs(), (0, amm_1.getSwapDirection)('base', direction)), newQuoteAssetReserve = _a[0], newBaseAssetReserve = _a[1];
45
+ var newAmm = Object.assign({}, market.amm);
46
+ var newMarket = Object.assign({}, market);
47
+ newMarket.amm = newAmm;
48
+ newMarket.amm.quoteAssetReserve = newQuoteAssetReserve;
49
+ newMarket.amm.baseAssetReserve = newBaseAssetReserve;
50
+ return newMarket;
51
+ }
52
+ exports.calculateNewMarketAfterTrade = calculateNewMarketAfterTrade;
53
+ function calculateMarkOracleSpread(market, oraclePriceData) {
54
+ var markPrice = calculateMarkPrice(market, oraclePriceData);
55
+ return calculateOracleSpread(markPrice, oraclePriceData);
56
+ }
57
+ exports.calculateMarkOracleSpread = calculateMarkOracleSpread;
58
+ function calculateOracleSpread(price, oraclePriceData) {
59
+ return price.sub(oraclePriceData.price);
60
+ }
61
+ exports.calculateOracleSpread = calculateOracleSpread;
62
+ function calculateMarketMarginRatio(market, size, marginCategory) {
63
+ var marginRatio;
64
+ switch (marginCategory) {
65
+ case 'Initial':
66
+ marginRatio = (0, margin_1.calculateSizePremiumLiabilityWeight)(size, market.imfFactor, new anchor_1.BN(market.marginRatioInitial), numericConstants_1.MARGIN_PRECISION).toNumber();
67
+ break;
68
+ case 'Maintenance':
69
+ marginRatio = market.marginRatioMaintenance;
70
+ break;
71
+ }
72
+ return marginRatio;
73
+ }
74
+ exports.calculateMarketMarginRatio = calculateMarketMarginRatio;
75
+ function calculateUnrealizedAssetWeight(market, unrealizedPnl, marginCategory) {
76
+ var assetWeight;
77
+ switch (marginCategory) {
78
+ case 'Initial':
79
+ assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(unrealizedPnl, market.unrealizedImfFactor, new anchor_1.BN(market.unrealizedInitialAssetWeight));
80
+ break;
81
+ case 'Maintenance':
82
+ assetWeight = new anchor_1.BN(market.unrealizedMaintenanceAssetWeight);
83
+ break;
84
+ }
85
+ return assetWeight;
86
+ }
87
+ exports.calculateUnrealizedAssetWeight = calculateUnrealizedAssetWeight;
88
+ function calculateMarketAvailablePNL(perpMarket, spotMarket) {
89
+ return (0, spotBalance_1.getTokenAmount)(perpMarket.pnlPool.balance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
90
+ }
91
+ exports.calculateMarketAvailablePNL = calculateMarketAvailablePNL;
92
+ function calculateNetUserImbalance(market, bank, oraclePriceData) {
93
+ var netUserPositionValue = market.amm.netBaseAssetAmount
94
+ .mul(oraclePriceData.price)
95
+ .div(numericConstants_1.BASE_PRECISION)
96
+ .div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
97
+ var netUserCostBasis = market.amm.quoteAssetAmountLong
98
+ .add(market.amm.quoteAssetAmountShort)
99
+ .sub(market.amm.cumulativeSocialLoss);
100
+ var userEntitledPnl = netUserPositionValue.add(netUserCostBasis);
101
+ var pnlPool = (0, spotBalance_1.getTokenAmount)(market.pnlPool.balance, bank, types_1.SpotBalanceType.DEPOSIT);
102
+ var imbalance = userEntitledPnl.sub(pnlPool);
103
+ return imbalance;
104
+ }
105
+ exports.calculateNetUserImbalance = calculateNetUserImbalance;
@@ -1,10 +1,10 @@
1
1
  import { BN } from '@project-serum/anchor';
2
2
  import {
3
- MarketAccount,
3
+ PerpMarketAccount,
4
4
  PositionDirection,
5
5
  MarginCategory,
6
- BankAccount,
7
- BankBalanceType,
6
+ SpotMarketAccount,
7
+ SpotBalanceType,
8
8
  } from '../types';
9
9
  import {
10
10
  calculateAmmReservesAfterSwap,
@@ -18,8 +18,13 @@ import {
18
18
  calculateSizePremiumLiabilityWeight,
19
19
  } from './margin';
20
20
  import { OraclePriceData } from '../oracles/types';
21
- import { MARGIN_PRECISION } from '../constants/numericConstants';
22
- import { getTokenAmount } from './bankBalance';
21
+ import {
22
+ BASE_PRECISION,
23
+ MARGIN_PRECISION,
24
+ PRICE_TO_QUOTE_PRECISION,
25
+ ZERO,
26
+ } from '../constants/numericConstants';
27
+ import { getTokenAmount } from './spotBalance';
23
28
 
24
29
  /**
25
30
  * Calculates market mark price
@@ -28,7 +33,7 @@ import { getTokenAmount } from './bankBalance';
28
33
  * @return markPrice : Precision MARK_PRICE_PRECISION
29
34
  */
30
35
  export function calculateMarkPrice(
31
- market: MarketAccount,
36
+ market: PerpMarketAccount,
32
37
  oraclePriceData: OraclePriceData
33
38
  ): BN {
34
39
  const newAmm = calculateUpdatedAMM(market.amm, oraclePriceData);
@@ -46,7 +51,7 @@ export function calculateMarkPrice(
46
51
  * @return bidPrice : Precision MARK_PRICE_PRECISION
47
52
  */
48
53
  export function calculateBidPrice(
49
- market: MarketAccount,
54
+ market: PerpMarketAccount,
50
55
  oraclePriceData: OraclePriceData
51
56
  ): BN {
52
57
  const { baseAssetReserve, quoteAssetReserve, newPeg } =
@@ -66,7 +71,7 @@ export function calculateBidPrice(
66
71
  * @return bidPrice : Precision MARK_PRICE_PRECISION
67
72
  */
68
73
  export function calculateAskPrice(
69
- market: MarketAccount,
74
+ market: PerpMarketAccount,
70
75
  oraclePriceData: OraclePriceData
71
76
  ): BN {
72
77
  const { baseAssetReserve, quoteAssetReserve, newPeg } =
@@ -82,8 +87,8 @@ export function calculateAskPrice(
82
87
  export function calculateNewMarketAfterTrade(
83
88
  baseAssetAmount: BN,
84
89
  direction: PositionDirection,
85
- market: MarketAccount
86
- ): MarketAccount {
90
+ market: PerpMarketAccount
91
+ ): PerpMarketAccount {
87
92
  const [newQuoteAssetReserve, newBaseAssetReserve] =
88
93
  calculateAmmReservesAfterSwap(
89
94
  market.amm,
@@ -102,7 +107,7 @@ export function calculateNewMarketAfterTrade(
102
107
  }
103
108
 
104
109
  export function calculateMarkOracleSpread(
105
- market: MarketAccount,
110
+ market: PerpMarketAccount,
106
111
  oraclePriceData: OraclePriceData
107
112
  ): BN {
108
113
  const markPrice = calculateMarkPrice(market, oraclePriceData);
@@ -117,7 +122,7 @@ export function calculateOracleSpread(
117
122
  }
118
123
 
119
124
  export function calculateMarketMarginRatio(
120
- market: MarketAccount,
125
+ market: PerpMarketAccount,
121
126
  size: BN,
122
127
  marginCategory: MarginCategory
123
128
  ): number {
@@ -140,18 +145,34 @@ export function calculateMarketMarginRatio(
140
145
  }
141
146
 
142
147
  export function calculateUnrealizedAssetWeight(
143
- market: MarketAccount,
148
+ market: PerpMarketAccount,
149
+ quoteSpotMarket: SpotMarketAccount,
144
150
  unrealizedPnl: BN,
145
- marginCategory: MarginCategory
151
+ marginCategory: MarginCategory,
152
+ oraclePriceData: OraclePriceData
146
153
  ): BN {
147
154
  let assetWeight: BN;
148
-
149
155
  switch (marginCategory) {
150
156
  case 'Initial':
157
+ assetWeight = new BN(market.unrealizedInitialAssetWeight);
158
+
159
+ if (market.unrealizedMaxImbalance.gt(ZERO)) {
160
+ const netUnsettledPnl = calculateNetUserImbalance(
161
+ market,
162
+ quoteSpotMarket,
163
+ oraclePriceData
164
+ );
165
+ if (netUnsettledPnl.gt(market.unrealizedMaxImbalance)) {
166
+ assetWeight = assetWeight
167
+ .mul(market.unrealizedMaxImbalance)
168
+ .div(netUnsettledPnl);
169
+ }
170
+ }
171
+
151
172
  assetWeight = calculateSizeDiscountAssetWeight(
152
173
  unrealizedPnl,
153
174
  market.unrealizedImfFactor,
154
- new BN(market.unrealizedInitialAssetWeight)
175
+ assetWeight
155
176
  );
156
177
  break;
157
178
  case 'Maintenance':
@@ -163,8 +184,39 @@ export function calculateUnrealizedAssetWeight(
163
184
  }
164
185
 
165
186
  export function calculateMarketAvailablePNL(
166
- market: MarketAccount,
167
- bank: BankAccount
187
+ perpMarket: PerpMarketAccount,
188
+ spotMarket: SpotMarketAccount
189
+ ): BN {
190
+ return getTokenAmount(
191
+ perpMarket.pnlPool.balance,
192
+ spotMarket,
193
+ SpotBalanceType.DEPOSIT
194
+ );
195
+ }
196
+
197
+ export function calculateNetUserImbalance(
198
+ market: PerpMarketAccount,
199
+ bank: SpotMarketAccount,
200
+ oraclePriceData: OraclePriceData
168
201
  ): BN {
169
- return getTokenAmount(market.pnlPool.balance, bank, BankBalanceType.DEPOSIT);
202
+ const netUserPositionValue = market.amm.netBaseAssetAmount
203
+ .mul(oraclePriceData.price)
204
+ .div(BASE_PRECISION)
205
+ .div(PRICE_TO_QUOTE_PRECISION);
206
+
207
+ const netUserCostBasis = market.amm.quoteAssetAmountLong
208
+ .add(market.amm.quoteAssetAmountShort)
209
+ .sub(market.amm.cumulativeSocialLoss);
210
+
211
+ const userEntitledPnl = netUserPositionValue.add(netUserCostBasis);
212
+
213
+ const pnlPool = getTokenAmount(
214
+ market.pnlPool.balance,
215
+ bank,
216
+ SpotBalanceType.DEPOSIT
217
+ );
218
+
219
+ const imbalance = userEntitledPnl.sub(pnlPool);
220
+
221
+ return imbalance;
170
222
  }
@@ -1,20 +1,32 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isOracleValid = void 0;
4
- const numericConstants_1 = require("../constants/numericConstants");
5
- const index_1 = require("../index");
2
+ exports.__esModule = true;
3
+ exports.isOracleTooDivergent = exports.isOracleValid = exports.oraclePriceBands = void 0;
4
+ var numericConstants_1 = require("../constants/numericConstants");
5
+ var index_1 = require("../index");
6
+ var assert_1 = require("../assert/assert");
7
+ function oraclePriceBands(market, oraclePriceData) {
8
+ var maxPercentDiff = market.marginRatioInitial - market.marginRatioMaintenance;
9
+ var offset = oraclePriceData.price
10
+ .mul(new index_1.BN(maxPercentDiff))
11
+ .div(numericConstants_1.MARGIN_PRECISION);
12
+ (0, assert_1.assert)(offset.gt(numericConstants_1.ZERO));
13
+ return [oraclePriceData.price.sub(offset), oraclePriceData.price.add(offset)];
14
+ }
15
+ exports.oraclePriceBands = oraclePriceBands;
6
16
  function isOracleValid(amm, oraclePriceData, oracleGuardRails, slot) {
7
- const isOraclePriceNonPositive = oraclePriceData.price.lt(numericConstants_1.ZERO);
8
- const isOraclePriceTooVolatile = oraclePriceData.price
17
+ var isOraclePriceNonPositive = oraclePriceData.price.lte(numericConstants_1.ZERO);
18
+ var isOraclePriceTooVolatile = oraclePriceData.price
9
19
  .div(index_1.BN.max(numericConstants_1.ONE, amm.lastOraclePriceTwap))
10
20
  .gt(oracleGuardRails.validity.tooVolatileRatio) ||
11
21
  amm.lastOraclePriceTwap
12
22
  .div(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.price))
13
23
  .gt(oracleGuardRails.validity.tooVolatileRatio);
14
- const isConfidenceTooLarge = oraclePriceData.price
15
- .div(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.confidence))
16
- .lt(oracleGuardRails.validity.confidenceIntervalMaxSize);
17
- const oracleIsStale = oraclePriceData.slot
24
+ var isConfidenceTooLarge = new index_1.BN(amm.baseSpread)
25
+ .add(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.confidence))
26
+ .mul(numericConstants_1.BID_ASK_SPREAD_PRECISION)
27
+ .div(oraclePriceData.price)
28
+ .gt(new index_1.BN(amm.maxSpread));
29
+ var oracleIsStale = oraclePriceData.slot
18
30
  .sub(new index_1.BN(slot))
19
31
  .gt(oracleGuardRails.validity.slotsBeforeStale);
20
32
  return !(!oraclePriceData.hasSufficientNumberOfDataPoints ||
@@ -24,3 +36,21 @@ function isOracleValid(amm, oraclePriceData, oracleGuardRails, slot) {
24
36
  isConfidenceTooLarge);
25
37
  }
26
38
  exports.isOracleValid = isOracleValid;
39
+ function isOracleTooDivergent(amm, oraclePriceData, oracleGuardRails, now) {
40
+ var sinceLastUpdate = now.sub(amm.lastOraclePriceTwapTs);
41
+ var sinceStart = index_1.BN.max(numericConstants_1.ZERO, new index_1.BN(60 * 5).sub(sinceLastUpdate));
42
+ var oracleTwap5min = amm.lastOraclePriceTwap5min
43
+ .mul(sinceStart)
44
+ .add(oraclePriceData.price)
45
+ .mul(sinceLastUpdate)
46
+ .div(sinceStart.add(sinceLastUpdate));
47
+ var oracleSpread = oracleTwap5min.sub(oraclePriceData.price);
48
+ var oracleSpreadPct = oracleSpread
49
+ .mul(numericConstants_1.MARK_PRICE_PRECISION)
50
+ .div(oracleTwap5min);
51
+ var tooDivergent = oracleSpreadPct
52
+ .abs()
53
+ .gte(numericConstants_1.BID_ASK_SPREAD_PRECISION.mul(oracleGuardRails.priceDivergence.markOracleDivergenceNumerator).div(oracleGuardRails.priceDivergence.markOracleDivergenceDenominator));
54
+ return tooDivergent;
55
+ }
56
+ exports.isOracleTooDivergent = isOracleTooDivergent;
@@ -2,11 +2,28 @@ import { AMM, OracleGuardRails } from '../types';
2
2
  import { OraclePriceData } from '../oracles/types';
3
3
  import {
4
4
  BID_ASK_SPREAD_PRECISION,
5
+ MARGIN_PRECISION,
5
6
  MARK_PRICE_PRECISION,
6
7
  ONE,
7
8
  ZERO,
8
9
  } from '../constants/numericConstants';
9
- import { BN } from '../index';
10
+ import { BN, PerpMarketAccount } from '../index';
11
+ import { assert } from '../assert/assert';
12
+
13
+ export function oraclePriceBands(
14
+ market: PerpMarketAccount,
15
+ oraclePriceData: OraclePriceData
16
+ ): [BN, BN] {
17
+ const maxPercentDiff =
18
+ market.marginRatioInitial - market.marginRatioMaintenance;
19
+ const offset = oraclePriceData.price
20
+ .mul(new BN(maxPercentDiff))
21
+ .div(MARGIN_PRECISION);
22
+
23
+ assert(offset.gt(ZERO));
24
+
25
+ return [oraclePriceData.price.sub(offset), oraclePriceData.price.add(offset)];
26
+ }
10
27
 
11
28
  export function isOracleValid(
12
29
  amm: AMM,
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ exports.__esModule = true;
3
+ exports.isOrderExpired = exports.calculateBaseAssetAmountToFillUpToLimitPrice = exports.calculateBaseAssetAmountForAmmToFulfill = exports.isFillableByVAMM = exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
4
+ var types_1 = require("../types");
5
+ var numericConstants_1 = require("../constants/numericConstants");
6
+ var anchor_1 = require("@project-serum/anchor");
7
+ var auction_1 = require("./auction");
8
+ var market_1 = require("./market");
9
+ var amm_1 = require("./amm");
10
+ function isOrderRiskIncreasing(user, order) {
11
+ if ((0, types_1.isVariant)(order.status, 'init')) {
12
+ return false;
13
+ }
14
+ var position = user.getUserPosition(order.marketIndex) ||
15
+ user.getEmptyPosition(order.marketIndex);
16
+ // if no position exists, it's risk increasing
17
+ if (position.baseAssetAmount.eq(numericConstants_1.ZERO)) {
18
+ return true;
19
+ }
20
+ // if position is long and order is long
21
+ if (position.baseAssetAmount.gt(numericConstants_1.ZERO) && (0, types_1.isVariant)(order.direction, 'long')) {
22
+ return true;
23
+ }
24
+ // if position is short and order is short
25
+ if (position.baseAssetAmount.lt(numericConstants_1.ZERO) &&
26
+ (0, types_1.isVariant)(order.direction, 'short')) {
27
+ return true;
28
+ }
29
+ var baseAssetAmountToFill = order.baseAssetAmount.sub(order.baseAssetAmountFilled);
30
+ // if order will flip position
31
+ if (baseAssetAmountToFill.gt(position.baseAssetAmount.abs().mul(numericConstants_1.TWO))) {
32
+ return true;
33
+ }
34
+ return false;
35
+ }
36
+ exports.isOrderRiskIncreasing = isOrderRiskIncreasing;
37
+ function isOrderRiskIncreasingInSameDirection(user, order) {
38
+ if ((0, types_1.isVariant)(order.status, 'init')) {
39
+ return false;
40
+ }
41
+ var position = user.getUserPosition(order.marketIndex) ||
42
+ user.getEmptyPosition(order.marketIndex);
43
+ // if no position exists, it's risk increasing
44
+ if (position.baseAssetAmount.eq(numericConstants_1.ZERO)) {
45
+ return true;
46
+ }
47
+ // if position is long and order is long
48
+ if (position.baseAssetAmount.gt(numericConstants_1.ZERO) && (0, types_1.isVariant)(order.direction, 'long')) {
49
+ return true;
50
+ }
51
+ // if position is short and order is short
52
+ if (position.baseAssetAmount.lt(numericConstants_1.ZERO) &&
53
+ (0, types_1.isVariant)(order.direction, 'short')) {
54
+ return true;
55
+ }
56
+ return false;
57
+ }
58
+ exports.isOrderRiskIncreasingInSameDirection = isOrderRiskIncreasingInSameDirection;
59
+ function isOrderReduceOnly(user, order) {
60
+ if ((0, types_1.isVariant)(order.status, 'init')) {
61
+ return false;
62
+ }
63
+ var position = user.getUserPosition(order.marketIndex) ||
64
+ user.getEmptyPosition(order.marketIndex);
65
+ // if position is long and order is long
66
+ if (position.baseAssetAmount.gte(numericConstants_1.ZERO) &&
67
+ (0, types_1.isVariant)(order.direction, 'long')) {
68
+ return false;
69
+ }
70
+ // if position is short and order is short
71
+ if (position.baseAssetAmount.lte(numericConstants_1.ZERO) &&
72
+ (0, types_1.isVariant)(order.direction, 'short')) {
73
+ return false;
74
+ }
75
+ return true;
76
+ }
77
+ exports.isOrderReduceOnly = isOrderReduceOnly;
78
+ function standardizeBaseAssetAmount(baseAssetAmount, stepSize) {
79
+ var remainder = baseAssetAmount.mod(stepSize);
80
+ return baseAssetAmount.sub(remainder);
81
+ }
82
+ exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
83
+ function getLimitPrice(order, market, oraclePriceData, slot) {
84
+ var limitPrice;
85
+ if (!order.oraclePriceOffset.eq(numericConstants_1.ZERO)) {
86
+ limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
87
+ }
88
+ else if ((0, types_1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket'])) {
89
+ if (!(0, auction_1.isAuctionComplete)(order, slot)) {
90
+ limitPrice = (0, auction_1.getAuctionPrice)(order, slot);
91
+ }
92
+ else if (!order.price.eq(numericConstants_1.ZERO)) {
93
+ limitPrice = order.price;
94
+ }
95
+ else if ((0, types_1.isVariant)(order.direction, 'long')) {
96
+ var askPrice = (0, market_1.calculateAskPrice)(market, oraclePriceData);
97
+ var delta = askPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
98
+ limitPrice = askPrice.add(delta);
99
+ }
100
+ else {
101
+ var bidPrice = (0, market_1.calculateBidPrice)(market, oraclePriceData);
102
+ var delta = bidPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
103
+ limitPrice = bidPrice.sub(delta);
104
+ }
105
+ }
106
+ else {
107
+ limitPrice = order.price;
108
+ }
109
+ return limitPrice;
110
+ }
111
+ exports.getLimitPrice = getLimitPrice;
112
+ function isFillableByVAMM(order, market, oraclePriceData, slot, maxAuctionDuration) {
113
+ return (((0, auction_1.isAuctionComplete)(order, slot) &&
114
+ !calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot).eq(numericConstants_1.ZERO)) ||
115
+ isOrderExpired(order, slot, maxAuctionDuration));
116
+ }
117
+ exports.isFillableByVAMM = isFillableByVAMM;
118
+ function calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot) {
119
+ if ((0, types_1.isOneOfVariant)(order.orderType, ['triggerMarket', 'triggerLimit']) &&
120
+ order.triggered === false) {
121
+ return numericConstants_1.ZERO;
122
+ }
123
+ var limitPrice = getLimitPrice(order, market, oraclePriceData, slot);
124
+ var baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData);
125
+ var maxBaseAssetAmount = (0, amm_1.calculateMaxBaseAssetAmountFillable)(market.amm, order.direction);
126
+ return anchor_1.BN.min(maxBaseAssetAmount, baseAssetAmount);
127
+ }
128
+ exports.calculateBaseAssetAmountForAmmToFulfill = calculateBaseAssetAmountForAmmToFulfill;
129
+ function calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData) {
130
+ var _a = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction, oraclePriceData), maxAmountToTrade = _a[0], direction = _a[1];
131
+ var baseAssetAmount = standardizeBaseAssetAmount(maxAmountToTrade, market.amm.baseAssetAmountStepSize);
132
+ // Check that directions are the same
133
+ var sameDirection = isSameDirection(direction, order.direction);
134
+ if (!sameDirection) {
135
+ return numericConstants_1.ZERO;
136
+ }
137
+ return baseAssetAmount.gt(order.baseAssetAmount)
138
+ ? order.baseAssetAmount
139
+ : baseAssetAmount;
140
+ }
141
+ exports.calculateBaseAssetAmountToFillUpToLimitPrice = calculateBaseAssetAmountToFillUpToLimitPrice;
142
+ function isSameDirection(firstDirection, secondDirection) {
143
+ return (((0, types_1.isVariant)(firstDirection, 'long') && (0, types_1.isVariant)(secondDirection, 'long')) ||
144
+ ((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
145
+ }
146
+ function isOrderExpired(order, slot, maxAuctionDuration) {
147
+ if (!(0, types_1.isVariant)(order.orderType, 'market') ||
148
+ !(0, types_1.isVariant)(order.status, 'open')) {
149
+ return false;
150
+ }
151
+ return new anchor_1.BN(slot).sub(order.slot).gt(new anchor_1.BN(maxAuctionDuration));
152
+ }
153
+ exports.isOrderExpired = isOrderExpired;
@@ -2,7 +2,7 @@ import { ClearingHouseUser } from '../clearingHouseUser';
2
2
  import {
3
3
  isOneOfVariant,
4
4
  isVariant,
5
- MarketAccount,
5
+ PerpMarketAccount,
6
6
  Order,
7
7
  PositionDirection,
8
8
  } from '../types';
@@ -131,7 +131,7 @@ export function standardizeBaseAssetAmount(
131
131
 
132
132
  export function getLimitPrice(
133
133
  order: Order,
134
- market: MarketAccount,
134
+ market: PerpMarketAccount,
135
135
  oraclePriceData: OraclePriceData,
136
136
  slot: number
137
137
  ): BN {
@@ -161,7 +161,7 @@ export function getLimitPrice(
161
161
 
162
162
  export function isFillableByVAMM(
163
163
  order: Order,
164
- market: MarketAccount,
164
+ market: PerpMarketAccount,
165
165
  oraclePriceData: OraclePriceData,
166
166
  slot: number,
167
167
  maxAuctionDuration: number
@@ -180,7 +180,7 @@ export function isFillableByVAMM(
180
180
 
181
181
  export function calculateBaseAssetAmountForAmmToFulfill(
182
182
  order: Order,
183
- market: MarketAccount,
183
+ market: PerpMarketAccount,
184
184
  oraclePriceData: OraclePriceData,
185
185
  slot: number
186
186
  ): BN {
@@ -209,7 +209,7 @@ export function calculateBaseAssetAmountForAmmToFulfill(
209
209
 
210
210
  export function calculateBaseAssetAmountToFillUpToLimitPrice(
211
211
  order: Order,
212
- market: MarketAccount,
212
+ market: PerpMarketAccount,
213
213
  limitPrice: BN,
214
214
  oraclePriceData: OraclePriceData
215
215
  ): BN {