@drift-labs/sdk 0.2.0-master.1 → 0.2.0-master.12

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 (142) hide show
  1. package/lib/accounts/types.d.ts +1 -0
  2. package/lib/admin.d.ts +8 -5
  3. package/lib/admin.js +43 -11
  4. package/lib/clearingHouse.d.ts +35 -20
  5. package/lib/clearingHouse.js +497 -154
  6. package/lib/clearingHouseUser.d.ts +12 -17
  7. package/lib/clearingHouseUser.js +97 -88
  8. package/lib/config.js +1 -1
  9. package/lib/constants/banks.d.ts +2 -2
  10. package/lib/constants/banks.js +12 -4
  11. package/lib/constants/numericConstants.d.ts +4 -0
  12. package/lib/constants/numericConstants.js +5 -1
  13. package/lib/events/eventList.js +3 -0
  14. package/lib/events/types.d.ts +2 -1
  15. package/lib/factory/bigNum.d.ts +9 -2
  16. package/lib/factory/bigNum.js +50 -16
  17. package/lib/idl/clearing_house.json +858 -177
  18. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  19. package/lib/index.d.ts +4 -2
  20. package/lib/index.js +8 -2
  21. package/lib/math/amm.d.ts +6 -1
  22. package/lib/math/amm.js +124 -41
  23. package/lib/math/auction.js +4 -1
  24. package/lib/math/bankBalance.d.ts +3 -1
  25. package/lib/math/bankBalance.js +54 -1
  26. package/lib/math/margin.d.ts +11 -0
  27. package/lib/math/margin.js +72 -0
  28. package/lib/math/market.d.ts +4 -1
  29. package/lib/math/market.js +35 -1
  30. package/lib/math/orders.d.ts +2 -2
  31. package/lib/math/orders.js +18 -11
  32. package/lib/math/position.d.ts +8 -0
  33. package/lib/math/position.js +44 -12
  34. package/lib/math/repeg.js +1 -1
  35. package/lib/math/trade.d.ts +1 -1
  36. package/lib/math/trade.js +7 -10
  37. package/lib/orderParams.d.ts +14 -5
  38. package/lib/orderParams.js +8 -96
  39. package/lib/orders.d.ts +2 -4
  40. package/lib/orders.js +7 -161
  41. package/lib/slot/SlotSubscriber.d.ts +7 -0
  42. package/lib/slot/SlotSubscriber.js +3 -0
  43. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  44. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  45. package/lib/tx/retryTxSender.js +9 -2
  46. package/lib/tx/utils.js +1 -1
  47. package/lib/types.d.ts +159 -15
  48. package/lib/types.js +59 -1
  49. package/lib/util/computeUnits.js +1 -1
  50. package/lib/util/getTokenAddress.d.ts +2 -0
  51. package/lib/util/getTokenAddress.js +9 -0
  52. package/package.json +3 -3
  53. package/src/accounts/bulkAccountLoader.js +197 -0
  54. package/src/accounts/bulkUserSubscription.js +33 -0
  55. package/src/accounts/pollingClearingHouseAccountSubscriber.js +311 -0
  56. package/src/accounts/pollingOracleSubscriber.js +93 -0
  57. package/src/accounts/pollingTokenAccountSubscriber.js +90 -0
  58. package/src/accounts/pollingUserAccountSubscriber.js +132 -0
  59. package/src/accounts/types.js +10 -0
  60. package/src/accounts/utils.js +7 -0
  61. package/src/accounts/webSocketAccountSubscriber.js +93 -0
  62. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +233 -0
  63. package/src/accounts/webSocketUserAccountSubscriber.js +62 -0
  64. package/src/addresses/marketAddresses.js +26 -0
  65. package/src/admin.ts +66 -14
  66. package/src/assert/assert.js +9 -0
  67. package/src/clearingHouse.ts +836 -254
  68. package/src/clearingHouseConfig.js +2 -0
  69. package/src/clearingHouseUser.ts +219 -121
  70. package/src/clearingHouseUserConfig.js +2 -0
  71. package/src/config.ts +1 -1
  72. package/src/constants/banks.js +42 -0
  73. package/src/constants/banks.ts +14 -4
  74. package/src/constants/markets.js +42 -0
  75. package/src/constants/numericConstants.js +41 -0
  76. package/src/constants/numericConstants.ts +5 -0
  77. package/src/events/eventList.js +77 -0
  78. package/src/events/eventList.ts +3 -0
  79. package/src/events/eventSubscriber.js +139 -0
  80. package/src/events/fetchLogs.js +50 -0
  81. package/src/events/pollingLogProvider.js +64 -0
  82. package/src/events/sort.js +44 -0
  83. package/src/events/txEventCache.js +71 -0
  84. package/src/events/types.js +20 -0
  85. package/src/events/types.ts +2 -0
  86. package/src/events/webSocketLogProvider.js +41 -0
  87. package/src/examples/makeTradeExample.js +80 -0
  88. package/src/factory/bigNum.js +390 -0
  89. package/src/factory/bigNum.ts +65 -18
  90. package/src/factory/oracleClient.js +20 -0
  91. package/src/idl/clearing_house.json +858 -177
  92. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  93. package/src/index.js +69 -0
  94. package/src/index.ts +4 -2
  95. package/src/math/amm.js +369 -0
  96. package/src/math/amm.ts +207 -52
  97. package/src/math/auction.js +42 -0
  98. package/src/math/auction.ts +5 -1
  99. package/src/math/bankBalance.ts +98 -1
  100. package/src/math/conversion.js +11 -0
  101. package/src/math/funding.js +248 -0
  102. package/src/math/margin.ts +124 -0
  103. package/src/math/market.ts +66 -1
  104. package/src/math/oracles.js +26 -0
  105. package/src/math/orders.ts +17 -13
  106. package/src/math/position.ts +63 -9
  107. package/src/math/repeg.js +128 -0
  108. package/src/math/repeg.ts +2 -1
  109. package/src/math/state.js +15 -0
  110. package/src/math/trade.js +253 -0
  111. package/src/math/trade.ts +23 -25
  112. package/src/math/utils.js +0 -1
  113. package/src/mockUSDCFaucet.js +280 -0
  114. package/src/oracles/oracleClientCache.js +19 -0
  115. package/src/oracles/pythClient.js +46 -0
  116. package/src/oracles/quoteAssetOracleClient.js +32 -0
  117. package/src/oracles/switchboardClient.js +69 -0
  118. package/src/oracles/types.js +2 -0
  119. package/src/orderParams.js +20 -0
  120. package/src/orderParams.ts +20 -141
  121. package/src/orders.ts +10 -287
  122. package/src/slot/SlotSubscriber.js +39 -0
  123. package/src/slot/SlotSubscriber.ts +11 -1
  124. package/src/token/index.js +38 -0
  125. package/src/tokenFaucet.js +189 -0
  126. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  127. package/src/tx/retryTxSender.ts +11 -3
  128. package/src/tx/types.js +2 -0
  129. package/src/tx/utils.js +17 -0
  130. package/src/tx/utils.ts +1 -1
  131. package/src/types.js +125 -0
  132. package/src/types.ts +155 -17
  133. package/src/userName.js +20 -0
  134. package/src/util/computeUnits.js +21 -11
  135. package/src/util/computeUnits.ts +1 -1
  136. package/src/util/getTokenAddress.js +9 -0
  137. package/src/util/getTokenAddress.ts +18 -0
  138. package/src/util/promiseTimeout.js +14 -0
  139. package/src/util/tps.js +27 -0
  140. package/src/wallet.js +35 -0
  141. package/tests/bn/test.ts +2 -0
  142. package/src/util/computeUnits.js.map +0 -1
@@ -1,10 +1,10 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { ClearingHouseUser } from '../clearingHouseUser';
3
- import { Order } from '../types';
3
+ import { MarketAccount, Order } from '../types';
4
4
  import { BN } from '@project-serum/anchor';
5
5
  import { OraclePriceData } from '../oracles/types';
6
6
  export declare function isOrderRiskIncreasing(user: ClearingHouseUser, order: Order): boolean;
7
7
  export declare function isOrderRiskIncreasingInSameDirection(user: ClearingHouseUser, order: Order): boolean;
8
8
  export declare function isOrderReduceOnly(user: ClearingHouseUser, order: Order): boolean;
9
9
  export declare function standardizeBaseAssetAmount(baseAssetAmount: BN, stepSize: BN): BN;
10
- export declare function getLimitPrice(order: Order, oraclePriceData: OraclePriceData, slot: number): BN;
10
+ export declare function getLimitPrice(order: Order, market: MarketAccount, oraclePriceData: OraclePriceData, slot: number): BN;
@@ -5,6 +5,7 @@ const types_1 = require("../types");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const anchor_1 = require("@project-serum/anchor");
7
7
  const auction_1 = require("./auction");
8
+ const market_1 = require("./market");
8
9
  function isOrderRiskIncreasing(user, order) {
9
10
  if ((0, types_1.isVariant)(order.status, 'init')) {
10
11
  return false;
@@ -78,23 +79,29 @@ function standardizeBaseAssetAmount(baseAssetAmount, stepSize) {
78
79
  return baseAssetAmount.sub(remainder);
79
80
  }
80
81
  exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
81
- function getLimitPrice(order, oraclePriceData, slot) {
82
+ function getLimitPrice(order, market, oraclePriceData, slot) {
82
83
  let limitPrice;
83
84
  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);
85
+ limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
86
+ }
87
+ else if ((0, types_1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket'])) {
88
+ if ((0, auction_1.isAuctionComplete)(order, slot)) {
89
+ limitPrice = (0, auction_1.getAuctionPrice)(order, slot);
90
+ }
91
+ else if (!order.price.eq(numericConstants_1.ZERO)) {
92
+ limitPrice = order.price;
93
+ }
94
+ else if ((0, types_1.isVariant)(order.direction, 'long')) {
95
+ const askPrice = (0, market_1.calculateAskPrice)(market, oraclePriceData);
96
+ const delta = askPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
97
+ limitPrice = askPrice.add(delta);
89
98
  }
90
99
  else {
91
- limitPrice = floatingPrice;
100
+ const bidPrice = (0, market_1.calculateBidPrice)(market, oraclePriceData);
101
+ const delta = bidPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
102
+ limitPrice = bidPrice.sub(delta);
92
103
  }
93
104
  }
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
105
  else {
99
106
  limitPrice = order.price;
100
107
  }
@@ -17,9 +17,11 @@ export declare function calculateBaseAssetValue(market: MarketAccount, userPosit
17
17
  * @param market
18
18
  * @param marketPosition
19
19
  * @param withFunding (adds unrealized funding payment pnl to result)
20
+ * @param oraclePriceData
20
21
  * @returns BaseAssetAmount : Precision QUOTE_PRECISION
21
22
  */
22
23
  export declare function calculatePositionPNL(market: MarketAccount, marketPosition: UserPosition, withFunding: boolean, oraclePriceData: OraclePriceData): BN;
24
+ export declare function calculateUnsettledPnl(market: MarketAccount, marketPosition: UserPosition, oraclePriceData: OraclePriceData): BN;
23
25
  /**
24
26
  *
25
27
  * @param market
@@ -34,6 +36,12 @@ export declare function positionIsAvailable(position: UserPosition): boolean;
34
36
  * @returns Precision: MARK_PRICE_PRECISION (10^10)
35
37
  */
36
38
  export declare function calculateEntryPrice(userPosition: UserPosition): BN;
39
+ /**
40
+ *
41
+ * @param userPosition
42
+ * @returns Precision: MARK_PRICE_PRECISION (10^10)
43
+ */
44
+ export declare function calculateCostBasis(userPosition: UserPosition): BN;
37
45
  export declare function findDirectionToClose(userPosition: UserPosition): PositionDirection;
38
46
  export declare function positionCurrentDirection(userPosition: UserPosition): PositionDirection;
39
47
  export declare function isEmptyPosition(userPosition: UserPosition): boolean;
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
3
+ exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateCostBasis = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculateUnsettledPnl = 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");
7
7
  const amm_1 = require("./amm");
8
+ const margin_1 = require("./margin");
8
9
  /**
9
10
  * calculateBaseAssetValue
10
11
  * = market value of closing entire position
@@ -53,20 +54,20 @@ exports.calculateBaseAssetValue = calculateBaseAssetValue;
53
54
  * @param market
54
55
  * @param marketPosition
55
56
  * @param withFunding (adds unrealized funding payment pnl to result)
57
+ * @param oraclePriceData
56
58
  * @returns BaseAssetAmount : Precision QUOTE_PRECISION
57
59
  */
58
60
  function calculatePositionPNL(market, marketPosition, withFunding = false, oraclePriceData) {
59
61
  if (marketPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
60
- return numericConstants_1.ZERO;
61
- }
62
- const baseAssetValue = calculateBaseAssetValue(market, marketPosition, oraclePriceData);
63
- let pnl;
64
- if (marketPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
65
- pnl = baseAssetValue.sub(marketPosition.quoteAssetAmount);
66
- }
67
- else {
68
- pnl = marketPosition.quoteAssetAmount.sub(baseAssetValue);
62
+ return marketPosition.quoteAssetAmount;
69
63
  }
64
+ const baseAssetValue = (0, margin_1.calculateMarginBaseAssetValue)(market, marketPosition, oraclePriceData);
65
+ const baseAssetValueSign = marketPosition.baseAssetAmount.isNeg()
66
+ ? new __1.BN(-1)
67
+ : new __1.BN(1);
68
+ let pnl = baseAssetValue
69
+ .mul(baseAssetValueSign)
70
+ .add(marketPosition.quoteAssetAmount);
70
71
  if (withFunding) {
71
72
  const fundingRatePnL = calculatePositionFundingPNL(market, marketPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
72
73
  pnl = pnl.add(fundingRatePnL);
@@ -74,6 +75,19 @@ function calculatePositionPNL(market, marketPosition, withFunding = false, oracl
74
75
  return pnl;
75
76
  }
76
77
  exports.calculatePositionPNL = calculatePositionPNL;
78
+ function calculateUnsettledPnl(market, marketPosition, oraclePriceData) {
79
+ const unrealizedPnl = calculatePositionPNL(market, marketPosition, true, oraclePriceData);
80
+ let unsettledPnl = unrealizedPnl;
81
+ if (unrealizedPnl.gt(numericConstants_1.ZERO)) {
82
+ const fundingPnL = calculatePositionFundingPNL(market, marketPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
83
+ const maxPositivePnl = __1.BN.max(marketPosition.quoteAssetAmount
84
+ .add(marketPosition.quoteEntryAmount)
85
+ .add(fundingPnL), numericConstants_1.ZERO);
86
+ unsettledPnl = __1.BN.min(maxPositivePnl, unrealizedPnl);
87
+ }
88
+ return unsettledPnl;
89
+ }
90
+ exports.calculateUnsettledPnl = calculateUnsettledPnl;
77
91
  /**
78
92
  *
79
93
  * @param market
@@ -101,7 +115,9 @@ function calculatePositionFundingPNL(market, marketPosition) {
101
115
  }
102
116
  exports.calculatePositionFundingPNL = calculatePositionFundingPNL;
103
117
  function positionIsAvailable(position) {
104
- return position.baseAssetAmount.eq(numericConstants_1.ZERO) && position.openOrders.eq(numericConstants_1.ZERO);
118
+ return (position.baseAssetAmount.eq(numericConstants_1.ZERO) &&
119
+ position.openOrders.eq(numericConstants_1.ZERO) &&
120
+ position.quoteAssetAmount.eq(numericConstants_1.ZERO));
105
121
  }
106
122
  exports.positionIsAvailable = positionIsAvailable;
107
123
  /**
@@ -113,13 +129,29 @@ function calculateEntryPrice(userPosition) {
113
129
  if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
114
130
  return numericConstants_1.ZERO;
115
131
  }
116
- return userPosition.quoteAssetAmount
132
+ return userPosition.quoteEntryAmount
117
133
  .mul(numericConstants_1.MARK_PRICE_PRECISION)
118
134
  .mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
119
135
  .div(userPosition.baseAssetAmount)
120
136
  .abs();
121
137
  }
122
138
  exports.calculateEntryPrice = calculateEntryPrice;
139
+ /**
140
+ *
141
+ * @param userPosition
142
+ * @returns Precision: MARK_PRICE_PRECISION (10^10)
143
+ */
144
+ function calculateCostBasis(userPosition) {
145
+ if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
146
+ return numericConstants_1.ZERO;
147
+ }
148
+ return userPosition.quoteAssetAmount
149
+ .mul(numericConstants_1.MARK_PRICE_PRECISION)
150
+ .mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
151
+ .div(userPosition.baseAssetAmount)
152
+ .abs();
153
+ }
154
+ exports.calculateCostBasis = calculateCostBasis;
123
155
  function findDirectionToClose(userPosition) {
124
156
  return userPosition.baseAssetAmount.gt(numericConstants_1.ZERO)
125
157
  ? types_1.PositionDirection.SHORT
package/lib/math/repeg.js CHANGED
@@ -107,7 +107,7 @@ function calculateBudgetedPeg(amm, cost, targetPrice) {
107
107
  const targetPeg = targetPrice
108
108
  .mul(amm.baseAssetReserve)
109
109
  .div(amm.quoteAssetReserve)
110
- .div(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.PEG_PRECISION));
110
+ .div(numericConstants_1.PRICE_DIV_PEG);
111
111
  const k = amm.sqrtK.mul(amm.sqrtK);
112
112
  const x = amm.baseAssetReserve;
113
113
  const y = amm.quoteAssetReserve;
@@ -33,7 +33,7 @@ export declare function calculateTradeSlippage(direction: PositionDirection, amo
33
33
  * | 'acquiredBase' => positive/negative change in user's base : BN AMM_RESERVE_PRECISION
34
34
  * | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
35
35
  */
36
- export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: MarketAccount, inputAssetType: AssetType, oraclePriceData: OraclePriceData, useSpread?: boolean): [BN, BN];
36
+ export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: MarketAccount, inputAssetType: AssetType, oraclePriceData: OraclePriceData, useSpread?: boolean): [BN, BN, BN];
37
37
  /**
38
38
  * calculateTargetPriceTrade
39
39
  * simple function for finding arbitraging trades
package/lib/math/trade.js CHANGED
@@ -43,15 +43,11 @@ function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quo
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, 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
46
+ const [acquiredBaseReserve, acquiredQuoteReserve, acquiredQuoteAssetAmount] = calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType, oraclePriceData, useSpread);
47
+ const entryPrice = acquiredQuoteAssetAmount
52
48
  .mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
53
49
  .mul(numericConstants_1.MARK_PRICE_PRECISION)
54
- .div(acquiredBase.abs());
50
+ .div(acquiredBaseReserve.abs());
55
51
  let amm;
56
52
  if (useSpread && market.amm.baseSpread > 0) {
57
53
  const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, direction, oraclePriceData);
@@ -65,7 +61,7 @@ function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quo
65
61
  else {
66
62
  amm = market.amm;
67
63
  }
68
- const newPrice = (0, amm_1.calculatePrice)(amm.baseAssetReserve.sub(acquiredBase), amm.quoteAssetReserve.sub(acquiredQuote), amm.pegMultiplier);
64
+ const newPrice = (0, amm_1.calculatePrice)(amm.baseAssetReserve.sub(acquiredBaseReserve), amm.quoteAssetReserve.sub(acquiredQuoteReserve), amm.pegMultiplier);
69
65
  if (direction == types_1.PositionDirection.SHORT) {
70
66
  (0, assert_1.assert)(newPrice.lte(oldPrice));
71
67
  }
@@ -98,7 +94,7 @@ exports.calculateTradeSlippage = calculateTradeSlippage;
98
94
  */
99
95
  function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType = 'quote', oraclePriceData, useSpread = true) {
100
96
  if (amount.eq(numericConstants_1.ZERO)) {
101
- return [numericConstants_1.ZERO, numericConstants_1.ZERO];
97
+ return [numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO];
102
98
  }
103
99
  const swapDirection = (0, amm_1.getSwapDirection)(inputAssetType, direction);
104
100
  let amm;
@@ -117,7 +113,8 @@ function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType
117
113
  const [newQuoteAssetReserve, newBaseAssetReserve] = (0, amm_1.calculateAmmReservesAfterSwap)(amm, inputAssetType, amount, swapDirection);
118
114
  const acquiredBase = amm.baseAssetReserve.sub(newBaseAssetReserve);
119
115
  const acquiredQuote = amm.quoteAssetReserve.sub(newQuoteAssetReserve);
120
- return [acquiredBase, acquiredQuote];
116
+ const acquiredQuoteAssetamount = (0, amm_1.calculateQuoteAssetAmountSwapped)(acquiredQuote.abs(), amm.pegMultiplier, swapDirection);
117
+ return [acquiredBase, acquiredQuote, acquiredQuoteAssetamount];
121
118
  }
122
119
  exports.calculateTradeAcquiredAmounts = calculateTradeAcquiredAmounts;
123
120
  /**
@@ -1,7 +1,16 @@
1
1
  /// <reference types="bn.js" />
2
- import { OrderParams, OrderTriggerCondition, PositionDirection } from './types';
2
+ import { OptionalOrderParams, OrderTriggerCondition } from './types';
3
3
  import { BN } from '@project-serum/anchor';
4
- export declare function getLimitOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, price: BN, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number, postOnly?: boolean, oraclePriceOffset?: BN, immediateOrCancel?: boolean): OrderParams;
5
- export declare function getTriggerMarketOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, triggerPrice: BN, triggerCondition: OrderTriggerCondition, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number): OrderParams;
6
- export declare function getTriggerLimitOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, price: BN, triggerPrice: BN, triggerCondition: OrderTriggerCondition, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number): OrderParams;
7
- export declare function getMarketOrderParams(marketIndex: BN, direction: PositionDirection, quoteAssetAmount: BN, baseAssetAmount: BN, reduceOnly: boolean, price?: BN, discountToken?: boolean, referrer?: boolean): OrderParams;
4
+ export declare function getLimitOrderParams(params: Omit<OptionalOrderParams, 'orderType'> & {
5
+ price: BN;
6
+ }): OptionalOrderParams;
7
+ export declare function getTriggerMarketOrderParams(params: Omit<OptionalOrderParams, 'orderType'> & {
8
+ triggerCondition: OrderTriggerCondition;
9
+ triggerPrice: BN;
10
+ }): OptionalOrderParams;
11
+ export declare function getTriggerLimitOrderParams(params: Omit<OptionalOrderParams, 'orderType'> & {
12
+ triggerCondition: OrderTriggerCondition;
13
+ triggerPrice: BN;
14
+ price: BN;
15
+ }): OptionalOrderParams;
16
+ export declare function getMarketOrderParams(params: Omit<OptionalOrderParams, 'orderType'>): OptionalOrderParams;
@@ -2,107 +2,19 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getMarketOrderParams = exports.getTriggerLimitOrderParams = exports.getTriggerMarketOrderParams = exports.getLimitOrderParams = void 0;
4
4
  const types_1 = require("./types");
5
- const numericConstants_1 = require("./constants/numericConstants");
6
- function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, reduceOnly, discountToken = false, referrer = false, userOrderId = 0, postOnly = false, oraclePriceOffset = numericConstants_1.ZERO, immediateOrCancel = false) {
7
- return {
8
- orderType: types_1.OrderType.LIMIT,
9
- userOrderId,
10
- marketIndex,
11
- direction,
12
- quoteAssetAmount: numericConstants_1.ZERO,
13
- baseAssetAmount,
14
- price,
15
- reduceOnly,
16
- postOnly,
17
- immediateOrCancel,
18
- positionLimit: numericConstants_1.ZERO,
19
- padding0: true,
20
- padding1: numericConstants_1.ZERO,
21
- optionalAccounts: {
22
- discountToken,
23
- referrer,
24
- },
25
- triggerCondition: types_1.OrderTriggerCondition.ABOVE,
26
- triggerPrice: numericConstants_1.ZERO,
27
- oraclePriceOffset,
28
- };
5
+ function getLimitOrderParams(params) {
6
+ return Object.assign({}, params, { orderType: types_1.OrderType.LIMIT });
29
7
  }
30
8
  exports.getLimitOrderParams = getLimitOrderParams;
31
- function getTriggerMarketOrderParams(marketIndex, direction, baseAssetAmount, triggerPrice, triggerCondition, reduceOnly, discountToken = false, referrer = false, userOrderId = 0) {
32
- return {
33
- orderType: types_1.OrderType.TRIGGER_MARKET,
34
- userOrderId,
35
- marketIndex,
36
- direction,
37
- quoteAssetAmount: numericConstants_1.ZERO,
38
- baseAssetAmount,
39
- price: numericConstants_1.ZERO,
40
- reduceOnly,
41
- postOnly: false,
42
- immediateOrCancel: false,
43
- positionLimit: numericConstants_1.ZERO,
44
- padding0: true,
45
- padding1: numericConstants_1.ZERO,
46
- optionalAccounts: {
47
- discountToken,
48
- referrer,
49
- },
50
- triggerCondition,
51
- triggerPrice,
52
- oraclePriceOffset: numericConstants_1.ZERO,
53
- };
9
+ function getTriggerMarketOrderParams(params) {
10
+ return Object.assign({}, params, { orderType: types_1.OrderType.TRIGGER_MARKET });
54
11
  }
55
12
  exports.getTriggerMarketOrderParams = getTriggerMarketOrderParams;
56
- function getTriggerLimitOrderParams(marketIndex, direction, baseAssetAmount, price, triggerPrice, triggerCondition, reduceOnly, discountToken = false, referrer = false, userOrderId = 0) {
57
- return {
58
- orderType: types_1.OrderType.TRIGGER_LIMIT,
59
- userOrderId,
60
- marketIndex,
61
- direction,
62
- quoteAssetAmount: numericConstants_1.ZERO,
63
- baseAssetAmount,
64
- price,
65
- reduceOnly,
66
- postOnly: false,
67
- immediateOrCancel: false,
68
- positionLimit: numericConstants_1.ZERO,
69
- padding0: true,
70
- padding1: numericConstants_1.ZERO,
71
- optionalAccounts: {
72
- discountToken,
73
- referrer,
74
- },
75
- triggerCondition,
76
- triggerPrice,
77
- oraclePriceOffset: numericConstants_1.ZERO,
78
- };
13
+ function getTriggerLimitOrderParams(params) {
14
+ return Object.assign({}, params, { orderType: types_1.OrderType.TRIGGER_LIMIT });
79
15
  }
80
16
  exports.getTriggerLimitOrderParams = getTriggerLimitOrderParams;
81
- function getMarketOrderParams(marketIndex, direction, quoteAssetAmount, baseAssetAmount, reduceOnly, price = numericConstants_1.ZERO, discountToken = false, referrer = false) {
82
- if (baseAssetAmount.eq(numericConstants_1.ZERO) && quoteAssetAmount.eq(numericConstants_1.ZERO)) {
83
- throw Error('baseAssetAmount or quoteAssetAmount must be zero');
84
- }
85
- return {
86
- orderType: types_1.OrderType.MARKET,
87
- userOrderId: 0,
88
- marketIndex,
89
- direction,
90
- quoteAssetAmount,
91
- baseAssetAmount,
92
- price,
93
- reduceOnly,
94
- postOnly: false,
95
- immediateOrCancel: false,
96
- positionLimit: numericConstants_1.ZERO,
97
- padding0: true,
98
- padding1: numericConstants_1.ZERO,
99
- optionalAccounts: {
100
- discountToken,
101
- referrer,
102
- },
103
- triggerCondition: types_1.OrderTriggerCondition.ABOVE,
104
- triggerPrice: numericConstants_1.ZERO,
105
- oraclePriceOffset: numericConstants_1.ZERO,
106
- };
17
+ function getMarketOrderParams(params) {
18
+ return Object.assign({}, params, { orderType: types_1.OrderType.MARKET });
107
19
  }
108
20
  exports.getMarketOrderParams = getMarketOrderParams;
package/lib/orders.d.ts CHANGED
@@ -1,9 +1,7 @@
1
1
  /// <reference types="bn.js" />
2
- import { MarketAccount, Order, UserAccount, UserPosition } from './types';
3
- import { BN, ClearingHouseUser } from '.';
2
+ import { MarketAccount, Order } from './types';
3
+ import { BN } from '.';
4
4
  import { OraclePriceData } from '.';
5
- export declare function calculateNewStateAfterOrder(userAccount: UserAccount, userPosition: UserPosition, market: MarketAccount, order: Order): [UserAccount, UserPosition, MarketAccount] | null;
6
5
  export declare function calculateBaseAssetAmountMarketCanExecute(market: MarketAccount, order: Order, oraclePriceData?: OraclePriceData): BN;
7
6
  export declare function calculateAmountToTradeForLimit(market: MarketAccount, order: Order, oraclePriceData?: OraclePriceData): BN;
8
7
  export declare function calculateAmountToTradeForTriggerLimit(market: MarketAccount, order: Order): BN;
9
- export declare function calculateBaseAssetAmountUserCanExecute(market: MarketAccount, order: Order, user: ClearingHouseUser, oraclePriceData?: OraclePriceData): BN;
package/lib/orders.js CHANGED
@@ -1,85 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateBaseAssetAmountUserCanExecute = exports.calculateAmountToTradeForTriggerLimit = exports.calculateAmountToTradeForLimit = exports.calculateBaseAssetAmountMarketCanExecute = exports.calculateNewStateAfterOrder = void 0;
3
+ exports.calculateAmountToTradeForTriggerLimit = exports.calculateAmountToTradeForLimit = exports.calculateBaseAssetAmountMarketCanExecute = void 0;
4
4
  const types_1 = require("./types");
5
5
  const _1 = require(".");
6
- const market_1 = require("./math/market");
7
6
  const numericConstants_1 = require("./constants/numericConstants");
8
7
  const amm_1 = require("./math/amm");
9
- const position_1 = require("./math/position");
10
- function calculateNewStateAfterOrder(userAccount, userPosition, market, order) {
11
- if ((0, types_1.isVariant)(order.status, 'init')) {
12
- return null;
13
- }
14
- const baseAssetAmountToTrade = calculateBaseAssetAmountMarketCanExecute(market, order);
15
- if (baseAssetAmountToTrade.lt(market.amm.baseAssetAmountStepSize)) {
16
- return null;
17
- }
18
- const userAccountAfter = Object.assign({}, userAccount);
19
- const userPositionAfter = Object.assign({}, userPosition);
20
- const currentPositionDirection = (0, position_1.positionCurrentDirection)(userPosition);
21
- const increasePosition = userPosition.baseAssetAmount.eq(numericConstants_1.ZERO) ||
22
- isSameDirection(order.direction, currentPositionDirection);
23
- if (increasePosition) {
24
- const marketAfter = (0, market_1.calculateNewMarketAfterTrade)(baseAssetAmountToTrade, order.direction, market);
25
- const { quoteAssetAmountSwapped, baseAssetAmountSwapped } = calculateAmountSwapped(market, marketAfter);
26
- userPositionAfter.baseAssetAmount = userPositionAfter.baseAssetAmount.add(baseAssetAmountSwapped);
27
- userPositionAfter.quoteAssetAmount = userPositionAfter.quoteAssetAmount.add(quoteAssetAmountSwapped);
28
- return [userAccountAfter, userPositionAfter, marketAfter];
29
- }
30
- else {
31
- const reversePosition = baseAssetAmountToTrade.gt(userPosition.baseAssetAmount.abs());
32
- if (reversePosition) {
33
- const intermediateMarket = (0, market_1.calculateNewMarketAfterTrade)(userPosition.baseAssetAmount, (0, position_1.findDirectionToClose)(userPosition), market);
34
- const { quoteAssetAmountSwapped: baseAssetValue } = calculateAmountSwapped(market, intermediateMarket);
35
- let pnl;
36
- if ((0, types_1.isVariant)(currentPositionDirection, 'long')) {
37
- pnl = baseAssetValue.sub(userPosition.quoteAssetAmount);
38
- }
39
- else {
40
- pnl = userPosition.quoteAssetAmount.sub(baseAssetValue);
41
- }
42
- userAccountAfter.collateral = userAccountAfter.collateral.add(pnl);
43
- const baseAssetAmountLeft = baseAssetAmountToTrade.sub(userPosition.baseAssetAmount.abs());
44
- const marketAfter = (0, market_1.calculateNewMarketAfterTrade)(baseAssetAmountLeft, order.direction, intermediateMarket);
45
- const { quoteAssetAmountSwapped, baseAssetAmountSwapped } = calculateAmountSwapped(intermediateMarket, marketAfter);
46
- userPositionAfter.quoteAssetAmount = quoteAssetAmountSwapped;
47
- userPositionAfter.baseAssetAmount = baseAssetAmountSwapped;
48
- return [userAccountAfter, userPositionAfter, marketAfter];
49
- }
50
- else {
51
- const marketAfter = (0, market_1.calculateNewMarketAfterTrade)(baseAssetAmountToTrade, order.direction, market);
52
- const { quoteAssetAmountSwapped: baseAssetValue, baseAssetAmountSwapped, } = calculateAmountSwapped(market, marketAfter);
53
- const costBasisRealized = userPosition.quoteAssetAmount
54
- .mul(baseAssetAmountSwapped.abs())
55
- .div(userPosition.baseAssetAmount.abs());
56
- let pnl;
57
- if ((0, types_1.isVariant)(currentPositionDirection, 'long')) {
58
- pnl = baseAssetValue.sub(costBasisRealized);
59
- }
60
- else {
61
- pnl = costBasisRealized.sub(baseAssetValue);
62
- }
63
- userAccountAfter.collateral = userAccountAfter.collateral.add(pnl);
64
- userPositionAfter.baseAssetAmount = userPositionAfter.baseAssetAmount.add(baseAssetAmountSwapped);
65
- userPositionAfter.quoteAssetAmount =
66
- userPositionAfter.quoteAssetAmount.sub(costBasisRealized);
67
- return [userAccountAfter, userPositionAfter, marketAfter];
68
- }
69
- }
70
- }
71
- exports.calculateNewStateAfterOrder = calculateNewStateAfterOrder;
72
- function calculateAmountSwapped(marketBefore, marketAfter) {
73
- return {
74
- quoteAssetAmountSwapped: marketBefore.amm.quoteAssetReserve
75
- .sub(marketAfter.amm.quoteAssetReserve)
76
- .abs()
77
- .mul(marketBefore.amm.pegMultiplier)
78
- .div(numericConstants_1.PEG_PRECISION)
79
- .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO),
80
- baseAssetAmountSwapped: marketBefore.amm.baseAssetReserve.sub(marketAfter.amm.baseAssetReserve),
81
- };
82
- }
83
8
  function calculateBaseAssetAmountMarketCanExecute(market, order, oraclePriceData) {
84
9
  if ((0, types_1.isVariant)(order.orderType, 'limit')) {
85
10
  return calculateAmountToTradeForLimit(market, order, oraclePriceData);
@@ -88,7 +13,6 @@ function calculateBaseAssetAmountMarketCanExecute(market, order, oraclePriceData
88
13
  return calculateAmountToTradeForTriggerLimit(market, order);
89
14
  }
90
15
  else if ((0, types_1.isVariant)(order.orderType, 'market')) {
91
- // should never be a market order queued
92
16
  return numericConstants_1.ZERO;
93
17
  }
94
18
  else {
@@ -102,17 +26,9 @@ function calculateAmountToTradeForLimit(market, order, oraclePriceData) {
102
26
  if (!oraclePriceData) {
103
27
  throw Error('Cant calculate limit price for oracle offset oracle without OraclePriceData');
104
28
  }
105
- const floatingPrice = oraclePriceData.price.add(order.oraclePriceOffset);
106
- if (order.postOnly) {
107
- limitPrice = (0, types_1.isVariant)(order.direction, 'long')
108
- ? _1.BN.min(order.price, floatingPrice)
109
- : _1.BN.max(order.price, floatingPrice);
110
- }
111
- else {
112
- limitPrice = floatingPrice;
113
- }
29
+ limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
114
30
  }
115
- const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction);
31
+ const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction, oraclePriceData);
116
32
  const baseAssetAmount = (0, _1.standardizeBaseAssetAmount)(maxAmountToTrade, market.amm.baseAssetAmountStepSize);
117
33
  // Check that directions are the same
118
34
  const sameDirection = isSameDirection(direction, order.direction);
@@ -125,11 +41,8 @@ function calculateAmountToTradeForLimit(market, order, oraclePriceData) {
125
41
  }
126
42
  exports.calculateAmountToTradeForLimit = calculateAmountToTradeForLimit;
127
43
  function calculateAmountToTradeForTriggerLimit(market, order) {
128
- if (order.baseAssetAmountFilled.eq(numericConstants_1.ZERO)) {
129
- const baseAssetAmount = calculateAmountToTradeForTriggerMarket(market, order);
130
- if (baseAssetAmount.eq(numericConstants_1.ZERO)) {
131
- return numericConstants_1.ZERO;
132
- }
44
+ if (!order.triggered) {
45
+ return numericConstants_1.ZERO;
133
46
  }
134
47
  return calculateAmountToTradeForLimit(market, order);
135
48
  }
@@ -139,75 +52,8 @@ function isSameDirection(firstDirection, secondDirection) {
139
52
  ((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
140
53
  }
141
54
  function calculateAmountToTradeForTriggerMarket(market, order) {
142
- return isTriggerConditionSatisfied(market, order)
143
- ? order.baseAssetAmount
144
- : numericConstants_1.ZERO;
145
- }
146
- function isTriggerConditionSatisfied(market, order, oraclePriceData) {
147
- const markPrice = (0, market_1.calculateMarkPrice)(market, oraclePriceData);
148
- if ((0, types_1.isVariant)(order.triggerCondition, 'above')) {
149
- return markPrice.gt(order.triggerPrice);
150
- }
151
- else {
152
- return markPrice.lt(order.triggerPrice);
153
- }
154
- }
155
- function calculateBaseAssetAmountUserCanExecute(market, order, user, oraclePriceData) {
156
- const maxLeverage = user.getMaxLeverage(order.marketIndex, 'Initial');
157
- const freeCollateral = user.getFreeCollateral();
158
- let quoteAssetAmount;
159
- if ((0, _1.isOrderRiskIncreasingInSameDirection)(user, order)) {
160
- quoteAssetAmount = freeCollateral.mul(maxLeverage).div(_1.TEN_THOUSAND);
161
- }
162
- else {
163
- const position = user.getUserPosition(order.marketIndex) ||
164
- user.getEmptyPosition(order.marketIndex);
165
- const positionValue = (0, _1.calculateBaseAssetValue)(market, position, oraclePriceData);
166
- quoteAssetAmount = freeCollateral
167
- .mul(maxLeverage)
168
- .div(_1.TEN_THOUSAND)
169
- .add(positionValue.mul(numericConstants_1.TWO));
170
- }
171
- if (quoteAssetAmount.lte(numericConstants_1.ZERO)) {
55
+ if (!order.triggered) {
172
56
  return numericConstants_1.ZERO;
173
57
  }
174
- const swapDirection = (0, types_1.isVariant)(order.direction, 'long')
175
- ? types_1.SwapDirection.ADD
176
- : types_1.SwapDirection.REMOVE;
177
- const useSpread = !order.postOnly;
178
- let amm;
179
- if (useSpread) {
180
- const { baseAssetReserve, quoteAssetReserve } = (0, _1.calculateSpreadReserves)(market.amm, order.direction, oraclePriceData);
181
- amm = {
182
- baseAssetReserve,
183
- quoteAssetReserve,
184
- sqrtK: market.amm.sqrtK,
185
- pegMultiplier: market.amm.pegMultiplier,
186
- };
187
- }
188
- else {
189
- amm = market.amm;
190
- }
191
- const baseAssetReservesBefore = amm.baseAssetReserve;
192
- const [_, baseAssetReservesAfter] = (0, _1.calculateAmmReservesAfterSwap)(amm, 'quote', quoteAssetAmount, swapDirection);
193
- let baseAssetAmount = baseAssetReservesBefore
194
- .sub(baseAssetReservesAfter)
195
- .abs();
196
- if (order.reduceOnly) {
197
- const position = user.getUserPosition(order.marketIndex) ||
198
- user.getEmptyPosition(order.marketIndex);
199
- if ((0, types_1.isVariant)(order.direction, 'long') &&
200
- position.baseAssetAmount.gte(numericConstants_1.ZERO)) {
201
- baseAssetAmount = numericConstants_1.ZERO;
202
- }
203
- else if ((0, types_1.isVariant)(order.direction, 'short') &&
204
- position.baseAssetAmount.lte(numericConstants_1.ZERO)) {
205
- baseAssetAmount = numericConstants_1.ZERO;
206
- }
207
- else {
208
- _1.BN.min(baseAssetAmount, position.baseAssetAmount.abs());
209
- }
210
- }
211
- return baseAssetAmount;
58
+ return order.baseAssetAmount;
212
59
  }
213
- exports.calculateBaseAssetAmountUserCanExecute = calculateBaseAssetAmountUserCanExecute;
@@ -1,9 +1,16 @@
1
+ /// <reference types="node" />
1
2
  import { Connection } from '@solana/web3.js';
3
+ import { EventEmitter } from 'events';
4
+ import StrictEventEmitter from 'strict-event-emitter-types/types/src';
2
5
  declare type SlotSubscriberConfig = {};
6
+ export interface SlotSubscriberEvents {
7
+ newSlot: (newSlot: number) => void;
8
+ }
3
9
  export declare class SlotSubscriber {
4
10
  private connection;
5
11
  currentSlot: number;
6
12
  subscriptionId: number;
13
+ eventEmitter: StrictEventEmitter<EventEmitter, SlotSubscriberEvents>;
7
14
  constructor(connection: Connection, _config?: SlotSubscriberConfig);
8
15
  subscribe(): Promise<void>;
9
16
  getSlot(): number;
@@ -1,14 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SlotSubscriber = void 0;
4
+ const events_1 = require("events");
4
5
  class SlotSubscriber {
5
6
  constructor(connection, _config) {
6
7
  this.connection = connection;
8
+ this.eventEmitter = new events_1.EventEmitter();
7
9
  }
8
10
  async subscribe() {
9
11
  this.currentSlot = await this.connection.getSlot('confirmed');
10
12
  this.subscriptionId = this.connection.onSlotChange((slotInfo) => {
11
13
  this.currentSlot = slotInfo.slot;
14
+ this.eventEmitter.emit('newSlot', slotInfo.slot);
12
15
  });
13
16
  }
14
17
  getSlot() {