@drift-labs/sdk 0.2.0-temp.2 → 2.0.1

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 (278) hide show
  1. package/README.md +27 -29
  2. package/lib/accounts/bulkAccountLoader.d.ts +2 -0
  3. package/lib/accounts/bulkAccountLoader.js +36 -29
  4. package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
  5. package/lib/accounts/bulkUserStatsSubscription.js +21 -0
  6. package/lib/accounts/bulkUserSubscription.d.ts +2 -2
  7. package/lib/accounts/bulkUserSubscription.js +0 -1
  8. package/lib/accounts/fetch.d.ts +2 -1
  9. package/lib/accounts/fetch.js +9 -1
  10. package/lib/accounts/{pollingClearingHouseAccountSubscriber.d.ts → pollingDriftClientAccountSubscriber.d.ts} +20 -25
  11. package/lib/accounts/{pollingClearingHouseAccountSubscriber.js → pollingDriftClientAccountSubscriber.js} +45 -49
  12. package/lib/accounts/{pollingOracleSubscriber.d.ts → pollingOracleAccountSubscriber.d.ts} +2 -2
  13. package/lib/accounts/{pollingOracleSubscriber.js → pollingOracleAccountSubscriber.js} +3 -3
  14. package/lib/accounts/pollingUserAccountSubscriber.d.ts +1 -1
  15. package/lib/accounts/pollingUserAccountSubscriber.js +5 -11
  16. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  17. package/lib/accounts/pollingUserStatsAccountSubscriber.js +107 -0
  18. package/lib/accounts/types.d.ts +26 -15
  19. package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +49 -0
  20. package/lib/accounts/{webSocketClearingHouseAccountSubscriber.js → webSocketDriftClientAccountSubscriber.js} +47 -45
  21. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  22. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  23. package/lib/addresses/marketAddresses.d.ts +1 -3
  24. package/lib/addresses/marketAddresses.js +1 -1
  25. package/lib/addresses/pda.d.ts +15 -9
  26. package/lib/addresses/pda.js +73 -35
  27. package/lib/adminClient.d.ts +65 -0
  28. package/lib/adminClient.js +637 -0
  29. package/lib/config.d.ts +10 -10
  30. package/lib/config.js +26 -22
  31. package/lib/constants/numericConstants.d.ts +29 -12
  32. package/lib/constants/numericConstants.js +40 -21
  33. package/lib/constants/perpMarkets.d.ts +18 -0
  34. package/lib/constants/{markets.js → perpMarkets.js} +20 -9
  35. package/lib/constants/spotMarkets.d.ts +19 -0
  36. package/lib/constants/spotMarkets.js +63 -0
  37. package/lib/dlob/DLOB.d.ts +82 -0
  38. package/lib/dlob/DLOB.js +694 -0
  39. package/lib/dlob/DLOBNode.d.ts +54 -0
  40. package/lib/dlob/DLOBNode.js +77 -0
  41. package/lib/dlob/NodeList.d.ts +27 -0
  42. package/lib/dlob/NodeList.js +144 -0
  43. package/lib/driftClient.d.ts +234 -0
  44. package/lib/driftClient.js +2108 -0
  45. package/lib/{clearingHouseConfig.d.ts → driftClientConfig.d.ts} +9 -9
  46. package/lib/{clearingHouseConfig.js → driftClientConfig.js} +0 -0
  47. package/lib/events/eventList.d.ts +0 -1
  48. package/lib/events/eventList.js +0 -7
  49. package/lib/events/eventSubscriber.d.ts +5 -2
  50. package/lib/events/eventSubscriber.js +25 -11
  51. package/lib/events/fetchLogs.d.ts +13 -2
  52. package/lib/events/fetchLogs.js +45 -14
  53. package/lib/events/pollingLogProvider.d.ts +2 -1
  54. package/lib/events/pollingLogProvider.js +7 -3
  55. package/lib/events/sort.js +8 -11
  56. package/lib/events/txEventCache.d.ts +0 -2
  57. package/lib/events/txEventCache.js +0 -14
  58. package/lib/events/types.d.ts +11 -3
  59. package/lib/events/types.js +8 -0
  60. package/lib/events/webSocketLogProvider.js +1 -1
  61. package/lib/examples/makeTradeExample.js +30 -18
  62. package/lib/factory/bigNum.d.ts +8 -4
  63. package/lib/factory/bigNum.js +109 -19
  64. package/lib/idl/drift.json +8392 -0
  65. package/lib/index.d.ts +29 -12
  66. package/lib/index.js +29 -12
  67. package/lib/math/amm.d.ts +9 -6
  68. package/lib/math/amm.js +91 -38
  69. package/lib/math/conversion.js +1 -1
  70. package/lib/math/exchangeStatus.d.ts +4 -0
  71. package/lib/math/exchangeStatus.js +18 -0
  72. package/lib/math/funding.d.ts +6 -6
  73. package/lib/math/funding.js +23 -21
  74. package/lib/math/insurance.d.ts +4 -0
  75. package/lib/math/insurance.js +27 -0
  76. package/lib/math/margin.d.ts +11 -0
  77. package/lib/math/margin.js +82 -0
  78. package/lib/math/market.d.ts +14 -9
  79. package/lib/math/market.js +70 -10
  80. package/lib/math/oracles.d.ts +4 -0
  81. package/lib/math/oracles.js +36 -8
  82. package/lib/math/orders.d.ts +16 -6
  83. package/lib/math/orders.js +97 -17
  84. package/lib/math/position.d.ts +27 -13
  85. package/lib/math/position.js +91 -37
  86. package/lib/math/repeg.js +17 -8
  87. package/lib/math/spotBalance.d.ts +22 -0
  88. package/lib/math/spotBalance.js +192 -0
  89. package/lib/math/spotMarket.d.ts +4 -0
  90. package/lib/math/spotMarket.js +8 -0
  91. package/lib/math/spotPosition.d.ts +6 -0
  92. package/lib/math/spotPosition.js +23 -0
  93. package/lib/math/trade.d.ts +10 -10
  94. package/lib/math/trade.js +27 -31
  95. package/lib/oracles/pythClient.js +1 -1
  96. package/lib/oracles/quoteAssetOracleClient.js +1 -1
  97. package/lib/oracles/switchboardClient.js +1 -1
  98. package/lib/orderParams.d.ts +4 -4
  99. package/lib/orderParams.js +12 -4
  100. package/lib/serum/serumFulfillmentConfigMap.d.ts +10 -0
  101. package/lib/serum/serumFulfillmentConfigMap.js +17 -0
  102. package/lib/serum/serumSubscriber.d.ts +27 -0
  103. package/lib/serum/serumSubscriber.js +56 -0
  104. package/lib/serum/types.d.ts +11 -0
  105. package/{src/oracles → lib/serum}/types.js +0 -0
  106. package/lib/tokenFaucet.d.ts +1 -0
  107. package/lib/tokenFaucet.js +23 -12
  108. package/lib/tx/retryTxSender.d.ts +1 -1
  109. package/lib/tx/retryTxSender.js +13 -4
  110. package/lib/tx/types.d.ts +1 -1
  111. package/lib/types.d.ts +631 -222
  112. package/lib/types.js +137 -24
  113. package/lib/user.d.ts +228 -0
  114. package/lib/user.js +959 -0
  115. package/lib/userConfig.d.ts +14 -0
  116. package/lib/{clearingHouseUserConfig.js → userConfig.js} +0 -0
  117. package/lib/userMap/userMap.d.ts +41 -0
  118. package/lib/userMap/userMap.js +85 -0
  119. package/lib/userMap/userStatsMap.d.ts +19 -0
  120. package/lib/userMap/userStatsMap.js +68 -0
  121. package/lib/userName.d.ts +1 -0
  122. package/lib/userName.js +3 -2
  123. package/lib/userStats.d.ts +18 -0
  124. package/lib/userStats.js +49 -0
  125. package/lib/userStatsConfig.d.ts +14 -0
  126. package/{src/clearingHouseConfig.js → lib/userStatsConfig.js} +0 -0
  127. package/lib/util/getTokenAddress.d.ts +2 -0
  128. package/lib/util/getTokenAddress.js +9 -0
  129. package/package.json +12 -5
  130. package/src/accounts/bulkAccountLoader.ts +44 -34
  131. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  132. package/src/accounts/bulkUserSubscription.ts +2 -3
  133. package/src/accounts/fetch.ts +27 -2
  134. package/src/accounts/{pollingClearingHouseAccountSubscriber.ts → pollingDriftClientAccountSubscriber.ts} +65 -75
  135. package/src/accounts/{pollingOracleSubscriber.ts → pollingOracleAccountSubscriber.ts} +2 -2
  136. package/src/accounts/pollingUserAccountSubscriber.ts +5 -12
  137. package/src/accounts/pollingUserStatsAccountSubscriber.ts +166 -0
  138. package/src/accounts/types.ts +35 -15
  139. package/src/accounts/{webSocketClearingHouseAccountSubscriber.ts → webSocketDriftClientAccountSubscriber.ts} +78 -73
  140. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  141. package/src/addresses/marketAddresses.ts +3 -4
  142. package/src/addresses/pda.ts +105 -33
  143. package/src/adminClient.ts +1207 -0
  144. package/src/config.ts +41 -34
  145. package/src/constants/numericConstants.ts +59 -26
  146. package/src/constants/{markets.ts → perpMarkets.ts} +22 -11
  147. package/src/constants/spotMarkets.ts +83 -0
  148. package/src/dlob/DLOB.ts +1120 -0
  149. package/src/dlob/DLOBNode.ts +155 -0
  150. package/src/dlob/NodeList.ts +195 -0
  151. package/src/driftClient.ts +3594 -0
  152. package/src/{clearingHouseConfig.ts → driftClientConfig.ts} +9 -8
  153. package/src/events/eventList.ts +1 -8
  154. package/src/events/eventSubscriber.ts +36 -14
  155. package/src/events/fetchLogs.ts +60 -15
  156. package/src/events/pollingLogProvider.ts +11 -3
  157. package/src/events/sort.ts +11 -15
  158. package/src/events/txEventCache.ts +0 -16
  159. package/src/events/types.ts +27 -2
  160. package/src/events/webSocketLogProvider.ts +1 -1
  161. package/src/examples/makeTradeExample.js +152 -75
  162. package/src/examples/makeTradeExample.ts +44 -28
  163. package/src/factory/bigNum.ts +150 -22
  164. package/src/idl/drift.json +8392 -0
  165. package/src/idl/pyth.json +98 -2
  166. package/src/index.ts +29 -12
  167. package/src/math/amm.ts +161 -48
  168. package/src/math/conversion.ts +2 -2
  169. package/src/math/exchangeStatus.ts +31 -0
  170. package/src/math/funding.ts +41 -31
  171. package/src/math/insurance.ts +35 -0
  172. package/src/math/margin.ts +133 -0
  173. package/src/math/market.ts +143 -14
  174. package/src/math/oracles.ts +63 -9
  175. package/src/math/orders.ts +168 -26
  176. package/src/math/position.ts +133 -59
  177. package/src/math/repeg.ts +19 -9
  178. package/src/math/spotBalance.ts +319 -0
  179. package/src/math/spotMarket.ts +9 -0
  180. package/src/math/spotPosition.ts +47 -0
  181. package/src/math/trade.ts +33 -37
  182. package/src/oracles/pythClient.ts +2 -2
  183. package/src/oracles/quoteAssetOracleClient.ts +2 -2
  184. package/src/oracles/switchboardClient.ts +2 -2
  185. package/src/orderParams.ts +16 -8
  186. package/src/serum/serumFulfillmentConfigMap.ts +26 -0
  187. package/src/serum/serumSubscriber.ts +99 -0
  188. package/src/serum/types.ts +13 -0
  189. package/src/tokenFaucet.ts +38 -15
  190. package/src/tx/retryTxSender.ts +16 -5
  191. package/src/tx/types.ts +2 -1
  192. package/src/types.ts +594 -195
  193. package/src/user.ts +1599 -0
  194. package/src/{clearingHouseUserConfig.ts → userConfig.ts} +5 -5
  195. package/src/userMap/userMap.ts +124 -0
  196. package/src/userMap/userStatsMap.ts +108 -0
  197. package/src/userName.ts +2 -1
  198. package/src/userStats.ts +75 -0
  199. package/src/userStatsConfig.ts +18 -0
  200. package/src/util/getTokenAddress.ts +18 -0
  201. package/tests/bn/test.ts +46 -11
  202. package/tests/dlob/helpers.ts +619 -0
  203. package/tests/dlob/test.ts +4586 -0
  204. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +0 -49
  205. package/lib/admin.d.ts +0 -44
  206. package/lib/admin.js +0 -438
  207. package/lib/clearingHouse.d.ts +0 -146
  208. package/lib/clearingHouse.js +0 -1154
  209. package/lib/clearingHouseUser.d.ts +0 -187
  210. package/lib/clearingHouseUser.js +0 -634
  211. package/lib/clearingHouseUserConfig.d.ts +0 -14
  212. package/lib/constants/banks.d.ts +0 -16
  213. package/lib/constants/banks.js +0 -41
  214. package/lib/constants/markets.d.ts +0 -19
  215. package/lib/idl/clearing_house.json +0 -4464
  216. package/lib/math/bankBalance.d.ts +0 -9
  217. package/lib/math/bankBalance.js +0 -75
  218. package/lib/math/state.d.ts +0 -8
  219. package/lib/math/state.js +0 -15
  220. package/lib/orders.d.ts +0 -8
  221. package/lib/orders.js +0 -134
  222. package/src/accounts/bulkAccountLoader.js +0 -197
  223. package/src/accounts/bulkUserSubscription.js +0 -33
  224. package/src/accounts/pollingClearingHouseAccountSubscriber.js +0 -311
  225. package/src/accounts/pollingOracleSubscriber.js +0 -93
  226. package/src/accounts/pollingTokenAccountSubscriber.js +0 -90
  227. package/src/accounts/pollingUserAccountSubscriber.js +0 -132
  228. package/src/accounts/types.js +0 -10
  229. package/src/accounts/utils.js +0 -7
  230. package/src/accounts/webSocketAccountSubscriber.js +0 -93
  231. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +0 -233
  232. package/src/accounts/webSocketUserAccountSubscriber.js +0 -62
  233. package/src/addresses/marketAddresses.js +0 -26
  234. package/src/admin.js +0 -517
  235. package/src/admin.ts +0 -730
  236. package/src/clearingHouse.ts +0 -1828
  237. package/src/clearingHouseUser.ts +0 -978
  238. package/src/clearingHouseUserConfig.js +0 -2
  239. package/src/config.js +0 -67
  240. package/src/constants/banks.js +0 -42
  241. package/src/constants/banks.ts +0 -50
  242. package/src/constants/markets.js +0 -42
  243. package/src/constants/numericConstants.js +0 -41
  244. package/src/events/eventSubscriber.js +0 -139
  245. package/src/events/fetchLogs.js +0 -50
  246. package/src/events/pollingLogProvider.js +0 -64
  247. package/src/events/sort.js +0 -44
  248. package/src/events/txEventCache.js +0 -71
  249. package/src/events/types.js +0 -20
  250. package/src/events/webSocketLogProvider.js +0 -41
  251. package/src/factory/bigNum.js +0 -390
  252. package/src/factory/oracleClient.js +0 -20
  253. package/src/idl/clearing_house.json +0 -4464
  254. package/src/index.js +0 -69
  255. package/src/math/amm.js +0 -369
  256. package/src/math/auction.js +0 -42
  257. package/src/math/bankBalance.ts +0 -112
  258. package/src/math/conversion.js +0 -11
  259. package/src/math/funding.js +0 -248
  260. package/src/math/oracles.js +0 -26
  261. package/src/math/repeg.js +0 -128
  262. package/src/math/state.js +0 -15
  263. package/src/math/state.ts +0 -14
  264. package/src/math/trade.js +0 -253
  265. package/src/math/utils.js +0 -26
  266. package/src/math/utils.js.map +0 -1
  267. package/src/mockUSDCFaucet.js +0 -280
  268. package/src/oracles/oracleClientCache.js +0 -19
  269. package/src/oracles/pythClient.js +0 -46
  270. package/src/oracles/quoteAssetOracleClient.js +0 -32
  271. package/src/oracles/switchboardClient.js +0 -69
  272. package/src/orderParams.js +0 -20
  273. package/src/orders.ts +0 -245
  274. package/src/slot/SlotSubscriber.js +0 -39
  275. package/src/tokenFaucet.js +0 -189
  276. package/src/types.js +0 -125
  277. package/src/userName.js +0 -20
  278. package/src/wallet.js +0 -35
@@ -1,13 +1,13 @@
1
1
  import { BN } from '@project-serum/anchor';
2
2
  import {
3
3
  AMM_RESERVE_PRECISION,
4
- MARK_PRICE_PRECISION,
4
+ PRICE_PRECISION,
5
5
  QUOTE_PRECISION,
6
6
  ZERO,
7
7
  } from '../constants/numericConstants';
8
- import { MarketAccount } from '../types';
9
- import { calculateMarkPrice } from './market';
8
+ import { PerpMarketAccount, isVariant } from '../types';
10
9
  import { OraclePriceData } from '../oracles/types';
10
+ import { calculateBidAskPrice } from './amm';
11
11
 
12
12
  /**
13
13
  *
@@ -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
 
@@ -48,10 +48,8 @@ export async function calculateAllEstimatedFundingRate(
48
48
  secondsInHour,
49
49
  BN.max(ZERO, secondsInHour.sub(timeSinceLastMarkChange))
50
50
  );
51
- const baseAssetPriceWithMantissa = calculateMarkPrice(
52
- market,
53
- oraclePriceData
54
- );
51
+ const [bid, ask] = calculateBidAskPrice(market.amm, oraclePriceData);
52
+ const baseAssetPriceWithMantissa = bid.add(ask).div(new BN(2));
55
53
 
56
54
  const markTwapWithMantissa = markTwapTimeSinceLastUpdate
57
55
  .mul(lastMarkTwapWithMantissa)
@@ -60,8 +58,10 @@ export async function calculateAllEstimatedFundingRate(
60
58
 
61
59
  // calculate real-time (predicted) oracle twap
62
60
  // note: oracle twap depends on `when the chord is struck` (market is trade)
63
- const lastOracleTwapWithMantissa = market.amm.lastOraclePriceTwap;
64
- const lastOraclePriceTwapTs = market.amm.lastOraclePriceTwapTs;
61
+ const lastOracleTwapWithMantissa =
62
+ market.amm.historicalOracleData.lastOraclePriceTwap;
63
+ const lastOraclePriceTwapTs =
64
+ market.amm.historicalOracleData.lastOraclePriceTwapTs;
65
65
 
66
66
  const oracleInvalidDuration = BN.max(
67
67
  ZERO,
@@ -85,12 +85,12 @@ export async function calculateAllEstimatedFundingRate(
85
85
  const oracleLiveVsTwap = oraclePrice
86
86
  .sub(lastOracleTwapWithMantissa)
87
87
  .abs()
88
- .mul(MARK_PRICE_PRECISION)
88
+ .mul(PRICE_PRECISION)
89
89
  .mul(new BN(100))
90
90
  .div(lastOracleTwapWithMantissa);
91
91
 
92
92
  // verify pyth live input is within 10% of last twap for live update
93
- if (oracleLiveVsTwap.lte(MARK_PRICE_PRECISION.mul(new BN(10)))) {
93
+ if (oracleLiveVsTwap.lte(PRICE_PRECISION.mul(new BN(10)))) {
94
94
  oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
95
95
  .mul(lastOracleTwapWithMantissa)
96
96
  .add(timeSinceLastMarkChange.mul(oraclePrice))
@@ -108,7 +108,7 @@ export async function calculateAllEstimatedFundingRate(
108
108
  );
109
109
 
110
110
  const twapSpreadPct = twapSpread
111
- .mul(MARK_PRICE_PRECISION)
111
+ .mul(PRICE_PRECISION)
112
112
  .mul(new BN(100))
113
113
  .div(shrunkLastOracleTwapwithMantissa);
114
114
 
@@ -125,7 +125,7 @@ export async function calculateAllEstimatedFundingRate(
125
125
  const interpRateQuote = twapSpreadPct
126
126
  .mul(periodAdjustment)
127
127
  .div(hoursInDay)
128
- .div(MARK_PRICE_PRECISION.div(QUOTE_PRECISION));
128
+ .div(PRICE_PRECISION.div(QUOTE_PRECISION));
129
129
 
130
130
  let feePoolSize = calculateFundingPool(market);
131
131
  if (interpRateQuote.lt(new BN(0))) {
@@ -135,9 +135,11 @@ export async function calculateAllEstimatedFundingRate(
135
135
  let cappedAltEst: BN;
136
136
  let largerSide: BN;
137
137
  let smallerSide: BN;
138
- if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort.abs())) {
139
- largerSide = market.baseAssetAmountLong.abs();
140
- smallerSide = market.baseAssetAmountShort.abs();
138
+ if (
139
+ market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort.abs())
140
+ ) {
141
+ largerSide = market.amm.baseAssetAmountLong.abs();
142
+ smallerSide = market.amm.baseAssetAmountShort.abs();
141
143
  if (twapSpread.gt(new BN(0))) {
142
144
  return [
143
145
  markTwapWithMantissa,
@@ -147,9 +149,11 @@ export async function calculateAllEstimatedFundingRate(
147
149
  interpEst,
148
150
  ];
149
151
  }
150
- } else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort.abs())) {
151
- largerSide = market.baseAssetAmountShort.abs();
152
- smallerSide = market.baseAssetAmountLong.abs();
152
+ } else if (
153
+ market.amm.baseAssetAmountLong.lt(market.amm.baseAssetAmountShort.abs())
154
+ ) {
155
+ largerSide = market.amm.baseAssetAmountShort.abs();
156
+ smallerSide = market.amm.baseAssetAmountLong.abs();
153
157
  if (twapSpread.lt(new BN(0))) {
154
158
  return [
155
159
  markTwapWithMantissa,
@@ -173,12 +177,12 @@ export async function calculateAllEstimatedFundingRate(
173
177
  // funding smaller flow
174
178
  cappedAltEst = smallerSide.mul(twapSpread).div(hoursInDay);
175
179
  const feePoolTopOff = feePoolSize
176
- .mul(MARK_PRICE_PRECISION.div(QUOTE_PRECISION))
180
+ .mul(PRICE_PRECISION.div(QUOTE_PRECISION))
177
181
  .mul(AMM_RESERVE_PRECISION);
178
182
  cappedAltEst = cappedAltEst.add(feePoolTopOff).div(largerSide);
179
183
 
180
184
  cappedAltEst = cappedAltEst
181
- .mul(MARK_PRICE_PRECISION)
185
+ .mul(PRICE_PRECISION)
182
186
  .mul(new BN(100))
183
187
  .div(oracleTwapWithMantissa)
184
188
  .mul(periodAdjustment);
@@ -208,7 +212,7 @@ export async function calculateAllEstimatedFundingRate(
208
212
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
209
213
  */
210
214
  export async function calculateEstimatedFundingRate(
211
- market: MarketAccount,
215
+ market: PerpMarketAccount,
212
216
  oraclePriceData?: OraclePriceData,
213
217
  periodAdjustment: BN = new BN(1),
214
218
  estimationMethod?: 'interpolated' | 'lowerbound' | 'capped'
@@ -238,7 +242,7 @@ export async function calculateEstimatedFundingRate(
238
242
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
239
243
  */
240
244
  export async function calculateLongShortFundingRate(
241
- market: MarketAccount,
245
+ market: PerpMarketAccount,
242
246
  oraclePriceData?: OraclePriceData,
243
247
  periodAdjustment: BN = new BN(1)
244
248
  ): Promise<[BN, BN]> {
@@ -249,9 +253,11 @@ export async function calculateLongShortFundingRate(
249
253
  periodAdjustment
250
254
  );
251
255
 
252
- if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort)) {
256
+ if (market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort)) {
253
257
  return [cappedAltEst, interpEst];
254
- } else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort)) {
258
+ } else if (
259
+ market.amm.baseAssetAmountLong.lt(market.amm.baseAssetAmountShort)
260
+ ) {
255
261
  return [interpEst, cappedAltEst];
256
262
  } else {
257
263
  return [interpEst, interpEst];
@@ -266,7 +272,7 @@ export async function calculateLongShortFundingRate(
266
272
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
267
273
  */
268
274
  export async function calculateLongShortFundingRateAndLiveTwaps(
269
- market: MarketAccount,
275
+ market: PerpMarketAccount,
270
276
  oraclePriceData?: OraclePriceData,
271
277
  periodAdjustment: BN = new BN(1)
272
278
  ): Promise<[BN, BN, BN, BN]> {
@@ -277,9 +283,13 @@ export async function calculateLongShortFundingRateAndLiveTwaps(
277
283
  periodAdjustment
278
284
  );
279
285
 
280
- if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort.abs())) {
286
+ if (
287
+ market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort.abs())
288
+ ) {
281
289
  return [markTwapLive, oracleTwapLive, cappedAltEst, interpEst];
282
- } else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort.abs())) {
290
+ } else if (
291
+ market.amm.baseAssetAmountLong.lt(market.amm.baseAssetAmountShort.abs())
292
+ ) {
283
293
  return [markTwapLive, oracleTwapLive, interpEst, cappedAltEst];
284
294
  } else {
285
295
  return [markTwapLive, oracleTwapLive, interpEst, interpEst];
@@ -291,7 +301,7 @@ export async function calculateLongShortFundingRateAndLiveTwaps(
291
301
  * @param market
292
302
  * @returns Estimated fee pool size
293
303
  */
294
- export function calculateFundingPool(market: MarketAccount): BN {
304
+ export function calculateFundingPool(market: PerpMarketAccount): BN {
295
305
  // todo
296
306
  const totalFeeLB = market.amm.totalExchangeFee.div(new BN(2));
297
307
  const feePool = BN.max(
@@ -0,0 +1,35 @@
1
+ import { ZERO } from '../constants/numericConstants';
2
+ import { BN } from '../index';
3
+
4
+ export function stakeAmountToShares(
5
+ amount: BN,
6
+ totalIfShares: BN,
7
+ insuranceFundVaultBalance: BN
8
+ ): BN {
9
+ let nShares: BN;
10
+ if (insuranceFundVaultBalance.gt(ZERO)) {
11
+ nShares = amount.mul(totalIfShares).div(insuranceFundVaultBalance);
12
+ } else {
13
+ nShares = amount;
14
+ }
15
+
16
+ return nShares;
17
+ }
18
+
19
+ export function unstakeSharesToAmount(
20
+ nShares: BN,
21
+ totalIfShares: BN,
22
+ insuranceFundVaultBalance: BN
23
+ ): BN {
24
+ let amount: BN;
25
+ if (totalIfShares.gt(ZERO)) {
26
+ amount = BN.max(
27
+ ZERO,
28
+ nShares.mul(insuranceFundVaultBalance).div(totalIfShares)
29
+ );
30
+ } else {
31
+ amount = ZERO;
32
+ }
33
+
34
+ return amount;
35
+ }
@@ -0,0 +1,133 @@
1
+ import { squareRootBN } from './utils';
2
+ import {
3
+ SPOT_MARKET_WEIGHT_PRECISION,
4
+ SPOT_MARKET_IMF_PRECISION,
5
+ ZERO,
6
+ BID_ASK_SPREAD_PRECISION,
7
+ AMM_RESERVE_PRECISION,
8
+ } from '../constants/numericConstants';
9
+ import { BN } from '@project-serum/anchor';
10
+ import { OraclePriceData } from '../oracles/types';
11
+ import { PerpMarketAccount, PerpPosition } from '..';
12
+ import { isVariant } from '../types';
13
+ import { assert } from '../assert/assert';
14
+
15
+ export function calculateSizePremiumLiabilityWeight(
16
+ size: BN, // AMM_RESERVE_PRECISION
17
+ imfFactor: BN,
18
+ liabilityWeight: BN,
19
+ precision: BN
20
+ ): BN {
21
+ if (imfFactor.eq(ZERO)) {
22
+ return liabilityWeight;
23
+ }
24
+
25
+ const sizeSqrt = squareRootBN(size.mul(new BN(10)).add(new BN(1))); //1e9 -> 1e10 -> 1e5
26
+
27
+ const denom0 = BN.max(new BN(1), SPOT_MARKET_IMF_PRECISION.div(imfFactor));
28
+ assert(denom0.gt(ZERO));
29
+ const liabilityWeightNumerator = liabilityWeight.sub(
30
+ liabilityWeight.div(
31
+ BN.max(new BN(1), SPOT_MARKET_IMF_PRECISION.div(imfFactor))
32
+ )
33
+ );
34
+
35
+ const denom = new BN(100_000).mul(SPOT_MARKET_IMF_PRECISION).div(precision);
36
+ assert(denom.gt(ZERO));
37
+
38
+ const sizePremiumLiabilityWeight = liabilityWeightNumerator.add(
39
+ sizeSqrt // 1e5
40
+ .mul(imfFactor)
41
+ .div(denom) // 1e5
42
+ );
43
+
44
+ const maxLiabilityWeight = BN.max(
45
+ liabilityWeight,
46
+ sizePremiumLiabilityWeight
47
+ );
48
+ return maxLiabilityWeight;
49
+ }
50
+
51
+ export function calculateSizeDiscountAssetWeight(
52
+ size: BN, // AMM_RESERVE_PRECISION
53
+ imfFactor: BN,
54
+ assetWeight: BN
55
+ ): BN {
56
+ if (imfFactor.eq(ZERO)) {
57
+ return assetWeight;
58
+ }
59
+
60
+ const sizeSqrt = squareRootBN(size.mul(new BN(10)).add(new BN(1))); //1e9 -> 1e10 -> 1e5
61
+ const imfNumerator = SPOT_MARKET_IMF_PRECISION.add(
62
+ SPOT_MARKET_IMF_PRECISION.div(new BN(10))
63
+ );
64
+
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
+ );
74
+
75
+ const minAssetWeight = BN.min(assetWeight, sizeDiscountAssetWeight);
76
+
77
+ return minAssetWeight;
78
+ }
79
+
80
+ export function calculateOraclePriceForPerpMargin(
81
+ perpPosition: PerpPosition,
82
+ market: PerpMarketAccount,
83
+ oraclePriceData: OraclePriceData
84
+ ): BN {
85
+ const oraclePriceOffset = BN.min(
86
+ new BN(market.amm.maxSpread)
87
+ .mul(oraclePriceData.price)
88
+ .div(BID_ASK_SPREAD_PRECISION),
89
+ oraclePriceData.confidence.add(
90
+ new BN(market.amm.baseSpread)
91
+ .mul(oraclePriceData.price)
92
+ .div(BID_ASK_SPREAD_PRECISION)
93
+ )
94
+ );
95
+
96
+ let marginPrice: BN;
97
+ if (perpPosition.baseAssetAmount.gt(ZERO)) {
98
+ marginPrice = oraclePriceData.price.sub(oraclePriceOffset);
99
+ } else {
100
+ marginPrice = oraclePriceData.price.add(oraclePriceOffset);
101
+ }
102
+
103
+ return marginPrice;
104
+ }
105
+
106
+ export function calculateBaseAssetValueWithOracle(
107
+ market: PerpMarketAccount,
108
+ perpPosition: PerpPosition,
109
+ oraclePriceData: OraclePriceData
110
+ ): BN {
111
+ let price = oraclePriceData.price;
112
+ if (isVariant(market.status, 'settlement')) {
113
+ price = market.expiryPrice;
114
+ }
115
+
116
+ return perpPosition.baseAssetAmount
117
+ .abs()
118
+ .mul(price)
119
+ .div(AMM_RESERVE_PRECISION);
120
+ }
121
+
122
+ export function calculateWorstCaseBaseAssetAmount(
123
+ perpPosition: PerpPosition
124
+ ): BN {
125
+ const allBids = perpPosition.baseAssetAmount.add(perpPosition.openBids);
126
+ const allAsks = perpPosition.baseAssetAmount.add(perpPosition.openAsks);
127
+
128
+ if (allBids.abs().gt(allAsks.abs())) {
129
+ return allBids;
130
+ } else {
131
+ return allAsks;
132
+ }
133
+ }
@@ -1,5 +1,11 @@
1
1
  import { BN } from '@project-serum/anchor';
2
- import { MarketAccount, PositionDirection } from '../types';
2
+ import {
3
+ PerpMarketAccount,
4
+ PositionDirection,
5
+ MarginCategory,
6
+ SpotMarketAccount,
7
+ SpotBalanceType,
8
+ } from '../types';
3
9
  import {
4
10
  calculateAmmReservesAfterSwap,
5
11
  calculatePrice,
@@ -7,16 +13,27 @@ import {
7
13
  getSwapDirection,
8
14
  calculateUpdatedAMM,
9
15
  } from './amm';
16
+ import {
17
+ calculateSizeDiscountAssetWeight,
18
+ calculateSizePremiumLiabilityWeight,
19
+ } from './margin';
10
20
  import { OraclePriceData } from '../oracles/types';
21
+ import {
22
+ BASE_PRECISION,
23
+ MARGIN_PRECISION,
24
+ PRICE_TO_QUOTE_PRECISION,
25
+ ZERO,
26
+ } from '../constants/numericConstants';
27
+ import { getTokenAmount } from './spotBalance';
11
28
 
12
29
  /**
13
30
  * Calculates market mark price
14
31
  *
15
32
  * @param market
16
- * @return markPrice : Precision MARK_PRICE_PRECISION
33
+ * @return markPrice : Precision PRICE_PRECISION
17
34
  */
18
- export function calculateMarkPrice(
19
- market: MarketAccount,
35
+ export function calculateReservePrice(
36
+ market: PerpMarketAccount,
20
37
  oraclePriceData: OraclePriceData
21
38
  ): BN {
22
39
  const newAmm = calculateUpdatedAMM(market.amm, oraclePriceData);
@@ -31,10 +48,10 @@ export function calculateMarkPrice(
31
48
  * Calculates market bid price
32
49
  *
33
50
  * @param market
34
- * @return bidPrice : Precision MARK_PRICE_PRECISION
51
+ * @return bidPrice : Precision PRICE_PRECISION
35
52
  */
36
53
  export function calculateBidPrice(
37
- market: MarketAccount,
54
+ market: PerpMarketAccount,
38
55
  oraclePriceData: OraclePriceData
39
56
  ): BN {
40
57
  const { baseAssetReserve, quoteAssetReserve, newPeg } =
@@ -51,10 +68,10 @@ export function calculateBidPrice(
51
68
  * Calculates market ask price
52
69
  *
53
70
  * @param market
54
- * @return bidPrice : Precision MARK_PRICE_PRECISION
71
+ * @return askPrice : Precision PRICE_PRECISION
55
72
  */
56
73
  export function calculateAskPrice(
57
- market: MarketAccount,
74
+ market: PerpMarketAccount,
58
75
  oraclePriceData: OraclePriceData
59
76
  ): BN {
60
77
  const { baseAssetReserve, quoteAssetReserve, newPeg } =
@@ -70,8 +87,8 @@ export function calculateAskPrice(
70
87
  export function calculateNewMarketAfterTrade(
71
88
  baseAssetAmount: BN,
72
89
  direction: PositionDirection,
73
- market: MarketAccount
74
- ): MarketAccount {
90
+ market: PerpMarketAccount
91
+ ): PerpMarketAccount {
75
92
  const [newQuoteAssetReserve, newBaseAssetReserve] =
76
93
  calculateAmmReservesAfterSwap(
77
94
  market.amm,
@@ -89,12 +106,12 @@ export function calculateNewMarketAfterTrade(
89
106
  return newMarket;
90
107
  }
91
108
 
92
- export function calculateMarkOracleSpread(
93
- market: MarketAccount,
109
+ export function calculateOracleReserveSpread(
110
+ market: PerpMarketAccount,
94
111
  oraclePriceData: OraclePriceData
95
112
  ): BN {
96
- const markPrice = calculateMarkPrice(market, oraclePriceData);
97
- return calculateOracleSpread(markPrice, oraclePriceData);
113
+ const reservePrice = calculateReservePrice(market, oraclePriceData);
114
+ return calculateOracleSpread(reservePrice, oraclePriceData);
98
115
  }
99
116
 
100
117
  export function calculateOracleSpread(
@@ -103,3 +120,115 @@ export function calculateOracleSpread(
103
120
  ): BN {
104
121
  return price.sub(oraclePriceData.price);
105
122
  }
123
+
124
+ export function calculateMarketMarginRatio(
125
+ market: PerpMarketAccount,
126
+ size: BN,
127
+ marginCategory: MarginCategory
128
+ ): number {
129
+ let marginRatio;
130
+ switch (marginCategory) {
131
+ case 'Initial':
132
+ marginRatio = calculateSizePremiumLiabilityWeight(
133
+ size,
134
+ new BN(market.imfFactor),
135
+ new BN(market.marginRatioInitial),
136
+ MARGIN_PRECISION
137
+ ).toNumber();
138
+ break;
139
+ case 'Maintenance':
140
+ marginRatio = calculateSizePremiumLiabilityWeight(
141
+ size,
142
+ new BN(market.imfFactor),
143
+ new BN(market.marginRatioMaintenance),
144
+ MARGIN_PRECISION
145
+ ).toNumber();
146
+ break;
147
+ }
148
+
149
+ return marginRatio;
150
+ }
151
+
152
+ export function calculateUnrealizedAssetWeight(
153
+ market: PerpMarketAccount,
154
+ quoteSpotMarket: SpotMarketAccount,
155
+ unrealizedPnl: BN,
156
+ marginCategory: MarginCategory,
157
+ oraclePriceData: OraclePriceData
158
+ ): BN {
159
+ let assetWeight: BN;
160
+ switch (marginCategory) {
161
+ case 'Initial':
162
+ assetWeight = new BN(market.unrealizedPnlInitialAssetWeight);
163
+
164
+ if (market.unrealizedPnlMaxImbalance.gt(ZERO)) {
165
+ const netUnsettledPnl = calculateNetUserPnlImbalance(
166
+ market,
167
+ quoteSpotMarket,
168
+ oraclePriceData
169
+ );
170
+ if (netUnsettledPnl.gt(market.unrealizedPnlMaxImbalance)) {
171
+ assetWeight = assetWeight
172
+ .mul(market.unrealizedPnlMaxImbalance)
173
+ .div(netUnsettledPnl);
174
+ }
175
+ }
176
+
177
+ assetWeight = calculateSizeDiscountAssetWeight(
178
+ unrealizedPnl,
179
+ new BN(market.unrealizedPnlImfFactor),
180
+ assetWeight
181
+ );
182
+ break;
183
+ case 'Maintenance':
184
+ assetWeight = new BN(market.unrealizedPnlMaintenanceAssetWeight);
185
+ break;
186
+ }
187
+
188
+ return assetWeight;
189
+ }
190
+
191
+ export function calculateMarketAvailablePNL(
192
+ perpMarket: PerpMarketAccount,
193
+ spotMarket: SpotMarketAccount
194
+ ): BN {
195
+ return getTokenAmount(
196
+ perpMarket.pnlPool.scaledBalance,
197
+ spotMarket,
198
+ SpotBalanceType.DEPOSIT
199
+ );
200
+ }
201
+
202
+ export function calculateNetUserPnl(
203
+ perpMarket: PerpMarketAccount,
204
+ oraclePriceData: OraclePriceData
205
+ ): BN {
206
+ const netUserPositionValue = perpMarket.amm.baseAssetAmountWithAmm
207
+ .mul(oraclePriceData.price)
208
+ .div(BASE_PRECISION)
209
+ .div(PRICE_TO_QUOTE_PRECISION);
210
+
211
+ const netUserCostBasis = perpMarket.amm.quoteAssetAmount;
212
+
213
+ const netUserPnl = netUserPositionValue.add(netUserCostBasis);
214
+
215
+ return netUserPnl;
216
+ }
217
+
218
+ export function calculateNetUserPnlImbalance(
219
+ perpMarket: PerpMarketAccount,
220
+ spotMarket: SpotMarketAccount,
221
+ oraclePriceData: OraclePriceData
222
+ ): BN {
223
+ const netUserPnl = calculateNetUserPnl(perpMarket, oraclePriceData);
224
+
225
+ const pnlPool = getTokenAmount(
226
+ perpMarket.pnlPool.scaledBalance,
227
+ spotMarket,
228
+ SpotBalanceType.DEPOSIT
229
+ );
230
+
231
+ const imbalance = netUserPnl.sub(pnlPool);
232
+
233
+ return imbalance;
234
+ }
@@ -1,7 +1,29 @@
1
1
  import { AMM, OracleGuardRails } from '../types';
2
2
  import { OraclePriceData } from '../oracles/types';
3
- import { ONE, ZERO } from '../constants/numericConstants';
4
- import { BN } from '../index';
3
+ import {
4
+ BID_ASK_SPREAD_PRECISION,
5
+ MARGIN_PRECISION,
6
+ PRICE_PRECISION,
7
+ ONE,
8
+ ZERO,
9
+ } from '../constants/numericConstants';
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
+ }
5
27
 
6
28
  export function isOracleValid(
7
29
  amm: AMM,
@@ -9,22 +31,24 @@ export function isOracleValid(
9
31
  oracleGuardRails: OracleGuardRails,
10
32
  slot: number
11
33
  ): boolean {
12
- const isOraclePriceNonPositive = oraclePriceData.price.lt(ZERO);
34
+ const isOraclePriceNonPositive = oraclePriceData.price.lte(ZERO);
13
35
  const isOraclePriceTooVolatile =
14
36
  oraclePriceData.price
15
- .div(BN.max(ONE, amm.lastOraclePriceTwap))
37
+ .div(BN.max(ONE, amm.historicalOracleData.lastOraclePriceTwap))
16
38
  .gt(oracleGuardRails.validity.tooVolatileRatio) ||
17
- amm.lastOraclePriceTwap
39
+ amm.historicalOracleData.lastOraclePriceTwap
18
40
  .div(BN.max(ONE, oraclePriceData.price))
19
41
  .gt(oracleGuardRails.validity.tooVolatileRatio);
20
42
 
21
- const isConfidenceTooLarge = oraclePriceData.price
22
- .div(BN.max(ONE, oraclePriceData.confidence))
23
- .lt(oracleGuardRails.validity.confidenceIntervalMaxSize);
43
+ const isConfidenceTooLarge = new BN(amm.baseSpread)
44
+ .add(BN.max(ONE, oraclePriceData.confidence))
45
+ .mul(BID_ASK_SPREAD_PRECISION)
46
+ .div(oraclePriceData.price)
47
+ .gt(new BN(amm.maxSpread));
24
48
 
25
49
  const oracleIsStale = oraclePriceData.slot
26
50
  .sub(new BN(slot))
27
- .gt(oracleGuardRails.validity.slotsBeforeStale);
51
+ .gt(oracleGuardRails.validity.slotsBeforeStaleForAmm);
28
52
 
29
53
  return !(
30
54
  !oraclePriceData.hasSufficientNumberOfDataPoints ||
@@ -34,3 +58,33 @@ export function isOracleValid(
34
58
  isConfidenceTooLarge
35
59
  );
36
60
  }
61
+
62
+ export function isOracleTooDivergent(
63
+ amm: AMM,
64
+ oraclePriceData: OraclePriceData,
65
+ oracleGuardRails: OracleGuardRails,
66
+ now: BN
67
+ ): boolean {
68
+ const sinceLastUpdate = now.sub(
69
+ amm.historicalOracleData.lastOraclePriceTwapTs
70
+ );
71
+ const sinceStart = BN.max(ZERO, new BN(60 * 5).sub(sinceLastUpdate));
72
+ const oracleTwap5min = amm.historicalOracleData.lastOraclePriceTwap5Min
73
+ .mul(sinceStart)
74
+ .add(oraclePriceData.price)
75
+ .mul(sinceLastUpdate)
76
+ .div(sinceStart.add(sinceLastUpdate));
77
+
78
+ const oracleSpread = oracleTwap5min.sub(oraclePriceData.price);
79
+ const oracleSpreadPct = oracleSpread.mul(PRICE_PRECISION).div(oracleTwap5min);
80
+
81
+ const tooDivergent = oracleSpreadPct
82
+ .abs()
83
+ .gte(
84
+ BID_ASK_SPREAD_PRECISION.mul(
85
+ oracleGuardRails.priceDivergence.markOracleDivergenceNumerator
86
+ ).div(oracleGuardRails.priceDivergence.markOracleDivergenceDenominator)
87
+ );
88
+
89
+ return tooDivergent;
90
+ }