@drift-labs/sdk 0.2.0-temp.1 → 2.0.0

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 (274) 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.js +3 -0
  48. package/lib/events/eventSubscriber.d.ts +5 -2
  49. package/lib/events/eventSubscriber.js +25 -11
  50. package/lib/events/fetchLogs.d.ts +13 -2
  51. package/lib/events/fetchLogs.js +45 -14
  52. package/lib/events/pollingLogProvider.d.ts +2 -1
  53. package/lib/events/pollingLogProvider.js +7 -3
  54. package/lib/events/sort.js +8 -11
  55. package/lib/events/types.d.ts +11 -3
  56. package/lib/events/types.js +8 -0
  57. package/lib/events/webSocketLogProvider.js +1 -1
  58. package/lib/examples/makeTradeExample.js +30 -18
  59. package/lib/factory/bigNum.d.ts +8 -4
  60. package/lib/factory/bigNum.js +109 -19
  61. package/lib/idl/drift.json +8392 -0
  62. package/lib/index.d.ts +29 -12
  63. package/lib/index.js +29 -12
  64. package/lib/math/amm.d.ts +9 -6
  65. package/lib/math/amm.js +91 -38
  66. package/lib/math/conversion.js +1 -1
  67. package/lib/math/exchangeStatus.d.ts +4 -0
  68. package/lib/math/exchangeStatus.js +18 -0
  69. package/lib/math/funding.d.ts +6 -6
  70. package/lib/math/funding.js +23 -21
  71. package/lib/math/insurance.d.ts +4 -0
  72. package/lib/math/insurance.js +27 -0
  73. package/lib/math/margin.d.ts +11 -0
  74. package/lib/math/margin.js +82 -0
  75. package/lib/math/market.d.ts +14 -9
  76. package/lib/math/market.js +70 -10
  77. package/lib/math/oracles.d.ts +4 -0
  78. package/lib/math/oracles.js +36 -8
  79. package/lib/math/orders.d.ts +16 -6
  80. package/lib/math/orders.js +97 -17
  81. package/lib/math/position.d.ts +27 -13
  82. package/lib/math/position.js +91 -37
  83. package/lib/math/repeg.js +17 -8
  84. package/lib/math/spotBalance.d.ts +22 -0
  85. package/lib/math/spotBalance.js +192 -0
  86. package/lib/math/spotMarket.d.ts +4 -0
  87. package/lib/math/spotMarket.js +8 -0
  88. package/lib/math/spotPosition.d.ts +6 -0
  89. package/lib/math/spotPosition.js +23 -0
  90. package/lib/math/trade.d.ts +10 -10
  91. package/lib/math/trade.js +27 -31
  92. package/lib/oracles/pythClient.js +1 -1
  93. package/lib/oracles/quoteAssetOracleClient.js +1 -1
  94. package/lib/oracles/switchboardClient.js +1 -1
  95. package/lib/orderParams.d.ts +4 -4
  96. package/lib/orderParams.js +12 -4
  97. package/lib/serum/serumFulfillmentConfigMap.d.ts +10 -0
  98. package/lib/serum/serumFulfillmentConfigMap.js +17 -0
  99. package/lib/serum/serumSubscriber.d.ts +27 -0
  100. package/lib/serum/serumSubscriber.js +56 -0
  101. package/lib/serum/types.d.ts +11 -0
  102. package/{src/oracles → lib/serum}/types.js +0 -0
  103. package/lib/tokenFaucet.d.ts +1 -0
  104. package/lib/tokenFaucet.js +23 -12
  105. package/lib/tx/retryTxSender.d.ts +1 -1
  106. package/lib/tx/retryTxSender.js +13 -4
  107. package/lib/tx/types.d.ts +1 -1
  108. package/lib/types.d.ts +631 -222
  109. package/lib/types.js +137 -24
  110. package/lib/user.d.ts +228 -0
  111. package/lib/user.js +959 -0
  112. package/lib/userConfig.d.ts +14 -0
  113. package/lib/{clearingHouseUserConfig.js → userConfig.js} +0 -0
  114. package/lib/userMap/userMap.d.ts +41 -0
  115. package/lib/userMap/userMap.js +85 -0
  116. package/lib/userMap/userStatsMap.d.ts +19 -0
  117. package/lib/userMap/userStatsMap.js +68 -0
  118. package/lib/userName.d.ts +1 -0
  119. package/lib/userName.js +3 -2
  120. package/lib/userStats.d.ts +18 -0
  121. package/lib/userStats.js +49 -0
  122. package/lib/userStatsConfig.d.ts +14 -0
  123. package/{src/clearingHouseConfig.js → lib/userStatsConfig.js} +0 -0
  124. package/lib/util/getTokenAddress.d.ts +2 -0
  125. package/lib/util/getTokenAddress.js +9 -0
  126. package/package.json +12 -5
  127. package/src/accounts/bulkAccountLoader.ts +44 -34
  128. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  129. package/src/accounts/bulkUserSubscription.ts +2 -3
  130. package/src/accounts/fetch.ts +27 -2
  131. package/src/accounts/{pollingClearingHouseAccountSubscriber.ts → pollingDriftClientAccountSubscriber.ts} +65 -75
  132. package/src/accounts/{pollingOracleSubscriber.ts → pollingOracleAccountSubscriber.ts} +2 -2
  133. package/src/accounts/pollingUserAccountSubscriber.ts +5 -12
  134. package/src/accounts/pollingUserStatsAccountSubscriber.ts +166 -0
  135. package/src/accounts/types.ts +35 -15
  136. package/src/accounts/{webSocketClearingHouseAccountSubscriber.ts → webSocketDriftClientAccountSubscriber.ts} +78 -73
  137. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  138. package/src/addresses/marketAddresses.ts +3 -4
  139. package/src/addresses/pda.ts +105 -33
  140. package/src/adminClient.ts +1207 -0
  141. package/src/config.ts +41 -34
  142. package/src/constants/numericConstants.ts +59 -26
  143. package/src/constants/{markets.ts → perpMarkets.ts} +22 -11
  144. package/src/constants/spotMarkets.ts +83 -0
  145. package/src/dlob/DLOB.ts +1120 -0
  146. package/src/dlob/DLOBNode.ts +155 -0
  147. package/src/dlob/NodeList.ts +195 -0
  148. package/src/driftClient.ts +3594 -0
  149. package/src/{clearingHouseConfig.ts → driftClientConfig.ts} +9 -8
  150. package/src/events/eventList.ts +3 -0
  151. package/src/events/eventSubscriber.ts +36 -14
  152. package/src/events/fetchLogs.ts +60 -15
  153. package/src/events/pollingLogProvider.ts +11 -3
  154. package/src/events/sort.ts +11 -15
  155. package/src/events/types.ts +27 -2
  156. package/src/events/webSocketLogProvider.ts +1 -1
  157. package/src/examples/makeTradeExample.js +152 -75
  158. package/src/examples/makeTradeExample.ts +44 -28
  159. package/src/factory/bigNum.ts +150 -22
  160. package/src/idl/drift.json +8392 -0
  161. package/src/idl/pyth.json +98 -2
  162. package/src/index.ts +29 -12
  163. package/src/math/amm.ts +161 -48
  164. package/src/math/conversion.ts +2 -2
  165. package/src/math/exchangeStatus.ts +31 -0
  166. package/src/math/funding.ts +41 -31
  167. package/src/math/insurance.ts +35 -0
  168. package/src/math/margin.ts +133 -0
  169. package/src/math/market.ts +143 -14
  170. package/src/math/oracles.ts +63 -9
  171. package/src/math/orders.ts +168 -26
  172. package/src/math/position.ts +133 -59
  173. package/src/math/repeg.ts +19 -9
  174. package/src/math/spotBalance.ts +319 -0
  175. package/src/math/spotMarket.ts +9 -0
  176. package/src/math/spotPosition.ts +47 -0
  177. package/src/math/trade.ts +33 -37
  178. package/src/oracles/pythClient.ts +2 -2
  179. package/src/oracles/quoteAssetOracleClient.ts +2 -2
  180. package/src/oracles/switchboardClient.ts +2 -2
  181. package/src/orderParams.ts +16 -8
  182. package/src/serum/serumFulfillmentConfigMap.ts +26 -0
  183. package/src/serum/serumSubscriber.ts +99 -0
  184. package/src/serum/types.ts +13 -0
  185. package/src/tokenFaucet.ts +38 -15
  186. package/src/tx/retryTxSender.ts +16 -5
  187. package/src/tx/types.ts +2 -1
  188. package/src/types.ts +594 -195
  189. package/src/user.ts +1599 -0
  190. package/src/{clearingHouseUserConfig.ts → userConfig.ts} +5 -5
  191. package/src/userMap/userMap.ts +124 -0
  192. package/src/userMap/userStatsMap.ts +108 -0
  193. package/src/userName.ts +2 -1
  194. package/src/userStats.ts +75 -0
  195. package/src/userStatsConfig.ts +18 -0
  196. package/src/util/getTokenAddress.ts +18 -0
  197. package/tests/bn/test.ts +46 -11
  198. package/tests/dlob/helpers.ts +619 -0
  199. package/tests/dlob/test.ts +4586 -0
  200. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +0 -49
  201. package/lib/admin.d.ts +0 -44
  202. package/lib/admin.js +0 -438
  203. package/lib/clearingHouse.d.ts +0 -146
  204. package/lib/clearingHouse.js +0 -1154
  205. package/lib/clearingHouseUser.d.ts +0 -187
  206. package/lib/clearingHouseUser.js +0 -634
  207. package/lib/clearingHouseUserConfig.d.ts +0 -14
  208. package/lib/constants/banks.d.ts +0 -16
  209. package/lib/constants/banks.js +0 -41
  210. package/lib/constants/markets.d.ts +0 -19
  211. package/lib/idl/clearing_house.json +0 -4464
  212. package/lib/math/bankBalance.d.ts +0 -9
  213. package/lib/math/bankBalance.js +0 -75
  214. package/lib/math/state.d.ts +0 -8
  215. package/lib/math/state.js +0 -15
  216. package/lib/orders.d.ts +0 -8
  217. package/lib/orders.js +0 -134
  218. package/src/accounts/bulkAccountLoader.js +0 -197
  219. package/src/accounts/bulkUserSubscription.js +0 -33
  220. package/src/accounts/pollingClearingHouseAccountSubscriber.js +0 -311
  221. package/src/accounts/pollingOracleSubscriber.js +0 -93
  222. package/src/accounts/pollingTokenAccountSubscriber.js +0 -90
  223. package/src/accounts/pollingUserAccountSubscriber.js +0 -132
  224. package/src/accounts/types.js +0 -10
  225. package/src/accounts/utils.js +0 -7
  226. package/src/accounts/webSocketAccountSubscriber.js +0 -93
  227. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +0 -233
  228. package/src/accounts/webSocketUserAccountSubscriber.js +0 -62
  229. package/src/addresses/marketAddresses.js +0 -26
  230. package/src/admin.js +0 -517
  231. package/src/admin.ts +0 -730
  232. package/src/clearingHouse.ts +0 -1828
  233. package/src/clearingHouseUser.ts +0 -978
  234. package/src/clearingHouseUserConfig.js +0 -2
  235. package/src/config.js +0 -67
  236. package/src/constants/banks.js +0 -42
  237. package/src/constants/banks.ts +0 -50
  238. package/src/constants/markets.js +0 -42
  239. package/src/constants/numericConstants.js +0 -41
  240. package/src/events/eventSubscriber.js +0 -139
  241. package/src/events/fetchLogs.js +0 -50
  242. package/src/events/pollingLogProvider.js +0 -64
  243. package/src/events/sort.js +0 -44
  244. package/src/events/txEventCache.js +0 -71
  245. package/src/events/types.js +0 -20
  246. package/src/events/webSocketLogProvider.js +0 -41
  247. package/src/factory/bigNum.js +0 -390
  248. package/src/factory/oracleClient.js +0 -20
  249. package/src/idl/clearing_house.json +0 -4464
  250. package/src/index.js +0 -69
  251. package/src/math/amm.js +0 -369
  252. package/src/math/auction.js +0 -42
  253. package/src/math/bankBalance.ts +0 -112
  254. package/src/math/conversion.js +0 -11
  255. package/src/math/funding.js +0 -248
  256. package/src/math/oracles.js +0 -26
  257. package/src/math/repeg.js +0 -128
  258. package/src/math/state.js +0 -15
  259. package/src/math/state.ts +0 -14
  260. package/src/math/trade.js +0 -253
  261. package/src/math/utils.js +0 -26
  262. package/src/math/utils.js.map +0 -1
  263. package/src/mockUSDCFaucet.js +0 -280
  264. package/src/oracles/oracleClientCache.js +0 -19
  265. package/src/oracles/pythClient.js +0 -46
  266. package/src/oracles/quoteAssetOracleClient.js +0 -32
  267. package/src/oracles/switchboardClient.js +0 -69
  268. package/src/orderParams.js +0 -20
  269. package/src/orders.ts +0 -245
  270. package/src/slot/SlotSubscriber.js +0 -39
  271. package/src/tokenFaucet.js +0 -189
  272. package/src/types.js +0 -125
  273. package/src/userName.js +0 -20
  274. package/src/wallet.js +0 -35
@@ -0,0 +1,319 @@
1
+ import {
2
+ SpotMarketAccount,
3
+ SpotBalanceType,
4
+ isVariant,
5
+ MarginCategory,
6
+ } from '../types';
7
+ import { BN } from '@project-serum/anchor';
8
+ import {
9
+ SPOT_MARKET_UTILIZATION_PRECISION,
10
+ ONE,
11
+ TEN,
12
+ ZERO,
13
+ SPOT_MARKET_RATE_PRECISION,
14
+ SPOT_MARKET_WEIGHT_PRECISION,
15
+ ONE_YEAR,
16
+ AMM_RESERVE_PRECISION,
17
+ } from '../constants/numericConstants';
18
+ import {
19
+ calculateSizeDiscountAssetWeight,
20
+ calculateSizePremiumLiabilityWeight,
21
+ } from './margin';
22
+ import { OraclePriceData } from '../oracles/types';
23
+
24
+ export function getBalance(
25
+ tokenAmount: BN,
26
+ spotMarket: SpotMarketAccount,
27
+ balanceType: SpotBalanceType
28
+ ): BN {
29
+ const precisionIncrease = TEN.pow(new BN(19 - spotMarket.decimals));
30
+
31
+ const cumulativeInterest = isVariant(balanceType, 'deposit')
32
+ ? spotMarket.cumulativeDepositInterest
33
+ : spotMarket.cumulativeBorrowInterest;
34
+
35
+ let balance = tokenAmount.mul(precisionIncrease).div(cumulativeInterest);
36
+
37
+ if (!balance.eq(ZERO) && isVariant(balanceType, 'borrow')) {
38
+ balance = balance.add(ONE);
39
+ }
40
+
41
+ return balance;
42
+ }
43
+
44
+ export function getTokenAmount(
45
+ balanceAmount: BN,
46
+ spotMarket: SpotMarketAccount,
47
+ balanceType: SpotBalanceType
48
+ ): BN {
49
+ const precisionDecrease = TEN.pow(new BN(19 - spotMarket.decimals));
50
+
51
+ const cumulativeInterest = isVariant(balanceType, 'deposit')
52
+ ? spotMarket.cumulativeDepositInterest
53
+ : spotMarket.cumulativeBorrowInterest;
54
+
55
+ return balanceAmount.mul(cumulativeInterest).div(precisionDecrease);
56
+ }
57
+
58
+ export function getSignedTokenAmount(
59
+ tokenAmount: BN,
60
+ balanceType: SpotBalanceType
61
+ ): BN {
62
+ if (isVariant(balanceType, 'deposit')) {
63
+ return tokenAmount;
64
+ } else {
65
+ return tokenAmount.abs().neg();
66
+ }
67
+ }
68
+
69
+ export function getTokenValue(
70
+ tokenAmount: BN,
71
+ spotDecimals: number,
72
+ oraclePriceData: OraclePriceData
73
+ ): BN {
74
+ if (tokenAmount.eq(ZERO)) {
75
+ return ZERO;
76
+ }
77
+
78
+ const precisionDecrease = TEN.pow(new BN(spotDecimals));
79
+
80
+ return tokenAmount.mul(oraclePriceData.price).div(precisionDecrease);
81
+ }
82
+
83
+ export function calculateAssetWeight(
84
+ balanceAmount: BN,
85
+ spotMarket: SpotMarketAccount,
86
+ marginCategory: MarginCategory
87
+ ): BN {
88
+ const sizePrecision = TEN.pow(new BN(spotMarket.decimals));
89
+ let sizeInAmmReservePrecision;
90
+ if (sizePrecision.gt(AMM_RESERVE_PRECISION)) {
91
+ sizeInAmmReservePrecision = balanceAmount.div(
92
+ sizePrecision.div(AMM_RESERVE_PRECISION)
93
+ );
94
+ } else {
95
+ sizeInAmmReservePrecision = balanceAmount
96
+ .mul(AMM_RESERVE_PRECISION)
97
+ .div(sizePrecision);
98
+ }
99
+
100
+ let assetWeight;
101
+
102
+ switch (marginCategory) {
103
+ case 'Initial':
104
+ assetWeight = calculateSizeDiscountAssetWeight(
105
+ sizeInAmmReservePrecision,
106
+ new BN(spotMarket.imfFactor),
107
+ new BN(spotMarket.initialAssetWeight)
108
+ );
109
+ break;
110
+ case 'Maintenance':
111
+ assetWeight = calculateSizeDiscountAssetWeight(
112
+ sizeInAmmReservePrecision,
113
+ new BN(spotMarket.imfFactor),
114
+ new BN(spotMarket.maintenanceAssetWeight)
115
+ );
116
+ break;
117
+ default:
118
+ assetWeight = new BN(spotMarket.initialAssetWeight);
119
+ break;
120
+ }
121
+
122
+ return assetWeight;
123
+ }
124
+
125
+ export function calculateLiabilityWeight(
126
+ balanceAmount: BN,
127
+ spotMarket: SpotMarketAccount,
128
+ marginCategory: MarginCategory
129
+ ): BN {
130
+ const sizePrecision = TEN.pow(new BN(spotMarket.decimals));
131
+ let sizeInAmmReservePrecision;
132
+ if (sizePrecision.gt(AMM_RESERVE_PRECISION)) {
133
+ sizeInAmmReservePrecision = balanceAmount.div(
134
+ sizePrecision.div(AMM_RESERVE_PRECISION)
135
+ );
136
+ } else {
137
+ sizeInAmmReservePrecision = balanceAmount
138
+ .mul(AMM_RESERVE_PRECISION)
139
+ .div(sizePrecision);
140
+ }
141
+
142
+ let assetWeight;
143
+
144
+ switch (marginCategory) {
145
+ case 'Initial':
146
+ assetWeight = calculateSizePremiumLiabilityWeight(
147
+ sizeInAmmReservePrecision,
148
+ new BN(spotMarket.imfFactor),
149
+ new BN(spotMarket.initialLiabilityWeight),
150
+ SPOT_MARKET_WEIGHT_PRECISION
151
+ );
152
+ break;
153
+ case 'Maintenance':
154
+ assetWeight = calculateSizePremiumLiabilityWeight(
155
+ sizeInAmmReservePrecision,
156
+ new BN(spotMarket.imfFactor),
157
+ new BN(spotMarket.maintenanceLiabilityWeight),
158
+ SPOT_MARKET_WEIGHT_PRECISION
159
+ );
160
+ break;
161
+ default:
162
+ assetWeight = spotMarket.initialLiabilityWeight;
163
+ break;
164
+ }
165
+
166
+ return assetWeight;
167
+ }
168
+
169
+ export function calculateUtilization(bank: SpotMarketAccount): BN {
170
+ const tokenDepositAmount = getTokenAmount(
171
+ bank.depositBalance,
172
+ bank,
173
+ SpotBalanceType.DEPOSIT
174
+ );
175
+ const tokenBorrowAmount = getTokenAmount(
176
+ bank.borrowBalance,
177
+ bank,
178
+ SpotBalanceType.BORROW
179
+ );
180
+
181
+ let utilization: BN;
182
+ if (tokenBorrowAmount.eq(ZERO) && tokenDepositAmount.eq(ZERO)) {
183
+ utilization = ZERO;
184
+ } else if (tokenDepositAmount.eq(ZERO)) {
185
+ utilization = SPOT_MARKET_UTILIZATION_PRECISION;
186
+ } else {
187
+ utilization = tokenBorrowAmount
188
+ .mul(SPOT_MARKET_UTILIZATION_PRECISION)
189
+ .div(tokenDepositAmount);
190
+ }
191
+
192
+ return utilization;
193
+ }
194
+
195
+ export function calculateInterestRate(bank: SpotMarketAccount): BN {
196
+ const utilization = calculateUtilization(bank);
197
+
198
+ let interestRate: BN;
199
+ if (utilization.gt(new BN(bank.optimalUtilization))) {
200
+ const surplusUtilization = utilization.sub(new BN(bank.optimalUtilization));
201
+ const borrowRateSlope = new BN(bank.maxBorrowRate - bank.optimalBorrowRate)
202
+ .mul(SPOT_MARKET_UTILIZATION_PRECISION)
203
+ .div(
204
+ SPOT_MARKET_UTILIZATION_PRECISION.sub(new BN(bank.optimalUtilization))
205
+ );
206
+
207
+ interestRate = new BN(bank.optimalBorrowRate).add(
208
+ surplusUtilization
209
+ .mul(borrowRateSlope)
210
+ .div(SPOT_MARKET_UTILIZATION_PRECISION)
211
+ );
212
+ } else {
213
+ const borrowRateSlope = new BN(bank.optimalBorrowRate)
214
+ .mul(SPOT_MARKET_UTILIZATION_PRECISION)
215
+ .div(
216
+ SPOT_MARKET_UTILIZATION_PRECISION.sub(new BN(bank.optimalUtilization))
217
+ );
218
+
219
+ interestRate = utilization
220
+ .mul(borrowRateSlope)
221
+ .div(SPOT_MARKET_UTILIZATION_PRECISION);
222
+ }
223
+
224
+ return interestRate;
225
+ }
226
+
227
+ export function calculateDepositRate(bank: SpotMarketAccount): BN {
228
+ const utilization = calculateUtilization(bank);
229
+ const borrowRate = calculateBorrowRate(bank);
230
+ const depositRate = borrowRate
231
+ .mul(utilization)
232
+ .div(SPOT_MARKET_UTILIZATION_PRECISION);
233
+ return depositRate;
234
+ }
235
+
236
+ export function calculateBorrowRate(bank: SpotMarketAccount): BN {
237
+ return calculateInterestRate(bank);
238
+ }
239
+
240
+ export function calculateInterestAccumulated(
241
+ bank: SpotMarketAccount,
242
+ now: BN
243
+ ): { borrowInterest: BN; depositInterest: BN } {
244
+ const interestRate = calculateInterestRate(bank);
245
+
246
+ const timeSinceLastUpdate = now.sub(bank.lastInterestTs);
247
+
248
+ const modifiedBorrowRate = interestRate.mul(timeSinceLastUpdate);
249
+
250
+ const utilization = calculateUtilization(bank);
251
+
252
+ const modifiedDepositRate = modifiedBorrowRate
253
+ .mul(utilization)
254
+ .div(SPOT_MARKET_UTILIZATION_PRECISION);
255
+
256
+ const borrowInterest = bank.cumulativeBorrowInterest
257
+ .mul(modifiedBorrowRate)
258
+ .div(ONE_YEAR)
259
+ .div(SPOT_MARKET_RATE_PRECISION)
260
+ .add(ONE);
261
+ const depositInterest = bank.cumulativeDepositInterest
262
+ .mul(modifiedDepositRate)
263
+ .div(ONE_YEAR)
264
+ .div(SPOT_MARKET_RATE_PRECISION);
265
+
266
+ return { borrowInterest, depositInterest };
267
+ }
268
+
269
+ export function calculateWithdrawLimit(
270
+ spotMarket: SpotMarketAccount,
271
+ now: BN
272
+ ): { borrowLimit: BN; withdrawLimit: BN } {
273
+ const marketDepositTokenAmount = getTokenAmount(
274
+ spotMarket.depositBalance,
275
+ spotMarket,
276
+ SpotBalanceType.DEPOSIT
277
+ );
278
+ const marketBorrowTokenAmount = getTokenAmount(
279
+ spotMarket.borrowBalance,
280
+ spotMarket,
281
+ SpotBalanceType.BORROW
282
+ );
283
+
284
+ const twentyFourHours = new BN(60 * 60 * 24);
285
+ const sinceLast = now.sub(spotMarket.lastTwapTs);
286
+ const sinceStart = BN.max(ZERO, twentyFourHours.sub(sinceLast));
287
+ const borrowTokenTwapLive = spotMarket.borrowTokenTwap
288
+ .mul(sinceStart)
289
+ .add(marketBorrowTokenAmount.mul(sinceLast))
290
+ .div(sinceLast.add(sinceStart));
291
+
292
+ const depositTokenTwapLive = spotMarket.depositTokenTwap
293
+ .mul(sinceStart)
294
+ .add(marketDepositTokenAmount.mul(sinceLast))
295
+ .div(sinceLast.add(sinceStart));
296
+
297
+ const maxBorrowTokens = BN.min(
298
+ BN.max(
299
+ marketDepositTokenAmount.div(new BN(6)),
300
+ borrowTokenTwapLive.add(borrowTokenTwapLive.div(new BN(5)))
301
+ ),
302
+ marketDepositTokenAmount.sub(marketDepositTokenAmount.div(new BN(5)))
303
+ ); // between ~15-80% utilization with friction on twap
304
+
305
+ const minDepositTokens = depositTokenTwapLive.sub(
306
+ BN.min(
307
+ BN.max(
308
+ depositTokenTwapLive.div(new BN(5)),
309
+ spotMarket.withdrawGuardThreshold
310
+ ),
311
+ depositTokenTwapLive
312
+ )
313
+ );
314
+
315
+ return {
316
+ borrowLimit: maxBorrowTokens.sub(marketBorrowTokenAmount),
317
+ withdrawLimit: marketDepositTokenAmount.sub(minDepositTokens),
318
+ };
319
+ }
@@ -0,0 +1,9 @@
1
+ import { BN } from '@project-serum/anchor';
2
+ import { SpotMarketAccount } from '../types';
3
+
4
+ export function castNumberToSpotPrecision(
5
+ value: number,
6
+ spotMarket: SpotMarketAccount
7
+ ): BN {
8
+ return new BN(value * Math.pow(10, spotMarket.decimals));
9
+ }
@@ -0,0 +1,47 @@
1
+ import { SpotMarketAccount, SpotPosition } from '../types';
2
+ import { ZERO } from '../constants/numericConstants';
3
+ import { BN } from '@project-serum/anchor';
4
+ import {
5
+ getSignedTokenAmount,
6
+ getTokenAmount,
7
+ getTokenValue,
8
+ } from './spotBalance';
9
+ import { OraclePriceData } from '../oracles/types';
10
+
11
+ export function isSpotPositionAvailable(position: SpotPosition): boolean {
12
+ return position.scaledBalance.eq(ZERO) && position.openOrders === 0;
13
+ }
14
+
15
+ export function getWorstCaseTokenAmounts(
16
+ spotPosition: SpotPosition,
17
+ spotMarketAccount: SpotMarketAccount,
18
+ oraclePriceData: OraclePriceData
19
+ ): [BN, BN] {
20
+ const tokenAmount = getSignedTokenAmount(
21
+ getTokenAmount(
22
+ spotPosition.scaledBalance,
23
+ spotMarketAccount,
24
+ spotPosition.balanceType
25
+ ),
26
+ spotPosition.balanceType
27
+ );
28
+
29
+ const tokenAmountAllBidsFill = tokenAmount.add(spotPosition.openBids);
30
+ const tokenAmountAllAsksFill = tokenAmount.add(spotPosition.openAsks);
31
+
32
+ if (tokenAmountAllAsksFill.abs().gt(tokenAmountAllBidsFill.abs())) {
33
+ const worstCaseQuoteTokenAmount = getTokenValue(
34
+ spotPosition.openAsks.neg(),
35
+ spotMarketAccount.decimals,
36
+ oraclePriceData
37
+ );
38
+ return [tokenAmountAllBidsFill, worstCaseQuoteTokenAmount];
39
+ } else {
40
+ const worstCaseQuoteTokenAmount = getTokenValue(
41
+ spotPosition.openBids.neg(),
42
+ spotMarketAccount.decimals,
43
+ oraclePriceData
44
+ );
45
+ return [tokenAmountAllAsksFill, worstCaseQuoteTokenAmount];
46
+ }
47
+ }
package/src/math/trade.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { MarketAccount, PositionDirection } from '../types';
1
+ import { PerpMarketAccount, PositionDirection } from '../types';
2
2
  import { BN } from '@project-serum/anchor';
3
3
  import { assert } from '../assert/assert';
4
4
  import {
5
- MARK_PRICE_PRECISION,
5
+ PRICE_PRECISION,
6
6
  PEG_PRECISION,
7
7
  AMM_TO_QUOTE_PRECISION_RATIO,
8
8
  ZERO,
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  calculateBidPrice,
12
12
  calculateAskPrice,
13
- calculateMarkPrice,
13
+ calculateReservePrice,
14
14
  } from './market';
15
15
  import {
16
16
  calculateAmmReservesAfterSwap,
@@ -48,18 +48,18 @@ export type PriceImpactUnit =
48
48
  * @param useSpread whether to consider spread with calculating slippage
49
49
  * @return [pctAvgSlippage, pctMaxSlippage, entryPrice, newPrice]
50
50
  *
51
- * 'pctAvgSlippage' => the percentage change to entryPrice (average est slippage in execution) : Precision MARK_PRICE_PRECISION
51
+ * 'pctAvgSlippage' => the percentage change to entryPrice (average est slippage in execution) : Precision PRICE_PRECISION
52
52
  *
53
- * 'pctMaxSlippage' => the percentage change to maxPrice (highest est slippage in execution) : Precision MARK_PRICE_PRECISION
53
+ * 'pctMaxSlippage' => the percentage change to maxPrice (highest est slippage in execution) : Precision PRICE_PRECISION
54
54
  *
55
- * 'entryPrice' => the average price of the trade : Precision MARK_PRICE_PRECISION
55
+ * 'entryPrice' => the average price of the trade : Precision PRICE_PRECISION
56
56
  *
57
- * 'newPrice' => the price of the asset after the trade : Precision MARK_PRICE_PRECISION
57
+ * 'newPrice' => the price of the asset after the trade : Precision PRICE_PRECISION
58
58
  */
59
59
  export function calculateTradeSlippage(
60
60
  direction: PositionDirection,
61
61
  amount: BN,
62
- market: MarketAccount,
62
+ market: PerpMarketAccount,
63
63
  inputAssetType: AssetType = 'quote',
64
64
  oraclePriceData?: OraclePriceData,
65
65
  useSpread = true
@@ -73,7 +73,7 @@ export function calculateTradeSlippage(
73
73
  oldPrice = calculateBidPrice(market, oraclePriceData);
74
74
  }
75
75
  } else {
76
- oldPrice = calculateMarkPrice(market, oraclePriceData);
76
+ oldPrice = calculateReservePrice(market, oraclePriceData);
77
77
  }
78
78
  if (amount.eq(ZERO)) {
79
79
  return [ZERO, ZERO, oldPrice, oldPrice];
@@ -90,7 +90,7 @@ export function calculateTradeSlippage(
90
90
 
91
91
  const entryPrice = acquiredQuoteAssetAmount
92
92
  .mul(AMM_TO_QUOTE_PRECISION_RATIO)
93
- .mul(MARK_PRICE_PRECISION)
93
+ .mul(PRICE_PRECISION)
94
94
  .div(acquiredBaseReserve.abs());
95
95
 
96
96
  let amm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
@@ -121,12 +121,12 @@ export function calculateTradeSlippage(
121
121
 
122
122
  const pctMaxSlippage = newPrice
123
123
  .sub(oldPrice)
124
- .mul(MARK_PRICE_PRECISION)
124
+ .mul(PRICE_PRECISION)
125
125
  .div(oldPrice)
126
126
  .abs();
127
127
  const pctAvgSlippage = entryPrice
128
128
  .sub(oldPrice)
129
- .mul(MARK_PRICE_PRECISION)
129
+ .mul(PRICE_PRECISION)
130
130
  .div(oldPrice)
131
131
  .abs();
132
132
 
@@ -147,7 +147,7 @@ export function calculateTradeSlippage(
147
147
  export function calculateTradeAcquiredAmounts(
148
148
  direction: PositionDirection,
149
149
  amount: BN,
150
- market: MarketAccount,
150
+ market: PerpMarketAccount,
151
151
  inputAssetType: AssetType = 'quote',
152
152
  oraclePriceData: OraclePriceData,
153
153
  useSpread = true
@@ -177,13 +177,13 @@ export function calculateTradeAcquiredAmounts(
177
177
 
178
178
  const acquiredBase = amm.baseAssetReserve.sub(newBaseAssetReserve);
179
179
  const acquiredQuote = amm.quoteAssetReserve.sub(newQuoteAssetReserve);
180
- const acquiredQuoteAssetamount = calculateQuoteAssetAmountSwapped(
180
+ const acquiredQuoteAssetAmount = calculateQuoteAssetAmountSwapped(
181
181
  acquiredQuote.abs(),
182
182
  amm.pegMultiplier,
183
183
  swapDirection
184
184
  );
185
185
 
186
- return [acquiredBase, acquiredQuote, acquiredQuoteAssetamount];
186
+ return [acquiredBase, acquiredQuote, acquiredQuoteAssetAmount];
187
187
  }
188
188
 
189
189
  /**
@@ -199,12 +199,12 @@ export function calculateTradeAcquiredAmounts(
199
199
  * [
200
200
  * direction => direction of trade required, PositionDirection
201
201
  * tradeSize => size of trade required, TODO-PRECISION
202
- * entryPrice => the entry price for the trade, MARK_PRICE_PRECISION
203
- * targetPrice => the target price MARK_PRICE_PRECISION
202
+ * entryPrice => the entry price for the trade, PRICE_PRECISION
203
+ * targetPrice => the target price PRICE_PRECISION
204
204
  * ]
205
205
  */
206
206
  export function calculateTargetPriceTrade(
207
- market: MarketAccount,
207
+ market: PerpMarketAccount,
208
208
  targetPrice: BN,
209
209
  pct: BN = MAXPCT,
210
210
  outputAssetType: AssetType = 'quote',
@@ -215,20 +215,20 @@ export function calculateTargetPriceTrade(
215
215
  assert(targetPrice.gt(ZERO));
216
216
  assert(pct.lte(MAXPCT) && pct.gt(ZERO));
217
217
 
218
- const markPriceBefore = calculateMarkPrice(market, oraclePriceData);
218
+ const reservePriceBefore = calculateReservePrice(market, oraclePriceData);
219
219
  const bidPriceBefore = calculateBidPrice(market, oraclePriceData);
220
220
  const askPriceBefore = calculateAskPrice(market, oraclePriceData);
221
221
 
222
222
  let direction;
223
- if (targetPrice.gt(markPriceBefore)) {
224
- const priceGap = targetPrice.sub(markPriceBefore);
223
+ if (targetPrice.gt(reservePriceBefore)) {
224
+ const priceGap = targetPrice.sub(reservePriceBefore);
225
225
  const priceGapScaled = priceGap.mul(pct).div(MAXPCT);
226
- targetPrice = markPriceBefore.add(priceGapScaled);
226
+ targetPrice = reservePriceBefore.add(priceGapScaled);
227
227
  direction = PositionDirection.LONG;
228
228
  } else {
229
- const priceGap = markPriceBefore.sub(targetPrice);
229
+ const priceGap = reservePriceBefore.sub(targetPrice);
230
230
  const priceGapScaled = priceGap.mul(pct).div(MAXPCT);
231
- targetPrice = markPriceBefore.sub(priceGapScaled);
231
+ targetPrice = reservePriceBefore.sub(priceGapScaled);
232
232
  direction = PositionDirection.SHORT;
233
233
  }
234
234
 
@@ -252,7 +252,7 @@ export function calculateTargetPriceTrade(
252
252
  }
253
253
 
254
254
  const invariant = market.amm.sqrtK.mul(market.amm.sqrtK);
255
- const k = invariant.mul(MARK_PRICE_PRECISION);
255
+ const k = invariant.mul(PRICE_PRECISION);
256
256
 
257
257
  let baseAssetReserveAfter;
258
258
  let quoteAssetReserveAfter;
@@ -265,21 +265,19 @@ export function calculateTargetPriceTrade(
265
265
  targetPrice.gt(bidPriceBefore)
266
266
  ) {
267
267
  // no trade, market is at target
268
- if (markPriceBefore.gt(targetPrice)) {
268
+ if (reservePriceBefore.gt(targetPrice)) {
269
269
  direction = PositionDirection.SHORT;
270
270
  } else {
271
271
  direction = PositionDirection.LONG;
272
272
  }
273
273
  tradeSize = ZERO;
274
274
  return [direction, tradeSize, targetPrice, targetPrice];
275
- } else if (markPriceBefore.gt(targetPrice)) {
275
+ } else if (reservePriceBefore.gt(targetPrice)) {
276
276
  // overestimate y2
277
277
  baseAssetReserveAfter = squareRootBN(
278
278
  k.div(targetPrice).mul(peg).div(PEG_PRECISION).sub(biasModifier)
279
279
  ).sub(new BN(1));
280
- quoteAssetReserveAfter = k
281
- .div(MARK_PRICE_PRECISION)
282
- .div(baseAssetReserveAfter);
280
+ quoteAssetReserveAfter = k.div(PRICE_PRECISION).div(baseAssetReserveAfter);
283
281
 
284
282
  markPriceAfter = calculatePrice(
285
283
  baseAssetReserveAfter,
@@ -293,14 +291,12 @@ export function calculateTargetPriceTrade(
293
291
  .div(PEG_PRECISION)
294
292
  .div(AMM_TO_QUOTE_PRECISION_RATIO);
295
293
  baseSize = baseAssetReserveAfter.sub(baseAssetReserveBefore);
296
- } else if (markPriceBefore.lt(targetPrice)) {
294
+ } else if (reservePriceBefore.lt(targetPrice)) {
297
295
  // underestimate y2
298
296
  baseAssetReserveAfter = squareRootBN(
299
297
  k.div(targetPrice).mul(peg).div(PEG_PRECISION).add(biasModifier)
300
298
  ).add(new BN(1));
301
- quoteAssetReserveAfter = k
302
- .div(MARK_PRICE_PRECISION)
303
- .div(baseAssetReserveAfter);
299
+ quoteAssetReserveAfter = k.div(PRICE_PRECISION).div(baseAssetReserveAfter);
304
300
 
305
301
  markPriceAfter = calculatePrice(
306
302
  baseAssetReserveAfter,
@@ -324,17 +320,17 @@ export function calculateTargetPriceTrade(
324
320
 
325
321
  let tp1 = targetPrice;
326
322
  let tp2 = markPriceAfter;
327
- let originalDiff = targetPrice.sub(markPriceBefore);
323
+ let originalDiff = targetPrice.sub(reservePriceBefore);
328
324
 
329
325
  if (direction == PositionDirection.SHORT) {
330
326
  tp1 = markPriceAfter;
331
327
  tp2 = targetPrice;
332
- originalDiff = markPriceBefore.sub(targetPrice);
328
+ originalDiff = reservePriceBefore.sub(targetPrice);
333
329
  }
334
330
 
335
331
  const entryPrice = tradeSize
336
332
  .mul(AMM_TO_QUOTE_PRECISION_RATIO)
337
- .mul(MARK_PRICE_PRECISION)
333
+ .mul(PRICE_PRECISION)
338
334
  .div(baseSize.abs());
339
335
 
340
336
  assert(tp1.sub(tp2).lte(originalDiff), 'Target Price Calculation incorrect');
@@ -2,7 +2,7 @@ import { parsePriceData } from '@pythnetwork/client';
2
2
  import { Connection, PublicKey } from '@solana/web3.js';
3
3
  import { OracleClient, OraclePriceData } from './types';
4
4
  import { BN } from '@project-serum/anchor';
5
- import { MARK_PRICE_PRECISION, TEN } from '../constants/numericConstants';
5
+ import { PRICE_PRECISION, TEN } from '../constants/numericConstants';
6
6
 
7
7
  export class PythClient implements OracleClient {
8
8
  private connection: Connection;
@@ -38,6 +38,6 @@ export function convertPythPrice(price: number, exponent: number): BN {
38
38
  exponent = Math.abs(exponent);
39
39
  const pythPrecision = TEN.pow(new BN(exponent).abs());
40
40
  return new BN(price * Math.pow(10, exponent))
41
- .mul(MARK_PRICE_PRECISION)
41
+ .mul(PRICE_PRECISION)
42
42
  .div(pythPrecision);
43
43
  }
@@ -1,10 +1,10 @@
1
1
  import { PublicKey } from '@solana/web3.js';
2
2
  import { OracleClient, OraclePriceData } from './types';
3
3
  import { BN } from '@project-serum/anchor';
4
- import { MARK_PRICE_PRECISION } from '../constants/numericConstants';
4
+ import { PRICE_PRECISION } from '../constants/numericConstants';
5
5
 
6
6
  export const QUOTE_ORACLE_PRICE_DATA: OraclePriceData = {
7
- price: MARK_PRICE_PRECISION,
7
+ price: PRICE_PRECISION,
8
8
  slot: new BN(0),
9
9
  confidence: new BN(1),
10
10
  hasSufficientNumberOfDataPoints: true,
@@ -1,7 +1,7 @@
1
1
  import { SwitchboardDecimal } from '@switchboard-xyz/switchboard-v2';
2
2
  import { Connection, Keypair, PublicKey } from '@solana/web3.js';
3
3
  import { BN, Program, Idl, AnchorProvider } from '@project-serum/anchor';
4
- import { MARK_PRICE_PRECISION, TEN } from '../constants/numericConstants';
4
+ import { PRICE_PRECISION, TEN } from '../constants/numericConstants';
5
5
  import { OracleClient, OraclePriceData } from './types';
6
6
  import { Wallet } from '../wallet';
7
7
  import switchboardV2Idl from '../idl/switchboard_v2.json';
@@ -74,6 +74,6 @@ function getSwitchboardProgram(connection: Connection): Program {
74
74
  function convertSwitchboardDecimal(switchboardDecimal: SwitchboardDecimal): BN {
75
75
  const switchboardPrecision = TEN.pow(new BN(switchboardDecimal.scale));
76
76
  return switchboardDecimal.mantissa
77
- .mul(MARK_PRICE_PRECISION)
77
+ .mul(PRICE_PRECISION)
78
78
  .div(switchboardPrecision);
79
79
  }
@@ -2,32 +2,40 @@ import { OptionalOrderParams, OrderTriggerCondition, OrderType } from './types';
2
2
  import { BN } from '@project-serum/anchor';
3
3
 
4
4
  export function getLimitOrderParams(
5
- params: Omit<OptionalOrderParams, 'orderType'> & { price: BN }
5
+ params: Omit<OptionalOrderParams, 'orderType' | 'marketType'> & { price: BN }
6
6
  ): OptionalOrderParams {
7
- return Object.assign({}, params, { orderType: OrderType.LIMIT });
7
+ return Object.assign({}, params, {
8
+ orderType: OrderType.LIMIT,
9
+ });
8
10
  }
9
11
 
10
12
  export function getTriggerMarketOrderParams(
11
- params: Omit<OptionalOrderParams, 'orderType'> & {
13
+ params: Omit<OptionalOrderParams, 'orderType' | 'marketType'> & {
12
14
  triggerCondition: OrderTriggerCondition;
13
15
  triggerPrice: BN;
14
16
  }
15
17
  ): OptionalOrderParams {
16
- return Object.assign({}, params, { orderType: OrderType.TRIGGER_MARKET });
18
+ return Object.assign({}, params, {
19
+ orderType: OrderType.TRIGGER_MARKET,
20
+ });
17
21
  }
18
22
 
19
23
  export function getTriggerLimitOrderParams(
20
- params: Omit<OptionalOrderParams, 'orderType'> & {
24
+ params: Omit<OptionalOrderParams, 'orderType' | 'marketType'> & {
21
25
  triggerCondition: OrderTriggerCondition;
22
26
  triggerPrice: BN;
23
27
  price: BN;
24
28
  }
25
29
  ): OptionalOrderParams {
26
- return Object.assign({}, params, { orderType: OrderType.TRIGGER_LIMIT });
30
+ return Object.assign({}, params, {
31
+ orderType: OrderType.TRIGGER_LIMIT,
32
+ });
27
33
  }
28
34
 
29
35
  export function getMarketOrderParams(
30
- params: Omit<OptionalOrderParams, 'orderType'>
36
+ params: Omit<OptionalOrderParams, 'orderType' | 'marketType'>
31
37
  ): OptionalOrderParams {
32
- return Object.assign({}, params, { orderType: OrderType.MARKET });
38
+ return Object.assign({}, params, {
39
+ orderType: OrderType.MARKET,
40
+ });
33
41
  }