@drift-labs/sdk 0.2.0-master.2 → 0.2.0-master.20

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 (152) hide show
  1. package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
  2. package/lib/accounts/bulkUserStatsSubscription.js +21 -0
  3. package/lib/accounts/bulkUserSubscription.js +0 -1
  4. package/lib/accounts/fetch.d.ts +2 -1
  5. package/lib/accounts/fetch.js +9 -1
  6. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  7. package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
  8. package/lib/accounts/types.d.ts +14 -1
  9. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  10. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  11. package/lib/addresses/pda.d.ts +1 -0
  12. package/lib/addresses/pda.js +8 -1
  13. package/lib/admin.d.ts +9 -5
  14. package/lib/admin.js +52 -11
  15. package/lib/clearingHouse.d.ts +52 -23
  16. package/lib/clearingHouse.js +727 -197
  17. package/lib/clearingHouseConfig.d.ts +1 -0
  18. package/lib/clearingHouseUser.d.ts +17 -17
  19. package/lib/clearingHouseUser.js +186 -101
  20. package/lib/clearingHouseUserStats.d.ts +18 -0
  21. package/lib/clearingHouseUserStats.js +49 -0
  22. package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
  23. package/lib/clearingHouseUserStatsConfig.js +2 -0
  24. package/lib/config.js +1 -1
  25. package/lib/constants/banks.d.ts +2 -2
  26. package/lib/constants/banks.js +12 -4
  27. package/lib/constants/numericConstants.d.ts +5 -0
  28. package/lib/constants/numericConstants.js +8 -3
  29. package/lib/events/eventList.js +3 -0
  30. package/lib/events/types.d.ts +3 -1
  31. package/lib/events/types.js +2 -0
  32. package/lib/factory/bigNum.d.ts +1 -0
  33. package/lib/factory/bigNum.js +34 -10
  34. package/lib/idl/clearing_house.json +1609 -388
  35. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  36. package/lib/index.d.ts +9 -3
  37. package/lib/index.js +13 -3
  38. package/lib/math/amm.d.ts +1 -0
  39. package/lib/math/amm.js +22 -38
  40. package/lib/math/auction.js +4 -1
  41. package/lib/math/bankBalance.d.ts +7 -1
  42. package/lib/math/bankBalance.js +77 -2
  43. package/lib/math/margin.d.ts +11 -0
  44. package/lib/math/margin.js +72 -0
  45. package/lib/math/market.d.ts +4 -1
  46. package/lib/math/market.js +35 -1
  47. package/lib/math/oracles.d.ts +3 -0
  48. package/lib/math/oracles.js +25 -5
  49. package/lib/math/orders.d.ts +5 -2
  50. package/lib/math/orders.js +53 -12
  51. package/lib/math/position.d.ts +8 -0
  52. package/lib/math/position.js +45 -12
  53. package/lib/math/trade.d.ts +1 -1
  54. package/lib/math/trade.js +7 -10
  55. package/lib/orderParams.d.ts +14 -5
  56. package/lib/orderParams.js +8 -96
  57. package/lib/slot/SlotSubscriber.d.ts +7 -0
  58. package/lib/slot/SlotSubscriber.js +3 -0
  59. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  60. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  61. package/lib/tx/retryTxSender.js +9 -2
  62. package/lib/tx/utils.js +1 -1
  63. package/lib/types.d.ts +233 -26
  64. package/lib/types.js +64 -1
  65. package/lib/util/computeUnits.js +1 -1
  66. package/lib/util/getTokenAddress.d.ts +2 -0
  67. package/lib/util/getTokenAddress.js +9 -0
  68. package/package.json +3 -3
  69. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  70. package/src/accounts/bulkUserSubscription.ts +0 -1
  71. package/src/accounts/fetch.ts +27 -2
  72. package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
  73. package/src/accounts/types.ts +18 -0
  74. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  75. package/src/addresses/marketAddresses.js +26 -0
  76. package/src/addresses/pda.ts +13 -0
  77. package/src/admin.ts +82 -15
  78. package/src/assert/assert.js +9 -0
  79. package/src/clearingHouse.ts +1224 -319
  80. package/src/clearingHouseConfig.ts +1 -0
  81. package/src/clearingHouseUser.ts +311 -148
  82. package/src/clearingHouseUserStats.ts +75 -0
  83. package/src/clearingHouseUserStatsConfig.ts +18 -0
  84. package/src/config.ts +1 -1
  85. package/src/constants/banks.js +42 -0
  86. package/src/constants/banks.ts +14 -4
  87. package/src/constants/markets.js +42 -0
  88. package/src/constants/numericConstants.js +41 -0
  89. package/src/constants/numericConstants.ts +14 -2
  90. package/src/events/eventList.js +77 -0
  91. package/src/events/eventList.ts +3 -0
  92. package/src/events/eventSubscriber.js +139 -0
  93. package/src/events/fetchLogs.js +50 -0
  94. package/src/events/pollingLogProvider.js +64 -0
  95. package/src/events/sort.js +44 -0
  96. package/src/events/txEventCache.js +71 -0
  97. package/src/events/types.ts +6 -0
  98. package/src/events/webSocketLogProvider.js +41 -0
  99. package/src/examples/makeTradeExample.js +80 -0
  100. package/src/factory/bigNum.js +390 -0
  101. package/src/factory/bigNum.ts +42 -13
  102. package/src/factory/oracleClient.js +20 -0
  103. package/src/idl/clearing_house.json +1609 -388
  104. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  105. package/src/index.ts +9 -3
  106. package/src/math/amm.ts +54 -55
  107. package/src/math/auction.js +42 -0
  108. package/src/math/auction.ts +5 -1
  109. package/src/math/bankBalance.ts +148 -2
  110. package/src/math/conversion.js +11 -0
  111. package/src/math/funding.js +248 -0
  112. package/src/math/margin.ts +124 -0
  113. package/src/math/market.ts +66 -1
  114. package/src/math/oracles.js +26 -0
  115. package/src/math/oracles.ts +42 -5
  116. package/src/math/orders.ts +112 -13
  117. package/src/math/position.ts +64 -9
  118. package/src/math/repeg.js +128 -0
  119. package/src/math/state.js +15 -0
  120. package/src/math/trade.js +253 -0
  121. package/src/math/trade.ts +23 -25
  122. package/src/math/utils.js +0 -1
  123. package/src/oracles/oracleClientCache.js +19 -0
  124. package/src/oracles/pythClient.js +46 -0
  125. package/src/oracles/quoteAssetOracleClient.js +32 -0
  126. package/src/oracles/switchboardClient.js +69 -0
  127. package/src/oracles/types.js +2 -0
  128. package/src/orderParams.js +20 -0
  129. package/src/orderParams.ts +20 -141
  130. package/src/slot/SlotSubscriber.js +39 -0
  131. package/src/slot/SlotSubscriber.ts +11 -1
  132. package/src/token/index.js +38 -0
  133. package/src/tokenFaucet.js +189 -0
  134. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  135. package/src/tx/retryTxSender.ts +11 -3
  136. package/src/tx/types.js +2 -0
  137. package/src/tx/utils.js +17 -0
  138. package/src/tx/utils.ts +1 -1
  139. package/src/types.ts +236 -27
  140. package/src/userName.js +20 -0
  141. package/src/util/computeUnits.js +21 -11
  142. package/src/util/computeUnits.ts +1 -1
  143. package/src/util/getTokenAddress.js +9 -0
  144. package/src/util/getTokenAddress.ts +18 -0
  145. package/src/util/promiseTimeout.js +14 -0
  146. package/src/util/tps.js +27 -0
  147. package/src/wallet.js +35 -0
  148. package/tests/bn/test.ts +10 -0
  149. package/lib/orders.d.ts +0 -8
  150. package/lib/orders.js +0 -142
  151. package/src/orders.ts +0 -251
  152. package/src/util/computeUnits.js.map +0 -1
@@ -1,19 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isOracleValid = void 0;
3
+ exports.isOracleTooDivergent = exports.isOracleValid = void 0;
4
4
  const numericConstants_1 = require("../constants/numericConstants");
5
5
  const index_1 = require("../index");
6
6
  function isOracleValid(amm, oraclePriceData, oracleGuardRails, slot) {
7
- const isOraclePriceNonPositive = oraclePriceData.price.lt(numericConstants_1.ZERO);
7
+ const isOraclePriceNonPositive = oraclePriceData.price.lte(numericConstants_1.ZERO);
8
8
  const isOraclePriceTooVolatile = oraclePriceData.price
9
9
  .div(index_1.BN.max(numericConstants_1.ONE, amm.lastOraclePriceTwap))
10
10
  .gt(oracleGuardRails.validity.tooVolatileRatio) ||
11
11
  amm.lastOraclePriceTwap
12
12
  .div(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.price))
13
13
  .gt(oracleGuardRails.validity.tooVolatileRatio);
14
- const isConfidenceTooLarge = oraclePriceData.price
15
- .div(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.confidence))
16
- .lt(oracleGuardRails.validity.confidenceIntervalMaxSize);
14
+ const isConfidenceTooLarge = new index_1.BN(amm.baseSpread)
15
+ .add(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.confidence))
16
+ .mul(numericConstants_1.BID_ASK_SPREAD_PRECISION)
17
+ .div(oraclePriceData.price)
18
+ .gt(new index_1.BN(amm.maxSpread));
17
19
  const oracleIsStale = oraclePriceData.slot
18
20
  .sub(new index_1.BN(slot))
19
21
  .gt(oracleGuardRails.validity.slotsBeforeStale);
@@ -24,3 +26,21 @@ function isOracleValid(amm, oraclePriceData, oracleGuardRails, slot) {
24
26
  isConfidenceTooLarge);
25
27
  }
26
28
  exports.isOracleValid = isOracleValid;
29
+ function isOracleTooDivergent(amm, oraclePriceData, oracleGuardRails, now) {
30
+ const sinceLastUpdate = now.sub(amm.lastOraclePriceTwapTs);
31
+ const sinceStart = index_1.BN.max(numericConstants_1.ZERO, new index_1.BN(60 * 5).sub(sinceLastUpdate));
32
+ const oracleTwap5min = amm.lastOraclePriceTwap5min
33
+ .mul(sinceStart)
34
+ .add(oraclePriceData.price)
35
+ .mul(sinceLastUpdate)
36
+ .div(sinceStart.add(sinceLastUpdate));
37
+ const oracleSpread = oracleTwap5min.sub(oraclePriceData.price);
38
+ const oracleSpreadPct = oracleSpread
39
+ .mul(numericConstants_1.MARK_PRICE_PRECISION)
40
+ .div(oracleTwap5min);
41
+ const tooDivergent = oracleSpreadPct
42
+ .abs()
43
+ .gte(numericConstants_1.BID_ASK_SPREAD_PRECISION.mul(oracleGuardRails.priceDivergence.markOracleDivergenceNumerator).div(oracleGuardRails.priceDivergence.markOracleDivergenceDenominator));
44
+ return tooDivergent;
45
+ }
46
+ exports.isOracleTooDivergent = isOracleTooDivergent;
@@ -1,10 +1,13 @@
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;
11
+ export declare function isFillableByVAMM(order: Order, market: MarketAccount, oraclePriceData: OraclePriceData, slot: number): boolean;
12
+ export declare function calculateBaseAssetAmountForAmmToFulfill(order: Order, market: MarketAccount, oraclePriceData: OraclePriceData, slot: number): BN;
13
+ export declare function calculateBaseAssetAmountToFillUpToLimitPrice(order: Order, market: MarketAccount, limitPrice: BN, oraclePriceData: OraclePriceData): BN;
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
3
+ exports.calculateBaseAssetAmountToFillUpToLimitPrice = exports.calculateBaseAssetAmountForAmmToFulfill = exports.isFillableByVAMM = 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
6
  const anchor_1 = require("@project-serum/anchor");
7
7
  const auction_1 = require("./auction");
8
+ const market_1 = require("./market");
9
+ const amm_1 = require("./amm");
8
10
  function isOrderRiskIncreasing(user, order) {
9
11
  if ((0, types_1.isVariant)(order.status, 'init')) {
10
12
  return false;
@@ -78,26 +80,65 @@ function standardizeBaseAssetAmount(baseAssetAmount, stepSize) {
78
80
  return baseAssetAmount.sub(remainder);
79
81
  }
80
82
  exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
81
- function getLimitPrice(order, oraclePriceData, slot) {
83
+ function getLimitPrice(order, market, oraclePriceData, slot) {
82
84
  let limitPrice;
83
85
  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);
86
+ limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
87
+ }
88
+ else if ((0, types_1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket'])) {
89
+ if ((0, auction_1.isAuctionComplete)(order, slot)) {
90
+ limitPrice = (0, auction_1.getAuctionPrice)(order, slot);
91
+ }
92
+ else if (!order.price.eq(numericConstants_1.ZERO)) {
93
+ limitPrice = order.price;
94
+ }
95
+ else if ((0, types_1.isVariant)(order.direction, 'long')) {
96
+ const askPrice = (0, market_1.calculateAskPrice)(market, oraclePriceData);
97
+ const delta = askPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
98
+ limitPrice = askPrice.add(delta);
89
99
  }
90
100
  else {
91
- limitPrice = floatingPrice;
101
+ const bidPrice = (0, market_1.calculateBidPrice)(market, oraclePriceData);
102
+ const delta = bidPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
103
+ limitPrice = bidPrice.sub(delta);
92
104
  }
93
105
  }
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
106
  else {
99
107
  limitPrice = order.price;
100
108
  }
101
109
  return limitPrice;
102
110
  }
103
111
  exports.getLimitPrice = getLimitPrice;
112
+ function isFillableByVAMM(order, market, oraclePriceData, slot) {
113
+ return ((0, auction_1.isAuctionComplete)(order, slot) &&
114
+ !calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot).eq(numericConstants_1.ZERO));
115
+ }
116
+ exports.isFillableByVAMM = isFillableByVAMM;
117
+ function calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot) {
118
+ if ((0, types_1.isOneOfVariant)(order.orderType, ['triggerMarket', 'triggerLimit']) &&
119
+ order.triggered === false) {
120
+ return numericConstants_1.ZERO;
121
+ }
122
+ const limitPrice = getLimitPrice(order, market, oraclePriceData, slot);
123
+ const baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData);
124
+ const maxBaseAssetAmount = (0, amm_1.calculateMaxBaseAssetAmountFillable)(market.amm, order.direction);
125
+ return anchor_1.BN.min(maxBaseAssetAmount, baseAssetAmount);
126
+ }
127
+ exports.calculateBaseAssetAmountForAmmToFulfill = calculateBaseAssetAmountForAmmToFulfill;
128
+ function calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData) {
129
+ const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction, oraclePriceData);
130
+ const baseAssetAmount = standardizeBaseAssetAmount(maxAmountToTrade, market.amm.baseAssetAmountStepSize);
131
+ // Check that directions are the same
132
+ const sameDirection = isSameDirection(direction, order.direction);
133
+ if (!sameDirection) {
134
+ return numericConstants_1.ZERO;
135
+ }
136
+ return baseAssetAmount.gt(order.baseAssetAmount)
137
+ ? order.baseAssetAmount
138
+ : baseAssetAmount;
139
+ }
140
+ exports.calculateBaseAssetAmountToFillUpToLimitPrice = calculateBaseAssetAmountToFillUpToLimitPrice;
141
+ function isSameDirection(firstDirection, secondDirection) {
142
+ return (((0, types_1.isVariant)(firstDirection, 'long') && (0, types_1.isVariant)(secondDirection, 'long')) ||
143
+ ((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
144
+ }
@@ -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
+ .sub(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,10 @@ 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) &&
121
+ position.lpShares.eq(numericConstants_1.ZERO));
105
122
  }
106
123
  exports.positionIsAvailable = positionIsAvailable;
107
124
  /**
@@ -113,13 +130,29 @@ function calculateEntryPrice(userPosition) {
113
130
  if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
114
131
  return numericConstants_1.ZERO;
115
132
  }
116
- return userPosition.quoteAssetAmount
133
+ return userPosition.quoteEntryAmount
117
134
  .mul(numericConstants_1.MARK_PRICE_PRECISION)
118
135
  .mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
119
136
  .div(userPosition.baseAssetAmount)
120
137
  .abs();
121
138
  }
122
139
  exports.calculateEntryPrice = calculateEntryPrice;
140
+ /**
141
+ *
142
+ * @param userPosition
143
+ * @returns Precision: MARK_PRICE_PRECISION (10^10)
144
+ */
145
+ function calculateCostBasis(userPosition) {
146
+ if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
147
+ return numericConstants_1.ZERO;
148
+ }
149
+ return userPosition.quoteAssetAmount
150
+ .mul(numericConstants_1.MARK_PRICE_PRECISION)
151
+ .mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
152
+ .div(userPosition.baseAssetAmount)
153
+ .abs();
154
+ }
155
+ exports.calculateCostBasis = calculateCostBasis;
123
156
  function findDirectionToClose(userPosition) {
124
157
  return userPosition.baseAssetAmount.gt(numericConstants_1.ZERO)
125
158
  ? types_1.PositionDirection.SHORT
@@ -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;
@@ -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() {
@@ -5,22 +5,25 @@ import { AccountInfo } from '@solana/spl-token';
5
5
  import { ConfirmOptions, Connection, PublicKey, TransactionInstruction, TransactionSignature } from '@solana/web3.js';
6
6
  import { BN } from '.';
7
7
  import { IWallet } from './types';
8
- export declare class MockUSDCFaucet {
8
+ export declare class TokenFaucet {
9
9
  connection: Connection;
10
10
  wallet: IWallet;
11
11
  program: Program;
12
12
  provider: AnchorProvider;
13
+ mint: PublicKey;
13
14
  opts?: ConfirmOptions;
14
- constructor(connection: Connection, wallet: IWallet, programId: PublicKey, opts?: ConfirmOptions);
15
- getMockUSDCFaucetStatePublicKeyAndNonce(): Promise<[
15
+ constructor(connection: Connection, wallet: IWallet, programId: PublicKey, mint: PublicKey, opts?: ConfirmOptions);
16
+ getFaucetConfigPublicKeyAndNonce(): Promise<[
16
17
  PublicKey,
17
18
  number
18
19
  ]>;
19
- mockUSDCFaucetStatePublicKey?: PublicKey;
20
- getMockUSDCFaucetStatePublicKey(): Promise<PublicKey>;
20
+ getMintAuthority(): Promise<PublicKey>;
21
+ getFaucetConfigPublicKey(): Promise<PublicKey>;
21
22
  initialize(): Promise<TransactionSignature>;
22
23
  fetchState(): Promise<any>;
24
+ private mintToUserIx;
23
25
  mintToUser(userTokenAccount: PublicKey, amount: BN): Promise<TransactionSignature>;
26
+ transferMintAuthority(): Promise<TransactionSignature>;
24
27
  createAssociatedTokenAccountAndMintTo(userPublicKey: PublicKey, amount: BN): Promise<[PublicKey, TransactionSignature]>;
25
28
  createAssociatedTokenAccountAndMintToInstructions(userPublicKey: PublicKey, amount: BN): Promise<[PublicKey, TransactionInstruction, TransactionInstruction]>;
26
29
  getAssosciatedMockUSDMintAddress(props: {