@drift-labs/sdk 0.2.0-master.25 → 0.2.0-master.27

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 (124) hide show
  1. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +14 -13
  2. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +30 -27
  3. package/lib/accounts/types.d.ts +9 -9
  4. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +15 -14
  5. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +38 -34
  6. package/lib/addresses/pda.d.ts +7 -6
  7. package/lib/addresses/pda.js +31 -27
  8. package/lib/admin.d.ts +13 -7
  9. package/lib/admin.js +111 -44
  10. package/lib/clearingHouse.d.ts +71 -42
  11. package/lib/clearingHouse.js +767 -278
  12. package/lib/clearingHouseConfig.d.ts +2 -2
  13. package/lib/clearingHouseUser.d.ts +24 -22
  14. package/lib/clearingHouseUser.js +273 -177
  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/lib/constants/{markets.js → 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/dlob/DLOB.d.ts +73 -0
  24. package/lib/dlob/DLOB.js +557 -0
  25. package/lib/dlob/DLOBNode.d.ts +52 -0
  26. package/lib/dlob/DLOBNode.js +82 -0
  27. package/lib/dlob/NodeList.d.ts +26 -0
  28. package/lib/dlob/NodeList.js +138 -0
  29. package/lib/events/types.d.ts +2 -1
  30. package/lib/events/types.js +1 -0
  31. package/lib/examples/makeTradeExample.js +7 -7
  32. package/lib/idl/clearing_house.json +1152 -503
  33. package/lib/index.d.ts +10 -3
  34. package/lib/index.js +10 -3
  35. package/lib/math/amm.d.ts +2 -2
  36. package/lib/math/amm.js +1 -1
  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 +11 -10
  42. package/lib/math/market.js +30 -7
  43. package/lib/math/oracles.d.ts +2 -1
  44. package/lib/math/oracles.js +11 -1
  45. package/lib/math/orders.d.ts +6 -6
  46. package/lib/math/orders.js +31 -16
  47. package/lib/math/position.d.ts +13 -13
  48. package/lib/math/position.js +19 -19
  49. package/lib/math/spotBalance.d.ts +22 -0
  50. package/lib/math/spotBalance.js +193 -0
  51. package/lib/math/spotMarket.d.ts +4 -0
  52. package/lib/math/spotMarket.js +8 -0
  53. package/lib/math/spotPosition.d.ts +6 -0
  54. package/lib/math/spotPosition.js +23 -0
  55. package/lib/math/state.js +2 -2
  56. package/lib/math/trade.d.ts +4 -4
  57. package/lib/orderParams.d.ts +4 -4
  58. package/lib/orderParams.js +12 -4
  59. package/lib/serum/serumSubscriber.d.ts +23 -0
  60. package/lib/serum/serumSubscriber.js +41 -0
  61. package/lib/serum/types.d.ts +11 -0
  62. package/lib/serum/types.js +2 -0
  63. package/lib/tx/retryTxSender.d.ts +1 -1
  64. package/lib/tx/retryTxSender.js +4 -2
  65. package/lib/tx/types.d.ts +1 -1
  66. package/lib/types.d.ts +148 -57
  67. package/lib/types.js +39 -11
  68. package/lib/userMap/userMap.d.ts +25 -0
  69. package/lib/userMap/userMap.js +73 -0
  70. package/lib/userMap/userStatsMap.d.ts +19 -0
  71. package/lib/userMap/userStatsMap.js +68 -0
  72. package/package.json +6 -3
  73. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +42 -38
  74. package/src/accounts/types.ts +12 -9
  75. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +65 -52
  76. package/src/addresses/pda.ts +49 -44
  77. package/src/admin.ts +190 -55
  78. package/src/clearingHouse.ts +1092 -365
  79. package/src/clearingHouseConfig.ts +2 -2
  80. package/src/clearingHouseUser.ts +518 -255
  81. package/src/config.ts +30 -30
  82. package/src/constants/numericConstants.ts +17 -15
  83. package/src/constants/{markets.ts → perpMarkets.ts} +5 -5
  84. package/src/constants/{banks.ts → spotMarkets.ts} +19 -19
  85. package/src/dlob/DLOB.ts +884 -0
  86. package/src/dlob/DLOBNode.ts +163 -0
  87. package/src/dlob/NodeList.ts +185 -0
  88. package/src/events/types.ts +3 -0
  89. package/src/examples/makeTradeExample.js +152 -75
  90. package/src/examples/makeTradeExample.ts +10 -8
  91. package/src/idl/clearing_house.json +1152 -503
  92. package/src/index.ts +10 -3
  93. package/src/math/amm.ts +6 -3
  94. package/src/math/funding.ts +7 -7
  95. package/src/math/margin.ts +34 -23
  96. package/src/math/market.ts +72 -20
  97. package/src/math/oracles.ts +18 -1
  98. package/src/math/orders.ts +33 -25
  99. package/src/math/position.ts +31 -31
  100. package/src/math/spotBalance.ts +316 -0
  101. package/src/math/spotMarket.ts +9 -0
  102. package/src/math/spotPosition.ts +47 -0
  103. package/src/math/state.ts +2 -2
  104. package/src/math/trade.ts +4 -4
  105. package/src/orderParams.ts +16 -8
  106. package/src/serum/serumSubscriber.ts +80 -0
  107. package/src/serum/types.ts +13 -0
  108. package/src/tx/retryTxSender.ts +5 -2
  109. package/src/tx/types.ts +2 -1
  110. package/src/types.ts +135 -56
  111. package/src/userMap/userMap.ts +100 -0
  112. package/src/userMap/userStatsMap.ts +110 -0
  113. package/tests/bn/test.ts +2 -3
  114. package/tests/dlob/helpers.ts +322 -0
  115. package/tests/dlob/test.ts +2865 -0
  116. package/lib/math/bankBalance.d.ts +0 -15
  117. package/lib/math/bankBalance.js +0 -150
  118. package/src/constants/numericConstants.js +0 -41
  119. package/src/math/bankBalance.ts +0 -258
  120. package/src/math/oracles.js +0 -26
  121. package/src/math/state.js +0 -15
  122. package/src/orderParams.js +0 -20
  123. package/src/slot/SlotSubscriber.js +0 -39
  124. package/src/tokenFaucet.js +0 -189
@@ -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,22 @@
1
+ /// <reference types="bn.js" />
2
+ import { SpotMarketAccount, SpotBalanceType, MarginCategory } from '../types';
3
+ import { BN } from '@project-serum/anchor';
4
+ import { OraclePriceData } from '../oracles/types';
5
+ export declare function getBalance(tokenAmount: BN, spotMarket: SpotMarketAccount, balanceType: SpotBalanceType): BN;
6
+ export declare function getTokenAmount(balanceAmount: BN, spotMarket: SpotMarketAccount, balanceType: SpotBalanceType): BN;
7
+ export declare function getSignedTokenAmount(tokenAmount: BN, balanceType: SpotBalanceType): BN;
8
+ export declare function getTokenValue(tokenAmount: BN, spotDecimals: number, oraclePriceData: OraclePriceData): BN;
9
+ export declare function calculateAssetWeight(balanceAmount: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
10
+ export declare function calculateLiabilityWeight(balanceAmount: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
11
+ export declare function calculateUtilization(bank: SpotMarketAccount): BN;
12
+ export declare function calculateInterestRate(bank: SpotMarketAccount): BN;
13
+ export declare function calculateDepositRate(bank: SpotMarketAccount): BN;
14
+ export declare function calculateBorrowRate(bank: SpotMarketAccount): BN;
15
+ export declare function calculateInterestAccumulated(bank: SpotMarketAccount, now: BN): {
16
+ borrowInterest: BN;
17
+ depositInterest: BN;
18
+ };
19
+ export declare function calculateWithdrawLimit(spotMarket: SpotMarketAccount, now: BN): {
20
+ borrowLimit: BN;
21
+ withdrawLimit: BN;
22
+ };
@@ -0,0 +1,193 @@
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.getTokenValue = exports.getSignedTokenAmount = 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 getSignedTokenAmount(tokenAmount, balanceType) {
29
+ if ((0, types_1.isVariant)(balanceType, 'deposit')) {
30
+ return tokenAmount;
31
+ }
32
+ else {
33
+ return tokenAmount.abs().neg();
34
+ }
35
+ }
36
+ exports.getSignedTokenAmount = getSignedTokenAmount;
37
+ function getTokenValue(tokenAmount, spotDecimals, oraclePriceData) {
38
+ if (tokenAmount.eq(numericConstants_1.ZERO)) {
39
+ return numericConstants_1.ZERO;
40
+ }
41
+ const precisionDecrease = numericConstants_1.TEN.pow(new anchor_1.BN(10 + spotDecimals - 6));
42
+ return tokenAmount.mul(oraclePriceData.price).div(precisionDecrease);
43
+ }
44
+ exports.getTokenValue = getTokenValue;
45
+ function calculateAssetWeight(balanceAmount, spotMarket, marginCategory) {
46
+ const sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(spotMarket.decimals));
47
+ let sizeInAmmReservePrecision;
48
+ if (sizePrecision.gt(numericConstants_1.AMM_RESERVE_PRECISION)) {
49
+ sizeInAmmReservePrecision = balanceAmount.div(sizePrecision.div(numericConstants_1.AMM_RESERVE_PRECISION));
50
+ }
51
+ else {
52
+ sizeInAmmReservePrecision = balanceAmount
53
+ .mul(numericConstants_1.AMM_RESERVE_PRECISION)
54
+ .div(sizePrecision);
55
+ }
56
+ let assetWeight;
57
+ switch (marginCategory) {
58
+ case 'Initial':
59
+ assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, spotMarket.imfFactor, spotMarket.initialAssetWeight);
60
+ break;
61
+ case 'Maintenance':
62
+ assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, spotMarket.imfFactor, spotMarket.maintenanceAssetWeight);
63
+ break;
64
+ default:
65
+ assetWeight = spotMarket.initialAssetWeight;
66
+ break;
67
+ }
68
+ return assetWeight;
69
+ }
70
+ exports.calculateAssetWeight = calculateAssetWeight;
71
+ function calculateLiabilityWeight(balanceAmount, spotMarket, marginCategory) {
72
+ const sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(spotMarket.decimals));
73
+ let sizeInAmmReservePrecision;
74
+ if (sizePrecision.gt(numericConstants_1.AMM_RESERVE_PRECISION)) {
75
+ sizeInAmmReservePrecision = balanceAmount.div(sizePrecision.div(numericConstants_1.AMM_RESERVE_PRECISION));
76
+ }
77
+ else {
78
+ sizeInAmmReservePrecision = balanceAmount
79
+ .mul(numericConstants_1.AMM_RESERVE_PRECISION)
80
+ .div(sizePrecision);
81
+ }
82
+ let assetWeight;
83
+ switch (marginCategory) {
84
+ case 'Initial':
85
+ assetWeight = (0, margin_1.calculateSizePremiumLiabilityWeight)(sizeInAmmReservePrecision, spotMarket.imfFactor, spotMarket.initialLiabilityWeight, numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
86
+ break;
87
+ case 'Maintenance':
88
+ assetWeight = (0, margin_1.calculateSizePremiumLiabilityWeight)(sizeInAmmReservePrecision, spotMarket.imfFactor, spotMarket.maintenanceLiabilityWeight, numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
89
+ break;
90
+ default:
91
+ assetWeight = spotMarket.initialLiabilityWeight;
92
+ break;
93
+ }
94
+ return assetWeight;
95
+ }
96
+ exports.calculateLiabilityWeight = calculateLiabilityWeight;
97
+ function calculateUtilization(bank) {
98
+ const tokenDepositAmount = getTokenAmount(bank.depositBalance, bank, types_1.SpotBalanceType.DEPOSIT);
99
+ const tokenBorrowAmount = getTokenAmount(bank.borrowBalance, bank, types_1.SpotBalanceType.BORROW);
100
+ let utilization;
101
+ if (tokenBorrowAmount.eq(numericConstants_1.ZERO) && tokenDepositAmount.eq(numericConstants_1.ZERO)) {
102
+ utilization = numericConstants_1.ZERO;
103
+ }
104
+ else if (tokenDepositAmount.eq(numericConstants_1.ZERO)) {
105
+ utilization = numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION;
106
+ }
107
+ else {
108
+ utilization = tokenBorrowAmount
109
+ .mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
110
+ .div(tokenDepositAmount);
111
+ }
112
+ return utilization;
113
+ }
114
+ exports.calculateUtilization = calculateUtilization;
115
+ function calculateInterestRate(bank) {
116
+ const utilization = calculateUtilization(bank);
117
+ let interestRate;
118
+ if (utilization.gt(bank.optimalUtilization)) {
119
+ const surplusUtilization = utilization.sub(bank.optimalUtilization);
120
+ const borrowRateSlope = bank.maxBorrowRate
121
+ .sub(bank.optimalBorrowRate)
122
+ .mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
123
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION.sub(bank.optimalUtilization));
124
+ interestRate = bank.optimalBorrowRate.add(surplusUtilization
125
+ .mul(borrowRateSlope)
126
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION));
127
+ }
128
+ else {
129
+ const borrowRateSlope = bank.optimalBorrowRate
130
+ .mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
131
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION.sub(bank.optimalUtilization));
132
+ interestRate = utilization
133
+ .mul(borrowRateSlope)
134
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
135
+ }
136
+ return interestRate;
137
+ }
138
+ exports.calculateInterestRate = calculateInterestRate;
139
+ function calculateDepositRate(bank) {
140
+ const utilization = calculateUtilization(bank);
141
+ const borrowRate = calculateBorrowRate(bank);
142
+ const depositRate = borrowRate
143
+ .mul(utilization)
144
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
145
+ return depositRate;
146
+ }
147
+ exports.calculateDepositRate = calculateDepositRate;
148
+ function calculateBorrowRate(bank) {
149
+ return calculateInterestRate(bank);
150
+ }
151
+ exports.calculateBorrowRate = calculateBorrowRate;
152
+ function calculateInterestAccumulated(bank, now) {
153
+ const interestRate = calculateInterestRate(bank);
154
+ const timeSinceLastUpdate = now.sub(bank.lastInterestTs);
155
+ const modifiedBorrowRate = interestRate.mul(timeSinceLastUpdate);
156
+ const utilization = calculateUtilization(bank);
157
+ const modifiedDepositRate = modifiedBorrowRate
158
+ .mul(utilization)
159
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
160
+ const borrowInterest = bank.cumulativeBorrowInterest
161
+ .mul(modifiedBorrowRate)
162
+ .div(numericConstants_1.ONE_YEAR)
163
+ .div(numericConstants_1.SPOT_MARKET_INTEREST_PRECISION)
164
+ .add(numericConstants_1.ONE);
165
+ const depositInterest = bank.cumulativeDepositInterest
166
+ .mul(modifiedDepositRate)
167
+ .div(numericConstants_1.ONE_YEAR)
168
+ .div(numericConstants_1.SPOT_MARKET_INTEREST_PRECISION);
169
+ return { borrowInterest, depositInterest };
170
+ }
171
+ exports.calculateInterestAccumulated = calculateInterestAccumulated;
172
+ function calculateWithdrawLimit(spotMarket, now) {
173
+ const marketDepositTokenAmount = getTokenAmount(spotMarket.depositBalance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
174
+ const marketBorrowTokenAmount = getTokenAmount(spotMarket.borrowBalance, spotMarket, types_1.SpotBalanceType.BORROW);
175
+ const twentyFourHours = new anchor_1.BN(60 * 60 * 24);
176
+ const sinceLast = now.sub(spotMarket.lastTwapTs);
177
+ const sinceStart = anchor_1.BN.max(numericConstants_1.ZERO, twentyFourHours.sub(sinceLast));
178
+ const borrowTokenTwapLive = spotMarket.borrowTokenTwap
179
+ .mul(sinceStart)
180
+ .add(marketBorrowTokenAmount.mul(sinceLast))
181
+ .div(sinceLast.add(sinceLast));
182
+ const depositTokenTwapLive = spotMarket.depositTokenTwap
183
+ .mul(sinceStart)
184
+ .add(marketDepositTokenAmount.mul(sinceLast))
185
+ .div(sinceLast.add(sinceLast));
186
+ 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
187
+ const minDepositTokens = depositTokenTwapLive.sub(anchor_1.BN.min(anchor_1.BN.max(depositTokenTwapLive.div(new anchor_1.BN(5)), spotMarket.withdrawGuardThreshold), depositTokenTwapLive));
188
+ return {
189
+ borrowLimit: maxBorrowTokens.sub(marketBorrowTokenAmount),
190
+ withdrawLimit: marketDepositTokenAmount.sub(minDepositTokens),
191
+ };
192
+ }
193
+ 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,6 @@
1
+ /// <reference types="bn.js" />
2
+ import { SpotMarketAccount, SpotPosition } from '../types';
3
+ import { BN } from '@project-serum/anchor';
4
+ import { OraclePriceData } from '../oracles/types';
5
+ export declare function isSpotPositionAvailable(position: SpotPosition): boolean;
6
+ export declare function getWorstCaseTokenAmounts(spotPosition: SpotPosition, spotMarketAccount: SpotMarketAccount, oraclePriceData: OraclePriceData): [BN, BN];
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getWorstCaseTokenAmounts = exports.isSpotPositionAvailable = void 0;
4
+ const numericConstants_1 = require("../constants/numericConstants");
5
+ const spotBalance_1 = require("./spotBalance");
6
+ function isSpotPositionAvailable(position) {
7
+ return position.balance.eq(numericConstants_1.ZERO) && position.openOrders === 0;
8
+ }
9
+ exports.isSpotPositionAvailable = isSpotPositionAvailable;
10
+ function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, oraclePriceData) {
11
+ const tokenAmount = (0, spotBalance_1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.balance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
12
+ const tokenAmountAllBidsFill = tokenAmount.add(spotPosition.openBids);
13
+ const tokenAmountAllAsksFill = tokenAmount.add(spotPosition.openAsks);
14
+ if (tokenAmountAllAsksFill.abs().gt(tokenAmountAllBidsFill.abs())) {
15
+ const worstCaseQuoteTokenAmount = (0, spotBalance_1.getTokenValue)(spotPosition.openBids.neg(), spotMarketAccount.decimals, oraclePriceData);
16
+ return [tokenAmountAllBidsFill, worstCaseQuoteTokenAmount];
17
+ }
18
+ else {
19
+ const worstCaseQuoteTokenAmount = (0, spotBalance_1.getTokenValue)(spotPosition.openAsks.neg(), spotMarketAccount.decimals, oraclePriceData);
20
+ return [tokenAmountAllAsksFill, worstCaseQuoteTokenAmount];
21
+ }
22
+ }
23
+ exports.getWorstCaseTokenAmounts = getWorstCaseTokenAmounts;
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
  }