@drift-labs/sdk 0.1.36-master.6 → 0.2.0-master.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) 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 +33 -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 +12 -4
  66. package/lib/index.js +12 -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/orders.d.ts +5 -0
  80. package/lib/math/orders.js +31 -1
  81. package/lib/math/position.d.ts +7 -4
  82. package/lib/math/position.js +27 -9
  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 -6
  98. package/lib/orders.js +10 -9
  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 +105 -98
  107. package/lib/types.js +13 -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 +209 -267
  128. package/src/clearingHouse.ts +921 -829
  129. package/src/clearingHouseConfig.ts +37 -0
  130. package/src/clearingHouseUser.ts +280 -127
  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 +33 -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 +507 -0
  146. package/src/factory/oracleClient.ts +7 -4
  147. package/src/idl/clearing_house.json +1739 -2287
  148. package/src/index.ts +12 -4
  149. package/src/math/amm.ts +229 -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 -13
  157. package/src/math/repeg.ts +175 -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 +35 -20
  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 +108 -110
  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 -9
  178. package/lib/addresses.js +0 -87
  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/tx/defaultTxSender.d.ts +0 -8
  188. package/lib/tx/defaultTxSender.js +0 -12
  189. package/src/addresses.ts +0 -71
  190. package/src/constants/accounts.ts +0 -26
  191. package/src/factory/clearingHouse.ts +0 -173
  192. package/src/factory/clearingHouseUser.ts +0 -73
  193. package/src/math/insuranceFund.ts +0 -29
  194. package/src/tx/defaultTxSender.ts +0 -24
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
3
+ exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
4
4
  const types_1 = require("../types");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
+ const anchor_1 = require("@project-serum/anchor");
7
+ const auction_1 = require("./auction");
6
8
  function isOrderRiskIncreasing(user, order) {
7
9
  if ((0, types_1.isVariant)(order.status, 'init')) {
8
10
  return false;
@@ -71,3 +73,31 @@ function isOrderReduceOnly(user, order) {
71
73
  return true;
72
74
  }
73
75
  exports.isOrderReduceOnly = isOrderReduceOnly;
76
+ function standardizeBaseAssetAmount(baseAssetAmount, stepSize) {
77
+ const remainder = baseAssetAmount.mod(stepSize);
78
+ return baseAssetAmount.sub(remainder);
79
+ }
80
+ exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
81
+ function getLimitPrice(order, oraclePriceData, slot) {
82
+ let limitPrice;
83
+ if (!order.oraclePriceOffset.eq(numericConstants_1.ZERO)) {
84
+ const floatingPrice = oraclePriceData.price.add(order.oraclePriceOffset);
85
+ if (order.postOnly) {
86
+ limitPrice = (0, types_1.isVariant)(order.direction, 'long')
87
+ ? anchor_1.BN.min(order.price, floatingPrice)
88
+ : anchor_1.BN.max(order.price, floatingPrice);
89
+ }
90
+ else {
91
+ limitPrice = floatingPrice;
92
+ }
93
+ }
94
+ else if ((0, types_1.isVariant)(order.orderType, 'market') ||
95
+ (0, types_1.isVariant)(order.orderType, 'triggerMarket')) {
96
+ limitPrice = (0, auction_1.getAuctionPrice)(order, slot);
97
+ }
98
+ else {
99
+ limitPrice = order.price;
100
+ }
101
+ return limitPrice;
102
+ }
103
+ exports.getLimitPrice = getLimitPrice;
@@ -1,14 +1,16 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { BN } from '../';
3
- import { Market, PositionDirection, UserPosition } from '../types';
3
+ import { OraclePriceData } from '../oracles/types';
4
+ import { MarketAccount, PositionDirection, UserPosition } from '../types';
4
5
  /**
5
6
  * calculateBaseAssetValue
6
7
  * = market value of closing entire position
7
8
  * @param market
8
9
  * @param userPosition
10
+ * @param oraclePriceData
9
11
  * @returns Base Asset Value. : Precision QUOTE_PRECISION
10
12
  */
11
- export declare function calculateBaseAssetValue(market: Market, userPosition: UserPosition): BN;
13
+ export declare function calculateBaseAssetValue(market: MarketAccount, userPosition: UserPosition, oraclePriceData: OraclePriceData): BN;
12
14
  /**
13
15
  * calculatePositionPNL
14
16
  * = BaseAssetAmount * (Avg Exit Price - Avg Entry Price)
@@ -17,14 +19,15 @@ export declare function calculateBaseAssetValue(market: Market, userPosition: Us
17
19
  * @param withFunding (adds unrealized funding payment pnl to result)
18
20
  * @returns BaseAssetAmount : Precision QUOTE_PRECISION
19
21
  */
20
- export declare function calculatePositionPNL(market: Market, marketPosition: UserPosition, withFunding?: boolean): BN;
22
+ export declare function calculatePositionPNL(market: MarketAccount, marketPosition: UserPosition, withFunding: boolean, oraclePriceData: OraclePriceData): BN;
21
23
  /**
22
24
  *
23
25
  * @param market
24
26
  * @param marketPosition
25
27
  * @returns // TODO-PRECISION
26
28
  */
27
- export declare function calculatePositionFundingPNL(market: Market, marketPosition: UserPosition): BN;
29
+ export declare function calculatePositionFundingPNL(market: MarketAccount, marketPosition: UserPosition): BN;
30
+ export declare function positionIsAvailable(position: UserPosition): boolean;
28
31
  /**
29
32
  *
30
33
  * @param userPosition
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateEntryPrice = exports.calculatePositionFundingPNL = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
3
+ exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
4
4
  const __1 = require("../");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const types_1 = require("../types");
@@ -10,24 +10,38 @@ const amm_1 = require("./amm");
10
10
  * = market value of closing entire position
11
11
  * @param market
12
12
  * @param userPosition
13
+ * @param oraclePriceData
13
14
  * @returns Base Asset Value. : Precision QUOTE_PRECISION
14
15
  */
15
- function calculateBaseAssetValue(market, userPosition) {
16
+ function calculateBaseAssetValue(market, userPosition, oraclePriceData) {
16
17
  if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
17
18
  return numericConstants_1.ZERO;
18
19
  }
19
20
  const directionToClose = findDirectionToClose(userPosition);
20
- const [newQuoteAssetReserve, _] = (0, amm_1.calculateAmmReservesAfterSwap)(market.amm, 'base', userPosition.baseAssetAmount.abs(), (0, amm_1.getSwapDirection)('base', directionToClose));
21
+ let prepegAmm;
22
+ if (market.amm.baseSpread > 0) {
23
+ const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, directionToClose, oraclePriceData);
24
+ prepegAmm = {
25
+ baseAssetReserve,
26
+ quoteAssetReserve,
27
+ sqrtK: sqrtK,
28
+ pegMultiplier: newPeg,
29
+ };
30
+ }
31
+ else {
32
+ prepegAmm = (0, amm_1.calculateUpdatedAMM)(market.amm, oraclePriceData);
33
+ }
34
+ const [newQuoteAssetReserve, _] = (0, amm_1.calculateAmmReservesAfterSwap)(prepegAmm, 'base', userPosition.baseAssetAmount.abs(), (0, amm_1.getSwapDirection)('base', directionToClose));
21
35
  switch (directionToClose) {
22
36
  case types_1.PositionDirection.SHORT:
23
- return market.amm.quoteAssetReserve
37
+ return prepegAmm.quoteAssetReserve
24
38
  .sub(newQuoteAssetReserve)
25
- .mul(market.amm.pegMultiplier)
39
+ .mul(prepegAmm.pegMultiplier)
26
40
  .div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
27
41
  case types_1.PositionDirection.LONG:
28
42
  return newQuoteAssetReserve
29
- .sub(market.amm.quoteAssetReserve)
30
- .mul(market.amm.pegMultiplier)
43
+ .sub(prepegAmm.quoteAssetReserve)
44
+ .mul(prepegAmm.pegMultiplier)
31
45
  .div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
32
46
  .add(numericConstants_1.ONE);
33
47
  }
@@ -41,11 +55,11 @@ exports.calculateBaseAssetValue = calculateBaseAssetValue;
41
55
  * @param withFunding (adds unrealized funding payment pnl to result)
42
56
  * @returns BaseAssetAmount : Precision QUOTE_PRECISION
43
57
  */
44
- function calculatePositionPNL(market, marketPosition, withFunding = false) {
58
+ function calculatePositionPNL(market, marketPosition, withFunding = false, oraclePriceData) {
45
59
  if (marketPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
46
60
  return numericConstants_1.ZERO;
47
61
  }
48
- const baseAssetValue = calculateBaseAssetValue(market, marketPosition);
62
+ const baseAssetValue = calculateBaseAssetValue(market, marketPosition, oraclePriceData);
49
63
  let pnl;
50
64
  if (marketPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
51
65
  pnl = baseAssetValue.sub(marketPosition.quoteAssetAmount);
@@ -86,6 +100,10 @@ function calculatePositionFundingPNL(market, marketPosition) {
86
100
  return perPositionFundingRate;
87
101
  }
88
102
  exports.calculatePositionFundingPNL = calculatePositionFundingPNL;
103
+ function positionIsAvailable(position) {
104
+ return position.baseAssetAmount.eq(numericConstants_1.ZERO) && position.openOrders.eq(numericConstants_1.ZERO);
105
+ }
106
+ exports.positionIsAvailable = positionIsAvailable;
89
107
  /**
90
108
  *
91
109
  * @param userPosition
@@ -0,0 +1,22 @@
1
+ /// <reference types="bn.js" />
2
+ import { BN } from '@project-serum/anchor';
3
+ import { AMM } from '../types';
4
+ /**
5
+ * Helper function calculating adjust k cost
6
+ * @param amm
7
+ * @param numerator
8
+ * @param denomenator
9
+ * @returns cost : Precision QUOTE_ASSET_PRECISION
10
+ */
11
+ export declare function calculateAdjustKCost(amm: AMM, numerator: BN, denomenator: BN): BN;
12
+ /**
13
+ * Helper function calculating adjust pegMultiplier (repeg) cost
14
+ *
15
+ * @param amm
16
+ * @param newPeg
17
+ * @returns cost : Precision QUOTE_ASSET_PRECISION
18
+ */
19
+ export declare function calculateRepegCost(amm: AMM, newPeg: BN): BN;
20
+ export declare function calculateBudgetedKBN(x: BN, y: BN, budget: BN, Q: BN, d: BN): [BN, BN];
21
+ export declare function calculateBudgetedK(amm: AMM, cost: BN): [BN, BN];
22
+ export declare function calculateBudgetedPeg(amm: AMM, cost: BN, targetPrice: BN): BN;
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateBudgetedPeg = exports.calculateBudgetedK = exports.calculateBudgetedKBN = exports.calculateRepegCost = exports.calculateAdjustKCost = void 0;
4
+ const anchor_1 = require("@project-serum/anchor");
5
+ const assert_1 = require("../assert/assert");
6
+ const numericConstants_1 = require("../constants/numericConstants");
7
+ /**
8
+ * Helper function calculating adjust k cost
9
+ * @param amm
10
+ * @param numerator
11
+ * @param denomenator
12
+ * @returns cost : Precision QUOTE_ASSET_PRECISION
13
+ */
14
+ function calculateAdjustKCost(amm, numerator, denomenator) {
15
+ // const k = market.amm.sqrtK.mul(market.amm.sqrtK);
16
+ const x = amm.baseAssetReserve;
17
+ const y = amm.quoteAssetReserve;
18
+ const d = amm.netBaseAssetAmount;
19
+ const Q = amm.pegMultiplier;
20
+ const quoteScale = y.mul(d).mul(Q); //.div(AMM_RESERVE_PRECISION);
21
+ const p = numerator.mul(numericConstants_1.MARK_PRICE_PRECISION).div(denomenator);
22
+ const cost = quoteScale
23
+ .div(x.add(d))
24
+ .sub(quoteScale
25
+ .mul(p)
26
+ .div(numericConstants_1.MARK_PRICE_PRECISION)
27
+ .div(x.mul(p).div(numericConstants_1.MARK_PRICE_PRECISION).add(d)))
28
+ .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
29
+ .div(numericConstants_1.PEG_PRECISION);
30
+ return cost.mul(new anchor_1.BN(-1));
31
+ }
32
+ exports.calculateAdjustKCost = calculateAdjustKCost;
33
+ /**
34
+ * Helper function calculating adjust pegMultiplier (repeg) cost
35
+ *
36
+ * @param amm
37
+ * @param newPeg
38
+ * @returns cost : Precision QUOTE_ASSET_PRECISION
39
+ */
40
+ function calculateRepegCost(amm, newPeg) {
41
+ const dqar = amm.quoteAssetReserve.sub(amm.terminalQuoteAssetReserve);
42
+ const cost = dqar
43
+ .mul(newPeg.sub(amm.pegMultiplier))
44
+ .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
45
+ .div(numericConstants_1.PEG_PRECISION);
46
+ return cost;
47
+ }
48
+ exports.calculateRepegCost = calculateRepegCost;
49
+ function calculateBudgetedKBN(x, y, budget, Q, d) {
50
+ (0, assert_1.assert)(Q.gt(new anchor_1.BN(0)));
51
+ const C = budget.mul(new anchor_1.BN(-1));
52
+ let dSign = new anchor_1.BN(1);
53
+ if (d.lt(new anchor_1.BN(0))) {
54
+ dSign = new anchor_1.BN(-1);
55
+ }
56
+ const pegged_y_d_d = y
57
+ .mul(d)
58
+ .mul(d)
59
+ .mul(Q)
60
+ .div(numericConstants_1.AMM_RESERVE_PRECISION)
61
+ .div(numericConstants_1.AMM_RESERVE_PRECISION)
62
+ .div(numericConstants_1.PEG_PRECISION);
63
+ const numer1 = pegged_y_d_d;
64
+ const numer2 = C.mul(d)
65
+ .div(numericConstants_1.QUOTE_PRECISION)
66
+ .mul(x.add(d))
67
+ .div(numericConstants_1.AMM_RESERVE_PRECISION)
68
+ .mul(dSign);
69
+ const denom1 = C.mul(x)
70
+ .mul(x.add(d))
71
+ .div(numericConstants_1.AMM_RESERVE_PRECISION)
72
+ .div(numericConstants_1.QUOTE_PRECISION);
73
+ const denom2 = pegged_y_d_d;
74
+ const numerator = numer1.sub(numer2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
75
+ const denominator = denom1.add(denom2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
76
+ return [numerator, denominator];
77
+ }
78
+ exports.calculateBudgetedKBN = calculateBudgetedKBN;
79
+ function calculateBudgetedK(amm, cost) {
80
+ // wolframalpha.com
81
+ // (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
82
+ // p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*d*d*Q)
83
+ // numer
84
+ // = y*d*d*Q - Cxd - Cdd
85
+ // = y/x*Q*d*d - Cd - Cd/x
86
+ // = mark - C/d - C/(x)
87
+ // = mark/C - 1/d - 1/x
88
+ // denom
89
+ // = C*x*x + C*x*d + y*d*d*Q
90
+ // = x/d**2 + 1 / d + mark/C
91
+ // todo: assumes k = x * y
92
+ // otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
93
+ const x = amm.baseAssetReserve;
94
+ const y = amm.quoteAssetReserve;
95
+ const d = amm.netBaseAssetAmount;
96
+ const Q = amm.pegMultiplier;
97
+ const [numerator, denominator] = calculateBudgetedKBN(x, y, cost, Q, d);
98
+ return [numerator, denominator];
99
+ }
100
+ exports.calculateBudgetedK = calculateBudgetedK;
101
+ function calculateBudgetedPeg(amm, cost, targetPrice) {
102
+ // wolframalpha.com
103
+ // (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
104
+ // p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
105
+ // todo: assumes k = x * y
106
+ // otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
107
+ const targetPeg = targetPrice
108
+ .mul(amm.baseAssetReserve)
109
+ .div(amm.quoteAssetReserve)
110
+ .div(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.PEG_PRECISION));
111
+ const k = amm.sqrtK.mul(amm.sqrtK);
112
+ const x = amm.baseAssetReserve;
113
+ const y = amm.quoteAssetReserve;
114
+ const d = amm.netBaseAssetAmount;
115
+ const Q = amm.pegMultiplier;
116
+ const C = cost.mul(new anchor_1.BN(-1));
117
+ const deltaQuoteAssetReserves = y.sub(k.div(x.add(d)));
118
+ const pegChangeDirection = targetPeg.sub(Q);
119
+ const useTargetPeg = (deltaQuoteAssetReserves.lt(numericConstants_1.ZERO) && pegChangeDirection.gt(numericConstants_1.ZERO)) ||
120
+ (deltaQuoteAssetReserves.gt(numericConstants_1.ZERO) && pegChangeDirection.lt(numericConstants_1.ZERO));
121
+ if (deltaQuoteAssetReserves.eq(numericConstants_1.ZERO) || useTargetPeg) {
122
+ return targetPeg;
123
+ }
124
+ const deltaPegMultiplier = C.mul(numericConstants_1.MARK_PRICE_PRECISION).div(deltaQuoteAssetReserves.div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO));
125
+ const newPeg = Q.sub(deltaPegMultiplier.mul(numericConstants_1.PEG_PRECISION).div(numericConstants_1.MARK_PRICE_PRECISION));
126
+ return newPeg;
127
+ }
128
+ exports.calculateBudgetedPeg = calculateBudgetedPeg;
@@ -1,7 +1,8 @@
1
1
  /// <reference types="bn.js" />
2
- import { Market, PositionDirection } from '../types';
2
+ import { MarketAccount, PositionDirection } from '../types';
3
3
  import { BN } from '@project-serum/anchor';
4
4
  import { AssetType } from './amm';
5
+ import { OraclePriceData } from '../oracles/types';
5
6
  export declare type PriceImpactUnit = 'entryPrice' | 'maxPrice' | 'priceDelta' | 'priceDeltaAsNumber' | 'pctAvg' | 'pctMax' | 'quoteAssetAmount' | 'quoteAssetAmountPeg' | 'acquiredBaseAssetAmount' | 'acquiredQuoteAssetAmount' | 'all';
6
7
  /**
7
8
  * Calculates avg/max slippage (price impact) for candidate trade
@@ -20,7 +21,7 @@ export declare type PriceImpactUnit = 'entryPrice' | 'maxPrice' | 'priceDelta' |
20
21
  *
21
22
  * 'newPrice' => the price of the asset after the trade : Precision MARK_PRICE_PRECISION
22
23
  */
23
- export declare function calculateTradeSlippage(direction: PositionDirection, amount: BN, market: Market, inputAssetType?: AssetType, useSpread?: boolean): [BN, BN, BN, BN];
24
+ export declare function calculateTradeSlippage(direction: PositionDirection, amount: BN, market: MarketAccount, inputAssetType?: AssetType, oraclePriceData?: OraclePriceData, useSpread?: boolean): [BN, BN, BN, BN];
24
25
  /**
25
26
  * Calculates acquired amounts for trade executed
26
27
  * @param direction
@@ -32,7 +33,7 @@ export declare function calculateTradeSlippage(direction: PositionDirection, amo
32
33
  * | 'acquiredBase' => positive/negative change in user's base : BN AMM_RESERVE_PRECISION
33
34
  * | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
34
35
  */
35
- export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: Market, inputAssetType?: AssetType, useSpread?: boolean): [BN, BN];
36
+ export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: MarketAccount, inputAssetType: AssetType, oraclePriceData: OraclePriceData, useSpread?: boolean): [BN, BN];
36
37
  /**
37
38
  * calculateTargetPriceTrade
38
39
  * simple function for finding arbitraging trades
@@ -50,4 +51,4 @@ export declare function calculateTradeAcquiredAmounts(direction: PositionDirecti
50
51
  * targetPrice => the target price MARK_PRICE_PRECISION
51
52
  * ]
52
53
  */
53
- export declare function calculateTargetPriceTrade(market: Market, targetPrice: BN, pct?: BN, outputAssetType?: AssetType, useSpread?: boolean): [PositionDirection, BN, BN, BN];
54
+ export declare function calculateTargetPriceTrade(market: MarketAccount, targetPrice: BN, pct?: BN, outputAssetType?: AssetType, oraclePriceData?: OraclePriceData, useSpread?: boolean): [PositionDirection, BN, BN, BN];
package/lib/math/trade.js CHANGED
@@ -27,32 +27,39 @@ const MAXPCT = new anchor_1.BN(1000); //percentage units are [0,1000] => [0,1]
27
27
  *
28
28
  * 'newPrice' => the price of the asset after the trade : Precision MARK_PRICE_PRECISION
29
29
  */
30
- function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quote', useSpread = true) {
30
+ function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quote', oraclePriceData, useSpread = true) {
31
31
  let oldPrice;
32
32
  if (useSpread && market.amm.baseSpread > 0) {
33
33
  if ((0, types_2.isVariant)(direction, 'long')) {
34
- oldPrice = (0, market_1.calculateAskPrice)(market);
34
+ oldPrice = (0, market_1.calculateAskPrice)(market, oraclePriceData);
35
35
  }
36
36
  else {
37
- oldPrice = (0, market_1.calculateBidPrice)(market);
37
+ oldPrice = (0, market_1.calculateBidPrice)(market, oraclePriceData);
38
38
  }
39
39
  }
40
40
  else {
41
- oldPrice = (0, market_1.calculateMarkPrice)(market);
41
+ oldPrice = (0, market_1.calculateMarkPrice)(market, oraclePriceData);
42
42
  }
43
43
  if (amount.eq(numericConstants_1.ZERO)) {
44
44
  return [numericConstants_1.ZERO, numericConstants_1.ZERO, oldPrice, oldPrice];
45
45
  }
46
- const [acquiredBase, acquiredQuote] = calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType, useSpread);
47
- const entryPrice = (0, amm_1.calculatePrice)(acquiredBase, acquiredQuote, market.amm.pegMultiplier).mul(new anchor_1.BN(-1));
46
+ const [acquiredBase, acquiredQuote] = calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType, oraclePriceData, useSpread);
47
+ const swapDirection = (0, types_2.isVariant)(direction, 'long')
48
+ ? types_1.SwapDirection.REMOVE
49
+ : types_1.SwapDirection.ADD;
50
+ const quoteAssetAmountAcquired = (0, amm_1.calculateQuoteAssetAmountSwapped)(acquiredQuote.abs(), market.amm.pegMultiplier, swapDirection);
51
+ const entryPrice = quoteAssetAmountAcquired
52
+ .mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
53
+ .mul(numericConstants_1.MARK_PRICE_PRECISION)
54
+ .div(acquiredBase.abs());
48
55
  let amm;
49
56
  if (useSpread && market.amm.baseSpread > 0) {
50
- const { baseAssetReserve, quoteAssetReserve } = (0, amm_1.calculateSpreadReserves)(market.amm, direction);
57
+ const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, direction, oraclePriceData);
51
58
  amm = {
52
59
  baseAssetReserve,
53
60
  quoteAssetReserve,
54
- sqrtK: market.amm.sqrtK,
55
- pegMultiplier: market.amm.pegMultiplier,
61
+ sqrtK: sqrtK,
62
+ pegMultiplier: newPeg,
56
63
  };
57
64
  }
58
65
  else {
@@ -60,10 +67,10 @@ function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quo
60
67
  }
61
68
  const newPrice = (0, amm_1.calculatePrice)(amm.baseAssetReserve.sub(acquiredBase), amm.quoteAssetReserve.sub(acquiredQuote), amm.pegMultiplier);
62
69
  if (direction == types_1.PositionDirection.SHORT) {
63
- (0, assert_1.assert)(newPrice.lt(oldPrice));
70
+ (0, assert_1.assert)(newPrice.lte(oldPrice));
64
71
  }
65
72
  else {
66
- (0, assert_1.assert)(oldPrice.lt(newPrice));
73
+ (0, assert_1.assert)(oldPrice.lte(newPrice));
67
74
  }
68
75
  const pctMaxSlippage = newPrice
69
76
  .sub(oldPrice)
@@ -89,19 +96,19 @@ exports.calculateTradeSlippage = calculateTradeSlippage;
89
96
  * | 'acquiredBase' => positive/negative change in user's base : BN AMM_RESERVE_PRECISION
90
97
  * | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
91
98
  */
92
- function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType = 'quote', useSpread = true) {
99
+ function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType = 'quote', oraclePriceData, useSpread = true) {
93
100
  if (amount.eq(numericConstants_1.ZERO)) {
94
101
  return [numericConstants_1.ZERO, numericConstants_1.ZERO];
95
102
  }
96
103
  const swapDirection = (0, amm_1.getSwapDirection)(inputAssetType, direction);
97
104
  let amm;
98
105
  if (useSpread && market.amm.baseSpread > 0) {
99
- const { baseAssetReserve, quoteAssetReserve } = (0, amm_1.calculateSpreadReserves)(market.amm, direction);
106
+ const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, direction, oraclePriceData);
100
107
  amm = {
101
108
  baseAssetReserve,
102
109
  quoteAssetReserve,
103
- sqrtK: market.amm.sqrtK,
104
- pegMultiplier: market.amm.pegMultiplier,
110
+ sqrtK: sqrtK,
111
+ pegMultiplier: newPeg,
105
112
  };
106
113
  }
107
114
  else {
@@ -130,13 +137,13 @@ exports.calculateTradeAcquiredAmounts = calculateTradeAcquiredAmounts;
130
137
  * targetPrice => the target price MARK_PRICE_PRECISION
131
138
  * ]
132
139
  */
133
- function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAssetType = 'quote', useSpread = true) {
140
+ function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAssetType = 'quote', oraclePriceData, useSpread = true) {
134
141
  (0, assert_1.assert)(market.amm.baseAssetReserve.gt(numericConstants_1.ZERO));
135
142
  (0, assert_1.assert)(targetPrice.gt(numericConstants_1.ZERO));
136
143
  (0, assert_1.assert)(pct.lte(MAXPCT) && pct.gt(numericConstants_1.ZERO));
137
- const markPriceBefore = (0, market_1.calculateMarkPrice)(market);
138
- const bidPriceBefore = (0, market_1.calculateBidPrice)(market);
139
- const askPriceBefore = (0, market_1.calculateAskPrice)(market);
144
+ const markPriceBefore = (0, market_1.calculateMarkPrice)(market, oraclePriceData);
145
+ const bidPriceBefore = (0, market_1.calculateBidPrice)(market, oraclePriceData);
146
+ const askPriceBefore = (0, market_1.calculateAskPrice)(market, oraclePriceData);
140
147
  let direction;
141
148
  if (targetPrice.gt(markPriceBefore)) {
142
149
  const priceGap = targetPrice.sub(markPriceBefore);
@@ -154,16 +161,17 @@ function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAsse
154
161
  let baseSize;
155
162
  let baseAssetReserveBefore;
156
163
  let quoteAssetReserveBefore;
164
+ let peg = market.amm.pegMultiplier;
157
165
  if (useSpread && market.amm.baseSpread > 0) {
158
- const { baseAssetReserve, quoteAssetReserve } = (0, amm_1.calculateSpreadReserves)(market.amm, direction);
166
+ const { baseAssetReserve, quoteAssetReserve, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, direction, oraclePriceData);
159
167
  baseAssetReserveBefore = baseAssetReserve;
160
168
  quoteAssetReserveBefore = quoteAssetReserve;
169
+ peg = newPeg;
161
170
  }
162
171
  else {
163
172
  baseAssetReserveBefore = market.amm.baseAssetReserve;
164
173
  quoteAssetReserveBefore = market.amm.quoteAssetReserve;
165
174
  }
166
- const peg = market.amm.pegMultiplier;
167
175
  const invariant = market.amm.sqrtK.mul(market.amm.sqrtK);
168
176
  const k = invariant.mul(numericConstants_1.MARK_PRICE_PRECISION);
169
177
  let baseAssetReserveAfter;