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

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 +6 -6
  2. package/lib/accounts/bulkAccountLoader.js +81 -95
  3. package/lib/accounts/bulkUserSubscription.js +13 -57
  4. package/lib/accounts/fetch.d.ts +4 -0
  5. package/lib/accounts/fetch.js +18 -0
  6. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +34 -38
  7. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +224 -224
  8. package/lib/accounts/pollingOracleSubscriber.d.ts +3 -3
  9. package/lib/accounts/pollingOracleSubscriber.js +37 -49
  10. package/lib/accounts/pollingTokenAccountSubscriber.d.ts +3 -3
  11. package/lib/accounts/pollingTokenAccountSubscriber.js +35 -50
  12. package/lib/accounts/pollingUserAccountSubscriber.d.ts +7 -13
  13. package/lib/accounts/pollingUserAccountSubscriber.js +71 -134
  14. package/lib/accounts/types.d.ts +34 -41
  15. package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -4
  16. package/lib/accounts/webSocketAccountSubscriber.js +39 -35
  17. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +33 -28
  18. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +153 -185
  19. package/lib/accounts/webSocketUserAccountSubscriber.d.ts +5 -11
  20. package/lib/accounts/webSocketUserAccountSubscriber.js +22 -67
  21. package/lib/addresses/marketAddresses.d.ts +4 -0
  22. package/lib/addresses/marketAddresses.js +15 -0
  23. package/lib/addresses/pda.d.ts +12 -0
  24. package/lib/addresses/pda.js +83 -0
  25. package/lib/admin.d.ts +9 -17
  26. package/lib/admin.js +375 -558
  27. package/lib/clearingHouse.d.ts +86 -109
  28. package/lib/clearingHouse.js +828 -895
  29. package/lib/clearingHouseConfig.d.ts +34 -0
  30. package/lib/clearingHouseConfig.js +2 -0
  31. package/lib/clearingHouseUser.d.ts +19 -22
  32. package/lib/clearingHouseUser.js +155 -141
  33. package/lib/clearingHouseUserConfig.d.ts +14 -0
  34. package/lib/clearingHouseUserConfig.js +2 -0
  35. package/lib/config.d.ts +12 -0
  36. package/lib/config.js +35 -4
  37. package/lib/constants/banks.d.ts +16 -0
  38. package/lib/constants/banks.js +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 +17 -0
  42. package/lib/constants/numericConstants.js +23 -6
  43. package/lib/events/eventList.d.ts +22 -0
  44. package/lib/events/eventList.js +77 -0
  45. package/lib/events/eventSubscriber.d.ts +34 -0
  46. package/lib/events/eventSubscriber.js +126 -0
  47. package/lib/events/fetchLogs.d.ts +13 -0
  48. package/lib/events/fetchLogs.js +39 -0
  49. package/lib/events/pollingLogProvider.d.ts +15 -0
  50. package/lib/events/pollingLogProvider.js +53 -0
  51. package/lib/events/sort.d.ts +2 -0
  52. package/lib/events/sort.js +44 -0
  53. package/lib/events/txEventCache.d.ts +24 -0
  54. package/lib/events/txEventCache.js +71 -0
  55. package/lib/events/types.d.ts +49 -0
  56. package/lib/events/types.js +20 -0
  57. package/lib/events/webSocketLogProvider.d.ts +12 -0
  58. package/lib/events/webSocketLogProvider.js +30 -0
  59. package/lib/examples/makeTradeExample.js +26 -27
  60. package/lib/factory/bigNum.d.ts +118 -0
  61. package/lib/factory/bigNum.js +364 -0
  62. package/lib/factory/oracleClient.d.ts +1 -2
  63. package/lib/factory/oracleClient.js +6 -2
  64. package/lib/idl/clearing_house.json +2287 -2938
  65. package/lib/index.d.ts +12 -4
  66. package/lib/index.js +12 -4
  67. package/lib/math/amm.d.ts +24 -29
  68. package/lib/math/amm.js +239 -178
  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/orders.d.ts +5 -0
  80. package/lib/math/orders.js +31 -1
  81. package/lib/math/position.d.ts +7 -5
  82. package/lib/math/position.js +27 -27
  83. package/lib/math/repeg.d.ts +22 -0
  84. package/lib/math/repeg.js +128 -0
  85. package/lib/math/trade.d.ts +5 -4
  86. package/lib/math/trade.js +29 -21
  87. package/lib/mockUSDCFaucet.js +87 -116
  88. package/lib/oracles/oracleClientCache.d.ts +8 -0
  89. package/lib/oracles/oracleClientCache.js +19 -0
  90. package/lib/oracles/pythClient.d.ts +3 -5
  91. package/lib/oracles/pythClient.js +12 -31
  92. package/lib/oracles/quoteAssetOracleClient.d.ts +9 -0
  93. package/lib/oracles/quoteAssetOracleClient.js +21 -0
  94. package/lib/oracles/switchboardClient.d.ts +3 -5
  95. package/lib/oracles/switchboardClient.js +29 -50
  96. package/lib/oracles/types.d.ts +6 -1
  97. package/lib/orders.d.ts +6 -7
  98. package/lib/orders.js +10 -80
  99. package/lib/slot/SlotSubscriber.d.ts +12 -0
  100. package/lib/slot/SlotSubscriber.js +23 -0
  101. package/lib/tx/retryTxSender.d.ts +2 -2
  102. package/lib/tx/retryTxSender.js +108 -123
  103. package/lib/tx/types.d.ts +5 -1
  104. package/lib/tx/utils.d.ts +1 -1
  105. package/lib/tx/utils.js +11 -2
  106. package/lib/types.d.ts +110 -109
  107. package/lib/types.js +14 -1
  108. package/lib/userName.d.ts +4 -0
  109. package/lib/userName.js +20 -0
  110. package/lib/util/computeUnits.js +10 -21
  111. package/lib/util/tps.js +11 -22
  112. package/lib/wallet.js +7 -20
  113. package/package.json +11 -4
  114. package/src/accounts/bulkAccountLoader.ts +21 -15
  115. package/src/accounts/bulkUserSubscription.ts +1 -45
  116. package/src/accounts/fetch.ts +33 -0
  117. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +249 -214
  118. package/src/accounts/pollingOracleSubscriber.ts +16 -8
  119. package/src/accounts/pollingTokenAccountSubscriber.ts +11 -8
  120. package/src/accounts/pollingUserAccountSubscriber.ts +21 -86
  121. package/src/accounts/types.ts +41 -70
  122. package/src/accounts/webSocketAccountSubscriber.ts +33 -16
  123. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +190 -240
  124. package/src/accounts/webSocketUserAccountSubscriber.ts +11 -71
  125. package/src/addresses/marketAddresses.ts +18 -0
  126. package/src/addresses/pda.ts +118 -0
  127. package/src/admin.ts +218 -346
  128. package/src/clearingHouse.ts +983 -952
  129. package/src/clearingHouseConfig.ts +37 -0
  130. package/src/clearingHouseUser.ts +275 -185
  131. package/src/clearingHouseUserConfig.ts +18 -0
  132. package/src/config.ts +54 -1
  133. package/src/constants/banks.ts +43 -0
  134. package/src/constants/markets.ts +16 -207
  135. package/src/constants/numericConstants.ts +34 -5
  136. package/src/events/eventList.ts +94 -0
  137. package/src/events/eventSubscriber.ts +194 -0
  138. package/src/events/fetchLogs.ts +80 -0
  139. package/src/events/pollingLogProvider.ts +79 -0
  140. package/src/events/sort.ts +65 -0
  141. package/src/events/txEventCache.ts +74 -0
  142. package/src/events/types.ts +98 -0
  143. package/src/events/webSocketLogProvider.ts +38 -0
  144. package/src/examples/makeTradeExample.ts +20 -11
  145. package/src/factory/bigNum.ts +524 -0
  146. package/src/factory/oracleClient.ts +7 -4
  147. package/src/idl/clearing_house.json +2287 -2938
  148. package/src/index.ts +12 -4
  149. package/src/math/amm.ts +414 -245
  150. package/src/math/auction.ts +39 -0
  151. package/src/math/bankBalance.ts +112 -0
  152. package/src/math/conversion.ts +1 -11
  153. package/src/math/funding.ts +12 -9
  154. package/src/math/market.ts +37 -30
  155. package/src/math/orders.ts +38 -0
  156. package/src/math/position.ts +48 -35
  157. package/src/math/repeg.ts +176 -0
  158. package/src/math/trade.ts +45 -35
  159. package/src/math/utils.js +27 -0
  160. package/src/math/utils.js.map +1 -0
  161. package/src/oracles/oracleClientCache.ts +20 -0
  162. package/src/oracles/pythClient.ts +4 -11
  163. package/src/oracles/quoteAssetOracleClient.ts +25 -0
  164. package/src/oracles/switchboardClient.ts +11 -24
  165. package/src/oracles/types.ts +7 -1
  166. package/src/orders.ts +24 -126
  167. package/src/slot/SlotSubscriber.ts +32 -0
  168. package/src/tx/retryTxSender.ts +6 -4
  169. package/src/tx/types.ts +6 -1
  170. package/src/tx/utils.ts +22 -3
  171. package/src/types.ts +111 -122
  172. package/src/userName.ts +20 -0
  173. package/src/util/computeUnits.js +17 -0
  174. package/src/util/computeUnits.js.map +1 -0
  175. package/tests/bn/test.ts +255 -0
  176. package/tsconfig.json +12 -12
  177. package/lib/addresses.d.ts +0 -10
  178. package/lib/addresses.js +0 -93
  179. package/lib/constants/accounts.d.ts +0 -15
  180. package/lib/constants/accounts.js +0 -18
  181. package/lib/factory/clearingHouse.d.ts +0 -35
  182. package/lib/factory/clearingHouse.js +0 -81
  183. package/lib/factory/clearingHouseUser.d.ts +0 -19
  184. package/lib/factory/clearingHouseUser.js +0 -34
  185. package/lib/math/insuranceFund.d.ts +0 -15
  186. package/lib/math/insuranceFund.js +0 -33
  187. package/lib/settlement.d.ts +0 -4
  188. package/lib/settlement.js +0 -10
  189. package/lib/tx/defaultTxSender.d.ts +0 -8
  190. package/lib/tx/defaultTxSender.js +0 -12
  191. package/src/addresses.ts +0 -82
  192. package/src/constants/accounts.ts +0 -26
  193. package/src/factory/clearingHouse.ts +0 -173
  194. package/src/factory/clearingHouseUser.ts +0 -73
  195. package/src/math/insuranceFund.ts +0 -29
  196. package/src/settlement.ts +0 -9
  197. package/src/tx/defaultTxSender.ts +0 -24
@@ -0,0 +1,176 @@
1
+ import { BN } from '@project-serum/anchor';
2
+ import { assert } from '../assert/assert';
3
+ import {
4
+ MARK_PRICE_PRECISION,
5
+ AMM_RESERVE_PRECISION,
6
+ PEG_PRECISION,
7
+ AMM_TO_QUOTE_PRECISION_RATIO,
8
+ PRICE_DIV_PEG,
9
+ QUOTE_PRECISION,
10
+ ZERO,
11
+ } from '../constants/numericConstants';
12
+ import { AMM } from '../types';
13
+ /**
14
+ * Helper function calculating adjust k cost
15
+ * @param amm
16
+ * @param numerator
17
+ * @param denomenator
18
+ * @returns cost : Precision QUOTE_ASSET_PRECISION
19
+ */
20
+ export function calculateAdjustKCost(
21
+ amm: AMM,
22
+ numerator: BN,
23
+ denomenator: BN
24
+ ): BN {
25
+ // const k = market.amm.sqrtK.mul(market.amm.sqrtK);
26
+ const x = amm.baseAssetReserve;
27
+ const y = amm.quoteAssetReserve;
28
+
29
+ const d = amm.netBaseAssetAmount;
30
+ const Q = amm.pegMultiplier;
31
+
32
+ const quoteScale = y.mul(d).mul(Q); //.div(AMM_RESERVE_PRECISION);
33
+
34
+ const p = numerator.mul(MARK_PRICE_PRECISION).div(denomenator);
35
+
36
+ const cost = quoteScale
37
+ .div(x.add(d))
38
+ .sub(
39
+ quoteScale
40
+ .mul(p)
41
+ .div(MARK_PRICE_PRECISION)
42
+ .div(x.mul(p).div(MARK_PRICE_PRECISION).add(d))
43
+ )
44
+ .div(AMM_TO_QUOTE_PRECISION_RATIO)
45
+ .div(PEG_PRECISION);
46
+
47
+ return cost.mul(new BN(-1));
48
+ }
49
+
50
+ /**
51
+ * Helper function calculating adjust pegMultiplier (repeg) cost
52
+ *
53
+ * @param amm
54
+ * @param newPeg
55
+ * @returns cost : Precision QUOTE_ASSET_PRECISION
56
+ */
57
+ export function calculateRepegCost(amm: AMM, newPeg: BN): BN {
58
+ const dqar = amm.quoteAssetReserve.sub(amm.terminalQuoteAssetReserve);
59
+ const cost = dqar
60
+ .mul(newPeg.sub(amm.pegMultiplier))
61
+ .div(AMM_TO_QUOTE_PRECISION_RATIO)
62
+ .div(PEG_PRECISION);
63
+ return cost;
64
+ }
65
+
66
+ export function calculateBudgetedKBN(
67
+ x: BN,
68
+ y: BN,
69
+ budget: BN,
70
+ Q: BN,
71
+ d: BN
72
+ ): [BN, BN] {
73
+ assert(Q.gt(new BN(0)));
74
+ const C = budget.mul(new BN(-1));
75
+
76
+ let dSign = new BN(1);
77
+ if (d.lt(new BN(0))) {
78
+ dSign = new BN(-1);
79
+ }
80
+ const pegged_y_d_d = y
81
+ .mul(d)
82
+ .mul(d)
83
+ .mul(Q)
84
+ .div(AMM_RESERVE_PRECISION)
85
+ .div(AMM_RESERVE_PRECISION)
86
+ .div(PEG_PRECISION);
87
+
88
+ const numer1 = pegged_y_d_d;
89
+ const numer2 = C.mul(d)
90
+ .div(QUOTE_PRECISION)
91
+ .mul(x.add(d))
92
+ .div(AMM_RESERVE_PRECISION)
93
+ .mul(dSign);
94
+
95
+ const denom1 = C.mul(x)
96
+ .mul(x.add(d))
97
+ .div(AMM_RESERVE_PRECISION)
98
+ .div(QUOTE_PRECISION);
99
+ const denom2 = pegged_y_d_d;
100
+
101
+ const numerator = numer1.sub(numer2).div(AMM_TO_QUOTE_PRECISION_RATIO);
102
+ const denominator = denom1.add(denom2).div(AMM_TO_QUOTE_PRECISION_RATIO);
103
+
104
+ return [numerator, denominator];
105
+ }
106
+
107
+ export function calculateBudgetedK(amm: AMM, cost: BN): [BN, BN] {
108
+ // wolframalpha.com
109
+ // (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
110
+ // p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*d*d*Q)
111
+
112
+ // numer
113
+ // = y*d*d*Q - Cxd - Cdd
114
+ // = y/x*Q*d*d - Cd - Cd/x
115
+ // = mark - C/d - C/(x)
116
+ // = mark/C - 1/d - 1/x
117
+
118
+ // denom
119
+ // = C*x*x + C*x*d + y*d*d*Q
120
+ // = x/d**2 + 1 / d + mark/C
121
+
122
+ // todo: assumes k = x * y
123
+ // otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
124
+
125
+ const x = amm.baseAssetReserve;
126
+ const y = amm.quoteAssetReserve;
127
+
128
+ const d = amm.netBaseAssetAmount;
129
+ const Q = amm.pegMultiplier;
130
+
131
+ const [numerator, denominator] = calculateBudgetedKBN(x, y, cost, Q, d);
132
+
133
+ return [numerator, denominator];
134
+ }
135
+
136
+ export function calculateBudgetedPeg(amm: AMM, cost: BN, targetPrice: BN): BN {
137
+ // wolframalpha.com
138
+ // (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
139
+ // p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
140
+
141
+ // todo: assumes k = x * y
142
+ // otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
143
+ const targetPeg = targetPrice
144
+ .mul(amm.baseAssetReserve)
145
+ .div(amm.quoteAssetReserve)
146
+ .div(PRICE_DIV_PEG);
147
+
148
+ const k = amm.sqrtK.mul(amm.sqrtK);
149
+ const x = amm.baseAssetReserve;
150
+ const y = amm.quoteAssetReserve;
151
+
152
+ const d = amm.netBaseAssetAmount;
153
+ const Q = amm.pegMultiplier;
154
+
155
+ const C = cost.mul(new BN(-1));
156
+
157
+ const deltaQuoteAssetReserves = y.sub(k.div(x.add(d)));
158
+ const pegChangeDirection = targetPeg.sub(Q);
159
+
160
+ const useTargetPeg =
161
+ (deltaQuoteAssetReserves.lt(ZERO) && pegChangeDirection.gt(ZERO)) ||
162
+ (deltaQuoteAssetReserves.gt(ZERO) && pegChangeDirection.lt(ZERO));
163
+
164
+ if (deltaQuoteAssetReserves.eq(ZERO) || useTargetPeg) {
165
+ return targetPeg;
166
+ }
167
+
168
+ const deltaPegMultiplier = C.mul(MARK_PRICE_PRECISION).div(
169
+ deltaQuoteAssetReserves.div(AMM_TO_QUOTE_PRECISION_RATIO)
170
+ );
171
+ const newPeg = Q.sub(
172
+ deltaPegMultiplier.mul(PEG_PRECISION).div(MARK_PRICE_PRECISION)
173
+ );
174
+
175
+ return newPeg;
176
+ }
package/src/math/trade.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Market, PositionDirection } from '../types';
1
+ import { MarketAccount, PositionDirection, SwapDirection } from '../types';
2
2
  import { BN } from '@project-serum/anchor';
3
3
  import { assert } from '../assert/assert';
4
4
  import {
@@ -17,10 +17,12 @@ import {
17
17
  calculatePrice,
18
18
  getSwapDirection,
19
19
  AssetType,
20
- calculateSpreadReserves,
20
+ calculateUpdatedAMMSpreadReserves,
21
+ calculateQuoteAssetAmountSwapped,
21
22
  } from './amm';
22
23
  import { squareRootBN } from './utils';
23
24
  import { isVariant } from '../types';
25
+ import { OraclePriceData } from '../oracles/types';
24
26
 
25
27
  const MAXPCT = new BN(1000); //percentage units are [0,1000] => [0,1]
26
28
 
@@ -57,20 +59,21 @@ export type PriceImpactUnit =
57
59
  export function calculateTradeSlippage(
58
60
  direction: PositionDirection,
59
61
  amount: BN,
60
- market: Market,
62
+ market: MarketAccount,
61
63
  inputAssetType: AssetType = 'quote',
64
+ oraclePriceData?: OraclePriceData,
62
65
  useSpread = true
63
66
  ): [BN, BN, BN, BN] {
64
67
  let oldPrice: BN;
65
68
 
66
69
  if (useSpread && market.amm.baseSpread > 0) {
67
70
  if (isVariant(direction, 'long')) {
68
- oldPrice = calculateAskPrice(market);
71
+ oldPrice = calculateAskPrice(market, oraclePriceData);
69
72
  } else {
70
- oldPrice = calculateBidPrice(market);
73
+ oldPrice = calculateBidPrice(market, oraclePriceData);
71
74
  }
72
75
  } else {
73
- oldPrice = calculateMarkPrice(market);
76
+ oldPrice = calculateMarkPrice(market, oraclePriceData);
74
77
  }
75
78
  if (amount.eq(ZERO)) {
76
79
  return [ZERO, ZERO, oldPrice, oldPrice];
@@ -80,26 +83,33 @@ export function calculateTradeSlippage(
80
83
  amount,
81
84
  market,
82
85
  inputAssetType,
86
+ oraclePriceData,
83
87
  useSpread
84
88
  );
85
89
 
86
- const entryPrice = calculatePrice(
87
- acquiredBase,
88
- acquiredQuote,
89
- market.amm.pegMultiplier
90
- ).mul(new BN(-1));
90
+ const swapDirection = isVariant(direction, 'long')
91
+ ? SwapDirection.REMOVE
92
+ : SwapDirection.ADD;
93
+ const quoteAssetAmountAcquired = calculateQuoteAssetAmountSwapped(
94
+ acquiredQuote.abs(),
95
+ market.amm.pegMultiplier,
96
+ swapDirection
97
+ );
98
+
99
+ const entryPrice = quoteAssetAmountAcquired
100
+ .mul(AMM_TO_QUOTE_PRECISION_RATIO)
101
+ .mul(MARK_PRICE_PRECISION)
102
+ .div(acquiredBase.abs());
91
103
 
92
104
  let amm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
93
105
  if (useSpread && market.amm.baseSpread > 0) {
94
- const { baseAssetReserve, quoteAssetReserve } = calculateSpreadReserves(
95
- market.amm,
96
- direction
97
- );
106
+ const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
107
+ calculateUpdatedAMMSpreadReserves(market.amm, direction, oraclePriceData);
98
108
  amm = {
99
109
  baseAssetReserve,
100
110
  quoteAssetReserve,
101
- sqrtK: market.amm.sqrtK,
102
- pegMultiplier: market.amm.pegMultiplier,
111
+ sqrtK: sqrtK,
112
+ pegMultiplier: newPeg,
103
113
  };
104
114
  } else {
105
115
  amm = market.amm;
@@ -112,9 +122,9 @@ export function calculateTradeSlippage(
112
122
  );
113
123
 
114
124
  if (direction == PositionDirection.SHORT) {
115
- assert(newPrice.lt(oldPrice));
125
+ assert(newPrice.lte(oldPrice));
116
126
  } else {
117
- assert(oldPrice.lt(newPrice));
127
+ assert(oldPrice.lte(newPrice));
118
128
  }
119
129
 
120
130
  const pctMaxSlippage = newPrice
@@ -145,8 +155,9 @@ export function calculateTradeSlippage(
145
155
  export function calculateTradeAcquiredAmounts(
146
156
  direction: PositionDirection,
147
157
  amount: BN,
148
- market: Market,
158
+ market: MarketAccount,
149
159
  inputAssetType: AssetType = 'quote',
160
+ oraclePriceData: OraclePriceData,
150
161
  useSpread = true
151
162
  ): [BN, BN] {
152
163
  if (amount.eq(ZERO)) {
@@ -157,15 +168,13 @@ export function calculateTradeAcquiredAmounts(
157
168
 
158
169
  let amm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
159
170
  if (useSpread && market.amm.baseSpread > 0) {
160
- const { baseAssetReserve, quoteAssetReserve } = calculateSpreadReserves(
161
- market.amm,
162
- direction
163
- );
171
+ const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
172
+ calculateUpdatedAMMSpreadReserves(market.amm, direction, oraclePriceData);
164
173
  amm = {
165
174
  baseAssetReserve,
166
175
  quoteAssetReserve,
167
- sqrtK: market.amm.sqrtK,
168
- pegMultiplier: market.amm.pegMultiplier,
176
+ sqrtK: sqrtK,
177
+ pegMultiplier: newPeg,
169
178
  };
170
179
  } else {
171
180
  amm = market.amm;
@@ -197,19 +206,20 @@ export function calculateTradeAcquiredAmounts(
197
206
  * ]
198
207
  */
199
208
  export function calculateTargetPriceTrade(
200
- market: Market,
209
+ market: MarketAccount,
201
210
  targetPrice: BN,
202
211
  pct: BN = MAXPCT,
203
212
  outputAssetType: AssetType = 'quote',
213
+ oraclePriceData?: OraclePriceData,
204
214
  useSpread = true
205
215
  ): [PositionDirection, BN, BN, BN] {
206
216
  assert(market.amm.baseAssetReserve.gt(ZERO));
207
217
  assert(targetPrice.gt(ZERO));
208
218
  assert(pct.lte(MAXPCT) && pct.gt(ZERO));
209
219
 
210
- const markPriceBefore = calculateMarkPrice(market);
211
- const bidPriceBefore = calculateBidPrice(market);
212
- const askPriceBefore = calculateAskPrice(market);
220
+ const markPriceBefore = calculateMarkPrice(market, oraclePriceData);
221
+ const bidPriceBefore = calculateBidPrice(market, oraclePriceData);
222
+ const askPriceBefore = calculateAskPrice(market, oraclePriceData);
213
223
 
214
224
  let direction;
215
225
  if (targetPrice.gt(markPriceBefore)) {
@@ -230,19 +240,19 @@ export function calculateTargetPriceTrade(
230
240
  let baseAssetReserveBefore: BN;
231
241
  let quoteAssetReserveBefore: BN;
232
242
 
243
+ let peg = market.amm.pegMultiplier;
244
+
233
245
  if (useSpread && market.amm.baseSpread > 0) {
234
- const { baseAssetReserve, quoteAssetReserve } = calculateSpreadReserves(
235
- market.amm,
236
- direction
237
- );
246
+ const { baseAssetReserve, quoteAssetReserve, newPeg } =
247
+ calculateUpdatedAMMSpreadReserves(market.amm, direction, oraclePriceData);
238
248
  baseAssetReserveBefore = baseAssetReserve;
239
249
  quoteAssetReserveBefore = quoteAssetReserve;
250
+ peg = newPeg;
240
251
  } else {
241
252
  baseAssetReserveBefore = market.amm.baseAssetReserve;
242
253
  quoteAssetReserveBefore = market.amm.quoteAssetReserve;
243
254
  }
244
255
 
245
- const peg = market.amm.pegMultiplier;
246
256
  const invariant = market.amm.sqrtK.mul(market.amm.sqrtK);
247
257
  const k = invariant.mul(MARK_PRICE_PRECISION);
248
258
 
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.squareRootBN = void 0;
4
+ const __1 = require("../");
5
+ const squareRootBN = (n, closeness = new __1.BN(1)) => {
6
+ // Assuming the sqrt of n as n only
7
+ let x = n;
8
+ // The closed guess will be stored in the root
9
+ let root;
10
+ // To count the number of iterations
11
+ let count = 0;
12
+ const TWO = new __1.BN(2);
13
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
14
+ while (count < Number.MAX_SAFE_INTEGER) {
15
+ count++;
16
+ // Calculate more closed x
17
+ root = x.add(n.div(x)).div(TWO);
18
+ // Check for closeness
19
+ if (x.sub(root).abs().lte(closeness))
20
+ break;
21
+ // Update root
22
+ x = root;
23
+ }
24
+ return root;
25
+ };
26
+ exports.squareRootBN = squareRootBN;
27
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["utils.ts"],"names":[],"mappings":";;;AAAA,2BAAyB;AAElB,MAAM,YAAY,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,IAAI,MAAE,CAAC,CAAC,CAAC,EAAE,EAAE;IACxD,mCAAmC;IACnC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,8CAA8C;IAC9C,IAAI,IAAI,CAAC;IAET,oCAAoC;IACpC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,GAAG,GAAG,IAAI,MAAE,CAAC,CAAC,CAAC,CAAC;IAEtB,6DAA6D;IAC7D,OAAO,KAAK,GAAG,MAAM,CAAC,gBAAgB,EAAE;QACvC,KAAK,EAAE,CAAC;QAER,0BAA0B;QAC1B,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEhC,sBAAsB;QACtB,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,MAAM;QAE5C,cAAc;QACd,CAAC,GAAG,IAAI,CAAC;KACT;IAED,OAAO,IAAI,CAAC;AACb,CAAC,CAAC;AA1BW,QAAA,YAAY,gBA0BvB"}
@@ -0,0 +1,20 @@
1
+ import { OracleClient } from './types';
2
+ import { OracleSource } from '../types';
3
+ import { getOracleClient } from '../factory/oracleClient';
4
+ import { Connection } from '@solana/web3.js';
5
+
6
+ export class OracleClientCache {
7
+ cache = new Map<string, OracleClient>();
8
+ public constructor() {}
9
+
10
+ public get(oracleSource: OracleSource, connection: Connection) {
11
+ const key = Object.keys(oracleSource)[0];
12
+ if (this.cache.has(key)) {
13
+ return this.cache.get(key);
14
+ }
15
+
16
+ const client = getOracleClient(oracleSource, connection);
17
+ this.cache.set(key, client);
18
+ return client;
19
+ }
20
+ }
@@ -1,21 +1,16 @@
1
- import { parsePriceData, PriceData } from '@pythnetwork/client';
1
+ import { parsePriceData } from '@pythnetwork/client';
2
2
  import { Connection, PublicKey } from '@solana/web3.js';
3
- import { OraclePriceData } from './types';
3
+ import { OracleClient, OraclePriceData } from './types';
4
4
  import { BN } from '@project-serum/anchor';
5
5
  import { MARK_PRICE_PRECISION, TEN } from '../constants/numericConstants';
6
6
 
7
- export class PythClient {
7
+ export class PythClient implements OracleClient {
8
8
  private connection: Connection;
9
9
 
10
10
  public constructor(connection: Connection) {
11
11
  this.connection = connection;
12
12
  }
13
13
 
14
- public async getPriceData(pricePublicKey: PublicKey): Promise<PriceData> {
15
- const account = await this.connection.getAccountInfo(pricePublicKey);
16
- return parsePriceData(account.data);
17
- }
18
-
19
14
  public async getOraclePriceData(
20
15
  pricePublicKey: PublicKey
21
16
  ): Promise<OraclePriceData> {
@@ -23,9 +18,7 @@ export class PythClient {
23
18
  return this.getOraclePriceDataFromBuffer(accountInfo.data);
24
19
  }
25
20
 
26
- public async getOraclePriceDataFromBuffer(
27
- buffer: Buffer
28
- ): Promise<OraclePriceData> {
21
+ public getOraclePriceDataFromBuffer(buffer: Buffer): OraclePriceData {
29
22
  const priceData = parsePriceData(buffer);
30
23
  return {
31
24
  price: convertPythPrice(priceData.aggregate.price, priceData.exponent),
@@ -0,0 +1,25 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ import { OracleClient, OraclePriceData } from './types';
3
+ import { BN } from '@project-serum/anchor';
4
+ import { MARK_PRICE_PRECISION } from '../constants/numericConstants';
5
+
6
+ export const QUOTE_ORACLE_PRICE_DATA: OraclePriceData = {
7
+ price: MARK_PRICE_PRECISION,
8
+ slot: new BN(0),
9
+ confidence: new BN(1),
10
+ hasSufficientNumberOfDataPoints: true,
11
+ };
12
+
13
+ export class QuoteAssetOracleClient implements OracleClient {
14
+ public constructor() {}
15
+
16
+ public async getOraclePriceData(
17
+ _pricePublicKey: PublicKey
18
+ ): Promise<OraclePriceData> {
19
+ return Promise.resolve(QUOTE_ORACLE_PRICE_DATA);
20
+ }
21
+
22
+ public getOraclePriceDataFromBuffer(_buffer: Buffer): OraclePriceData {
23
+ return QUOTE_ORACLE_PRICE_DATA;
24
+ }
25
+ }
@@ -1,25 +1,18 @@
1
- import {
2
- getSwitchboardPid,
3
- SwitchboardDecimal,
4
- } from '@switchboard-xyz/switchboard-v2';
1
+ import { SwitchboardDecimal } from '@switchboard-xyz/switchboard-v2';
5
2
  import { Connection, Keypair, PublicKey } from '@solana/web3.js';
6
- import { DriftEnv } from '../config';
7
3
  import { BN, Program, Idl, AnchorProvider } from '@project-serum/anchor';
8
4
  import { MARK_PRICE_PRECISION, TEN } from '../constants/numericConstants';
9
5
  import { OracleClient, OraclePriceData } from './types';
10
6
  import { Wallet } from '../wallet';
11
7
  import switchboardV2Idl from '../idl/switchboard_v2.json';
12
8
 
13
- // cache switchboard program for every client object since itll always be the same
14
- const programMap = new Map<string, Program>();
9
+ let program: Program | undefined;
15
10
 
16
11
  export class SwitchboardClient implements OracleClient {
17
12
  connection: Connection;
18
- env: DriftEnv;
19
13
 
20
- public constructor(connection: Connection, env: DriftEnv) {
14
+ public constructor(connection: Connection) {
21
15
  this.connection = connection;
22
- this.env = env;
23
16
  }
24
17
 
25
18
  public async getOraclePriceData(
@@ -29,10 +22,8 @@ export class SwitchboardClient implements OracleClient {
29
22
  return this.getOraclePriceDataFromBuffer(accountInfo.data);
30
23
  }
31
24
 
32
- public async getOraclePriceDataFromBuffer(
33
- buffer: Buffer
34
- ): Promise<OraclePriceData> {
35
- const program = await this.getProgram();
25
+ public getOraclePriceDataFromBuffer(buffer: Buffer): OraclePriceData {
26
+ const program = this.getProgram();
36
27
 
37
28
  const aggregatorAccountData =
38
29
  program.account.aggregatorAccountData.coder.accounts.decode(
@@ -61,23 +52,19 @@ export class SwitchboardClient implements OracleClient {
61
52
  };
62
53
  }
63
54
 
64
- public async getProgram(): Promise<Program> {
65
- if (programMap.has(this.env)) {
66
- return programMap.get(this.env);
55
+ public getProgram(): Program {
56
+ if (program) {
57
+ return program;
67
58
  }
68
59
 
69
- const program = await getSwitchboardProgram(this.env, this.connection);
70
- programMap.set(this.env, program);
60
+ program = getSwitchboardProgram(this.connection);
71
61
  return program;
72
62
  }
73
63
  }
74
64
 
75
- async function getSwitchboardProgram(
76
- env: DriftEnv,
77
- connection: Connection
78
- ): Promise<Program> {
65
+ function getSwitchboardProgram(connection: Connection): Program {
79
66
  const DEFAULT_KEYPAIR = Keypair.fromSeed(new Uint8Array(32).fill(1));
80
- const programId = getSwitchboardPid(env);
67
+ const programId = PublicKey.default;
81
68
  const wallet = new Wallet(DEFAULT_KEYPAIR);
82
69
  const provider = new AnchorProvider(connection, wallet, {});
83
70
 
@@ -1,5 +1,6 @@
1
1
  import { BN } from '@project-serum/anchor';
2
2
  import { PublicKey } from '@solana/web3.js';
3
+ import { OracleSource } from '../types';
3
4
 
4
5
  export type OraclePriceData = {
5
6
  price: BN;
@@ -10,7 +11,12 @@ export type OraclePriceData = {
10
11
  twapConfidence?: BN;
11
12
  };
12
13
 
14
+ export type OracleInfo = {
15
+ publicKey: PublicKey;
16
+ source: OracleSource;
17
+ };
18
+
13
19
  export interface OracleClient {
14
- getOraclePriceDataFromBuffer(buffer: Buffer): Promise<OraclePriceData>;
20
+ getOraclePriceDataFromBuffer(buffer: Buffer): OraclePriceData;
15
21
  getOraclePriceData(publicKey: PublicKey): Promise<OraclePriceData>;
16
22
  }