@drift-labs/sdk 0.1.36-master.7 → 0.2.0-master.10

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 (254) hide show
  1. package/lib/accounts/bulkAccountLoader.d.ts +6 -6
  2. package/lib/accounts/bulkAccountLoader.js +81 -95
  3. package/lib/accounts/bulkUserSubscription.js +13 -57
  4. package/lib/accounts/fetch.d.ts +4 -0
  5. package/lib/accounts/fetch.js +18 -0
  6. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +34 -38
  7. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +224 -224
  8. package/lib/accounts/pollingOracleSubscriber.d.ts +3 -3
  9. package/lib/accounts/pollingOracleSubscriber.js +37 -49
  10. package/lib/accounts/pollingTokenAccountSubscriber.d.ts +3 -3
  11. package/lib/accounts/pollingTokenAccountSubscriber.js +35 -50
  12. package/lib/accounts/pollingUserAccountSubscriber.d.ts +7 -13
  13. package/lib/accounts/pollingUserAccountSubscriber.js +71 -134
  14. package/lib/accounts/types.d.ts +34 -41
  15. package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -4
  16. package/lib/accounts/webSocketAccountSubscriber.js +39 -35
  17. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +33 -28
  18. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +153 -185
  19. package/lib/accounts/webSocketUserAccountSubscriber.d.ts +5 -11
  20. package/lib/accounts/webSocketUserAccountSubscriber.js +22 -67
  21. package/lib/addresses/marketAddresses.d.ts +4 -0
  22. package/lib/addresses/marketAddresses.js +15 -0
  23. package/lib/addresses/pda.d.ts +12 -0
  24. package/lib/addresses/pda.js +83 -0
  25. package/lib/admin.d.ts +12 -18
  26. package/lib/admin.js +398 -558
  27. package/lib/clearingHouse.d.ts +83 -109
  28. package/lib/clearingHouse.js +832 -893
  29. package/lib/clearingHouseConfig.d.ts +34 -0
  30. package/lib/clearingHouseConfig.js +2 -0
  31. package/lib/clearingHouseUser.d.ts +19 -22
  32. package/lib/clearingHouseUser.js +155 -141
  33. package/lib/clearingHouseUserConfig.d.ts +14 -0
  34. package/lib/clearingHouseUserConfig.js +2 -0
  35. package/lib/config.d.ts +12 -0
  36. package/lib/config.js +35 -4
  37. package/lib/constants/banks.d.ts +16 -0
  38. package/lib/constants/banks.js +41 -0
  39. package/lib/constants/markets.d.ts +8 -3
  40. package/lib/constants/markets.js +13 -206
  41. package/lib/constants/numericConstants.d.ts +17 -0
  42. package/lib/constants/numericConstants.js +23 -6
  43. package/lib/events/eventList.d.ts +22 -0
  44. package/lib/events/eventList.js +77 -0
  45. package/lib/events/eventSubscriber.d.ts +34 -0
  46. package/lib/events/eventSubscriber.js +126 -0
  47. package/lib/events/fetchLogs.d.ts +13 -0
  48. package/lib/events/fetchLogs.js +39 -0
  49. package/lib/events/pollingLogProvider.d.ts +15 -0
  50. package/lib/events/pollingLogProvider.js +53 -0
  51. package/lib/events/sort.d.ts +2 -0
  52. package/lib/events/sort.js +44 -0
  53. package/lib/events/txEventCache.d.ts +24 -0
  54. package/lib/events/txEventCache.js +71 -0
  55. package/lib/events/types.d.ts +49 -0
  56. package/lib/events/types.js +20 -0
  57. package/lib/events/webSocketLogProvider.d.ts +12 -0
  58. package/lib/events/webSocketLogProvider.js +30 -0
  59. package/lib/examples/makeTradeExample.js +26 -27
  60. package/lib/factory/bigNum.d.ts +118 -0
  61. package/lib/factory/bigNum.js +364 -0
  62. package/lib/factory/oracleClient.d.ts +1 -2
  63. package/lib/factory/oracleClient.js +6 -2
  64. package/lib/idl/clearing_house.json +2258 -2774
  65. package/lib/index.d.ts +14 -5
  66. package/lib/index.js +18 -5
  67. package/lib/math/amm.d.ts +24 -29
  68. package/lib/math/amm.js +209 -176
  69. package/lib/math/auction.d.ts +5 -0
  70. package/lib/math/auction.js +42 -0
  71. package/lib/math/bankBalance.d.ts +9 -0
  72. package/lib/math/bankBalance.js +75 -0
  73. package/lib/math/conversion.d.ts +0 -1
  74. package/lib/math/conversion.js +1 -5
  75. package/lib/math/funding.d.ts +6 -6
  76. package/lib/math/funding.js +158 -175
  77. package/lib/math/market.d.ts +6 -6
  78. package/lib/math/market.js +10 -9
  79. package/lib/math/orders.d.ts +6 -1
  80. package/lib/math/orders.js +38 -1
  81. package/lib/math/position.d.ts +7 -5
  82. package/lib/math/position.js +29 -27
  83. package/lib/math/repeg.d.ts +22 -0
  84. package/lib/math/repeg.js +128 -0
  85. package/lib/math/trade.d.ts +5 -4
  86. package/lib/math/trade.js +29 -24
  87. package/lib/mockUSDCFaucet.js +87 -116
  88. package/lib/oracles/oracleClientCache.d.ts +8 -0
  89. package/lib/oracles/oracleClientCache.js +19 -0
  90. package/lib/oracles/pythClient.d.ts +3 -5
  91. package/lib/oracles/pythClient.js +12 -31
  92. package/lib/oracles/quoteAssetOracleClient.d.ts +9 -0
  93. package/lib/oracles/quoteAssetOracleClient.js +21 -0
  94. package/lib/oracles/switchboardClient.d.ts +3 -5
  95. package/lib/oracles/switchboardClient.js +29 -50
  96. package/lib/oracles/types.d.ts +6 -1
  97. package/lib/orderParams.d.ts +14 -5
  98. package/lib/orderParams.js +8 -96
  99. package/lib/orders.d.ts +6 -7
  100. package/lib/orders.js +11 -89
  101. package/lib/slot/SlotSubscriber.d.ts +19 -0
  102. package/lib/slot/SlotSubscriber.js +26 -0
  103. package/lib/tx/retryTxSender.d.ts +2 -2
  104. package/lib/tx/retryTxSender.js +108 -123
  105. package/lib/tx/types.d.ts +5 -1
  106. package/lib/tx/utils.d.ts +1 -1
  107. package/lib/tx/utils.js +11 -2
  108. package/lib/types.d.ts +180 -110
  109. package/lib/types.js +54 -1
  110. package/lib/userName.d.ts +4 -0
  111. package/lib/userName.js +20 -0
  112. package/lib/util/computeUnits.js +10 -21
  113. package/lib/util/tps.js +11 -22
  114. package/lib/wallet.js +7 -20
  115. package/package.json +11 -4
  116. package/src/accounts/bulkAccountLoader.js +197 -0
  117. package/src/accounts/bulkAccountLoader.ts +21 -15
  118. package/src/accounts/bulkUserSubscription.js +33 -0
  119. package/src/accounts/bulkUserSubscription.ts +1 -45
  120. package/src/accounts/fetch.js +29 -0
  121. package/src/accounts/fetch.ts +33 -0
  122. package/src/accounts/pollingClearingHouseAccountSubscriber.js +311 -0
  123. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +249 -214
  124. package/src/accounts/pollingOracleSubscriber.js +93 -0
  125. package/src/accounts/pollingOracleSubscriber.ts +16 -8
  126. package/src/accounts/pollingTokenAccountSubscriber.js +90 -0
  127. package/src/accounts/pollingTokenAccountSubscriber.ts +11 -8
  128. package/src/accounts/pollingUserAccountSubscriber.js +132 -0
  129. package/src/accounts/pollingUserAccountSubscriber.ts +21 -86
  130. package/src/accounts/types.js +10 -0
  131. package/src/accounts/types.ts +41 -70
  132. package/src/accounts/utils.js +7 -0
  133. package/src/accounts/webSocketAccountSubscriber.js +93 -0
  134. package/src/accounts/webSocketAccountSubscriber.ts +33 -16
  135. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +233 -0
  136. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +190 -240
  137. package/src/accounts/webSocketUserAccountSubscriber.js +62 -0
  138. package/src/accounts/webSocketUserAccountSubscriber.ts +11 -71
  139. package/src/addresses/marketAddresses.js +26 -0
  140. package/src/addresses/marketAddresses.ts +18 -0
  141. package/{lib/addresses.js → src/addresses/pda.js} +45 -34
  142. package/src/addresses/pda.ts +118 -0
  143. package/src/admin.ts +247 -336
  144. package/src/assert/assert.js +9 -0
  145. package/src/clearingHouse.ts +1023 -1026
  146. package/src/clearingHouseConfig.ts +37 -0
  147. package/src/clearingHouseUser.ts +275 -185
  148. package/src/clearingHouseUserConfig.ts +18 -0
  149. package/src/config.ts +54 -1
  150. package/src/constants/banks.ts +50 -0
  151. package/src/constants/markets.ts +16 -207
  152. package/src/constants/numericConstants.ts +34 -5
  153. package/src/events/eventList.js +77 -0
  154. package/src/events/eventList.ts +94 -0
  155. package/src/events/eventSubscriber.js +139 -0
  156. package/src/events/eventSubscriber.ts +194 -0
  157. package/src/events/fetchLogs.js +50 -0
  158. package/src/events/fetchLogs.ts +80 -0
  159. package/src/events/pollingLogProvider.js +64 -0
  160. package/src/events/pollingLogProvider.ts +79 -0
  161. package/src/events/sort.js +44 -0
  162. package/src/events/sort.ts +65 -0
  163. package/src/events/txEventCache.js +71 -0
  164. package/src/events/txEventCache.ts +74 -0
  165. package/src/events/types.js +20 -0
  166. package/src/events/types.ts +98 -0
  167. package/src/events/webSocketLogProvider.js +41 -0
  168. package/src/events/webSocketLogProvider.ts +38 -0
  169. package/src/examples/makeTradeExample.js +80 -0
  170. package/src/examples/makeTradeExample.ts +20 -11
  171. package/src/factory/bigNum.js +364 -0
  172. package/src/factory/bigNum.ts +524 -0
  173. package/src/factory/oracleClient.js +20 -0
  174. package/src/factory/oracleClient.ts +7 -4
  175. package/src/idl/clearing_house.json +2258 -2774
  176. package/src/index.js +69 -0
  177. package/src/index.ts +14 -5
  178. package/src/math/amm.js +369 -0
  179. package/src/math/amm.ts +382 -243
  180. package/src/math/auction.js +42 -0
  181. package/src/math/auction.ts +43 -0
  182. package/src/math/bankBalance.js +75 -0
  183. package/src/math/bankBalance.ts +112 -0
  184. package/src/math/conversion.js +11 -0
  185. package/src/math/conversion.ts +1 -11
  186. package/src/math/funding.js +248 -0
  187. package/src/math/funding.ts +12 -9
  188. package/src/math/market.js +57 -0
  189. package/src/math/market.ts +37 -30
  190. package/src/math/oracles.js +26 -0
  191. package/src/math/orders.js +110 -0
  192. package/src/math/orders.ts +43 -1
  193. package/src/math/position.js +140 -0
  194. package/src/math/position.ts +52 -35
  195. package/src/math/repeg.js +128 -0
  196. package/src/math/repeg.ts +176 -0
  197. package/src/math/state.js +15 -0
  198. package/src/math/trade.js +253 -0
  199. package/src/math/trade.ts +55 -47
  200. package/src/math/utils.js +26 -0
  201. package/src/math/utils.js.map +1 -0
  202. package/src/mockUSDCFaucet.js +171 -0
  203. package/src/oracles/oracleClientCache.js +19 -0
  204. package/src/oracles/oracleClientCache.ts +20 -0
  205. package/src/oracles/pythClient.js +46 -0
  206. package/src/oracles/pythClient.ts +4 -11
  207. package/src/oracles/quoteAssetOracleClient.js +32 -0
  208. package/src/oracles/quoteAssetOracleClient.ts +25 -0
  209. package/src/oracles/switchboardClient.js +69 -0
  210. package/src/oracles/switchboardClient.ts +11 -24
  211. package/src/oracles/types.js +2 -0
  212. package/src/oracles/types.ts +7 -1
  213. package/src/orderParams.js +20 -0
  214. package/src/orderParams.ts +20 -141
  215. package/src/orders.js +134 -0
  216. package/src/orders.ts +25 -134
  217. package/src/slot/SlotSubscriber.js +39 -0
  218. package/src/slot/SlotSubscriber.ts +42 -0
  219. package/src/token/index.js +38 -0
  220. package/src/tx/retryTxSender.js +188 -0
  221. package/src/tx/retryTxSender.ts +6 -4
  222. package/src/tx/types.js +2 -0
  223. package/src/tx/types.ts +6 -1
  224. package/src/tx/utils.js +17 -0
  225. package/src/tx/utils.ts +22 -3
  226. package/src/types.js +114 -0
  227. package/src/types.ts +176 -124
  228. package/src/userName.js +20 -0
  229. package/src/userName.ts +20 -0
  230. package/src/util/promiseTimeout.js +14 -0
  231. package/src/util/tps.js +27 -0
  232. package/src/wallet.js +35 -0
  233. package/tests/bn/test.ts +255 -0
  234. package/tsconfig.json +12 -12
  235. package/lib/addresses.d.ts +0 -10
  236. package/lib/constants/accounts.d.ts +0 -15
  237. package/lib/constants/accounts.js +0 -18
  238. package/lib/factory/clearingHouse.d.ts +0 -35
  239. package/lib/factory/clearingHouse.js +0 -81
  240. package/lib/factory/clearingHouseUser.d.ts +0 -19
  241. package/lib/factory/clearingHouseUser.js +0 -34
  242. package/lib/math/insuranceFund.d.ts +0 -15
  243. package/lib/math/insuranceFund.js +0 -33
  244. package/lib/settlement.d.ts +0 -4
  245. package/lib/settlement.js +0 -10
  246. package/lib/tx/defaultTxSender.d.ts +0 -8
  247. package/lib/tx/defaultTxSender.js +0 -12
  248. package/src/addresses.ts +0 -82
  249. package/src/constants/accounts.ts +0 -26
  250. package/src/factory/clearingHouse.ts +0 -173
  251. package/src/factory/clearingHouseUser.ts +0 -73
  252. package/src/math/insuranceFund.ts +0 -29
  253. package/src/settlement.ts +0 -9
  254. package/src/tx/defaultTxSender.ts +0 -24
@@ -1,10 +1,11 @@
1
1
  import { BN } from '@project-serum/anchor';
2
- import { Market, PositionDirection } from '../types';
2
+ import { MarketAccount, PositionDirection } from '../types';
3
3
  import {
4
4
  calculateAmmReservesAfterSwap,
5
5
  calculatePrice,
6
- calculateSpreadReserves,
6
+ calculateUpdatedAMMSpreadReserves,
7
7
  getSwapDirection,
8
+ calculateUpdatedAMM,
8
9
  } from './amm';
9
10
  import { OraclePriceData } from '../oracles/types';
10
11
 
@@ -14,11 +15,15 @@ import { OraclePriceData } from '../oracles/types';
14
15
  * @param market
15
16
  * @return markPrice : Precision MARK_PRICE_PRECISION
16
17
  */
17
- export function calculateMarkPrice(market: Market): BN {
18
+ export function calculateMarkPrice(
19
+ market: MarketAccount,
20
+ oraclePriceData: OraclePriceData
21
+ ): BN {
22
+ const newAmm = calculateUpdatedAMM(market.amm, oraclePriceData);
18
23
  return calculatePrice(
19
- market.amm.baseAssetReserve,
20
- market.amm.quoteAssetReserve,
21
- market.amm.pegMultiplier
24
+ newAmm.baseAssetReserve,
25
+ newAmm.quoteAssetReserve,
26
+ newAmm.pegMultiplier
22
27
  );
23
28
  }
24
29
 
@@ -28,17 +33,18 @@ export function calculateMarkPrice(market: Market): BN {
28
33
  * @param market
29
34
  * @return bidPrice : Precision MARK_PRICE_PRECISION
30
35
  */
31
- export function calculateBidPrice(market: Market): BN {
32
- const { baseAssetReserve, quoteAssetReserve } = calculateSpreadReserves(
33
- market.amm,
34
- PositionDirection.SHORT
35
- );
36
+ export function calculateBidPrice(
37
+ market: MarketAccount,
38
+ oraclePriceData: OraclePriceData
39
+ ): BN {
40
+ const { baseAssetReserve, quoteAssetReserve, newPeg } =
41
+ calculateUpdatedAMMSpreadReserves(
42
+ market.amm,
43
+ PositionDirection.SHORT,
44
+ oraclePriceData
45
+ );
36
46
 
37
- return calculatePrice(
38
- baseAssetReserve,
39
- quoteAssetReserve,
40
- market.amm.pegMultiplier
41
- );
47
+ return calculatePrice(baseAssetReserve, quoteAssetReserve, newPeg);
42
48
  }
43
49
 
44
50
  /**
@@ -47,24 +53,25 @@ export function calculateBidPrice(market: Market): BN {
47
53
  * @param market
48
54
  * @return bidPrice : Precision MARK_PRICE_PRECISION
49
55
  */
50
- export function calculateAskPrice(market: Market): BN {
51
- const { baseAssetReserve, quoteAssetReserve } = calculateSpreadReserves(
52
- market.amm,
53
- PositionDirection.LONG
54
- );
56
+ export function calculateAskPrice(
57
+ market: MarketAccount,
58
+ oraclePriceData: OraclePriceData
59
+ ): BN {
60
+ const { baseAssetReserve, quoteAssetReserve, newPeg } =
61
+ calculateUpdatedAMMSpreadReserves(
62
+ market.amm,
63
+ PositionDirection.LONG,
64
+ oraclePriceData
65
+ );
55
66
 
56
- return calculatePrice(
57
- baseAssetReserve,
58
- quoteAssetReserve,
59
- market.amm.pegMultiplier
60
- );
67
+ return calculatePrice(baseAssetReserve, quoteAssetReserve, newPeg);
61
68
  }
62
69
 
63
70
  export function calculateNewMarketAfterTrade(
64
71
  baseAssetAmount: BN,
65
72
  direction: PositionDirection,
66
- market: Market
67
- ): Market {
73
+ market: MarketAccount
74
+ ): MarketAccount {
68
75
  const [newQuoteAssetReserve, newBaseAssetReserve] =
69
76
  calculateAmmReservesAfterSwap(
70
77
  market.amm,
@@ -83,10 +90,10 @@ export function calculateNewMarketAfterTrade(
83
90
  }
84
91
 
85
92
  export function calculateMarkOracleSpread(
86
- market: Market,
93
+ market: MarketAccount,
87
94
  oraclePriceData: OraclePriceData
88
95
  ): BN {
89
- const markPrice = calculateMarkPrice(market);
96
+ const markPrice = calculateMarkPrice(market, oraclePriceData);
90
97
  return calculateOracleSpread(markPrice, oraclePriceData);
91
98
  }
92
99
 
@@ -0,0 +1,26 @@
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");
6
+ function isOracleValid(amm, oraclePriceData, oracleGuardRails, slot) {
7
+ const isOraclePriceNonPositive = oraclePriceData.price.lt(numericConstants_1.ZERO);
8
+ const isOraclePriceTooVolatile = oraclePriceData.price
9
+ .div(index_1.BN.max(numericConstants_1.ONE, amm.lastOraclePriceTwap))
10
+ .gt(oracleGuardRails.validity.tooVolatileRatio) ||
11
+ amm.lastOraclePriceTwap
12
+ .div(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.price))
13
+ .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
18
+ .sub(new index_1.BN(slot))
19
+ .gt(oracleGuardRails.validity.slotsBeforeStale);
20
+ return !(!oraclePriceData.hasSufficientNumberOfDataPoints ||
21
+ oracleIsStale ||
22
+ isOraclePriceNonPositive ||
23
+ isOraclePriceTooVolatile ||
24
+ isConfidenceTooLarge);
25
+ }
26
+ exports.isOracleValid = isOracleValid;
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
4
+ const types_1 = require("../types");
5
+ const numericConstants_1 = require("../constants/numericConstants");
6
+ const anchor_1 = require("@project-serum/anchor");
7
+ const auction_1 = require("./auction");
8
+ const market_1 = require("./market");
9
+ function isOrderRiskIncreasing(user, order) {
10
+ if (types_1.isVariant(order.status, 'init')) {
11
+ return false;
12
+ }
13
+ const position = user.getUserPosition(order.marketIndex) ||
14
+ user.getEmptyPosition(order.marketIndex);
15
+ // if no position exists, it's risk increasing
16
+ if (position.baseAssetAmount.eq(numericConstants_1.ZERO)) {
17
+ return true;
18
+ }
19
+ // if position is long and order is long
20
+ if (position.baseAssetAmount.gt(numericConstants_1.ZERO) && types_1.isVariant(order.direction, 'long')) {
21
+ return true;
22
+ }
23
+ // if position is short and order is short
24
+ if (position.baseAssetAmount.lt(numericConstants_1.ZERO) &&
25
+ types_1.isVariant(order.direction, 'short')) {
26
+ return true;
27
+ }
28
+ const baseAssetAmountToFill = order.baseAssetAmount.sub(order.baseAssetAmountFilled);
29
+ // if order will flip position
30
+ if (baseAssetAmountToFill.gt(position.baseAssetAmount.abs().mul(numericConstants_1.TWO))) {
31
+ return true;
32
+ }
33
+ return false;
34
+ }
35
+ exports.isOrderRiskIncreasing = isOrderRiskIncreasing;
36
+ function isOrderRiskIncreasingInSameDirection(user, order) {
37
+ if (types_1.isVariant(order.status, 'init')) {
38
+ return false;
39
+ }
40
+ const position = user.getUserPosition(order.marketIndex) ||
41
+ user.getEmptyPosition(order.marketIndex);
42
+ // if no position exists, it's risk increasing
43
+ if (position.baseAssetAmount.eq(numericConstants_1.ZERO)) {
44
+ return true;
45
+ }
46
+ // if position is long and order is long
47
+ if (position.baseAssetAmount.gt(numericConstants_1.ZERO) && types_1.isVariant(order.direction, 'long')) {
48
+ return true;
49
+ }
50
+ // if position is short and order is short
51
+ if (position.baseAssetAmount.lt(numericConstants_1.ZERO) &&
52
+ types_1.isVariant(order.direction, 'short')) {
53
+ return true;
54
+ }
55
+ return false;
56
+ }
57
+ exports.isOrderRiskIncreasingInSameDirection = isOrderRiskIncreasingInSameDirection;
58
+ function isOrderReduceOnly(user, order) {
59
+ if (types_1.isVariant(order.status, 'init')) {
60
+ return false;
61
+ }
62
+ const position = user.getUserPosition(order.marketIndex) ||
63
+ user.getEmptyPosition(order.marketIndex);
64
+ // if position is long and order is long
65
+ if (position.baseAssetAmount.gte(numericConstants_1.ZERO) &&
66
+ types_1.isVariant(order.direction, 'long')) {
67
+ return false;
68
+ }
69
+ // if position is short and order is short
70
+ if (position.baseAssetAmount.lte(numericConstants_1.ZERO) &&
71
+ types_1.isVariant(order.direction, 'short')) {
72
+ return false;
73
+ }
74
+ return true;
75
+ }
76
+ exports.isOrderReduceOnly = isOrderReduceOnly;
77
+ function standardizeBaseAssetAmount(baseAssetAmount, stepSize) {
78
+ const remainder = baseAssetAmount.mod(stepSize);
79
+ return baseAssetAmount.sub(remainder);
80
+ }
81
+ exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
82
+ function getLimitPrice(order, market, oraclePriceData, slot) {
83
+ let limitPrice;
84
+ if (!order.oraclePriceOffset.eq(numericConstants_1.ZERO)) {
85
+ limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
86
+ }
87
+ else if (types_1.isOneOfVariant(order.orderType, ['market', 'triggerMarket'])) {
88
+ if (auction_1.isAuctionComplete(order, slot)) {
89
+ limitPrice = auction_1.getAuctionPrice(order, slot);
90
+ }
91
+ else if (!order.price.eq(numericConstants_1.ZERO)) {
92
+ limitPrice = order.price;
93
+ }
94
+ else if (types_1.isVariant(order.direction, 'long')) {
95
+ const askPrice = market_1.calculateAskPrice(market, oraclePriceData);
96
+ const delta = askPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
97
+ limitPrice = askPrice.add(delta);
98
+ }
99
+ else {
100
+ const bidPrice = market_1.calculateBidPrice(market, oraclePriceData);
101
+ const delta = bidPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
102
+ limitPrice = bidPrice.sub(delta);
103
+ }
104
+ }
105
+ else {
106
+ limitPrice = order.price;
107
+ }
108
+ return limitPrice;
109
+ }
110
+ exports.getLimitPrice = getLimitPrice;
@@ -1,6 +1,10 @@
1
1
  import { ClearingHouseUser } from '../clearingHouseUser';
2
- import { isVariant, Order } from '../types';
2
+ import { isOneOfVariant, isVariant, MarketAccount, Order } from '../types';
3
3
  import { ZERO, TWO } from '../constants/numericConstants';
4
+ import { BN } from '@project-serum/anchor';
5
+ import { OraclePriceData } from '../oracles/types';
6
+ import { getAuctionPrice, isAuctionComplete } from './auction';
7
+ import { calculateAskPrice, calculateBidPrice } from './market';
4
8
 
5
9
  export function isOrderRiskIncreasing(
6
10
  user: ClearingHouseUser,
@@ -106,3 +110,41 @@ export function isOrderReduceOnly(
106
110
 
107
111
  return true;
108
112
  }
113
+
114
+ export function standardizeBaseAssetAmount(
115
+ baseAssetAmount: BN,
116
+ stepSize: BN
117
+ ): BN {
118
+ const remainder = baseAssetAmount.mod(stepSize);
119
+ return baseAssetAmount.sub(remainder);
120
+ }
121
+
122
+ export function getLimitPrice(
123
+ order: Order,
124
+ market: MarketAccount,
125
+ oraclePriceData: OraclePriceData,
126
+ slot: number
127
+ ): BN {
128
+ let limitPrice;
129
+ if (!order.oraclePriceOffset.eq(ZERO)) {
130
+ limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
131
+ } else if (isOneOfVariant(order.orderType, ['market', 'triggerMarket'])) {
132
+ if (isAuctionComplete(order, slot)) {
133
+ limitPrice = getAuctionPrice(order, slot);
134
+ } else if (!order.price.eq(ZERO)) {
135
+ limitPrice = order.price;
136
+ } else if (isVariant(order.direction, 'long')) {
137
+ const askPrice = calculateAskPrice(market, oraclePriceData);
138
+ const delta = askPrice.div(new BN(market.amm.maxSlippageRatio));
139
+ limitPrice = askPrice.add(delta);
140
+ } else {
141
+ const bidPrice = calculateBidPrice(market, oraclePriceData);
142
+ const delta = bidPrice.div(new BN(market.amm.maxSlippageRatio));
143
+ limitPrice = bidPrice.sub(delta);
144
+ }
145
+ } else {
146
+ limitPrice = order.price;
147
+ }
148
+
149
+ return limitPrice;
150
+ }
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
4
+ const __1 = require("../");
5
+ const numericConstants_1 = require("../constants/numericConstants");
6
+ const types_1 = require("../types");
7
+ const amm_1 = require("./amm");
8
+ /**
9
+ * calculateBaseAssetValue
10
+ * = market value of closing entire position
11
+ * @param market
12
+ * @param userPosition
13
+ * @param oraclePriceData
14
+ * @returns Base Asset Value. : Precision QUOTE_PRECISION
15
+ */
16
+ function calculateBaseAssetValue(market, userPosition, oraclePriceData) {
17
+ if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
18
+ return numericConstants_1.ZERO;
19
+ }
20
+ const directionToClose = findDirectionToClose(userPosition);
21
+ let prepegAmm;
22
+ if (market.amm.baseSpread > 0) {
23
+ const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = amm_1.calculateUpdatedAMMSpreadReserves(market.amm, directionToClose, oraclePriceData);
24
+ prepegAmm = {
25
+ baseAssetReserve,
26
+ quoteAssetReserve,
27
+ sqrtK: sqrtK,
28
+ pegMultiplier: newPeg,
29
+ };
30
+ }
31
+ else {
32
+ prepegAmm = amm_1.calculateUpdatedAMM(market.amm, oraclePriceData);
33
+ }
34
+ const [newQuoteAssetReserve, _] = amm_1.calculateAmmReservesAfterSwap(prepegAmm, 'base', userPosition.baseAssetAmount.abs(), amm_1.getSwapDirection('base', directionToClose));
35
+ switch (directionToClose) {
36
+ case types_1.PositionDirection.SHORT:
37
+ return prepegAmm.quoteAssetReserve
38
+ .sub(newQuoteAssetReserve)
39
+ .mul(prepegAmm.pegMultiplier)
40
+ .div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
41
+ case types_1.PositionDirection.LONG:
42
+ return newQuoteAssetReserve
43
+ .sub(prepegAmm.quoteAssetReserve)
44
+ .mul(prepegAmm.pegMultiplier)
45
+ .div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
46
+ .add(numericConstants_1.ONE);
47
+ }
48
+ }
49
+ exports.calculateBaseAssetValue = calculateBaseAssetValue;
50
+ /**
51
+ * calculatePositionPNL
52
+ * = BaseAssetAmount * (Avg Exit Price - Avg Entry Price)
53
+ * @param market
54
+ * @param marketPosition
55
+ * @param withFunding (adds unrealized funding payment pnl to result)
56
+ * @returns BaseAssetAmount : Precision QUOTE_PRECISION
57
+ */
58
+ function calculatePositionPNL(market, marketPosition, withFunding = false, oraclePriceData) {
59
+ if (marketPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
60
+ return numericConstants_1.ZERO;
61
+ }
62
+ const baseAssetValue = calculateBaseAssetValue(market, marketPosition, oraclePriceData);
63
+ let pnl;
64
+ if (marketPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
65
+ pnl = baseAssetValue.sub(marketPosition.quoteAssetAmount);
66
+ }
67
+ else {
68
+ pnl = marketPosition.quoteAssetAmount.sub(baseAssetValue);
69
+ }
70
+ if (withFunding) {
71
+ const fundingRatePnL = calculatePositionFundingPNL(market, marketPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
72
+ pnl = pnl.add(fundingRatePnL);
73
+ }
74
+ return pnl;
75
+ }
76
+ exports.calculatePositionPNL = calculatePositionPNL;
77
+ /**
78
+ *
79
+ * @param market
80
+ * @param marketPosition
81
+ * @returns // TODO-PRECISION
82
+ */
83
+ function calculatePositionFundingPNL(market, marketPosition) {
84
+ if (marketPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
85
+ return numericConstants_1.ZERO;
86
+ }
87
+ let ammCumulativeFundingRate;
88
+ if (marketPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
89
+ ammCumulativeFundingRate = market.amm.cumulativeFundingRateLong;
90
+ }
91
+ else {
92
+ ammCumulativeFundingRate = market.amm.cumulativeFundingRateShort;
93
+ }
94
+ const perPositionFundingRate = ammCumulativeFundingRate
95
+ .sub(marketPosition.lastCumulativeFundingRate)
96
+ .mul(marketPosition.baseAssetAmount)
97
+ .div(numericConstants_1.AMM_RESERVE_PRECISION)
98
+ .div(numericConstants_1.FUNDING_PAYMENT_PRECISION)
99
+ .mul(new __1.BN(-1));
100
+ return perPositionFundingRate;
101
+ }
102
+ exports.calculatePositionFundingPNL = calculatePositionFundingPNL;
103
+ function positionIsAvailable(position) {
104
+ return (position.baseAssetAmount.eq(numericConstants_1.ZERO) &&
105
+ position.openOrders.eq(numericConstants_1.ZERO) &&
106
+ position.unsettledPnl.eq(numericConstants_1.ZERO));
107
+ }
108
+ exports.positionIsAvailable = positionIsAvailable;
109
+ /**
110
+ *
111
+ * @param userPosition
112
+ * @returns Precision: MARK_PRICE_PRECISION (10^10)
113
+ */
114
+ function calculateEntryPrice(userPosition) {
115
+ if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
116
+ return numericConstants_1.ZERO;
117
+ }
118
+ return userPosition.quoteAssetAmount
119
+ .mul(numericConstants_1.MARK_PRICE_PRECISION)
120
+ .mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
121
+ .div(userPosition.baseAssetAmount)
122
+ .abs();
123
+ }
124
+ exports.calculateEntryPrice = calculateEntryPrice;
125
+ function findDirectionToClose(userPosition) {
126
+ return userPosition.baseAssetAmount.gt(numericConstants_1.ZERO)
127
+ ? types_1.PositionDirection.SHORT
128
+ : types_1.PositionDirection.LONG;
129
+ }
130
+ exports.findDirectionToClose = findDirectionToClose;
131
+ function positionCurrentDirection(userPosition) {
132
+ return userPosition.baseAssetAmount.gte(numericConstants_1.ZERO)
133
+ ? types_1.PositionDirection.LONG
134
+ : types_1.PositionDirection.SHORT;
135
+ }
136
+ exports.positionCurrentDirection = positionCurrentDirection;
137
+ function isEmptyPosition(userPosition) {
138
+ return (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO) && userPosition.openOrders.eq(numericConstants_1.ZERO));
139
+ }
140
+ exports.isEmptyPosition = isEmptyPosition;
@@ -9,29 +9,54 @@ import {
9
9
  PRICE_TO_QUOTE_PRECISION,
10
10
  ZERO,
11
11
  } from '../constants/numericConstants';
12
- import { Market, PositionDirection, UserPosition } from '../types';
13
- import { calculateAmmReservesAfterSwap, getSwapDirection } from './amm';
14
- import { SETTLEMENT_RATIO_PRECISION, SETTLEMENT_RATIOS } from '../settlement';
12
+ import { OraclePriceData } from '../oracles/types';
13
+ import { MarketAccount, PositionDirection, UserPosition } from '../types';
14
+ import {
15
+ calculateUpdatedAMM,
16
+ calculateUpdatedAMMSpreadReserves,
17
+ calculateAmmReservesAfterSwap,
18
+ getSwapDirection,
19
+ } from './amm';
15
20
 
16
21
  /**
17
22
  * calculateBaseAssetValue
18
23
  * = market value of closing entire position
19
24
  * @param market
20
25
  * @param userPosition
26
+ * @param oraclePriceData
21
27
  * @returns Base Asset Value. : Precision QUOTE_PRECISION
22
28
  */
23
29
  export function calculateBaseAssetValue(
24
- market: Market,
25
- userPosition: UserPosition
30
+ market: MarketAccount,
31
+ userPosition: UserPosition,
32
+ oraclePriceData: OraclePriceData
26
33
  ): BN {
27
34
  if (userPosition.baseAssetAmount.eq(ZERO)) {
28
35
  return ZERO;
29
36
  }
30
37
 
31
38
  const directionToClose = findDirectionToClose(userPosition);
39
+ let prepegAmm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
40
+
41
+ if (market.amm.baseSpread > 0) {
42
+ const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
43
+ calculateUpdatedAMMSpreadReserves(
44
+ market.amm,
45
+ directionToClose,
46
+ oraclePriceData
47
+ );
48
+ prepegAmm = {
49
+ baseAssetReserve,
50
+ quoteAssetReserve,
51
+ sqrtK: sqrtK,
52
+ pegMultiplier: newPeg,
53
+ };
54
+ } else {
55
+ prepegAmm = calculateUpdatedAMM(market.amm, oraclePriceData);
56
+ }
32
57
 
33
58
  const [newQuoteAssetReserve, _] = calculateAmmReservesAfterSwap(
34
- market.amm,
59
+ prepegAmm,
35
60
  'base',
36
61
  userPosition.baseAssetAmount.abs(),
37
62
  getSwapDirection('base', directionToClose)
@@ -39,15 +64,15 @@ export function calculateBaseAssetValue(
39
64
 
40
65
  switch (directionToClose) {
41
66
  case PositionDirection.SHORT:
42
- return market.amm.quoteAssetReserve
67
+ return prepegAmm.quoteAssetReserve
43
68
  .sub(newQuoteAssetReserve)
44
- .mul(market.amm.pegMultiplier)
69
+ .mul(prepegAmm.pegMultiplier)
45
70
  .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
46
71
 
47
72
  case PositionDirection.LONG:
48
73
  return newQuoteAssetReserve
49
- .sub(market.amm.quoteAssetReserve)
50
- .mul(market.amm.pegMultiplier)
74
+ .sub(prepegAmm.quoteAssetReserve)
75
+ .mul(prepegAmm.pegMultiplier)
51
76
  .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
52
77
  .add(ONE);
53
78
  }
@@ -62,15 +87,20 @@ export function calculateBaseAssetValue(
62
87
  * @returns BaseAssetAmount : Precision QUOTE_PRECISION
63
88
  */
64
89
  export function calculatePositionPNL(
65
- market: Market,
90
+ market: MarketAccount,
66
91
  marketPosition: UserPosition,
67
- withFunding = false
92
+ withFunding = false,
93
+ oraclePriceData: OraclePriceData
68
94
  ): BN {
69
95
  if (marketPosition.baseAssetAmount.eq(ZERO)) {
70
96
  return ZERO;
71
97
  }
72
98
 
73
- const baseAssetValue = calculateBaseAssetValue(market, marketPosition);
99
+ const baseAssetValue = calculateBaseAssetValue(
100
+ market,
101
+ marketPosition,
102
+ oraclePriceData
103
+ );
74
104
 
75
105
  let pnl;
76
106
  if (marketPosition.baseAssetAmount.gt(ZERO)) {
@@ -91,27 +121,6 @@ export function calculatePositionPNL(
91
121
  return pnl;
92
122
  }
93
123
 
94
- export function calculateSettledPositionPNL(
95
- market: Market,
96
- marketPosition: UserPosition
97
- ): BN {
98
- let pnl = calculatePositionPNL(market, marketPosition);
99
-
100
- if (pnl.gt(ZERO)) {
101
- try {
102
- pnl = pnl
103
- .mul(new BN(SETTLEMENT_RATIOS[marketPosition.marketIndex.toNumber()]))
104
- .div(SETTLEMENT_RATIO_PRECISION);
105
- } catch (e) {
106
- console.log(pnl.toString());
107
- console.log(marketPosition.marketIndex.toNumber());
108
- throw e;
109
- }
110
- }
111
-
112
- return pnl;
113
- }
114
-
115
124
  /**
116
125
  *
117
126
  * @param market
@@ -119,7 +128,7 @@ export function calculateSettledPositionPNL(
119
128
  * @returns // TODO-PRECISION
120
129
  */
121
130
  export function calculatePositionFundingPNL(
122
- market: Market,
131
+ market: MarketAccount,
123
132
  marketPosition: UserPosition
124
133
  ): BN {
125
134
  if (marketPosition.baseAssetAmount.eq(ZERO)) {
@@ -143,6 +152,14 @@ export function calculatePositionFundingPNL(
143
152
  return perPositionFundingRate;
144
153
  }
145
154
 
155
+ export function positionIsAvailable(position: UserPosition): boolean {
156
+ return (
157
+ position.baseAssetAmount.eq(ZERO) &&
158
+ position.openOrders.eq(ZERO) &&
159
+ position.unsettledPnl.eq(ZERO)
160
+ );
161
+ }
162
+
146
163
  /**
147
164
  *
148
165
  * @param userPosition