@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,21 +1,27 @@
1
- import { ClearingHouseUser } from '../clearingHouseUser';
2
- import { isOneOfVariant, isVariant, MarketAccount, Order } from '../types';
1
+ import { User } from '../user';
2
+ import {
3
+ isOneOfVariant,
4
+ isVariant,
5
+ PerpMarketAccount,
6
+ Order,
7
+ PositionDirection,
8
+ } from '../types';
3
9
  import { ZERO, TWO } from '../constants/numericConstants';
4
10
  import { BN } from '@project-serum/anchor';
5
11
  import { OraclePriceData } from '../oracles/types';
6
12
  import { getAuctionPrice, isAuctionComplete } from './auction';
7
- import { calculateAskPrice, calculateBidPrice } from './market';
13
+ import {
14
+ calculateMaxBaseAssetAmountFillable,
15
+ calculateMaxBaseAssetAmountToTrade,
16
+ } from './amm';
8
17
 
9
- export function isOrderRiskIncreasing(
10
- user: ClearingHouseUser,
11
- order: Order
12
- ): boolean {
18
+ export function isOrderRiskIncreasing(user: User, order: Order): boolean {
13
19
  if (isVariant(order.status, 'init')) {
14
20
  return false;
15
21
  }
16
22
 
17
23
  const position =
18
- user.getUserPosition(order.marketIndex) ||
24
+ user.getPerpPosition(order.marketIndex) ||
19
25
  user.getEmptyPosition(order.marketIndex);
20
26
 
21
27
  // if no position exists, it's risk increasing
@@ -48,7 +54,7 @@ export function isOrderRiskIncreasing(
48
54
  }
49
55
 
50
56
  export function isOrderRiskIncreasingInSameDirection(
51
- user: ClearingHouseUser,
57
+ user: User,
52
58
  order: Order
53
59
  ): boolean {
54
60
  if (isVariant(order.status, 'init')) {
@@ -56,7 +62,7 @@ export function isOrderRiskIncreasingInSameDirection(
56
62
  }
57
63
 
58
64
  const position =
59
- user.getUserPosition(order.marketIndex) ||
65
+ user.getPerpPosition(order.marketIndex) ||
60
66
  user.getEmptyPosition(order.marketIndex);
61
67
 
62
68
  // if no position exists, it's risk increasing
@@ -80,16 +86,13 @@ export function isOrderRiskIncreasingInSameDirection(
80
86
  return false;
81
87
  }
82
88
 
83
- export function isOrderReduceOnly(
84
- user: ClearingHouseUser,
85
- order: Order
86
- ): boolean {
89
+ export function isOrderReduceOnly(user: User, order: Order): boolean {
87
90
  if (isVariant(order.status, 'init')) {
88
91
  return false;
89
92
  }
90
93
 
91
94
  const position =
92
- user.getUserPosition(order.marketIndex) ||
95
+ user.getPerpPosition(order.marketIndex) ||
93
96
  user.getEmptyPosition(order.marketIndex);
94
97
 
95
98
  // if position is long and order is long
@@ -121,26 +124,25 @@ export function standardizeBaseAssetAmount(
121
124
 
122
125
  export function getLimitPrice(
123
126
  order: Order,
124
- market: MarketAccount,
125
127
  oraclePriceData: OraclePriceData,
126
128
  slot: number
127
129
  ): BN {
128
130
  let limitPrice;
129
- if (!order.oraclePriceOffset.eq(ZERO)) {
130
- limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
131
+ if (order.oraclePriceOffset !== 0) {
132
+ limitPrice = oraclePriceData.price.add(new BN(order.oraclePriceOffset));
131
133
  } else if (isOneOfVariant(order.orderType, ['market', 'triggerMarket'])) {
132
- if (isAuctionComplete(order, slot)) {
134
+ if (!isAuctionComplete(order, slot)) {
133
135
  limitPrice = getAuctionPrice(order, slot);
134
136
  } else if (!order.price.eq(ZERO)) {
135
137
  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
138
  } else {
141
- const bidPrice = calculateBidPrice(market, oraclePriceData);
142
- const delta = bidPrice.div(new BN(market.amm.maxSlippageRatio));
143
- limitPrice = bidPrice.sub(delta);
139
+ // check oracle validity?
140
+ const oraclePrice1Pct = oraclePriceData.price.div(new BN(100));
141
+ if (isVariant(order.direction, 'long')) {
142
+ limitPrice = oraclePriceData.price.add(oraclePrice1Pct);
143
+ } else {
144
+ limitPrice = oraclePriceData.price.sub(oraclePrice1Pct);
145
+ }
144
146
  }
145
147
  } else {
146
148
  limitPrice = order.price;
@@ -148,3 +150,143 @@ export function getLimitPrice(
148
150
 
149
151
  return limitPrice;
150
152
  }
153
+
154
+ export function getOptionalLimitPrice(
155
+ order: Order,
156
+ oraclePriceData: OraclePriceData,
157
+ slot: number
158
+ ): BN | undefined {
159
+ if (hasLimitPrice(order, slot)) {
160
+ return getLimitPrice(order, oraclePriceData, slot);
161
+ } else {
162
+ return undefined;
163
+ }
164
+ }
165
+
166
+ export function hasLimitPrice(order: Order, slot: number): boolean {
167
+ return (
168
+ order.price.gt(ZERO) ||
169
+ order.oraclePriceOffset != 0 ||
170
+ !isAuctionComplete(order, slot)
171
+ );
172
+ }
173
+
174
+ export function isFillableByVAMM(
175
+ order: Order,
176
+ market: PerpMarketAccount,
177
+ oraclePriceData: OraclePriceData,
178
+ slot: number,
179
+ ts: number
180
+ ): boolean {
181
+ return (
182
+ (isAuctionComplete(order, slot) &&
183
+ !calculateBaseAssetAmountForAmmToFulfill(
184
+ order,
185
+ market,
186
+ oraclePriceData,
187
+ slot
188
+ ).eq(ZERO)) ||
189
+ isOrderExpired(order, ts)
190
+ );
191
+ }
192
+
193
+ export function calculateBaseAssetAmountForAmmToFulfill(
194
+ order: Order,
195
+ market: PerpMarketAccount,
196
+ oraclePriceData: OraclePriceData,
197
+ slot: number
198
+ ): BN {
199
+ if (mustBeTriggered(order) && !isTriggered(order)) {
200
+ return ZERO;
201
+ }
202
+
203
+ const limitPrice = getOptionalLimitPrice(order, oraclePriceData, slot);
204
+ let baseAssetAmount;
205
+ if (limitPrice !== undefined) {
206
+ baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(
207
+ order,
208
+ market,
209
+ limitPrice,
210
+ oraclePriceData
211
+ );
212
+ } else {
213
+ baseAssetAmount = order.baseAssetAmount.sub(order.baseAssetAmountFilled);
214
+ }
215
+
216
+ const maxBaseAssetAmount = calculateMaxBaseAssetAmountFillable(
217
+ market.amm,
218
+ order.direction
219
+ );
220
+
221
+ return BN.min(maxBaseAssetAmount, baseAssetAmount);
222
+ }
223
+
224
+ export function calculateBaseAssetAmountToFillUpToLimitPrice(
225
+ order: Order,
226
+ market: PerpMarketAccount,
227
+ limitPrice: BN,
228
+ oraclePriceData: OraclePriceData
229
+ ): BN {
230
+ const [maxAmountToTrade, direction] = calculateMaxBaseAssetAmountToTrade(
231
+ market.amm,
232
+ limitPrice,
233
+ order.direction,
234
+ oraclePriceData
235
+ );
236
+
237
+ const baseAssetAmount = standardizeBaseAssetAmount(
238
+ maxAmountToTrade,
239
+ market.amm.orderStepSize
240
+ );
241
+
242
+ // Check that directions are the same
243
+ const sameDirection = isSameDirection(direction, order.direction);
244
+ if (!sameDirection) {
245
+ return ZERO;
246
+ }
247
+
248
+ const baseAssetAmountUnfilled = order.baseAssetAmount.sub(
249
+ order.baseAssetAmountFilled
250
+ );
251
+ return baseAssetAmount.gt(baseAssetAmountUnfilled)
252
+ ? baseAssetAmountUnfilled
253
+ : baseAssetAmount;
254
+ }
255
+
256
+ function isSameDirection(
257
+ firstDirection: PositionDirection,
258
+ secondDirection: PositionDirection
259
+ ): boolean {
260
+ return (
261
+ (isVariant(firstDirection, 'long') && isVariant(secondDirection, 'long')) ||
262
+ (isVariant(firstDirection, 'short') && isVariant(secondDirection, 'short'))
263
+ );
264
+ }
265
+
266
+ export function isOrderExpired(order: Order, ts: number): boolean {
267
+ if (
268
+ isOneOfVariant(order.orderType, ['triggerMarket', 'triggerLimit']) ||
269
+ !isVariant(order.status, 'open') ||
270
+ order.maxTs.eq(ZERO)
271
+ ) {
272
+ return false;
273
+ }
274
+
275
+ return new BN(ts).gt(order.maxTs);
276
+ }
277
+
278
+ export function isMarketOrder(order: Order): boolean {
279
+ return isOneOfVariant(order.orderType, ['market', 'triggerMarket']);
280
+ }
281
+
282
+ export function isLimitOrder(order: Order): boolean {
283
+ return isOneOfVariant(order.orderType, ['limit', 'triggerLimit']);
284
+ }
285
+
286
+ export function mustBeTriggered(order: Order): boolean {
287
+ return isOneOfVariant(order.orderType, ['triggerMarket', 'triggerLimit']);
288
+ }
289
+
290
+ export function isTriggered(order: Order): boolean {
291
+ return isOneOfVariant(order.orderType, ['triggeredAbove', 'triggeredBelow']);
292
+ }
@@ -1,22 +1,23 @@
1
- import { BN } from '../';
1
+ import { BN, SpotMarketAccount } from '../';
2
2
  import {
3
3
  AMM_RESERVE_PRECISION,
4
4
  AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO,
5
5
  AMM_TO_QUOTE_PRECISION_RATIO,
6
- FUNDING_PAYMENT_PRECISION,
7
- MARK_PRICE_PRECISION,
6
+ FUNDING_RATE_BUFFER_PRECISION,
7
+ PRICE_PRECISION,
8
8
  ONE,
9
- PRICE_TO_QUOTE_PRECISION,
10
9
  ZERO,
11
10
  } from '../constants/numericConstants';
12
11
  import { OraclePriceData } from '../oracles/types';
13
- import { MarketAccount, PositionDirection, UserPosition } from '../types';
12
+ import { PerpMarketAccount, PositionDirection, PerpPosition } from '../types';
14
13
  import {
15
14
  calculateUpdatedAMM,
16
15
  calculateUpdatedAMMSpreadReserves,
17
16
  calculateAmmReservesAfterSwap,
18
17
  getSwapDirection,
19
18
  } from './amm';
19
+ import { calculateBaseAssetValueWithOracle } from './margin';
20
+ import { calculateNetUserPnlImbalance } from './market';
20
21
 
21
22
  /**
22
23
  * calculateBaseAssetValue
@@ -27,9 +28,11 @@ import {
27
28
  * @returns Base Asset Value. : Precision QUOTE_PRECISION
28
29
  */
29
30
  export function calculateBaseAssetValue(
30
- market: MarketAccount,
31
- userPosition: UserPosition,
32
- oraclePriceData: OraclePriceData
31
+ market: PerpMarketAccount,
32
+ userPosition: PerpPosition,
33
+ oraclePriceData: OraclePriceData,
34
+ useSpread = true,
35
+ skipUpdate = false
33
36
  ): BN {
34
37
  if (userPosition.baseAssetAmount.eq(ZERO)) {
35
38
  return ZERO;
@@ -38,21 +41,25 @@ export function calculateBaseAssetValue(
38
41
  const directionToClose = findDirectionToClose(userPosition);
39
42
  let prepegAmm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
40
43
 
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
- };
44
+ if (!skipUpdate) {
45
+ if (market.amm.baseSpread > 0 && useSpread) {
46
+ const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
47
+ calculateUpdatedAMMSpreadReserves(
48
+ market.amm,
49
+ directionToClose,
50
+ oraclePriceData
51
+ );
52
+ prepegAmm = {
53
+ baseAssetReserve,
54
+ quoteAssetReserve,
55
+ sqrtK: sqrtK,
56
+ pegMultiplier: newPeg,
57
+ };
58
+ } else {
59
+ prepegAmm = calculateUpdatedAMM(market.amm, oraclePriceData);
60
+ }
54
61
  } else {
55
- prepegAmm = calculateUpdatedAMM(market.amm, oraclePriceData);
62
+ prepegAmm = market.amm;
56
63
  }
57
64
 
58
65
  const [newQuoteAssetReserve, _] = calculateAmmReservesAfterSwap(
@@ -82,38 +89,36 @@ export function calculateBaseAssetValue(
82
89
  * calculatePositionPNL
83
90
  * = BaseAssetAmount * (Avg Exit Price - Avg Entry Price)
84
91
  * @param market
85
- * @param marketPosition
92
+ * @param PerpPosition
86
93
  * @param withFunding (adds unrealized funding payment pnl to result)
94
+ * @param oraclePriceData
87
95
  * @returns BaseAssetAmount : Precision QUOTE_PRECISION
88
96
  */
89
97
  export function calculatePositionPNL(
90
- market: MarketAccount,
91
- marketPosition: UserPosition,
98
+ market: PerpMarketAccount,
99
+ perpPosition: PerpPosition,
92
100
  withFunding = false,
93
101
  oraclePriceData: OraclePriceData
94
102
  ): BN {
95
- if (marketPosition.baseAssetAmount.eq(ZERO)) {
96
- return ZERO;
103
+ if (perpPosition.baseAssetAmount.eq(ZERO)) {
104
+ return perpPosition.quoteAssetAmount;
97
105
  }
98
106
 
99
- const baseAssetValue = calculateBaseAssetValue(
107
+ const baseAssetValue = calculateBaseAssetValueWithOracle(
100
108
  market,
101
- marketPosition,
109
+ perpPosition,
102
110
  oraclePriceData
103
111
  );
104
112
 
105
- let pnl;
106
- if (marketPosition.baseAssetAmount.gt(ZERO)) {
107
- pnl = baseAssetValue.sub(marketPosition.quoteAssetAmount);
108
- } else {
109
- pnl = marketPosition.quoteAssetAmount.sub(baseAssetValue);
110
- }
113
+ const baseAssetValueSign = perpPosition.baseAssetAmount.isNeg()
114
+ ? new BN(-1)
115
+ : new BN(1);
116
+ let pnl = baseAssetValue
117
+ .mul(baseAssetValueSign)
118
+ .add(perpPosition.quoteAssetAmount);
111
119
 
112
120
  if (withFunding) {
113
- const fundingRatePnL = calculatePositionFundingPNL(
114
- market,
115
- marketPosition
116
- ).div(PRICE_TO_QUOTE_PRECISION);
121
+ const fundingRatePnL = calculatePositionFundingPNL(market, perpPosition);
117
122
 
118
123
  pnl = pnl.add(fundingRatePnL);
119
124
  }
@@ -121,64 +126,135 @@ export function calculatePositionPNL(
121
126
  return pnl;
122
127
  }
123
128
 
129
+ export function calculateClaimablePnl(
130
+ market: PerpMarketAccount,
131
+ spotMarket: SpotMarketAccount,
132
+ perpPosition: PerpPosition,
133
+ oraclePriceData: OraclePriceData
134
+ ): BN {
135
+ const unrealizedPnl = calculatePositionPNL(
136
+ market,
137
+ perpPosition,
138
+ true,
139
+ oraclePriceData
140
+ );
141
+
142
+ const fundingPnL = calculatePositionFundingPNL(market, perpPosition);
143
+
144
+ let unsettledPnl = unrealizedPnl.add(fundingPnL);
145
+ if (unrealizedPnl.gt(ZERO)) {
146
+ const excessPnlPool = BN.max(
147
+ ZERO,
148
+ calculateNetUserPnlImbalance(market, spotMarket, oraclePriceData).mul(
149
+ new BN(-1)
150
+ )
151
+ );
152
+
153
+ const maxPositivePnl = BN.max(
154
+ perpPosition.quoteAssetAmount
155
+ .sub(perpPosition.quoteEntryAmount)
156
+ .add(excessPnlPool),
157
+ ZERO
158
+ );
159
+
160
+ unsettledPnl = BN.min(maxPositivePnl, unrealizedPnl);
161
+ }
162
+ return unsettledPnl;
163
+ }
164
+
124
165
  /**
125
166
  *
126
167
  * @param market
127
- * @param marketPosition
168
+ * @param PerpPosition
128
169
  * @returns // TODO-PRECISION
129
170
  */
130
171
  export function calculatePositionFundingPNL(
131
- market: MarketAccount,
132
- marketPosition: UserPosition
172
+ market: PerpMarketAccount,
173
+ perpPosition: PerpPosition
133
174
  ): BN {
134
- if (marketPosition.baseAssetAmount.eq(ZERO)) {
175
+ if (perpPosition.baseAssetAmount.eq(ZERO)) {
135
176
  return ZERO;
136
177
  }
137
178
 
138
179
  let ammCumulativeFundingRate: BN;
139
- if (marketPosition.baseAssetAmount.gt(ZERO)) {
180
+ if (perpPosition.baseAssetAmount.gt(ZERO)) {
140
181
  ammCumulativeFundingRate = market.amm.cumulativeFundingRateLong;
141
182
  } else {
142
183
  ammCumulativeFundingRate = market.amm.cumulativeFundingRateShort;
143
184
  }
144
185
 
145
186
  const perPositionFundingRate = ammCumulativeFundingRate
146
- .sub(marketPosition.lastCumulativeFundingRate)
147
- .mul(marketPosition.baseAssetAmount)
187
+ .sub(perpPosition.lastCumulativeFundingRate)
188
+ .mul(perpPosition.baseAssetAmount)
148
189
  .div(AMM_RESERVE_PRECISION)
149
- .div(FUNDING_PAYMENT_PRECISION)
190
+ .div(FUNDING_RATE_BUFFER_PRECISION)
150
191
  .mul(new BN(-1));
151
192
 
152
193
  return perPositionFundingRate;
153
194
  }
154
195
 
155
- export function positionIsAvailable(position: UserPosition): boolean {
196
+ export function positionIsAvailable(position: PerpPosition): boolean {
156
197
  return (
157
198
  position.baseAssetAmount.eq(ZERO) &&
158
- position.openOrders.eq(ZERO) &&
159
- position.unsettledPnl.eq(ZERO)
199
+ position.openOrders === 0 &&
200
+ position.quoteAssetAmount.eq(ZERO) &&
201
+ position.lpShares.eq(ZERO)
160
202
  );
161
203
  }
162
204
 
163
205
  /**
164
206
  *
165
207
  * @param userPosition
166
- * @returns Precision: MARK_PRICE_PRECISION (10^10)
208
+ * @returns Precision: PRICE_PRECISION (10^6)
167
209
  */
168
- export function calculateEntryPrice(userPosition: UserPosition): BN {
210
+ export function calculateBreakEvenPrice(userPosition: PerpPosition): BN {
211
+ if (userPosition.baseAssetAmount.eq(ZERO)) {
212
+ return ZERO;
213
+ }
214
+
215
+ return userPosition.quoteBreakEvenAmount
216
+ .mul(PRICE_PRECISION)
217
+ .mul(AMM_TO_QUOTE_PRECISION_RATIO)
218
+ .div(userPosition.baseAssetAmount)
219
+ .abs();
220
+ }
221
+
222
+ /**
223
+ *
224
+ * @param userPosition
225
+ * @returns Precision: PRICE_PRECISION (10^6)
226
+ */
227
+ export function calculateEntryPrice(userPosition: PerpPosition): BN {
228
+ if (userPosition.baseAssetAmount.eq(ZERO)) {
229
+ return ZERO;
230
+ }
231
+
232
+ return userPosition.quoteEntryAmount
233
+ .mul(PRICE_PRECISION)
234
+ .mul(AMM_TO_QUOTE_PRECISION_RATIO)
235
+ .div(userPosition.baseAssetAmount)
236
+ .abs();
237
+ }
238
+
239
+ /**
240
+ *
241
+ * @param userPosition
242
+ * @returns Precision: PRICE_PRECISION (10^10)
243
+ */
244
+ export function calculateCostBasis(userPosition: PerpPosition): BN {
169
245
  if (userPosition.baseAssetAmount.eq(ZERO)) {
170
246
  return ZERO;
171
247
  }
172
248
 
173
249
  return userPosition.quoteAssetAmount
174
- .mul(MARK_PRICE_PRECISION)
250
+ .mul(PRICE_PRECISION)
175
251
  .mul(AMM_TO_QUOTE_PRECISION_RATIO)
176
252
  .div(userPosition.baseAssetAmount)
177
253
  .abs();
178
254
  }
179
255
 
180
256
  export function findDirectionToClose(
181
- userPosition: UserPosition
257
+ userPosition: PerpPosition
182
258
  ): PositionDirection {
183
259
  return userPosition.baseAssetAmount.gt(ZERO)
184
260
  ? PositionDirection.SHORT
@@ -186,15 +262,13 @@ export function findDirectionToClose(
186
262
  }
187
263
 
188
264
  export function positionCurrentDirection(
189
- userPosition: UserPosition
265
+ userPosition: PerpPosition
190
266
  ): PositionDirection {
191
267
  return userPosition.baseAssetAmount.gte(ZERO)
192
268
  ? PositionDirection.LONG
193
269
  : PositionDirection.SHORT;
194
270
  }
195
271
 
196
- export function isEmptyPosition(userPosition: UserPosition): boolean {
197
- return (
198
- userPosition.baseAssetAmount.eq(ZERO) && userPosition.openOrders.eq(ZERO)
199
- );
272
+ export function isEmptyPosition(userPosition: PerpPosition): boolean {
273
+ return userPosition.baseAssetAmount.eq(ZERO) && userPosition.openOrders === 0;
200
274
  }
package/src/math/repeg.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { BN } from '@project-serum/anchor';
2
2
  import { assert } from '../assert/assert';
3
3
  import {
4
- MARK_PRICE_PRECISION,
4
+ PRICE_PRECISION,
5
5
  AMM_RESERVE_PRECISION,
6
6
  PEG_PRECISION,
7
7
  AMM_TO_QUOTE_PRECISION_RATIO,
@@ -26,20 +26,20 @@ export function calculateAdjustKCost(
26
26
  const x = amm.baseAssetReserve;
27
27
  const y = amm.quoteAssetReserve;
28
28
 
29
- const d = amm.netBaseAssetAmount;
29
+ const d = amm.baseAssetAmountWithAmm;
30
30
  const Q = amm.pegMultiplier;
31
31
 
32
32
  const quoteScale = y.mul(d).mul(Q); //.div(AMM_RESERVE_PRECISION);
33
33
 
34
- const p = numerator.mul(MARK_PRICE_PRECISION).div(denomenator);
34
+ const p = numerator.mul(PRICE_PRECISION).div(denomenator);
35
35
 
36
36
  const cost = quoteScale
37
37
  .div(x.add(d))
38
38
  .sub(
39
39
  quoteScale
40
40
  .mul(p)
41
- .div(MARK_PRICE_PRECISION)
42
- .div(x.mul(p).div(MARK_PRICE_PRECISION).add(d))
41
+ .div(PRICE_PRECISION)
42
+ .div(x.mul(p).div(PRICE_PRECISION).add(d))
43
43
  )
44
44
  .div(AMM_TO_QUOTE_PRECISION_RATIO)
45
45
  .div(PEG_PRECISION);
@@ -98,6 +98,16 @@ export function calculateBudgetedKBN(
98
98
  .div(QUOTE_PRECISION);
99
99
  const denom2 = pegged_y_d_d;
100
100
 
101
+ // protocol is spending to increase k
102
+ if (C.lt(ZERO)) {
103
+ // thus denom1 is negative and solution is unstable
104
+ if (denom1.abs().gt(denom2.abs())) {
105
+ console.log('denom1 > denom2', denom1.toString(), denom2.toString());
106
+ console.log('budget cost exceeds stable K solution');
107
+ return [new BN(10000), new BN(1)];
108
+ }
109
+ }
110
+
101
111
  const numerator = numer1.sub(numer2).div(AMM_TO_QUOTE_PRECISION_RATIO);
102
112
  const denominator = denom1.add(denom2).div(AMM_TO_QUOTE_PRECISION_RATIO);
103
113
 
@@ -125,7 +135,7 @@ export function calculateBudgetedK(amm: AMM, cost: BN): [BN, BN] {
125
135
  const x = amm.baseAssetReserve;
126
136
  const y = amm.quoteAssetReserve;
127
137
 
128
- const d = amm.netBaseAssetAmount;
138
+ const d = amm.baseAssetAmountWithAmm;
129
139
  const Q = amm.pegMultiplier;
130
140
 
131
141
  const [numerator, denominator] = calculateBudgetedKBN(x, y, cost, Q, d);
@@ -149,7 +159,7 @@ export function calculateBudgetedPeg(amm: AMM, cost: BN, targetPrice: BN): BN {
149
159
  const x = amm.baseAssetReserve;
150
160
  const y = amm.quoteAssetReserve;
151
161
 
152
- const d = amm.netBaseAssetAmount;
162
+ const d = amm.baseAssetAmountWithAmm;
153
163
  const Q = amm.pegMultiplier;
154
164
 
155
165
  const C = cost.mul(new BN(-1));
@@ -165,11 +175,11 @@ export function calculateBudgetedPeg(amm: AMM, cost: BN, targetPrice: BN): BN {
165
175
  return targetPeg;
166
176
  }
167
177
 
168
- const deltaPegMultiplier = C.mul(MARK_PRICE_PRECISION).div(
178
+ const deltaPegMultiplier = C.mul(PRICE_PRECISION).div(
169
179
  deltaQuoteAssetReserves.div(AMM_TO_QUOTE_PRECISION_RATIO)
170
180
  );
171
181
  const newPeg = Q.sub(
172
- deltaPegMultiplier.mul(PEG_PRECISION).div(MARK_PRICE_PRECISION)
182
+ deltaPegMultiplier.mul(PEG_PRECISION).div(PRICE_PRECISION)
173
183
  );
174
184
 
175
185
  return newPeg;