@drift-labs/sdk 0.2.0-master.24 → 0.2.0-master.26

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 (193) hide show
  1. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +13 -13
  2. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +27 -27
  3. package/lib/accounts/types.d.ts +8 -9
  4. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +14 -14
  5. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +35 -34
  6. package/lib/addresses/pda.d.ts +8 -6
  7. package/lib/addresses/pda.js +35 -27
  8. package/lib/admin.d.ts +9 -6
  9. package/lib/admin.js +90 -54
  10. package/lib/clearingHouse.d.ts +71 -42
  11. package/lib/clearingHouse.js +765 -282
  12. package/lib/clearingHouseConfig.d.ts +2 -2
  13. package/lib/clearingHouseUser.d.ts +19 -17
  14. package/lib/clearingHouseUser.js +145 -123
  15. package/lib/config.d.ts +7 -7
  16. package/lib/config.js +21 -21
  17. package/lib/constants/numericConstants.d.ts +12 -12
  18. package/lib/constants/numericConstants.js +13 -13
  19. package/lib/constants/{markets.d.ts → perpMarkets.d.ts} +5 -5
  20. package/{src/constants/markets.js → lib/constants/perpMarkets.js} +4 -4
  21. package/lib/constants/{banks.d.ts → spotMarkets.d.ts} +6 -6
  22. package/lib/constants/{banks.js → spotMarkets.js} +16 -16
  23. package/lib/events/eventSubscriber.d.ts +4 -2
  24. package/lib/events/eventSubscriber.js +16 -9
  25. package/lib/events/fetchLogs.d.ts +10 -1
  26. package/lib/events/fetchLogs.js +27 -7
  27. package/lib/events/pollingLogProvider.d.ts +2 -1
  28. package/lib/events/pollingLogProvider.js +6 -2
  29. package/lib/events/types.d.ts +4 -2
  30. package/lib/events/types.js +2 -0
  31. package/lib/examples/makeTradeExample.js +18 -6
  32. package/lib/idl/clearing_house.json +1128 -347
  33. package/lib/index.d.ts +6 -3
  34. package/lib/index.js +6 -3
  35. package/lib/math/amm.d.ts +5 -3
  36. package/lib/math/amm.js +42 -4
  37. package/lib/math/funding.d.ts +6 -6
  38. package/lib/math/funding.js +2 -1
  39. package/lib/math/margin.d.ts +4 -4
  40. package/lib/math/margin.js +18 -11
  41. package/lib/math/market.d.ts +10 -9
  42. package/lib/math/market.js +29 -6
  43. package/lib/math/oracles.d.ts +2 -1
  44. package/lib/math/oracles.js +11 -1
  45. package/lib/math/orders.d.ts +5 -5
  46. package/lib/math/position.d.ts +13 -13
  47. package/lib/math/position.js +19 -19
  48. package/lib/math/spotBalance.d.ts +19 -0
  49. package/lib/math/spotBalance.js +176 -0
  50. package/lib/math/spotMarket.d.ts +4 -0
  51. package/lib/math/spotMarket.js +8 -0
  52. package/lib/math/spotPosition.d.ts +2 -0
  53. package/lib/math/spotPosition.js +8 -0
  54. package/lib/math/state.js +2 -2
  55. package/lib/math/trade.d.ts +4 -4
  56. package/lib/orderParams.d.ts +4 -4
  57. package/lib/orderParams.js +12 -4
  58. package/lib/serum/serumSubscriber.d.ts +23 -0
  59. package/lib/serum/serumSubscriber.js +41 -0
  60. package/lib/serum/types.d.ts +11 -0
  61. package/lib/serum/types.js +2 -0
  62. package/lib/tx/retryTxSender.d.ts +1 -1
  63. package/lib/tx/retryTxSender.js +4 -2
  64. package/lib/tx/types.d.ts +1 -1
  65. package/lib/types.d.ts +148 -39
  66. package/lib/types.js +37 -9
  67. package/my-script/.env +7 -0
  68. package/my-script/getUserStats.ts +106 -0
  69. package/my-script/multiConnections.ts +119 -0
  70. package/my-script/test-regex.ts +11 -0
  71. package/my-script/utils.ts +52 -0
  72. package/package.json +1 -1
  73. package/src/accounts/bulkAccountLoader.js +249 -0
  74. package/src/accounts/bulkUserStatsSubscription.js +75 -0
  75. package/src/accounts/bulkUserSubscription.js +75 -0
  76. package/src/accounts/fetch.js +92 -0
  77. package/src/accounts/pollingClearingHouseAccountSubscriber.js +465 -0
  78. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +38 -38
  79. package/src/accounts/pollingOracleSubscriber.js +156 -0
  80. package/src/accounts/pollingTokenAccountSubscriber.js +141 -0
  81. package/src/accounts/pollingUserAccountSubscriber.js +208 -0
  82. package/src/accounts/pollingUserStatsAccountSubscriber.js +208 -0
  83. package/src/accounts/types.js +28 -0
  84. package/src/accounts/types.ts +11 -9
  85. package/src/accounts/utils.js +7 -0
  86. package/src/accounts/webSocketAccountSubscriber.js +138 -0
  87. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +433 -0
  88. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +59 -52
  89. package/src/accounts/webSocketUserAccountSubscriber.js +113 -0
  90. package/src/accounts/webSocketUserStatsAccountSubsriber.js +113 -0
  91. package/src/addresses/pda.js +186 -0
  92. package/src/addresses/pda.ts +56 -42
  93. package/src/admin.js +1284 -0
  94. package/src/admin.ts +149 -75
  95. package/src/assert/assert.js +1 -1
  96. package/src/clearingHouse.js +3433 -0
  97. package/src/clearingHouse.ts +1097 -380
  98. package/src/clearingHouseConfig.js +2 -0
  99. package/src/clearingHouseConfig.ts +2 -2
  100. package/src/clearingHouseUser.js +874 -0
  101. package/src/clearingHouseUser.ts +237 -172
  102. package/src/clearingHouseUserConfig.js +2 -0
  103. package/src/clearingHouseUserStats.js +115 -0
  104. package/src/clearingHouseUserStatsConfig.js +2 -0
  105. package/src/config.js +80 -0
  106. package/src/config.ts +30 -30
  107. package/src/constants/numericConstants.js +18 -11
  108. package/src/constants/numericConstants.ts +17 -15
  109. package/{lib/constants/markets.js → src/constants/perpMarkets.js} +11 -11
  110. package/src/constants/{markets.ts → perpMarkets.ts} +5 -5
  111. package/src/constants/spotMarkets.js +51 -0
  112. package/src/constants/{banks.ts → spotMarkets.ts} +19 -19
  113. package/src/events/eventList.js +66 -23
  114. package/src/events/eventSubscriber.js +202 -0
  115. package/src/events/eventSubscriber.ts +20 -12
  116. package/src/events/fetchLogs.js +117 -0
  117. package/src/events/fetchLogs.ts +35 -8
  118. package/src/events/pollingLogProvider.js +113 -0
  119. package/src/events/pollingLogProvider.ts +10 -2
  120. package/src/events/sort.js +41 -0
  121. package/src/events/txEventCache.js +22 -19
  122. package/src/events/types.js +25 -0
  123. package/src/events/types.ts +7 -1
  124. package/src/events/webSocketLogProvider.js +76 -0
  125. package/src/examples/makeTradeExample.ts +27 -6
  126. package/src/factory/bigNum.js +183 -180
  127. package/src/factory/oracleClient.js +9 -9
  128. package/src/idl/clearing_house.json +1128 -347
  129. package/src/index.js +75 -0
  130. package/src/index.ts +6 -3
  131. package/src/math/amm.js +422 -0
  132. package/src/math/amm.ts +73 -5
  133. package/src/math/auction.js +10 -10
  134. package/src/math/conversion.js +4 -3
  135. package/src/math/funding.js +223 -175
  136. package/src/math/funding.ts +7 -7
  137. package/src/math/insurance.js +27 -0
  138. package/src/math/margin.js +77 -0
  139. package/src/math/margin.ts +34 -23
  140. package/src/math/market.js +105 -0
  141. package/src/math/market.ts +71 -19
  142. package/src/math/oracles.js +40 -10
  143. package/src/math/oracles.ts +18 -1
  144. package/src/math/orders.js +153 -0
  145. package/src/math/orders.ts +5 -5
  146. package/src/math/position.js +172 -0
  147. package/src/math/position.ts +31 -31
  148. package/src/math/repeg.js +40 -40
  149. package/src/math/spotBalance.js +176 -0
  150. package/src/math/spotBalance.ts +290 -0
  151. package/src/math/spotMarket.js +8 -0
  152. package/src/math/spotMarket.ts +9 -0
  153. package/src/math/spotPosition.js +8 -0
  154. package/src/math/spotPosition.ts +6 -0
  155. package/src/math/state.ts +2 -2
  156. package/src/math/trade.js +81 -74
  157. package/src/math/trade.ts +4 -4
  158. package/src/math/utils.js +8 -7
  159. package/src/oracles/oracleClientCache.js +10 -9
  160. package/src/oracles/pythClient.js +52 -17
  161. package/src/oracles/quoteAssetOracleClient.js +44 -13
  162. package/src/oracles/switchboardClient.js +69 -37
  163. package/src/oracles/types.js +1 -1
  164. package/src/orderParams.js +14 -6
  165. package/src/orderParams.ts +16 -8
  166. package/src/serum/serumSubscriber.js +102 -0
  167. package/src/serum/serumSubscriber.ts +80 -0
  168. package/src/serum/types.js +2 -0
  169. package/src/serum/types.ts +13 -0
  170. package/src/slot/SlotSubscriber.js +67 -20
  171. package/src/token/index.js +4 -4
  172. package/src/tokenFaucet.js +288 -154
  173. package/src/tx/retryTxSender.js +280 -0
  174. package/src/tx/retryTxSender.ts +5 -2
  175. package/src/tx/types.js +1 -1
  176. package/src/tx/types.ts +2 -1
  177. package/src/tx/utils.js +7 -6
  178. package/src/types.js +216 -0
  179. package/src/types.ts +131 -39
  180. package/src/userName.js +5 -5
  181. package/src/util/computeUnits.js +46 -11
  182. package/src/util/promiseTimeout.js +5 -5
  183. package/src/util/tps.js +46 -12
  184. package/src/wallet.js +55 -18
  185. package/lib/math/bankBalance.d.ts +0 -15
  186. package/lib/math/bankBalance.js +0 -150
  187. package/src/addresses/marketAddresses.js +0 -26
  188. package/src/constants/banks.js +0 -42
  189. package/src/examples/makeTradeExample.js +0 -80
  190. package/src/math/bankBalance.ts +0 -258
  191. package/src/math/state.js +0 -15
  192. package/src/math/utils.js.map +0 -1
  193. package/src/util/getTokenAddress.js +0 -9
@@ -52,36 +52,36 @@ exports.calculateBaseAssetValue = calculateBaseAssetValue;
52
52
  * calculatePositionPNL
53
53
  * = BaseAssetAmount * (Avg Exit Price - Avg Entry Price)
54
54
  * @param market
55
- * @param marketPosition
55
+ * @param PerpPosition
56
56
  * @param withFunding (adds unrealized funding payment pnl to result)
57
57
  * @param oraclePriceData
58
58
  * @returns BaseAssetAmount : Precision QUOTE_PRECISION
59
59
  */
60
- function calculatePositionPNL(market, marketPosition, withFunding = false, oraclePriceData) {
61
- if (marketPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
62
- return marketPosition.quoteAssetAmount;
60
+ function calculatePositionPNL(market, perpPosition, withFunding = false, oraclePriceData) {
61
+ if (perpPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
62
+ return perpPosition.quoteAssetAmount;
63
63
  }
64
- const baseAssetValue = (0, margin_1.calculateBaseAssetValueWithOracle)(market, marketPosition, oraclePriceData);
65
- const baseAssetValueSign = marketPosition.baseAssetAmount.isNeg()
64
+ const baseAssetValue = (0, margin_1.calculateBaseAssetValueWithOracle)(market, perpPosition, oraclePriceData);
65
+ const baseAssetValueSign = perpPosition.baseAssetAmount.isNeg()
66
66
  ? new __1.BN(-1)
67
67
  : new __1.BN(1);
68
68
  let pnl = baseAssetValue
69
69
  .mul(baseAssetValueSign)
70
- .add(marketPosition.quoteAssetAmount);
70
+ .add(perpPosition.quoteAssetAmount);
71
71
  if (withFunding) {
72
- const fundingRatePnL = calculatePositionFundingPNL(market, marketPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
72
+ const fundingRatePnL = calculatePositionFundingPNL(market, perpPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
73
73
  pnl = pnl.add(fundingRatePnL);
74
74
  }
75
75
  return pnl;
76
76
  }
77
77
  exports.calculatePositionPNL = calculatePositionPNL;
78
- function calculateUnsettledPnl(market, marketPosition, oraclePriceData) {
79
- const unrealizedPnl = calculatePositionPNL(market, marketPosition, true, oraclePriceData);
78
+ function calculateUnsettledPnl(market, perpPosition, oraclePriceData) {
79
+ const unrealizedPnl = calculatePositionPNL(market, perpPosition, true, oraclePriceData);
80
80
  let unsettledPnl = unrealizedPnl;
81
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)
82
+ const fundingPnL = calculatePositionFundingPNL(market, perpPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
83
+ const maxPositivePnl = __1.BN.max(perpPosition.quoteAssetAmount
84
+ .sub(perpPosition.quoteEntryAmount)
85
85
  .add(fundingPnL), numericConstants_1.ZERO);
86
86
  unsettledPnl = __1.BN.min(maxPositivePnl, unrealizedPnl);
87
87
  }
@@ -91,23 +91,23 @@ exports.calculateUnsettledPnl = calculateUnsettledPnl;
91
91
  /**
92
92
  *
93
93
  * @param market
94
- * @param marketPosition
94
+ * @param PerpPosition
95
95
  * @returns // TODO-PRECISION
96
96
  */
97
- function calculatePositionFundingPNL(market, marketPosition) {
98
- if (marketPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
97
+ function calculatePositionFundingPNL(market, perpPosition) {
98
+ if (perpPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
99
99
  return numericConstants_1.ZERO;
100
100
  }
101
101
  let ammCumulativeFundingRate;
102
- if (marketPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
102
+ if (perpPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
103
103
  ammCumulativeFundingRate = market.amm.cumulativeFundingRateLong;
104
104
  }
105
105
  else {
106
106
  ammCumulativeFundingRate = market.amm.cumulativeFundingRateShort;
107
107
  }
108
108
  const perPositionFundingRate = ammCumulativeFundingRate
109
- .sub(marketPosition.lastCumulativeFundingRate)
110
- .mul(marketPosition.baseAssetAmount)
109
+ .sub(perpPosition.lastCumulativeFundingRate)
110
+ .mul(perpPosition.baseAssetAmount)
111
111
  .div(numericConstants_1.AMM_RESERVE_PRECISION)
112
112
  .div(numericConstants_1.FUNDING_PAYMENT_PRECISION)
113
113
  .mul(new __1.BN(-1));
@@ -0,0 +1,19 @@
1
+ /// <reference types="bn.js" />
2
+ import { SpotMarketAccount, SpotBalanceType, MarginCategory } from '../types';
3
+ import { BN } from '@project-serum/anchor';
4
+ export declare function getBalance(tokenAmount: BN, spotMarket: SpotMarketAccount, balanceType: SpotBalanceType): BN;
5
+ export declare function getTokenAmount(balanceAmount: BN, spotMarket: SpotMarketAccount, balanceType: SpotBalanceType): BN;
6
+ export declare function calculateAssetWeight(balanceAmount: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
7
+ export declare function calculateLiabilityWeight(balanceAmount: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
8
+ export declare function calculateUtilization(bank: SpotMarketAccount): BN;
9
+ export declare function calculateInterestRate(bank: SpotMarketAccount): BN;
10
+ export declare function calculateDepositRate(bank: SpotMarketAccount): BN;
11
+ export declare function calculateBorrowRate(bank: SpotMarketAccount): BN;
12
+ export declare function calculateInterestAccumulated(bank: SpotMarketAccount, now: BN): {
13
+ borrowInterest: BN;
14
+ depositInterest: BN;
15
+ };
16
+ export declare function calculateWithdrawLimit(spotMarket: SpotMarketAccount, now: BN): {
17
+ borrowLimit: BN;
18
+ withdrawLimit: BN;
19
+ };
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateWithdrawLimit = exports.calculateInterestAccumulated = exports.calculateBorrowRate = exports.calculateDepositRate = exports.calculateInterestRate = exports.calculateUtilization = exports.calculateLiabilityWeight = exports.calculateAssetWeight = exports.getTokenAmount = exports.getBalance = void 0;
4
+ const types_1 = require("../types");
5
+ const anchor_1 = require("@project-serum/anchor");
6
+ const numericConstants_1 = require("../constants/numericConstants");
7
+ const margin_1 = require("./margin");
8
+ function getBalance(tokenAmount, spotMarket, balanceType) {
9
+ const precisionIncrease = numericConstants_1.TEN.pow(new anchor_1.BN(16 - spotMarket.decimals));
10
+ const cumulativeInterest = (0, types_1.isVariant)(balanceType, 'deposit')
11
+ ? spotMarket.cumulativeDepositInterest
12
+ : spotMarket.cumulativeBorrowInterest;
13
+ let balance = tokenAmount.mul(precisionIncrease).div(cumulativeInterest);
14
+ if (!balance.eq(numericConstants_1.ZERO) && (0, types_1.isVariant)(balanceType, 'borrow')) {
15
+ balance = balance.add(numericConstants_1.ONE);
16
+ }
17
+ return balance;
18
+ }
19
+ exports.getBalance = getBalance;
20
+ function getTokenAmount(balanceAmount, spotMarket, balanceType) {
21
+ const precisionDecrease = numericConstants_1.TEN.pow(new anchor_1.BN(16 - spotMarket.decimals));
22
+ const cumulativeInterest = (0, types_1.isVariant)(balanceType, 'deposit')
23
+ ? spotMarket.cumulativeDepositInterest
24
+ : spotMarket.cumulativeBorrowInterest;
25
+ return balanceAmount.mul(cumulativeInterest).div(precisionDecrease);
26
+ }
27
+ exports.getTokenAmount = getTokenAmount;
28
+ function calculateAssetWeight(balanceAmount, spotMarket, marginCategory) {
29
+ const sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(spotMarket.decimals));
30
+ let sizeInAmmReservePrecision;
31
+ if (sizePrecision.gt(numericConstants_1.AMM_RESERVE_PRECISION)) {
32
+ sizeInAmmReservePrecision = balanceAmount.div(sizePrecision.div(numericConstants_1.AMM_RESERVE_PRECISION));
33
+ }
34
+ else {
35
+ sizeInAmmReservePrecision = balanceAmount
36
+ .mul(numericConstants_1.AMM_RESERVE_PRECISION)
37
+ .div(sizePrecision);
38
+ }
39
+ let assetWeight;
40
+ switch (marginCategory) {
41
+ case 'Initial':
42
+ assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, spotMarket.imfFactor, spotMarket.initialAssetWeight);
43
+ break;
44
+ case 'Maintenance':
45
+ assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, spotMarket.imfFactor, spotMarket.maintenanceAssetWeight);
46
+ break;
47
+ default:
48
+ assetWeight = spotMarket.initialAssetWeight;
49
+ break;
50
+ }
51
+ return assetWeight;
52
+ }
53
+ exports.calculateAssetWeight = calculateAssetWeight;
54
+ function calculateLiabilityWeight(balanceAmount, spotMarket, marginCategory) {
55
+ const sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(spotMarket.decimals));
56
+ let sizeInAmmReservePrecision;
57
+ if (sizePrecision.gt(numericConstants_1.AMM_RESERVE_PRECISION)) {
58
+ sizeInAmmReservePrecision = balanceAmount.div(sizePrecision.div(numericConstants_1.AMM_RESERVE_PRECISION));
59
+ }
60
+ else {
61
+ sizeInAmmReservePrecision = balanceAmount
62
+ .mul(numericConstants_1.AMM_RESERVE_PRECISION)
63
+ .div(sizePrecision);
64
+ }
65
+ let assetWeight;
66
+ switch (marginCategory) {
67
+ case 'Initial':
68
+ assetWeight = (0, margin_1.calculateSizePremiumLiabilityWeight)(sizeInAmmReservePrecision, spotMarket.imfFactor, spotMarket.initialLiabilityWeight, numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
69
+ break;
70
+ case 'Maintenance':
71
+ assetWeight = (0, margin_1.calculateSizePremiumLiabilityWeight)(sizeInAmmReservePrecision, spotMarket.imfFactor, spotMarket.maintenanceLiabilityWeight, numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
72
+ break;
73
+ default:
74
+ assetWeight = spotMarket.initialLiabilityWeight;
75
+ break;
76
+ }
77
+ return assetWeight;
78
+ }
79
+ exports.calculateLiabilityWeight = calculateLiabilityWeight;
80
+ function calculateUtilization(bank) {
81
+ const tokenDepositAmount = getTokenAmount(bank.depositBalance, bank, types_1.SpotBalanceType.DEPOSIT);
82
+ const tokenBorrowAmount = getTokenAmount(bank.borrowBalance, bank, types_1.SpotBalanceType.BORROW);
83
+ let utilization;
84
+ if (tokenBorrowAmount.eq(numericConstants_1.ZERO) && tokenDepositAmount.eq(numericConstants_1.ZERO)) {
85
+ utilization = numericConstants_1.ZERO;
86
+ }
87
+ else if (tokenDepositAmount.eq(numericConstants_1.ZERO)) {
88
+ utilization = numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION;
89
+ }
90
+ else {
91
+ utilization = tokenBorrowAmount
92
+ .mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
93
+ .div(tokenDepositAmount);
94
+ }
95
+ return utilization;
96
+ }
97
+ exports.calculateUtilization = calculateUtilization;
98
+ function calculateInterestRate(bank) {
99
+ const utilization = calculateUtilization(bank);
100
+ let interestRate;
101
+ if (utilization.gt(bank.optimalUtilization)) {
102
+ const surplusUtilization = utilization.sub(bank.optimalUtilization);
103
+ const borrowRateSlope = bank.maxBorrowRate
104
+ .sub(bank.optimalBorrowRate)
105
+ .mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
106
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION.sub(bank.optimalUtilization));
107
+ interestRate = bank.optimalBorrowRate.add(surplusUtilization
108
+ .mul(borrowRateSlope)
109
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION));
110
+ }
111
+ else {
112
+ const borrowRateSlope = bank.optimalBorrowRate
113
+ .mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
114
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION.sub(bank.optimalUtilization));
115
+ interestRate = utilization
116
+ .mul(borrowRateSlope)
117
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
118
+ }
119
+ return interestRate;
120
+ }
121
+ exports.calculateInterestRate = calculateInterestRate;
122
+ function calculateDepositRate(bank) {
123
+ const utilization = calculateUtilization(bank);
124
+ const borrowRate = calculateBorrowRate(bank);
125
+ const depositRate = borrowRate
126
+ .mul(utilization)
127
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
128
+ return depositRate;
129
+ }
130
+ exports.calculateDepositRate = calculateDepositRate;
131
+ function calculateBorrowRate(bank) {
132
+ return calculateInterestRate(bank);
133
+ }
134
+ exports.calculateBorrowRate = calculateBorrowRate;
135
+ function calculateInterestAccumulated(bank, now) {
136
+ const interestRate = calculateInterestRate(bank);
137
+ const timeSinceLastUpdate = now.sub(bank.lastInterestTs);
138
+ const modifiedBorrowRate = interestRate.mul(timeSinceLastUpdate);
139
+ const utilization = calculateUtilization(bank);
140
+ const modifiedDepositRate = modifiedBorrowRate
141
+ .mul(utilization)
142
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
143
+ const borrowInterest = bank.cumulativeBorrowInterest
144
+ .mul(modifiedBorrowRate)
145
+ .div(numericConstants_1.ONE_YEAR)
146
+ .div(numericConstants_1.SPOT_MARKET_INTEREST_PRECISION)
147
+ .add(numericConstants_1.ONE);
148
+ const depositInterest = bank.cumulativeDepositInterest
149
+ .mul(modifiedDepositRate)
150
+ .div(numericConstants_1.ONE_YEAR)
151
+ .div(numericConstants_1.SPOT_MARKET_INTEREST_PRECISION);
152
+ return { borrowInterest, depositInterest };
153
+ }
154
+ exports.calculateInterestAccumulated = calculateInterestAccumulated;
155
+ function calculateWithdrawLimit(spotMarket, now) {
156
+ const marketDepositTokenAmount = getTokenAmount(spotMarket.depositBalance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
157
+ const marketBorrowTokenAmount = getTokenAmount(spotMarket.borrowBalance, spotMarket, types_1.SpotBalanceType.BORROW);
158
+ const twentyFourHours = new anchor_1.BN(60 * 60 * 24);
159
+ const sinceLast = now.sub(spotMarket.lastTwapTs);
160
+ const sinceStart = anchor_1.BN.max(numericConstants_1.ZERO, twentyFourHours.sub(sinceLast));
161
+ const borrowTokenTwapLive = spotMarket.borrowTokenTwap
162
+ .mul(sinceStart)
163
+ .add(marketBorrowTokenAmount.mul(sinceLast))
164
+ .div(sinceLast.add(sinceLast));
165
+ const depositTokenTwapLive = spotMarket.depositTokenTwap
166
+ .mul(sinceStart)
167
+ .add(marketDepositTokenAmount.mul(sinceLast))
168
+ .div(sinceLast.add(sinceLast));
169
+ const maxBorrowTokens = anchor_1.BN.min(anchor_1.BN.max(marketDepositTokenAmount.div(new anchor_1.BN(6)), borrowTokenTwapLive.add(borrowTokenTwapLive.div(new anchor_1.BN(5)))), marketDepositTokenAmount.sub(marketDepositTokenAmount.div(new anchor_1.BN(10)))); // between ~15-90% utilization with friction on twap
170
+ const minDepositTokens = depositTokenTwapLive.sub(anchor_1.BN.min(anchor_1.BN.max(depositTokenTwapLive.div(new anchor_1.BN(5)), spotMarket.withdrawGuardThreshold), depositTokenTwapLive));
171
+ return {
172
+ borrowLimit: maxBorrowTokens.sub(marketBorrowTokenAmount),
173
+ withdrawLimit: marketDepositTokenAmount.sub(minDepositTokens),
174
+ };
175
+ }
176
+ exports.calculateWithdrawLimit = calculateWithdrawLimit;
@@ -0,0 +1,4 @@
1
+ /// <reference types="bn.js" />
2
+ import { BN } from '@project-serum/anchor';
3
+ import { SpotMarketAccount } from '../types';
4
+ export declare function castNumberToSpotPrecision(value: number, spotMarket: SpotMarketAccount): BN;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.castNumberToSpotPrecision = void 0;
4
+ const anchor_1 = require("@project-serum/anchor");
5
+ function castNumberToSpotPrecision(value, spotMarket) {
6
+ return new anchor_1.BN(value * Math.pow(10, spotMarket.decimals));
7
+ }
8
+ exports.castNumberToSpotPrecision = castNumberToSpotPrecision;
@@ -0,0 +1,2 @@
1
+ import { SpotPosition } from '../types';
2
+ export declare function isSpotPositionAvailable(position: SpotPosition): boolean;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSpotPositionAvailable = void 0;
4
+ const numericConstants_1 = require("../constants/numericConstants");
5
+ function isSpotPositionAvailable(position) {
6
+ return position.balance.eq(numericConstants_1.ZERO) && position.openOrders === 0;
7
+ }
8
+ exports.isSpotPositionAvailable = isSpotPositionAvailable;
package/lib/math/state.js CHANGED
@@ -8,8 +8,8 @@ exports.getExchangeFee = void 0;
8
8
  * @returns Precision : basis points (bps)
9
9
  */
10
10
  function getExchangeFee(state) {
11
- const exchangeFee = state.feeStructure.feeNumerator.toNumber() /
12
- state.feeStructure.feeDenominator.toNumber();
11
+ const exchangeFee = state.perpFeeStructure.feeNumerator.toNumber() /
12
+ state.perpFeeStructure.feeDenominator.toNumber();
13
13
  return exchangeFee;
14
14
  }
15
15
  exports.getExchangeFee = getExchangeFee;
@@ -1,5 +1,5 @@
1
1
  /// <reference types="bn.js" />
2
- import { MarketAccount, PositionDirection } from '../types';
2
+ import { PerpMarketAccount, PositionDirection } from '../types';
3
3
  import { BN } from '@project-serum/anchor';
4
4
  import { AssetType } from './amm';
5
5
  import { OraclePriceData } from '../oracles/types';
@@ -21,7 +21,7 @@ export declare type PriceImpactUnit = 'entryPrice' | 'maxPrice' | 'priceDelta' |
21
21
  *
22
22
  * 'newPrice' => the price of the asset after the trade : Precision MARK_PRICE_PRECISION
23
23
  */
24
- export declare function calculateTradeSlippage(direction: PositionDirection, amount: BN, market: MarketAccount, inputAssetType?: AssetType, oraclePriceData?: OraclePriceData, useSpread?: boolean): [BN, BN, BN, BN];
24
+ export declare function calculateTradeSlippage(direction: PositionDirection, amount: BN, market: PerpMarketAccount, inputAssetType?: AssetType, oraclePriceData?: OraclePriceData, useSpread?: boolean): [BN, BN, BN, BN];
25
25
  /**
26
26
  * Calculates acquired amounts for trade executed
27
27
  * @param direction
@@ -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, BN];
36
+ export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: PerpMarketAccount, inputAssetType: AssetType, oraclePriceData: OraclePriceData, useSpread?: boolean): [BN, BN, BN];
37
37
  /**
38
38
  * calculateTargetPriceTrade
39
39
  * simple function for finding arbitraging trades
@@ -51,4 +51,4 @@ export declare function calculateTradeAcquiredAmounts(direction: PositionDirecti
51
51
  * targetPrice => the target price MARK_PRICE_PRECISION
52
52
  * ]
53
53
  */
54
- export declare function calculateTargetPriceTrade(market: MarketAccount, targetPrice: BN, pct?: BN, outputAssetType?: AssetType, oraclePriceData?: OraclePriceData, useSpread?: boolean): [PositionDirection, BN, BN, BN];
54
+ export declare function calculateTargetPriceTrade(market: PerpMarketAccount, targetPrice: BN, pct?: BN, outputAssetType?: AssetType, oraclePriceData?: OraclePriceData, useSpread?: boolean): [PositionDirection, BN, BN, BN];
@@ -1,16 +1,16 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { OptionalOrderParams, OrderTriggerCondition } from './types';
3
3
  import { BN } from '@project-serum/anchor';
4
- export declare function getLimitOrderParams(params: Omit<OptionalOrderParams, 'orderType'> & {
4
+ export declare function getLimitOrderParams(params: Omit<OptionalOrderParams, 'orderType' | 'marketType'> & {
5
5
  price: BN;
6
6
  }): OptionalOrderParams;
7
- export declare function getTriggerMarketOrderParams(params: Omit<OptionalOrderParams, 'orderType'> & {
7
+ export declare function getTriggerMarketOrderParams(params: Omit<OptionalOrderParams, 'orderType' | 'marketType'> & {
8
8
  triggerCondition: OrderTriggerCondition;
9
9
  triggerPrice: BN;
10
10
  }): OptionalOrderParams;
11
- export declare function getTriggerLimitOrderParams(params: Omit<OptionalOrderParams, 'orderType'> & {
11
+ export declare function getTriggerLimitOrderParams(params: Omit<OptionalOrderParams, 'orderType' | 'marketType'> & {
12
12
  triggerCondition: OrderTriggerCondition;
13
13
  triggerPrice: BN;
14
14
  price: BN;
15
15
  }): OptionalOrderParams;
16
- export declare function getMarketOrderParams(params: Omit<OptionalOrderParams, 'orderType'>): OptionalOrderParams;
16
+ export declare function getMarketOrderParams(params: Omit<OptionalOrderParams, 'orderType' | 'marketType'>): OptionalOrderParams;
@@ -3,18 +3,26 @@ 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
5
  function getLimitOrderParams(params) {
6
- return Object.assign({}, params, { orderType: types_1.OrderType.LIMIT });
6
+ return Object.assign({}, params, {
7
+ orderType: types_1.OrderType.LIMIT,
8
+ });
7
9
  }
8
10
  exports.getLimitOrderParams = getLimitOrderParams;
9
11
  function getTriggerMarketOrderParams(params) {
10
- return Object.assign({}, params, { orderType: types_1.OrderType.TRIGGER_MARKET });
12
+ return Object.assign({}, params, {
13
+ orderType: types_1.OrderType.TRIGGER_MARKET,
14
+ });
11
15
  }
12
16
  exports.getTriggerMarketOrderParams = getTriggerMarketOrderParams;
13
17
  function getTriggerLimitOrderParams(params) {
14
- return Object.assign({}, params, { orderType: types_1.OrderType.TRIGGER_LIMIT });
18
+ return Object.assign({}, params, {
19
+ orderType: types_1.OrderType.TRIGGER_LIMIT,
20
+ });
15
21
  }
16
22
  exports.getTriggerLimitOrderParams = getTriggerLimitOrderParams;
17
23
  function getMarketOrderParams(params) {
18
- return Object.assign({}, params, { orderType: types_1.OrderType.MARKET });
24
+ return Object.assign({}, params, {
25
+ orderType: types_1.OrderType.MARKET,
26
+ });
19
27
  }
20
28
  exports.getMarketOrderParams = getMarketOrderParams;
@@ -0,0 +1,23 @@
1
+ import { Connection, PublicKey } from '@solana/web3.js';
2
+ import { BulkAccountLoader } from '../accounts/bulkAccountLoader';
3
+ import { Market, Orderbook } from '@project-serum/serum';
4
+ import { SerumMarketSubscriberConfig } from './types';
5
+ export declare class SerumSubscriber {
6
+ connection: Connection;
7
+ programId: PublicKey;
8
+ marketAddress: PublicKey;
9
+ accountLoader: BulkAccountLoader;
10
+ market: Market;
11
+ subscribed: boolean;
12
+ asksAddress: PublicKey;
13
+ asks: Orderbook;
14
+ asksCallbackId: string;
15
+ lastAsksSlot: number;
16
+ bidsAddress: PublicKey;
17
+ bids: Orderbook;
18
+ bidsCallbackId: string;
19
+ lastBidsSlot: number;
20
+ constructor(config: SerumMarketSubscriberConfig);
21
+ subscribe(): Promise<void>;
22
+ unsubscribe(): Promise<void>;
23
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SerumSubscriber = void 0;
4
+ const serum_1 = require("@project-serum/serum");
5
+ class SerumSubscriber {
6
+ constructor(config) {
7
+ this.connection = config.connection;
8
+ this.programId = config.programId;
9
+ this.marketAddress = config.marketAddress;
10
+ this.accountLoader = config.accountSubscription.accountLoader;
11
+ }
12
+ async subscribe() {
13
+ if (this.subscribed) {
14
+ return;
15
+ }
16
+ this.market = await serum_1.Market.load(this.connection, this.marketAddress, undefined, this.programId);
17
+ this.asksAddress = this.market.asksAddress;
18
+ this.asks = await this.market.loadAsks(this.connection);
19
+ this.asksCallbackId = this.accountLoader.addAccount(this.asksAddress, (buffer, slot) => {
20
+ this.lastAsksSlot = slot;
21
+ this.asks = serum_1.Orderbook.decode(this.market, buffer);
22
+ console.log(this.asks.getL2(3));
23
+ });
24
+ this.bidsAddress = this.market.bidsAddress;
25
+ this.bids = await this.market.loadBids(this.connection);
26
+ this.bidsCallbackId = this.accountLoader.addAccount(this.bidsAddress, (buffer, slot) => {
27
+ this.lastBidsSlot = slot;
28
+ this.bids = serum_1.Orderbook.decode(this.market, buffer);
29
+ });
30
+ this.subscribed = true;
31
+ }
32
+ async unsubscribe() {
33
+ if (!this.subscribed) {
34
+ return;
35
+ }
36
+ this.accountLoader.removeAccount(this.asksAddress, this.asksCallbackId);
37
+ this.accountLoader.removeAccount(this.bidsAddress, this.bidsCallbackId);
38
+ this.subscribed = false;
39
+ }
40
+ }
41
+ exports.SerumSubscriber = SerumSubscriber;
@@ -0,0 +1,11 @@
1
+ import { Connection, PublicKey } from '@solana/web3.js';
2
+ import { BulkAccountLoader } from '../accounts/bulkAccountLoader';
3
+ export declare type SerumMarketSubscriberConfig = {
4
+ connection: Connection;
5
+ programId: PublicKey;
6
+ marketAddress: PublicKey;
7
+ accountSubscription: {
8
+ type: 'polling';
9
+ accountLoader: BulkAccountLoader;
10
+ };
11
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -11,7 +11,7 @@ export declare class RetryTxSender implements TxSender {
11
11
  retrySleep: number;
12
12
  additionalConnections: Connection[];
13
13
  constructor(provider: AnchorProvider, timeout?: number, retrySleep?: number, additionalConnections?: Connection[]);
14
- send(tx: Transaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions): Promise<TxSigAndSlot>;
14
+ send(tx: Transaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
15
15
  prepareTx(tx: Transaction, additionalSigners: Array<Signer>, opts: ConfirmOptions): Promise<Transaction>;
16
16
  confirmTransaction(signature: TransactionSignature, commitment?: Commitment): Promise<RpcResponseAndContext<SignatureResult>>;
17
17
  getTimestamp(): number;
@@ -15,14 +15,16 @@ class RetryTxSender {
15
15
  this.retrySleep = retrySleep !== null && retrySleep !== void 0 ? retrySleep : DEFAULT_RETRY;
16
16
  this.additionalConnections = additionalConnections;
17
17
  }
18
- async send(tx, additionalSigners, opts) {
18
+ async send(tx, additionalSigners, opts, preSigned) {
19
19
  if (additionalSigners === undefined) {
20
20
  additionalSigners = [];
21
21
  }
22
22
  if (opts === undefined) {
23
23
  opts = this.provider.opts;
24
24
  }
25
- await this.prepareTx(tx, additionalSigners, opts);
25
+ if (!preSigned) {
26
+ await this.prepareTx(tx, additionalSigners, opts);
27
+ }
26
28
  const rawTransaction = tx.serialize();
27
29
  const startTime = this.getTimestamp();
28
30
  let txid;
package/lib/tx/types.d.ts CHANGED
@@ -6,5 +6,5 @@ export declare type TxSigAndSlot = {
6
6
  };
7
7
  export interface TxSender {
8
8
  provider: Provider;
9
- send(tx: Transaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions): Promise<TxSigAndSlot>;
9
+ send(tx: Transaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
10
10
  }