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

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 (124) hide show
  1. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +14 -13
  2. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +30 -27
  3. package/lib/accounts/types.d.ts +9 -9
  4. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +15 -14
  5. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +38 -34
  6. package/lib/addresses/pda.d.ts +7 -6
  7. package/lib/addresses/pda.js +31 -27
  8. package/lib/admin.d.ts +13 -7
  9. package/lib/admin.js +111 -44
  10. package/lib/clearingHouse.d.ts +71 -42
  11. package/lib/clearingHouse.js +767 -278
  12. package/lib/clearingHouseConfig.d.ts +2 -2
  13. package/lib/clearingHouseUser.d.ts +24 -22
  14. package/lib/clearingHouseUser.js +273 -177
  15. package/lib/config.d.ts +7 -7
  16. package/lib/config.js +21 -21
  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/lib/constants/{markets.js → 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/dlob/DLOB.d.ts +73 -0
  24. package/lib/dlob/DLOB.js +557 -0
  25. package/lib/dlob/DLOBNode.d.ts +52 -0
  26. package/lib/dlob/DLOBNode.js +82 -0
  27. package/lib/dlob/NodeList.d.ts +26 -0
  28. package/lib/dlob/NodeList.js +138 -0
  29. package/lib/events/types.d.ts +2 -1
  30. package/lib/events/types.js +1 -0
  31. package/lib/examples/makeTradeExample.js +7 -7
  32. package/lib/idl/clearing_house.json +1152 -503
  33. package/lib/index.d.ts +10 -3
  34. package/lib/index.js +10 -3
  35. package/lib/math/amm.d.ts +2 -2
  36. package/lib/math/amm.js +1 -1
  37. package/lib/math/funding.d.ts +6 -6
  38. package/lib/math/funding.js +2 -1
  39. package/lib/math/margin.d.ts +4 -4
  40. package/lib/math/margin.js +18 -11
  41. package/lib/math/market.d.ts +11 -10
  42. package/lib/math/market.js +30 -7
  43. package/lib/math/oracles.d.ts +2 -1
  44. package/lib/math/oracles.js +11 -1
  45. package/lib/math/orders.d.ts +6 -6
  46. package/lib/math/orders.js +31 -16
  47. package/lib/math/position.d.ts +13 -13
  48. package/lib/math/position.js +19 -19
  49. package/lib/math/spotBalance.d.ts +22 -0
  50. package/lib/math/spotBalance.js +193 -0
  51. package/lib/math/spotMarket.d.ts +4 -0
  52. package/lib/math/spotMarket.js +8 -0
  53. package/lib/math/spotPosition.d.ts +6 -0
  54. package/lib/math/spotPosition.js +23 -0
  55. package/lib/math/state.js +2 -2
  56. package/lib/math/trade.d.ts +4 -4
  57. package/lib/orderParams.d.ts +4 -4
  58. package/lib/orderParams.js +12 -4
  59. package/lib/serum/serumSubscriber.d.ts +23 -0
  60. package/lib/serum/serumSubscriber.js +41 -0
  61. package/lib/serum/types.d.ts +11 -0
  62. package/lib/serum/types.js +2 -0
  63. package/lib/tx/retryTxSender.d.ts +1 -1
  64. package/lib/tx/retryTxSender.js +4 -2
  65. package/lib/tx/types.d.ts +1 -1
  66. package/lib/types.d.ts +148 -57
  67. package/lib/types.js +39 -11
  68. package/lib/userMap/userMap.d.ts +25 -0
  69. package/lib/userMap/userMap.js +73 -0
  70. package/lib/userMap/userStatsMap.d.ts +19 -0
  71. package/lib/userMap/userStatsMap.js +68 -0
  72. package/package.json +6 -3
  73. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +42 -38
  74. package/src/accounts/types.ts +12 -9
  75. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +65 -52
  76. package/src/addresses/pda.ts +49 -44
  77. package/src/admin.ts +190 -55
  78. package/src/clearingHouse.ts +1092 -365
  79. package/src/clearingHouseConfig.ts +2 -2
  80. package/src/clearingHouseUser.ts +518 -255
  81. package/src/config.ts +30 -30
  82. package/src/constants/numericConstants.ts +17 -15
  83. package/src/constants/{markets.ts → perpMarkets.ts} +5 -5
  84. package/src/constants/{banks.ts → spotMarkets.ts} +19 -19
  85. package/src/dlob/DLOB.ts +884 -0
  86. package/src/dlob/DLOBNode.ts +163 -0
  87. package/src/dlob/NodeList.ts +185 -0
  88. package/src/events/types.ts +3 -0
  89. package/src/examples/makeTradeExample.js +152 -75
  90. package/src/examples/makeTradeExample.ts +10 -8
  91. package/src/idl/clearing_house.json +1152 -503
  92. package/src/index.ts +10 -3
  93. package/src/math/amm.ts +6 -3
  94. package/src/math/funding.ts +7 -7
  95. package/src/math/margin.ts +34 -23
  96. package/src/math/market.ts +72 -20
  97. package/src/math/oracles.ts +18 -1
  98. package/src/math/orders.ts +33 -25
  99. package/src/math/position.ts +31 -31
  100. package/src/math/spotBalance.ts +316 -0
  101. package/src/math/spotMarket.ts +9 -0
  102. package/src/math/spotPosition.ts +47 -0
  103. package/src/math/state.ts +2 -2
  104. package/src/math/trade.ts +4 -4
  105. package/src/orderParams.ts +16 -8
  106. package/src/serum/serumSubscriber.ts +80 -0
  107. package/src/serum/types.ts +13 -0
  108. package/src/tx/retryTxSender.ts +5 -2
  109. package/src/tx/types.ts +2 -1
  110. package/src/types.ts +135 -56
  111. package/src/userMap/userMap.ts +100 -0
  112. package/src/userMap/userStatsMap.ts +110 -0
  113. package/tests/bn/test.ts +2 -3
  114. package/tests/dlob/helpers.ts +322 -0
  115. package/tests/dlob/test.ts +2865 -0
  116. package/lib/math/bankBalance.d.ts +0 -15
  117. package/lib/math/bankBalance.js +0 -150
  118. package/src/constants/numericConstants.js +0 -41
  119. package/src/math/bankBalance.ts +0 -258
  120. package/src/math/oracles.js +0 -26
  121. package/src/math/state.js +0 -15
  122. package/src/orderParams.js +0 -20
  123. package/src/slot/SlotSubscriber.js +0 -39
  124. package/src/tokenFaucet.js +0 -189
package/src/index.ts CHANGED
@@ -7,7 +7,7 @@ export * from './oracles/types';
7
7
  export * from './oracles/pythClient';
8
8
  export * from './oracles/switchboardClient';
9
9
  export * from './types';
10
- export * from './constants/markets';
10
+ export * from './constants/perpMarkets';
11
11
  export * from './accounts/fetch';
12
12
  export * from './accounts/webSocketClearingHouseAccountSubscriber';
13
13
  export * from './accounts/bulkAccountLoader';
@@ -32,6 +32,7 @@ export * from './events/types';
32
32
  export * from './events/eventSubscriber';
33
33
  export * from './events/fetchLogs';
34
34
  export * from './math/auction';
35
+ export * from './math/spotMarket';
35
36
  export * from './math/conversion';
36
37
  export * from './math/funding';
37
38
  export * from './math/market';
@@ -50,11 +51,17 @@ export * from './types';
50
51
  export * from './math/utils';
51
52
  export * from './config';
52
53
  export * from './constants/numericConstants';
54
+ export * from './serum/serumSubscriber';
53
55
  export * from './tx/retryTxSender';
54
56
  export * from './util/computeUnits';
55
57
  export * from './util/tps';
56
- export * from './math/bankBalance';
57
- export * from './constants/banks';
58
+ export * from './math/spotBalance';
59
+ export * from './constants/spotMarkets';
58
60
  export * from './clearingHouseConfig';
61
+ export * from './dlob/DLOB';
62
+ export * from './dlob/DLOBNode';
63
+ export * from './dlob/NodeList';
64
+ export * from './userMap/userMap';
65
+ export * from './userMap/userStatsMap';
59
66
 
60
67
  export { BN, PublicKey, pyth };
package/src/math/amm.ts CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  AMM,
16
16
  PositionDirection,
17
17
  SwapDirection,
18
- MarketAccount,
18
+ PerpMarketAccount,
19
19
  isVariant,
20
20
  } from '../types';
21
21
  import { assert } from '../assert/assert';
@@ -418,7 +418,10 @@ export function calculateSpreadBN(
418
418
  );
419
419
  }
420
420
 
421
- const maxTargetSpread: number = maxSpread;
421
+ const maxTargetSpread: number = Math.max(
422
+ maxSpread,
423
+ lastOracleMarkSpreadPct.abs().toNumber()
424
+ );
422
425
 
423
426
  const MAX_INVENTORY_SKEW = 5;
424
427
 
@@ -613,7 +616,7 @@ export function getSwapDirection(
613
616
  * @param market
614
617
  * @returns cost : Precision MARK_PRICE_PRECISION
615
618
  */
616
- export function calculateTerminalPrice(market: MarketAccount) {
619
+ export function calculateTerminalPrice(market: PerpMarketAccount) {
617
620
  const directionToClose = market.amm.netBaseAssetAmount.gt(ZERO)
618
621
  ? PositionDirection.SHORT
619
622
  : PositionDirection.LONG;
@@ -5,7 +5,7 @@ import {
5
5
  QUOTE_PRECISION,
6
6
  ZERO,
7
7
  } from '../constants/numericConstants';
8
- import { MarketAccount } from '../types';
8
+ import { PerpMarketAccount, isVariant } from '../types';
9
9
  import { calculateMarkPrice } from './market';
10
10
  import { OraclePriceData } from '../oracles/types';
11
11
 
@@ -17,7 +17,7 @@ import { OraclePriceData } from '../oracles/types';
17
17
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
18
18
  */
19
19
  export async function calculateAllEstimatedFundingRate(
20
- market: MarketAccount,
20
+ market: PerpMarketAccount,
21
21
  oraclePriceData?: OraclePriceData,
22
22
  periodAdjustment: BN = new BN(1)
23
23
  ): Promise<[BN, BN, BN, BN, BN]> {
@@ -29,7 +29,7 @@ export async function calculateAllEstimatedFundingRate(
29
29
  const hoursInDay = new BN(24);
30
30
  const ONE = new BN(1);
31
31
 
32
- if (!market.initialized) {
32
+ if (isVariant(market.status, 'uninitialized')) {
33
33
  return [ZERO, ZERO, ZERO, ZERO, ZERO];
34
34
  }
35
35
 
@@ -208,7 +208,7 @@ export async function calculateAllEstimatedFundingRate(
208
208
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
209
209
  */
210
210
  export async function calculateEstimatedFundingRate(
211
- market: MarketAccount,
211
+ market: PerpMarketAccount,
212
212
  oraclePriceData?: OraclePriceData,
213
213
  periodAdjustment: BN = new BN(1),
214
214
  estimationMethod?: 'interpolated' | 'lowerbound' | 'capped'
@@ -238,7 +238,7 @@ export async function calculateEstimatedFundingRate(
238
238
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
239
239
  */
240
240
  export async function calculateLongShortFundingRate(
241
- market: MarketAccount,
241
+ market: PerpMarketAccount,
242
242
  oraclePriceData?: OraclePriceData,
243
243
  periodAdjustment: BN = new BN(1)
244
244
  ): Promise<[BN, BN]> {
@@ -266,7 +266,7 @@ export async function calculateLongShortFundingRate(
266
266
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
267
267
  */
268
268
  export async function calculateLongShortFundingRateAndLiveTwaps(
269
- market: MarketAccount,
269
+ market: PerpMarketAccount,
270
270
  oraclePriceData?: OraclePriceData,
271
271
  periodAdjustment: BN = new BN(1)
272
272
  ): Promise<[BN, BN, BN, BN]> {
@@ -291,7 +291,7 @@ export async function calculateLongShortFundingRateAndLiveTwaps(
291
291
  * @param market
292
292
  * @returns Estimated fee pool size
293
293
  */
294
- export function calculateFundingPool(market: MarketAccount): BN {
294
+ export function calculateFundingPool(market: PerpMarketAccount): BN {
295
295
  // todo
296
296
  const totalFeeLB = market.amm.totalExchangeFee.div(new BN(2));
297
297
  const feePool = BN.max(
@@ -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;
@@ -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 } =
@@ -63,10 +68,10 @@ export function calculateBidPrice(
63
68
  * Calculates market ask price
64
69
  *
65
70
  * @param market
66
- * @return bidPrice : Precision MARK_PRICE_PRECISION
71
+ * @return askPrice : 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
168
189
  ): BN {
169
- return getTokenAmount(market.pnlPool.balance, bank, BankBalanceType.DEPOSIT);
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
201
+ ): BN {
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
  }
@@ -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,
@@ -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,9 +131,9 @@ export function standardizeBaseAssetAmount(
131
131
 
132
132
  export function getLimitPrice(
133
133
  order: Order,
134
- market: MarketAccount,
135
134
  oraclePriceData: OraclePriceData,
136
- slot: number
135
+ slot: number,
136
+ perpMarket?: PerpMarketAccount
137
137
  ): BN {
138
138
  let limitPrice;
139
139
  if (!order.oraclePriceOffset.eq(ZERO)) {
@@ -143,14 +143,26 @@ export function getLimitPrice(
143
143
  limitPrice = getAuctionPrice(order, slot);
144
144
  } else if (!order.price.eq(ZERO)) {
145
145
  limitPrice = order.price;
146
- } else if (isVariant(order.direction, 'long')) {
147
- const askPrice = calculateAskPrice(market, oraclePriceData);
148
- const delta = askPrice.div(new BN(market.amm.maxSlippageRatio));
149
- limitPrice = askPrice.add(delta);
150
146
  } else {
151
- const bidPrice = calculateBidPrice(market, oraclePriceData);
152
- const delta = bidPrice.div(new BN(market.amm.maxSlippageRatio));
153
- limitPrice = bidPrice.sub(delta);
147
+ if (perpMarket) {
148
+ if (isVariant(order.direction, 'long')) {
149
+ const askPrice = calculateAskPrice(perpMarket, oraclePriceData);
150
+ const delta = askPrice.div(new BN(perpMarket.amm.maxSlippageRatio));
151
+ limitPrice = askPrice.add(delta);
152
+ } else {
153
+ const bidPrice = calculateBidPrice(perpMarket, oraclePriceData);
154
+ const delta = bidPrice.div(new BN(perpMarket.amm.maxSlippageRatio));
155
+ limitPrice = bidPrice.sub(delta);
156
+ }
157
+ } else {
158
+ // check oracle validity?
159
+ const oraclePrice1Pct = oraclePriceData.price.div(new BN(100));
160
+ if (isVariant(order.direction, 'long')) {
161
+ limitPrice = oraclePriceData.price.add(oraclePrice1Pct);
162
+ } else {
163
+ limitPrice = oraclePriceData.price.sub(oraclePrice1Pct);
164
+ }
165
+ }
154
166
  }
155
167
  } else {
156
168
  limitPrice = order.price;
@@ -161,10 +173,9 @@ export function getLimitPrice(
161
173
 
162
174
  export function isFillableByVAMM(
163
175
  order: Order,
164
- market: MarketAccount,
176
+ market: PerpMarketAccount,
165
177
  oraclePriceData: OraclePriceData,
166
- slot: number,
167
- maxAuctionDuration: number
178
+ slot: number
168
179
  ): boolean {
169
180
  return (
170
181
  (isAuctionComplete(order, slot) &&
@@ -174,13 +185,13 @@ export function isFillableByVAMM(
174
185
  oraclePriceData,
175
186
  slot
176
187
  ).eq(ZERO)) ||
177
- isOrderExpired(order, slot, maxAuctionDuration)
188
+ isOrderExpired(order, slot)
178
189
  );
179
190
  }
180
191
 
181
192
  export function calculateBaseAssetAmountForAmmToFulfill(
182
193
  order: Order,
183
- market: MarketAccount,
194
+ market: PerpMarketAccount,
184
195
  oraclePriceData: OraclePriceData,
185
196
  slot: number
186
197
  ): BN {
@@ -191,7 +202,7 @@ export function calculateBaseAssetAmountForAmmToFulfill(
191
202
  return ZERO;
192
203
  }
193
204
 
194
- const limitPrice = getLimitPrice(order, market, oraclePriceData, slot);
205
+ const limitPrice = getLimitPrice(order, oraclePriceData, slot, market);
195
206
  const baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(
196
207
  order,
197
208
  market,
@@ -209,7 +220,7 @@ export function calculateBaseAssetAmountForAmmToFulfill(
209
220
 
210
221
  export function calculateBaseAssetAmountToFillUpToLimitPrice(
211
222
  order: Order,
212
- market: MarketAccount,
223
+ market: PerpMarketAccount,
213
224
  limitPrice: BN,
214
225
  oraclePriceData: OraclePriceData
215
226
  ): BN {
@@ -246,17 +257,14 @@ function isSameDirection(
246
257
  );
247
258
  }
248
259
 
249
- export function isOrderExpired(
250
- order: Order,
251
- slot: number,
252
- maxAuctionDuration: number
253
- ): boolean {
260
+ export function isOrderExpired(order: Order, slot: number): boolean {
254
261
  if (
255
- !isVariant(order.orderType, 'market') ||
256
- !isVariant(order.status, 'open')
262
+ isOneOfVariant(order.orderType, ['triggerMarket', 'triggerLimit']) ||
263
+ !isVariant(order.status, 'open') ||
264
+ order.timeInForce === 0
257
265
  ) {
258
266
  return false;
259
267
  }
260
268
 
261
- return new BN(slot).sub(order.slot).gt(new BN(maxAuctionDuration));
269
+ return new BN(slot).sub(order.slot).gt(new BN(order.timeInForce));
262
270
  }