@drift-labs/sdk 0.1.36-master.5 → 0.2.0-master.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 (197) hide show
  1. package/lib/accounts/bulkAccountLoader.d.ts +7 -6
  2. package/lib/accounts/bulkAccountLoader.js +83 -93
  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 +8 -12
  26. package/lib/admin.js +366 -490
  27. package/lib/clearingHouse.d.ts +84 -103
  28. package/lib/clearingHouse.js +779 -810
  29. package/lib/clearingHouseConfig.d.ts +34 -0
  30. package/lib/clearingHouseConfig.js +2 -0
  31. package/lib/clearingHouseUser.d.ts +19 -18
  32. package/lib/clearingHouseUser.js +157 -115
  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 +34 -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 +16 -0
  42. package/lib/constants/numericConstants.js +22 -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 +112 -0
  61. package/lib/factory/bigNum.js +356 -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 +1739 -2287
  65. package/lib/index.d.ts +13 -4
  66. package/lib/index.js +13 -4
  67. package/lib/math/amm.d.ts +19 -29
  68. package/lib/math/amm.js +129 -179
  69. package/lib/math/auction.d.ts +5 -0
  70. package/lib/math/auction.js +39 -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/oracles.d.ts +3 -0
  80. package/lib/math/oracles.js +26 -0
  81. package/lib/math/orders.d.ts +5 -0
  82. package/lib/math/orders.js +31 -1
  83. package/lib/math/position.d.ts +7 -4
  84. package/lib/math/position.js +27 -9
  85. package/lib/math/repeg.d.ts +22 -0
  86. package/lib/math/repeg.js +128 -0
  87. package/lib/math/trade.d.ts +13 -8
  88. package/lib/math/trade.js +85 -22
  89. package/lib/mockUSDCFaucet.js +87 -116
  90. package/lib/oracles/oracleClientCache.d.ts +8 -0
  91. package/lib/oracles/oracleClientCache.js +19 -0
  92. package/lib/oracles/pythClient.d.ts +3 -5
  93. package/lib/oracles/pythClient.js +12 -30
  94. package/lib/oracles/quoteAssetOracleClient.d.ts +9 -0
  95. package/lib/oracles/quoteAssetOracleClient.js +21 -0
  96. package/lib/oracles/switchboardClient.d.ts +3 -5
  97. package/lib/oracles/switchboardClient.js +29 -47
  98. package/lib/oracles/types.d.ts +7 -1
  99. package/lib/orders.d.ts +6 -6
  100. package/lib/orders.js +10 -9
  101. package/lib/slot/SlotSubscriber.d.ts +12 -0
  102. package/lib/slot/SlotSubscriber.js +23 -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 +105 -98
  109. package/lib/types.js +13 -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 +10 -3
  116. package/src/accounts/bulkAccountLoader.ts +26 -15
  117. package/src/accounts/bulkUserSubscription.ts +1 -45
  118. package/src/accounts/fetch.ts +33 -0
  119. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +249 -214
  120. package/src/accounts/pollingOracleSubscriber.ts +16 -8
  121. package/src/accounts/pollingTokenAccountSubscriber.ts +11 -8
  122. package/src/accounts/pollingUserAccountSubscriber.ts +21 -86
  123. package/src/accounts/types.ts +41 -70
  124. package/src/accounts/webSocketAccountSubscriber.ts +33 -16
  125. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +190 -240
  126. package/src/accounts/webSocketUserAccountSubscriber.ts +11 -71
  127. package/src/addresses/marketAddresses.ts +18 -0
  128. package/src/addresses/pda.ts +118 -0
  129. package/src/admin.ts +209 -267
  130. package/src/clearingHouse.ts +921 -829
  131. package/src/clearingHouseConfig.ts +37 -0
  132. package/src/clearingHouseUser.ts +280 -127
  133. package/src/clearingHouseUserConfig.ts +18 -0
  134. package/src/config.ts +54 -1
  135. package/src/constants/banks.ts +43 -0
  136. package/src/constants/markets.ts +16 -207
  137. package/src/constants/numericConstants.ts +33 -5
  138. package/src/events/eventList.ts +94 -0
  139. package/src/events/eventSubscriber.ts +194 -0
  140. package/src/events/fetchLogs.ts +80 -0
  141. package/src/events/pollingLogProvider.ts +79 -0
  142. package/src/events/sort.ts +65 -0
  143. package/src/events/txEventCache.ts +74 -0
  144. package/src/events/types.ts +98 -0
  145. package/src/events/webSocketLogProvider.ts +38 -0
  146. package/src/examples/makeTradeExample.ts +20 -11
  147. package/src/factory/bigNum.ts +507 -0
  148. package/src/factory/oracleClient.ts +7 -4
  149. package/src/idl/clearing_house.json +1739 -2287
  150. package/src/index.ts +13 -4
  151. package/src/math/amm.ts +229 -245
  152. package/src/math/auction.ts +39 -0
  153. package/src/math/bankBalance.ts +112 -0
  154. package/src/math/conversion.ts +1 -11
  155. package/src/math/funding.ts +12 -9
  156. package/src/math/market.ts +37 -30
  157. package/src/math/oracles.ts +36 -0
  158. package/src/math/orders.ts +38 -0
  159. package/src/math/position.ts +48 -13
  160. package/src/math/repeg.ts +175 -0
  161. package/src/math/trade.ts +114 -36
  162. package/src/math/utils.js +27 -0
  163. package/src/math/utils.js.map +1 -0
  164. package/src/oracles/oracleClientCache.ts +20 -0
  165. package/src/oracles/pythClient.ts +5 -11
  166. package/src/oracles/quoteAssetOracleClient.ts +25 -0
  167. package/src/oracles/switchboardClient.ts +16 -24
  168. package/src/oracles/types.ts +8 -1
  169. package/src/orders.ts +35 -20
  170. package/src/slot/SlotSubscriber.ts +32 -0
  171. package/src/tx/retryTxSender.ts +6 -4
  172. package/src/tx/types.ts +6 -1
  173. package/src/tx/utils.ts +22 -3
  174. package/src/types.ts +108 -110
  175. package/src/userName.ts +20 -0
  176. package/src/util/computeUnits.js +17 -0
  177. package/src/util/computeUnits.js.map +1 -0
  178. package/tests/bn/test.ts +255 -0
  179. package/tsconfig.json +12 -12
  180. package/lib/addresses.d.ts +0 -9
  181. package/lib/addresses.js +0 -87
  182. package/lib/constants/accounts.d.ts +0 -15
  183. package/lib/constants/accounts.js +0 -18
  184. package/lib/factory/clearingHouse.d.ts +0 -35
  185. package/lib/factory/clearingHouse.js +0 -81
  186. package/lib/factory/clearingHouseUser.d.ts +0 -19
  187. package/lib/factory/clearingHouseUser.js +0 -34
  188. package/lib/math/insuranceFund.d.ts +0 -15
  189. package/lib/math/insuranceFund.js +0 -33
  190. package/lib/tx/defaultTxSender.d.ts +0 -8
  191. package/lib/tx/defaultTxSender.js +0 -12
  192. package/src/addresses.ts +0 -71
  193. package/src/constants/accounts.ts +0 -26
  194. package/src/factory/clearingHouse.ts +0 -173
  195. package/src/factory/clearingHouseUser.ts +0 -73
  196. package/src/math/insuranceFund.ts +0 -29
  197. package/src/tx/defaultTxSender.ts +0 -24
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@ export * from './oracles/pythClient';
7
7
  export * from './oracles/switchboardClient';
8
8
  export * from './types';
9
9
  export * from './constants/markets';
10
+ export * from './accounts/fetch';
10
11
  export * from './accounts/webSocketClearingHouseAccountSubscriber';
11
12
  export * from './accounts/bulkAccountLoader';
12
13
  export * from './accounts/bulkUserSubscription';
@@ -14,23 +15,28 @@ export * from './accounts/pollingClearingHouseAccountSubscriber';
14
15
  export * from './accounts/pollingOracleSubscriber';
15
16
  export * from './accounts/pollingTokenAccountSubscriber';
16
17
  export * from './accounts/types';
17
- export * from './addresses';
18
+ export * from './addresses/pda';
18
19
  export * from './admin';
19
20
  export * from './clearingHouseUser';
21
+ export * from './clearingHouseUserConfig';
20
22
  export * from './clearingHouse';
21
- export * from './factory/clearingHouse';
22
- export * from './factory/clearingHouseUser';
23
23
  export * from './factory/oracleClient';
24
+ export * from './factory/bigNum';
25
+ export * from './events/types';
26
+ export * from './events/eventSubscriber';
27
+ export * from './math/auction';
24
28
  export * from './math/conversion';
25
29
  export * from './math/funding';
26
- export * from './math/insuranceFund';
27
30
  export * from './math/market';
28
31
  export * from './math/position';
32
+ export * from './math/oracles';
29
33
  export * from './math/amm';
30
34
  export * from './math/trade';
31
35
  export * from './math/orders';
36
+ export * from './math/repeg';
32
37
  export * from './orders';
33
38
  export * from './orderParams';
39
+ export * from './slot/SlotSubscriber';
34
40
  export * from './wallet';
35
41
  export * from './types';
36
42
  export * from './math/utils';
@@ -39,5 +45,8 @@ export * from './constants/numericConstants';
39
45
  export * from './tx/retryTxSender';
40
46
  export * from './util/computeUnits';
41
47
  export * from './util/tps';
48
+ export * from './math/bankBalance';
49
+ export * from './constants/banks';
50
+ export * from './clearingHouseConfig';
42
51
 
43
52
  export { BN, PublicKey };
package/src/math/amm.ts CHANGED
@@ -4,50 +4,189 @@ import {
4
4
  MARK_PRICE_PRECISION,
5
5
  PEG_PRECISION,
6
6
  ZERO,
7
- AMM_TO_QUOTE_PRECISION_RATIO,
8
- QUOTE_PRECISION,
9
- AMM_RESERVE_PRECISION,
10
7
  BID_ASK_SPREAD_PRECISION,
11
8
  ONE,
9
+ // QUOTE_PRECISION,
10
+ AMM_TO_QUOTE_PRECISION_RATIO,
12
11
  } from '../constants/numericConstants';
13
- import { calculateBaseAssetValue } from './position';
14
12
  import {
15
13
  AMM,
16
14
  PositionDirection,
17
15
  SwapDirection,
18
- Market,
16
+ MarketAccount,
19
17
  isVariant,
20
18
  } from '../types';
21
19
  import { assert } from '../assert/assert';
20
+ import { squareRootBN } from '..';
21
+
22
+ import { OraclePriceData } from '../oracles/types';
22
23
  import {
23
- calculatePositionPNL,
24
- calculateMarkPrice,
25
- convertToNumber,
26
- squareRootBN,
27
- } from '..';
24
+ calculateRepegCost,
25
+ calculateAdjustKCost,
26
+ calculateBudgetedPeg,
27
+ } from './repeg';
28
+ export function calculateNewAmm(
29
+ amm: AMM,
30
+ oraclePriceData: OraclePriceData
31
+ ): [BN, BN, BN, BN] {
32
+ let pKNumer = new BN(1);
33
+ let pKDenom = new BN(1);
34
+
35
+ const targetPrice = oraclePriceData.price;
36
+ let newPeg = targetPrice
37
+ .mul(amm.baseAssetReserve)
38
+ .div(amm.quoteAssetReserve)
39
+ .add(MARK_PRICE_PRECISION.div(PEG_PRECISION).div(new BN(2)))
40
+ .div(MARK_PRICE_PRECISION.div(PEG_PRECISION));
41
+ let prePegCost = calculateRepegCost(amm, newPeg);
42
+
43
+ const totalFeeLB = amm.totalExchangeFee.div(new BN(2));
44
+ const budget = BN.max(ZERO, amm.totalFeeMinusDistributions.sub(totalFeeLB));
45
+
46
+ if (prePegCost.gt(budget)) {
47
+ [pKNumer, pKDenom] = [new BN(999), new BN(1000)];
48
+ const deficitMadeup = calculateAdjustKCost(amm, pKNumer, pKDenom);
49
+ assert(deficitMadeup.lte(new BN(0)));
50
+ prePegCost = budget.add(deficitMadeup.abs());
51
+ const newAmm = Object.assign({}, amm);
52
+ newAmm.baseAssetReserve = newAmm.baseAssetReserve.mul(pKNumer).div(pKDenom);
53
+ newAmm.sqrtK = newAmm.sqrtK.mul(pKNumer).div(pKDenom);
54
+ const invariant = newAmm.sqrtK.mul(newAmm.sqrtK);
55
+ newAmm.quoteAssetReserve = invariant.div(newAmm.baseAssetReserve);
56
+ const directionToClose = amm.netBaseAssetAmount.gt(ZERO)
57
+ ? PositionDirection.SHORT
58
+ : PositionDirection.LONG;
59
+
60
+ const [newQuoteAssetReserve, _newBaseAssetReserve] =
61
+ calculateAmmReservesAfterSwap(
62
+ newAmm,
63
+ 'base',
64
+ amm.netBaseAssetAmount.abs(),
65
+ getSwapDirection('base', directionToClose)
66
+ );
67
+
68
+ newAmm.terminalQuoteAssetReserve = newQuoteAssetReserve;
69
+
70
+ newPeg = calculateBudgetedPeg(newAmm, prePegCost, targetPrice);
71
+ prePegCost = calculateRepegCost(newAmm, newPeg);
72
+ }
73
+
74
+ return [prePegCost, pKNumer, pKDenom, newPeg];
75
+ }
76
+
77
+ export function calculateUpdatedAMM(
78
+ amm: AMM,
79
+ oraclePriceData: OraclePriceData
80
+ ): AMM {
81
+ if (amm.curveUpdateIntensity == 0) {
82
+ return amm;
83
+ }
84
+ const newAmm = Object.assign({}, amm);
85
+ const [prepegCost, pKNumer, pKDenom, newPeg] = calculateNewAmm(
86
+ amm,
87
+ oraclePriceData
88
+ );
89
+
90
+ newAmm.baseAssetReserve = newAmm.baseAssetReserve.mul(pKNumer).div(pKDenom);
91
+ newAmm.sqrtK = newAmm.sqrtK.mul(pKNumer).div(pKDenom);
92
+ const invariant = newAmm.sqrtK.mul(newAmm.sqrtK);
93
+ newAmm.quoteAssetReserve = invariant.div(newAmm.baseAssetReserve);
94
+ newAmm.pegMultiplier = newPeg;
95
+
96
+ const directionToClose = amm.netBaseAssetAmount.gt(ZERO)
97
+ ? PositionDirection.SHORT
98
+ : PositionDirection.LONG;
99
+
100
+ const [newQuoteAssetReserve, _newBaseAssetReserve] =
101
+ calculateAmmReservesAfterSwap(
102
+ newAmm,
103
+ 'base',
104
+ amm.netBaseAssetAmount.abs(),
105
+ getSwapDirection('base', directionToClose)
106
+ );
107
+
108
+ newAmm.terminalQuoteAssetReserve = newQuoteAssetReserve;
109
+
110
+ newAmm.totalFeeMinusDistributions =
111
+ newAmm.totalFeeMinusDistributions.sub(prepegCost);
112
+
113
+ return newAmm;
114
+ }
115
+
116
+ export function calculateUpdatedAMMSpreadReserves(
117
+ amm: AMM,
118
+ direction: PositionDirection,
119
+ oraclePriceData: OraclePriceData
120
+ ): { baseAssetReserve: BN; quoteAssetReserve: BN; sqrtK: BN; newPeg: BN } {
121
+ const newAmm = calculateUpdatedAMM(amm, oraclePriceData);
122
+ const dirReserves = calculateSpreadReserves(
123
+ newAmm,
124
+ direction,
125
+ oraclePriceData
126
+ );
127
+ const result = {
128
+ baseAssetReserve: dirReserves.baseAssetReserve,
129
+ quoteAssetReserve: dirReserves.quoteAssetReserve,
130
+ sqrtK: newAmm.sqrtK,
131
+ newPeg: newAmm.pegMultiplier,
132
+ };
133
+
134
+ return result;
135
+ }
136
+
137
+ export function calculateBidAskPrice(
138
+ amm: AMM,
139
+ oraclePriceData: OraclePriceData
140
+ ): [BN, BN] {
141
+ const newAmm = calculateUpdatedAMM(amm, oraclePriceData);
142
+ const askReserves = calculateSpreadReserves(
143
+ newAmm,
144
+ PositionDirection.LONG,
145
+ oraclePriceData
146
+ );
147
+ const bidReserves = calculateSpreadReserves(
148
+ newAmm,
149
+ PositionDirection.SHORT,
150
+ oraclePriceData
151
+ );
152
+
153
+ const askPrice = calculatePrice(
154
+ askReserves.baseAssetReserve,
155
+ askReserves.quoteAssetReserve,
156
+ newAmm.pegMultiplier
157
+ );
158
+
159
+ const bidPrice = calculatePrice(
160
+ bidReserves.baseAssetReserve,
161
+ bidReserves.quoteAssetReserve,
162
+ newAmm.pegMultiplier
163
+ );
164
+
165
+ return [bidPrice, askPrice];
166
+ }
28
167
 
29
168
  /**
30
169
  * Calculates a price given an arbitrary base and quote amount (they must have the same precision)
31
170
  *
32
- * @param baseAssetAmount
33
- * @param quoteAssetAmount
34
- * @param peg_multiplier
171
+ * @param baseAssetReserves
172
+ * @param quoteAssetReserves
173
+ * @param pegMultiplier
35
174
  * @returns price : Precision MARK_PRICE_PRECISION
36
175
  */
37
176
  export function calculatePrice(
38
- baseAssetAmount: BN,
39
- quoteAssetAmount: BN,
40
- peg_multiplier: BN
177
+ baseAssetReserves: BN,
178
+ quoteAssetReserves: BN,
179
+ pegMultiplier: BN
41
180
  ): BN {
42
- if (baseAssetAmount.abs().lte(ZERO)) {
181
+ if (baseAssetReserves.abs().lte(ZERO)) {
43
182
  return new BN(0);
44
183
  }
45
184
 
46
- return quoteAssetAmount
185
+ return quoteAssetReserves
47
186
  .mul(MARK_PRICE_PRECISION)
48
- .mul(peg_multiplier)
187
+ .mul(pegMultiplier)
49
188
  .div(PEG_PRECISION)
50
- .div(baseAssetAmount);
189
+ .div(baseAssetReserves);
51
190
  }
52
191
 
53
192
  export type AssetType = 'quote' | 'base';
@@ -100,15 +239,65 @@ export function calculateAmmReservesAfterSwap(
100
239
 
101
240
  export function calculateSpread(
102
241
  amm: AMM,
103
- direction: PositionDirection
242
+ direction: PositionDirection,
243
+ oraclePriceData: OraclePriceData
104
244
  ): number {
105
- let spread;
245
+ let spread = amm.baseSpread / 2;
106
246
 
107
- // future logic
108
- if (isVariant(direction, 'long')) {
109
- spread = amm.baseSpread;
110
- } else {
111
- spread = amm.baseSpread;
247
+ if (amm.baseSpread == 0 || amm.curveUpdateIntensity == 0) {
248
+ return spread;
249
+ }
250
+
251
+ const markPrice = calculatePrice(
252
+ amm.baseAssetReserve,
253
+ amm.quoteAssetReserve,
254
+ amm.pegMultiplier
255
+ );
256
+
257
+ const targetPrice = oraclePriceData?.price || markPrice;
258
+
259
+ const targetMarkSpreadPct = markPrice
260
+ .sub(targetPrice)
261
+ .mul(BID_ASK_SPREAD_PRECISION)
262
+ .div(markPrice);
263
+
264
+ // oracle retreat
265
+ if (
266
+ (isVariant(direction, 'long') && targetMarkSpreadPct.lt(ZERO)) ||
267
+ (isVariant(direction, 'short') && targetMarkSpreadPct.gt(ZERO))
268
+ ) {
269
+ spread = Math.max(spread, targetMarkSpreadPct.abs().toNumber());
270
+ }
271
+
272
+ // inventory skew
273
+ const MAX_INVENTORY_SKEW = 5;
274
+ if (
275
+ (amm.netBaseAssetAmount.gt(ZERO) && isVariant(direction, 'long')) ||
276
+ (amm.netBaseAssetAmount.lt(ZERO) && isVariant(direction, 'short')) ||
277
+ amm.totalFeeMinusDistributions.eq(ZERO)
278
+ ) {
279
+ const netCostBasis = amm.quoteAssetAmountLong.sub(
280
+ amm.quoteAssetAmountShort
281
+ );
282
+ const netBaseAssetValue = amm.quoteAssetReserve
283
+ .sub(amm.terminalQuoteAssetReserve)
284
+ .mul(amm.pegMultiplier)
285
+ .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
286
+
287
+ const localBaseAssetValue = amm.netBaseAssetAmount
288
+ .mul(markPrice)
289
+ .div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
290
+ const netPnl = netBaseAssetValue.sub(netCostBasis);
291
+ const localPnl = localBaseAssetValue.sub(netCostBasis);
292
+
293
+ let effectiveLeverage = MAX_INVENTORY_SKEW;
294
+ if (amm.totalFeeMinusDistributions.gt(ZERO)) {
295
+ effectiveLeverage =
296
+ localPnl.sub(netPnl).toNumber() /
297
+ amm.totalFeeMinusDistributions.toNumber();
298
+ }
299
+
300
+ spread *= Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
112
301
  }
113
302
 
114
303
  return spread;
@@ -116,12 +305,13 @@ export function calculateSpread(
116
305
 
117
306
  export function calculateSpreadReserves(
118
307
  amm: AMM,
119
- direction: PositionDirection
308
+ direction: PositionDirection,
309
+ oraclePriceData: OraclePriceData
120
310
  ): {
121
311
  baseAssetReserve: BN;
122
312
  quoteAssetReserve: BN;
123
313
  } {
124
- const spread = calculateSpread(amm, direction);
314
+ const spread = calculateSpread(amm, direction, oraclePriceData);
125
315
 
126
316
  if (spread === 0) {
127
317
  return {
@@ -131,7 +321,7 @@ export function calculateSpreadReserves(
131
321
  }
132
322
 
133
323
  const quoteAsserReserveDelta = amm.quoteAssetReserve.div(
134
- BID_ASK_SPREAD_PRECISION.div(new BN(spread / 4))
324
+ BID_ASK_SPREAD_PRECISION.div(new BN(spread / 2))
135
325
  );
136
326
 
137
327
  let quoteAssetReserve;
@@ -194,133 +384,14 @@ export function getSwapDirection(
194
384
  return SwapDirection.ADD;
195
385
  }
196
386
 
197
- /**
198
- * Helper function calculating adjust k cost
199
- * @param market
200
- * @param marketIndex
201
- * @param numerator
202
- * @param denomenator
203
- * @returns cost : Precision QUOTE_ASSET_PRECISION
204
- */
205
- export function calculateAdjustKCost(
206
- market: Market,
207
- marketIndex: BN,
208
- numerator: BN,
209
- denomenator: BN
210
- ): BN {
211
- const netUserPosition = {
212
- baseAssetAmount: market.baseAssetAmount,
213
- lastCumulativeFundingRate: market.amm.cumulativeFundingRate,
214
- marketIndex: new BN(marketIndex),
215
- quoteAssetAmount: new BN(0),
216
- openOrders: new BN(0),
217
- };
218
-
219
- const currentValue = calculateBaseAssetValue(market, netUserPosition);
220
-
221
- const marketNewK = Object.assign({}, market);
222
- marketNewK.amm = Object.assign({}, market.amm);
223
-
224
- marketNewK.amm.baseAssetReserve = market.amm.baseAssetReserve
225
- .mul(numerator)
226
- .div(denomenator);
227
- marketNewK.amm.quoteAssetReserve = market.amm.quoteAssetReserve
228
- .mul(numerator)
229
- .div(denomenator);
230
- marketNewK.amm.sqrtK = market.amm.sqrtK.mul(numerator).div(denomenator);
231
-
232
- netUserPosition.quoteAssetAmount = currentValue;
233
-
234
- const cost = calculatePositionPNL(marketNewK, netUserPosition);
235
-
236
- const p = PEG_PRECISION.mul(numerator).div(denomenator);
237
- const x = market.amm.baseAssetReserve;
238
- const y = market.amm.quoteAssetReserve;
239
- const delta = market.baseAssetAmount;
240
- const k = market.amm.sqrtK.mul(market.amm.sqrtK);
241
-
242
- const numer1 = PEG_PRECISION.sub(p).mul(y).div(PEG_PRECISION);
243
- const numer20 = k
244
- .mul(p)
245
- .mul(p)
246
- .div(PEG_PRECISION)
247
- .div(PEG_PRECISION)
248
- .div(x.mul(p).div(PEG_PRECISION).add(delta));
249
- const numer21 = k.div(x.add(delta));
250
-
251
- const formulaCost = numer21
252
- .sub(numer20)
253
- .sub(numer1)
254
- .mul(market.amm.pegMultiplier)
255
- .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
256
- console.log(convertToNumber(formulaCost, QUOTE_PRECISION));
257
-
258
- // p.div(p.mul(x).add(delta)).sub()
259
-
260
- return cost;
261
- }
262
-
263
- /**
264
- * Helper function calculating adjust pegMultiplier (repeg) cost
265
- *
266
- * @param market
267
- * @param marketIndex
268
- * @param newPeg
269
- * @returns cost : Precision QUOTE_ASSET_PRECISION
270
- */
271
- export function calculateRepegCost(
272
- market: Market,
273
- marketIndex: BN,
274
- newPeg: BN
275
- ): BN {
276
- const netUserPosition = {
277
- baseAssetAmount: market.baseAssetAmount,
278
- lastCumulativeFundingRate: market.amm.cumulativeFundingRate,
279
- marketIndex: new BN(marketIndex),
280
- quoteAssetAmount: new BN(0),
281
- openOrders: new BN(0),
282
- };
283
-
284
- const currentValue = calculateBaseAssetValue(market, netUserPosition);
285
- netUserPosition.quoteAssetAmount = currentValue;
286
- const prevMarketPrice = calculateMarkPrice(market);
287
- const marketNewPeg = Object.assign({}, market);
288
- marketNewPeg.amm = Object.assign({}, market.amm);
289
-
290
- // const marketNewPeg = JSON.parse(JSON.stringify(market));
291
- marketNewPeg.amm.pegMultiplier = newPeg;
292
-
293
- console.log(
294
- 'Price moves from',
295
- convertToNumber(prevMarketPrice),
296
- 'to',
297
- convertToNumber(calculateMarkPrice(marketNewPeg))
298
- );
299
-
300
- const cost = calculatePositionPNL(marketNewPeg, netUserPosition);
301
-
302
- const k = market.amm.sqrtK.mul(market.amm.sqrtK);
303
- const newQuoteAssetReserve = k.div(
304
- market.amm.baseAssetReserve.add(netUserPosition.baseAssetAmount)
305
- );
306
- const deltaQuoteAssetReserves = newQuoteAssetReserve.sub(
307
- market.amm.quoteAssetReserve
308
- );
309
- const cost2 = deltaQuoteAssetReserves
310
- .mul(market.amm.pegMultiplier.sub(newPeg))
311
- .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
312
- console.log(convertToNumber(cost2, QUOTE_PRECISION));
313
- return cost;
314
- }
315
-
316
387
  /**
317
388
  * Helper function calculating terminal price of amm
318
389
  *
319
390
  * @param market
320
391
  * @returns cost : Precision MARK_PRICE_PRECISION
321
392
  */
322
- export function calculateTerminalPrice(market: Market) {
323
- const directionToClose = market.baseAssetAmount.gt(ZERO)
393
+ export function calculateTerminalPrice(market: MarketAccount) {
394
+ const directionToClose = market.amm.netBaseAssetAmount.gt(ZERO)
324
395
  ? PositionDirection.SHORT
325
396
  : PositionDirection.LONG;
326
397
 
@@ -328,7 +399,7 @@ export function calculateTerminalPrice(market: Market) {
328
399
  calculateAmmReservesAfterSwap(
329
400
  market.amm,
330
401
  'base',
331
- market.baseAssetAmount.abs(),
402
+ market.amm.netBaseAssetAmount.abs(),
332
403
  getSwapDirection('base', directionToClose)
333
404
  );
334
405
 
@@ -345,7 +416,7 @@ export function calculateMaxBaseAssetAmountToTrade(
345
416
  amm: AMM,
346
417
  limit_price: BN,
347
418
  direction: PositionDirection,
348
- useSpread: boolean
419
+ oraclePriceData?: OraclePriceData
349
420
  ): [BN, PositionDirection] {
350
421
  const invariant = amm.sqrtK.mul(amm.sqrtK);
351
422
 
@@ -357,15 +428,11 @@ export function calculateMaxBaseAssetAmountToTrade(
357
428
 
358
429
  const newBaseAssetReserve = squareRootBN(newBaseAssetReserveSquared);
359
430
 
360
- let baseAssetReserveBefore;
361
- if (useSpread) {
362
- baseAssetReserveBefore = calculateSpreadReserves(
363
- amm,
364
- direction
365
- ).baseAssetReserve;
366
- } else {
367
- baseAssetReserveBefore = amm.baseAssetReserve;
368
- }
431
+ const baseAssetReserveBefore = calculateSpreadReserves(
432
+ amm,
433
+ direction,
434
+ oraclePriceData
435
+ ).baseAssetReserve;
369
436
 
370
437
  if (newBaseAssetReserve.gt(baseAssetReserveBefore)) {
371
438
  return [
@@ -383,89 +450,6 @@ export function calculateMaxBaseAssetAmountToTrade(
383
450
  }
384
451
  }
385
452
 
386
- export function calculateBudgetedK(market: Market, cost: BN): [BN, BN] {
387
- // wolframalpha.com
388
- // (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
389
- // p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
390
-
391
- // todo: assumes k = x * y
392
- // otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
393
-
394
- // const k = market.amm.sqrtK.mul(market.amm.sqrtK);
395
- const x = market.amm.baseAssetReserve;
396
- const y = market.amm.quoteAssetReserve;
397
-
398
- const d = market.baseAssetAmount;
399
- const Q = market.amm.pegMultiplier;
400
-
401
- const C = cost.mul(new BN(-1));
402
-
403
- const numer1 = y.mul(d).mul(Q).div(AMM_RESERVE_PRECISION).div(PEG_PRECISION);
404
- const numer2 = C.mul(x.add(d)).div(QUOTE_PRECISION);
405
- const denom1 = C.mul(x)
406
- .mul(x.add(d))
407
- .div(AMM_RESERVE_PRECISION)
408
- .div(QUOTE_PRECISION);
409
- const denom2 = y
410
- .mul(d)
411
- .mul(d)
412
- .mul(Q)
413
- .div(AMM_RESERVE_PRECISION)
414
- .div(AMM_RESERVE_PRECISION)
415
- .div(PEG_PRECISION);
416
-
417
- const numerator = d
418
- .mul(numer1.add(numer2))
419
- .div(AMM_RESERVE_PRECISION)
420
- .div(AMM_RESERVE_PRECISION)
421
- .div(AMM_TO_QUOTE_PRECISION_RATIO);
422
- const denominator = denom1
423
- .add(denom2)
424
- .div(AMM_RESERVE_PRECISION)
425
- .div(AMM_TO_QUOTE_PRECISION_RATIO);
426
- console.log(numerator, denominator);
427
- // const p = (numerator).div(denominator);
428
-
429
- // const formulaCost = (numer21.sub(numer20).sub(numer1)).mul(market.amm.pegMultiplier).div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
430
- // console.log(convertToNumber(formulaCost, QUOTE_PRECISION))
431
-
432
- return [numerator, denominator];
433
- }
434
-
435
- export function calculateBudgetedPeg(market: Market, cost: BN): BN {
436
- // wolframalpha.com
437
- // (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
438
- // p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
439
-
440
- // todo: assumes k = x * y
441
- // otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
442
-
443
- const k = market.amm.sqrtK.mul(market.amm.sqrtK);
444
- const x = market.amm.baseAssetReserve;
445
- const y = market.amm.quoteAssetReserve;
446
-
447
- const d = market.baseAssetAmount;
448
- const Q = market.amm.pegMultiplier;
449
-
450
- const C = cost.mul(new BN(-1));
451
-
452
- const deltaQuoteAssetReserves = y.sub(k.div(x.add(d)));
453
- const deltaPegMultiplier = C.mul(MARK_PRICE_PRECISION)
454
- .div(deltaQuoteAssetReserves.div(AMM_TO_QUOTE_PRECISION_RATIO))
455
- .mul(PEG_PRECISION)
456
- .div(QUOTE_PRECISION);
457
- console.log(
458
- Q.toNumber(),
459
- 'change by',
460
- deltaPegMultiplier.toNumber() / MARK_PRICE_PRECISION.toNumber()
461
- );
462
- const newPeg = Q.sub(
463
- deltaPegMultiplier.mul(PEG_PRECISION).div(MARK_PRICE_PRECISION)
464
- );
465
-
466
- return newPeg;
467
- }
468
-
469
453
  export function calculateQuoteAssetAmountSwapped(
470
454
  quoteAssetReserves: BN,
471
455
  pegMultiplier: BN,
@@ -0,0 +1,39 @@
1
+ import { isVariant, Order } from '../types';
2
+ import { BN, ZERO } from '../.';
3
+
4
+ export function isAuctionComplete(order: Order, slot: number): boolean {
5
+ return new BN(slot).sub(order.slot).gte(new BN(order.auctionDuration));
6
+ }
7
+
8
+ export function getAuctionPrice(order: Order, slot: number): BN {
9
+ const slotsElapsed = new BN(slot).sub(order.slot);
10
+
11
+ const deltaDenominator = new BN(order.auctionDuration);
12
+ const deltaNumerator = BN.min(slotsElapsed, deltaDenominator);
13
+
14
+ if (deltaDenominator.eq(ZERO)) {
15
+ return order.auctionEndPrice;
16
+ }
17
+
18
+ let priceDelta;
19
+ if (isVariant(order.direction, 'long')) {
20
+ priceDelta = order.auctionEndPrice
21
+ .sub(order.auctionStartPrice)
22
+ .mul(deltaNumerator)
23
+ .div(deltaDenominator);
24
+ } else {
25
+ priceDelta = order.auctionStartPrice
26
+ .sub(order.auctionEndPrice)
27
+ .mul(deltaNumerator)
28
+ .div(deltaDenominator);
29
+ }
30
+
31
+ let price;
32
+ if (isVariant(order.direction, 'long')) {
33
+ price = order.auctionStartPrice.add(priceDelta);
34
+ } else {
35
+ price = order.auctionStartPrice.sub(priceDelta);
36
+ }
37
+
38
+ return price;
39
+ }