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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/lib/accounts/types.d.ts +1 -0
  2. package/lib/admin.d.ts +8 -5
  3. package/lib/admin.js +43 -11
  4. package/lib/clearingHouse.d.ts +35 -20
  5. package/lib/clearingHouse.js +497 -154
  6. package/lib/clearingHouseUser.d.ts +12 -17
  7. package/lib/clearingHouseUser.js +97 -88
  8. package/lib/config.js +1 -1
  9. package/lib/constants/banks.d.ts +2 -2
  10. package/lib/constants/banks.js +12 -4
  11. package/lib/constants/numericConstants.d.ts +4 -0
  12. package/lib/constants/numericConstants.js +5 -1
  13. package/lib/events/eventList.js +3 -0
  14. package/lib/events/types.d.ts +2 -1
  15. package/lib/factory/bigNum.d.ts +9 -2
  16. package/lib/factory/bigNum.js +50 -16
  17. package/lib/idl/clearing_house.json +858 -177
  18. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  19. package/lib/index.d.ts +4 -2
  20. package/lib/index.js +8 -2
  21. package/lib/math/amm.d.ts +6 -1
  22. package/lib/math/amm.js +124 -41
  23. package/lib/math/auction.js +4 -1
  24. package/lib/math/bankBalance.d.ts +3 -1
  25. package/lib/math/bankBalance.js +54 -1
  26. package/lib/math/margin.d.ts +11 -0
  27. package/lib/math/margin.js +72 -0
  28. package/lib/math/market.d.ts +4 -1
  29. package/lib/math/market.js +35 -1
  30. package/lib/math/orders.d.ts +2 -2
  31. package/lib/math/orders.js +18 -11
  32. package/lib/math/position.d.ts +8 -0
  33. package/lib/math/position.js +44 -12
  34. package/lib/math/repeg.js +1 -1
  35. package/lib/math/trade.d.ts +1 -1
  36. package/lib/math/trade.js +7 -10
  37. package/lib/orderParams.d.ts +14 -5
  38. package/lib/orderParams.js +8 -96
  39. package/lib/orders.d.ts +2 -4
  40. package/lib/orders.js +7 -161
  41. package/lib/slot/SlotSubscriber.d.ts +7 -0
  42. package/lib/slot/SlotSubscriber.js +3 -0
  43. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  44. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  45. package/lib/tx/retryTxSender.js +9 -2
  46. package/lib/tx/utils.js +1 -1
  47. package/lib/types.d.ts +159 -15
  48. package/lib/types.js +59 -1
  49. package/lib/util/computeUnits.js +1 -1
  50. package/lib/util/getTokenAddress.d.ts +2 -0
  51. package/lib/util/getTokenAddress.js +9 -0
  52. package/package.json +3 -3
  53. package/src/accounts/bulkAccountLoader.js +197 -0
  54. package/src/accounts/bulkUserSubscription.js +33 -0
  55. package/src/accounts/pollingClearingHouseAccountSubscriber.js +311 -0
  56. package/src/accounts/pollingOracleSubscriber.js +93 -0
  57. package/src/accounts/pollingTokenAccountSubscriber.js +90 -0
  58. package/src/accounts/pollingUserAccountSubscriber.js +132 -0
  59. package/src/accounts/types.js +10 -0
  60. package/src/accounts/utils.js +7 -0
  61. package/src/accounts/webSocketAccountSubscriber.js +93 -0
  62. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +233 -0
  63. package/src/accounts/webSocketUserAccountSubscriber.js +62 -0
  64. package/src/addresses/marketAddresses.js +26 -0
  65. package/src/admin.ts +66 -14
  66. package/src/assert/assert.js +9 -0
  67. package/src/clearingHouse.ts +836 -254
  68. package/src/clearingHouseConfig.js +2 -0
  69. package/src/clearingHouseUser.ts +219 -121
  70. package/src/clearingHouseUserConfig.js +2 -0
  71. package/src/config.ts +1 -1
  72. package/src/constants/banks.js +42 -0
  73. package/src/constants/banks.ts +14 -4
  74. package/src/constants/markets.js +42 -0
  75. package/src/constants/numericConstants.js +41 -0
  76. package/src/constants/numericConstants.ts +5 -0
  77. package/src/events/eventList.js +77 -0
  78. package/src/events/eventList.ts +3 -0
  79. package/src/events/eventSubscriber.js +139 -0
  80. package/src/events/fetchLogs.js +50 -0
  81. package/src/events/pollingLogProvider.js +64 -0
  82. package/src/events/sort.js +44 -0
  83. package/src/events/txEventCache.js +71 -0
  84. package/src/events/types.js +20 -0
  85. package/src/events/types.ts +2 -0
  86. package/src/events/webSocketLogProvider.js +41 -0
  87. package/src/examples/makeTradeExample.js +80 -0
  88. package/src/factory/bigNum.js +390 -0
  89. package/src/factory/bigNum.ts +65 -18
  90. package/src/factory/oracleClient.js +20 -0
  91. package/src/idl/clearing_house.json +858 -177
  92. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  93. package/src/index.js +69 -0
  94. package/src/index.ts +4 -2
  95. package/src/math/amm.js +369 -0
  96. package/src/math/amm.ts +207 -52
  97. package/src/math/auction.js +42 -0
  98. package/src/math/auction.ts +5 -1
  99. package/src/math/bankBalance.ts +98 -1
  100. package/src/math/conversion.js +11 -0
  101. package/src/math/funding.js +248 -0
  102. package/src/math/margin.ts +124 -0
  103. package/src/math/market.ts +66 -1
  104. package/src/math/oracles.js +26 -0
  105. package/src/math/orders.ts +17 -13
  106. package/src/math/position.ts +63 -9
  107. package/src/math/repeg.js +128 -0
  108. package/src/math/repeg.ts +2 -1
  109. package/src/math/state.js +15 -0
  110. package/src/math/trade.js +253 -0
  111. package/src/math/trade.ts +23 -25
  112. package/src/math/utils.js +0 -1
  113. package/src/mockUSDCFaucet.js +280 -0
  114. package/src/oracles/oracleClientCache.js +19 -0
  115. package/src/oracles/pythClient.js +46 -0
  116. package/src/oracles/quoteAssetOracleClient.js +32 -0
  117. package/src/oracles/switchboardClient.js +69 -0
  118. package/src/oracles/types.js +2 -0
  119. package/src/orderParams.js +20 -0
  120. package/src/orderParams.ts +20 -141
  121. package/src/orders.ts +10 -287
  122. package/src/slot/SlotSubscriber.js +39 -0
  123. package/src/slot/SlotSubscriber.ts +11 -1
  124. package/src/token/index.js +38 -0
  125. package/src/tokenFaucet.js +189 -0
  126. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  127. package/src/tx/retryTxSender.ts +11 -3
  128. package/src/tx/types.js +2 -0
  129. package/src/tx/utils.js +17 -0
  130. package/src/tx/utils.ts +1 -1
  131. package/src/types.js +125 -0
  132. package/src/types.ts +155 -17
  133. package/src/userName.js +20 -0
  134. package/src/util/computeUnits.js +21 -11
  135. package/src/util/computeUnits.ts +1 -1
  136. package/src/util/getTokenAddress.js +9 -0
  137. package/src/util/getTokenAddress.ts +18 -0
  138. package/src/util/promiseTimeout.js +14 -0
  139. package/src/util/tps.js +27 -0
  140. package/src/wallet.js +35 -0
  141. package/tests/bn/test.ts +2 -0
  142. package/src/util/computeUnits.js.map +0 -1
@@ -61,48 +61,43 @@ export declare class ClearingHouseUser {
61
61
  getFreeCollateral(): BN;
62
62
  getInitialMarginRequirement(): BN;
63
63
  /**
64
- * @returns The partial margin requirement in USDC. : QUOTE_PRECISION
64
+ * @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
65
65
  */
66
- getPartialMarginRequirement(): BN;
66
+ getMaintenanceMarginRequirement(): BN;
67
67
  /**
68
68
  * calculates unrealized position price pnl
69
69
  * @returns : Precision QUOTE_PRECISION
70
70
  */
71
- getUnrealizedPNL(withFunding?: boolean, marketIndex?: BN): BN;
72
- /**
73
- * calculates unrealized position price pnl
74
- * @returns : Precision QUOTE_PRECISION
75
- */
76
- getUnsettledPNL(marketIndex?: BN): BN;
71
+ getUnrealizedPNL(withFunding?: boolean, marketIndex?: BN, withWeightMarginCategory?: MarginCategory): BN;
77
72
  /**
78
73
  * calculates unrealized funding payment pnl
79
74
  * @returns : Precision QUOTE_PRECISION
80
75
  */
81
76
  getUnrealizedFundingPNL(marketIndex?: BN): BN;
82
- getTotalLiability(): BN;
83
- getCollateralValue(bankIndex?: BN): BN;
77
+ getBankLiabilityValue(bankIndex?: BN, withWeightMarginCategory?: MarginCategory): BN;
78
+ getBankAssetValue(bankIndex?: BN, withWeightMarginCategory?: MarginCategory): BN;
79
+ getNetBankValue(withWeightMarginCategory?: MarginCategory): BN;
84
80
  /**
85
81
  * calculates TotalCollateral: collateral + unrealized pnl
86
- * TODO: rename to total equity (for perpetuals swaps)
87
82
  * @returns : Precision QUOTE_PRECISION
88
83
  */
89
- getTotalCollateral(): BN;
84
+ getTotalCollateral(marginCategory?: MarginCategory): BN;
90
85
  /**
91
- * calculates sum of position value across all positions
86
+ * calculates sum of position value across all positions in margin system
92
87
  * @returns : Precision QUOTE_PRECISION
93
88
  */
94
89
  getTotalPositionValue(): BN;
95
90
  /**
96
- * calculates position value from closing 100%
91
+ * calculates position value in margin system
97
92
  * @returns : Precision QUOTE_PRECISION
98
93
  */
99
94
  getPositionValue(marketIndex: BN, oraclePriceData: OraclePriceData): BN;
100
95
  getPositionSide(currentPosition: Pick<UserPosition, 'baseAssetAmount'>): PositionDirection | undefined;
101
96
  /**
102
- * calculates average exit price for closing 100% of position
97
+ * calculates average exit price (optionally for closing up to 100% of position)
103
98
  * @returns : Precision MARK_PRICE_PRECISION
104
99
  */
105
- getPositionEstimatedExitPriceAndPnl(position: UserPosition, amountToClose?: BN): [BN, BN];
100
+ getPositionEstimatedExitPriceAndPnl(position: UserPosition, amountToClose?: BN, useAMMClose?: boolean): [BN, BN];
106
101
  /**
107
102
  * calculates current user leverage across all positions
108
103
  * @returns : Precision TEN_THOUSAND
@@ -132,7 +127,7 @@ export declare class ClearingHouseUser {
132
127
  * @param partial
133
128
  * @returns Precision : MARK_PRICE_PRECISION
134
129
  */
135
- liquidationPrice(marketPosition: Pick<UserPosition, 'marketIndex'>, positionBaseSizeChange?: BN, partial?: boolean): BN;
130
+ liquidationPrice(marketPosition: Pick<UserPosition, 'marketIndex'>, positionBaseSizeChange?: BN): BN;
136
131
  /**
137
132
  * Calculates the estimated liquidation price for a position after closing a quote amount of the position.
138
133
  * @param positionMarketIndex
@@ -6,6 +6,7 @@ const position_1 = require("./math/position");
6
6
  const numericConstants_1 = require("./constants/numericConstants");
7
7
  const _1 = require(".");
8
8
  const bankBalance_1 = require("./math/bankBalance");
9
+ const margin_1 = require("./math/margin");
9
10
  const pollingUserAccountSubscriber_1 = require("./accounts/pollingUserAccountSubscriber");
10
11
  const webSocketUserAccountSubscriber_1 = require("./accounts/webSocketUserAccountSubscriber");
11
12
  class ClearingHouseUser {
@@ -68,7 +69,6 @@ class ClearingHouseUser {
68
69
  quoteAssetAmount: numericConstants_1.ZERO,
69
70
  quoteEntryAmount: numericConstants_1.ZERO,
70
71
  openOrders: numericConstants_1.ZERO,
71
- unsettledPnl: numericConstants_1.ZERO,
72
72
  openBids: numericConstants_1.ZERO,
73
73
  openAsks: numericConstants_1.ZERO,
74
74
  };
@@ -114,49 +114,55 @@ class ClearingHouseUser {
114
114
  return freeCollateral.gte(numericConstants_1.ZERO) ? freeCollateral : numericConstants_1.ZERO;
115
115
  }
116
116
  getInitialMarginRequirement() {
117
- return this.getUserAccount()
118
- .positions.reduce((marginRequirement, marketPosition) => {
117
+ const postionMarginRequirement = this.getUserAccount().positions.reduce((marginRequirement, marketPosition) => {
119
118
  const market = this.clearingHouse.getMarketAccount(marketPosition.marketIndex);
120
- return marginRequirement.add((0, _1.calculateBaseAssetValue)(market, marketPosition, this.getOracleDataForMarket(market.marketIndex))
121
- .mul(new _1.BN(market.marginRatioInitial))
122
- .div(numericConstants_1.MARGIN_PRECISION));
123
- }, numericConstants_1.ZERO)
124
- .add(this.getTotalLiability());
119
+ const worstCaseBaseAssetAmount = (0, margin_1.calculateWorstCaseBaseAssetAmount)(marketPosition);
120
+ const worstCaseAssetValue = worstCaseBaseAssetAmount
121
+ .abs()
122
+ .mul(this.getOracleDataForMarket(market.marketIndex).price)
123
+ .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO.mul(numericConstants_1.MARK_PRICE_PRECISION));
124
+ const marketMarginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(market, worstCaseBaseAssetAmount.abs(), 'Initial'));
125
+ return marginRequirement.add(worstCaseAssetValue.mul(marketMarginRatio).div(numericConstants_1.MARGIN_PRECISION));
126
+ }, numericConstants_1.ZERO);
127
+ const bankMarginRequirement = this.getBankLiabilityValue(undefined, 'Initial');
128
+ return bankMarginRequirement.add(postionMarginRequirement);
125
129
  }
126
130
  /**
127
- * @returns The partial margin requirement in USDC. : QUOTE_PRECISION
131
+ * @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
128
132
  */
129
- getPartialMarginRequirement() {
133
+ getMaintenanceMarginRequirement() {
130
134
  return this.getUserAccount()
131
135
  .positions.reduce((marginRequirement, marketPosition) => {
132
136
  const market = this.clearingHouse.getMarketAccount(marketPosition.marketIndex);
133
- return marginRequirement.add((0, _1.calculateBaseAssetValue)(market, marketPosition, this.getOracleDataForMarket(market.marketIndex))
134
- .mul(new _1.BN(market.marginRatioPartial))
137
+ const worstCaseBaseAssetAmount = (0, margin_1.calculateWorstCaseBaseAssetAmount)(marketPosition);
138
+ const worstCaseAssetValue = worstCaseBaseAssetAmount
139
+ .abs()
140
+ .mul(this.getOracleDataForMarket(market.marketIndex).price)
141
+ .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO.mul(numericConstants_1.MARK_PRICE_PRECISION));
142
+ return marginRequirement.add(worstCaseAssetValue
143
+ .mul(new _1.BN((0, _1.calculateMarketMarginRatio)(market, worstCaseBaseAssetAmount.abs(), 'Maintenance')))
135
144
  .div(numericConstants_1.MARGIN_PRECISION));
136
145
  }, numericConstants_1.ZERO)
137
- .add(this.getTotalLiability());
146
+ .add(this.getBankLiabilityValue(undefined, 'Maintenance'));
138
147
  }
139
148
  /**
140
149
  * calculates unrealized position price pnl
141
150
  * @returns : Precision QUOTE_PRECISION
142
151
  */
143
- getUnrealizedPNL(withFunding, marketIndex) {
152
+ getUnrealizedPNL(withFunding, marketIndex, withWeightMarginCategory) {
144
153
  return this.getUserAccount()
145
154
  .positions.filter((pos) => marketIndex ? pos.marketIndex === marketIndex : true)
146
155
  .reduce((pnl, marketPosition) => {
147
156
  const market = this.clearingHouse.getMarketAccount(marketPosition.marketIndex);
148
- return pnl.add((0, _1.calculatePositionPNL)(market, marketPosition, withFunding, this.getOracleDataForMarket(market.marketIndex)));
149
- }, numericConstants_1.ZERO);
150
- }
151
- /**
152
- * calculates unrealized position price pnl
153
- * @returns : Precision QUOTE_PRECISION
154
- */
155
- getUnsettledPNL(marketIndex) {
156
- return this.getUserAccount()
157
- .positions.filter((pos) => marketIndex ? pos.marketIndex === marketIndex : true)
158
- .reduce((pnl, marketPosition) => {
159
- return pnl.add(marketPosition.unsettledPnl);
157
+ let pnl0 = (0, _1.calculatePositionPNL)(market, marketPosition, withFunding, this.getOracleDataForMarket(market.marketIndex));
158
+ if (withWeightMarginCategory !== undefined) {
159
+ if (pnl0.gt(numericConstants_1.ZERO)) {
160
+ pnl0 = pnl0
161
+ .mul((0, _1.calculateUnsettledAssetWeight)(market, pnl0, withWeightMarginCategory))
162
+ .div(new _1.BN(numericConstants_1.BANK_WEIGHT_PRECISION));
163
+ }
164
+ }
165
+ return pnl.add(pnl0);
160
166
  }, numericConstants_1.ZERO);
161
167
  }
162
168
  /**
@@ -171,45 +177,58 @@ class ClearingHouseUser {
171
177
  return pnl.add((0, _1.calculatePositionFundingPNL)(market, marketPosition));
172
178
  }, numericConstants_1.ZERO);
173
179
  }
174
- getTotalLiability() {
175
- return this.getUserAccount().bankBalances.reduce((totalAssetValue, bankBalance) => {
180
+ getBankLiabilityValue(bankIndex, withWeightMarginCategory) {
181
+ return this.getUserAccount().bankBalances.reduce((totalLiabilityValue, bankBalance) => {
176
182
  if (bankBalance.balance.eq(numericConstants_1.ZERO) ||
177
- (0, types_1.isVariant)(bankBalance.balanceType, 'deposit')) {
178
- return totalAssetValue;
183
+ (0, types_1.isVariant)(bankBalance.balanceType, 'deposit') ||
184
+ (bankIndex !== undefined && !bankBalance.bankIndex.eq(bankIndex))) {
185
+ return totalLiabilityValue;
179
186
  }
180
187
  // Todo this needs to account for whether it's based on initial or maintenance requirements
181
188
  const bankAccount = this.clearingHouse.getBankAccount(bankBalance.bankIndex);
182
189
  const tokenAmount = (0, bankBalance_1.getTokenAmount)(bankBalance.balance, bankAccount, bankBalance.balanceType);
183
- return totalAssetValue.add(tokenAmount
190
+ let liabilityValue = tokenAmount
184
191
  .mul(this.getOracleDataForBank(bankAccount.bankIndex).price)
185
- .mul(bankAccount.initialLiabilityWeight)
186
- .div(numericConstants_1.BANK_WEIGHT_PRECISION)
187
- .div(numericConstants_1.MARK_PRICE_PRECISION));
192
+ .div(numericConstants_1.MARK_PRICE_PRECISION)
193
+ .div(new _1.BN(10).pow(new _1.BN(bankAccount.decimals).sub(numericConstants_1.BANK_BALANCE_PRECISION_EXP)));
194
+ if (withWeightMarginCategory !== undefined) {
195
+ const weight = (0, bankBalance_1.calculateLiabilityWeight)(tokenAmount, bankAccount, withWeightMarginCategory);
196
+ liabilityValue = liabilityValue
197
+ .mul(weight)
198
+ .div(numericConstants_1.BANK_WEIGHT_PRECISION);
199
+ }
200
+ return totalLiabilityValue.add(liabilityValue);
188
201
  }, numericConstants_1.ZERO);
189
202
  }
190
- getCollateralValue(bankIndex) {
203
+ getBankAssetValue(bankIndex, withWeightMarginCategory) {
191
204
  return this.getUserAccount().bankBalances.reduce((totalAssetValue, bankBalance) => {
192
205
  if (bankBalance.balance.eq(numericConstants_1.ZERO) ||
206
+ (0, types_1.isVariant)(bankBalance.balanceType, 'borrow') ||
193
207
  (bankIndex !== undefined && !bankBalance.bankIndex.eq(bankIndex))) {
194
208
  return totalAssetValue;
195
209
  }
196
210
  // Todo this needs to account for whether it's based on initial or maintenance requirements
197
211
  const bankAccount = this.clearingHouse.getBankAccount(bankBalance.bankIndex);
198
- let tokenAmount = (0, bankBalance_1.getTokenAmount)(bankBalance.balance, bankAccount, bankBalance.balanceType);
199
- if ((0, types_1.isVariant)(bankBalance.balanceType, 'borrow')) {
200
- tokenAmount = tokenAmount.mul(new _1.BN(-1));
201
- }
202
- return totalAssetValue.add(tokenAmount
212
+ const tokenAmount = (0, bankBalance_1.getTokenAmount)(bankBalance.balance, bankAccount, bankBalance.balanceType);
213
+ let assetValue = tokenAmount
203
214
  .mul(this.getOracleDataForBank(bankAccount.bankIndex).price)
204
- .div(numericConstants_1.MARK_PRICE_PRECISION));
215
+ .div(numericConstants_1.MARK_PRICE_PRECISION)
216
+ .div(new _1.BN(10).pow(new _1.BN(bankAccount.decimals).sub(numericConstants_1.BANK_BALANCE_PRECISION_EXP)));
217
+ if (withWeightMarginCategory !== undefined) {
218
+ const weight = (0, bankBalance_1.calculateAssetWeight)(tokenAmount, bankAccount, withWeightMarginCategory);
219
+ assetValue = assetValue.mul(weight).div(numericConstants_1.BANK_WEIGHT_PRECISION);
220
+ }
221
+ return totalAssetValue.add(assetValue);
205
222
  }, numericConstants_1.ZERO);
206
223
  }
224
+ getNetBankValue(withWeightMarginCategory) {
225
+ return this.getBankAssetValue(undefined, withWeightMarginCategory).sub(this.getBankLiabilityValue(undefined, withWeightMarginCategory));
226
+ }
207
227
  /**
208
228
  * calculates TotalCollateral: collateral + unrealized pnl
209
- * TODO: rename to total equity (for perpetuals swaps)
210
229
  * @returns : Precision QUOTE_PRECISION
211
230
  */
212
- getTotalCollateral() {
231
+ getTotalCollateral(marginCategory = 'Initial') {
213
232
  return this.getUserAccount()
214
233
  .bankBalances.reduce((totalAssetValue, bankBalance) => {
215
234
  if (bankBalance.balance.eq(numericConstants_1.ZERO) ||
@@ -219,33 +238,36 @@ class ClearingHouseUser {
219
238
  // Todo this needs to account for whether it's based on initial or maintenance requirements
220
239
  const bankAccount = this.clearingHouse.getBankAccount(bankBalance.bankIndex);
221
240
  const tokenAmount = (0, bankBalance_1.getTokenAmount)(bankBalance.balance, bankAccount, bankBalance.balanceType);
241
+ const weight = (0, bankBalance_1.calculateAssetWeight)(tokenAmount, bankAccount, marginCategory);
222
242
  return totalAssetValue.add(tokenAmount
223
243
  .mul(this.getOracleDataForBank(bankAccount.bankIndex).price)
224
- .mul(bankAccount.initialAssetWeight)
244
+ .mul(weight)
225
245
  .div(numericConstants_1.BANK_WEIGHT_PRECISION)
226
- .div(numericConstants_1.MARK_PRICE_PRECISION));
246
+ .div(numericConstants_1.MARK_PRICE_PRECISION)
247
+ // Adjust for decimals of bank account
248
+ .div(new _1.BN(10).pow(new _1.BN(bankAccount.decimals).sub(numericConstants_1.BANK_BALANCE_PRECISION_EXP))));
227
249
  }, numericConstants_1.ZERO)
228
- .add(this.getUnrealizedPNL(true))
229
- .add(this.getUnsettledPNL());
250
+ .add(this.getUnrealizedPNL(true, undefined, marginCategory));
230
251
  }
231
252
  /**
232
- * calculates sum of position value across all positions
253
+ * calculates sum of position value across all positions in margin system
233
254
  * @returns : Precision QUOTE_PRECISION
234
255
  */
235
256
  getTotalPositionValue() {
236
257
  return this.getUserAccount().positions.reduce((positionValue, marketPosition) => {
237
258
  const market = this.clearingHouse.getMarketAccount(marketPosition.marketIndex);
238
- return positionValue.add((0, _1.calculateBaseAssetValue)(market, marketPosition, this.getOracleDataForMarket(market.marketIndex)));
259
+ const posVal = (0, margin_1.calculateMarginBaseAssetValue)(market, marketPosition, this.getOracleDataForMarket(market.marketIndex));
260
+ return positionValue.add(posVal);
239
261
  }, numericConstants_1.ZERO);
240
262
  }
241
263
  /**
242
- * calculates position value from closing 100%
264
+ * calculates position value in margin system
243
265
  * @returns : Precision QUOTE_PRECISION
244
266
  */
245
267
  getPositionValue(marketIndex, oraclePriceData) {
246
268
  const userPosition = this.getUserPosition(marketIndex) || this.getEmptyPosition(marketIndex);
247
269
  const market = this.clearingHouse.getMarketAccount(userPosition.marketIndex);
248
- return (0, _1.calculateBaseAssetValue)(market, userPosition, oraclePriceData);
270
+ return (0, margin_1.calculateMarginBaseAssetValue)(market, userPosition, oraclePriceData);
249
271
  }
250
272
  getPositionSide(currentPosition) {
251
273
  if (currentPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
@@ -259,10 +281,10 @@ class ClearingHouseUser {
259
281
  }
260
282
  }
261
283
  /**
262
- * calculates average exit price for closing 100% of position
284
+ * calculates average exit price (optionally for closing up to 100% of position)
263
285
  * @returns : Precision MARK_PRICE_PRECISION
264
286
  */
265
- getPositionEstimatedExitPriceAndPnl(position, amountToClose) {
287
+ getPositionEstimatedExitPriceAndPnl(position, amountToClose, useAMMClose = false) {
266
288
  const market = this.clearingHouse.getMarketAccount(position.marketIndex);
267
289
  const entryPrice = (0, position_1.calculateEntryPrice)(position);
268
290
  const oraclePriceData = this.getOracleDataForMarket(position.marketIndex);
@@ -277,7 +299,13 @@ class ClearingHouseUser {
277
299
  quoteAssetAmount: position.quoteAssetAmount,
278
300
  };
279
301
  }
280
- const baseAssetValue = (0, _1.calculateBaseAssetValue)(market, position, oraclePriceData);
302
+ let baseAssetValue;
303
+ if (useAMMClose) {
304
+ baseAssetValue = (0, _1.calculateBaseAssetValue)(market, position, oraclePriceData);
305
+ }
306
+ else {
307
+ baseAssetValue = (0, margin_1.calculateMarginBaseAssetValue)(market, position, oraclePriceData);
308
+ }
281
309
  if (position.baseAssetAmount.eq(numericConstants_1.ZERO)) {
282
310
  return [numericConstants_1.ZERO, numericConstants_1.ZERO];
283
311
  }
@@ -311,21 +339,10 @@ class ClearingHouseUser {
311
339
  */
312
340
  getMaxLeverage(marketIndex, category = 'Initial') {
313
341
  const market = this.clearingHouse.getMarketAccount(marketIndex);
314
- let marginRatioCategory;
315
- switch (category) {
316
- case 'Initial':
317
- marginRatioCategory = market.marginRatioInitial;
318
- break;
319
- case 'Maintenance':
320
- marginRatioCategory = market.marginRatioMaintenance;
321
- break;
322
- case 'Partial':
323
- marginRatioCategory = market.marginRatioPartial;
324
- break;
325
- default:
326
- marginRatioCategory = market.marginRatioInitial;
327
- break;
328
- }
342
+ const marginRatioCategory = (0, _1.calculateMarketMarginRatio)(market,
343
+ // worstCaseBaseAssetAmount.abs(),
344
+ numericConstants_1.ZERO, // todo
345
+ category);
329
346
  const maxLeverage = numericConstants_1.TEN_THOUSAND.mul(numericConstants_1.TEN_THOUSAND).div(new _1.BN(marginRatioCategory));
330
347
  return maxLeverage;
331
348
  }
@@ -342,7 +359,7 @@ class ClearingHouseUser {
342
359
  }
343
360
  canBeLiquidated() {
344
361
  const totalCollateral = this.getTotalCollateral();
345
- const partialMaintenanceRequirement = this.getPartialMarginRequirement();
362
+ const partialMaintenanceRequirement = this.getMaintenanceMarginRequirement();
346
363
  const marginRatio = this.getMarginRatio();
347
364
  const canLiquidate = totalCollateral.lt(partialMaintenanceRequirement);
348
365
  return [canLiquidate, marginRatio];
@@ -372,7 +389,7 @@ class ClearingHouseUser {
372
389
  * @param partial
373
390
  * @returns Precision : MARK_PRICE_PRECISION
374
391
  */
375
- liquidationPrice(marketPosition, positionBaseSizeChange = numericConstants_1.ZERO, partial = false) {
392
+ liquidationPrice(marketPosition, positionBaseSizeChange = numericConstants_1.ZERO) {
376
393
  // solves formula for example canBeLiquidated below
377
394
  /* example: assume BTC price is $40k (examine 10% up/down)
378
395
 
@@ -398,25 +415,21 @@ class ClearingHouseUser {
398
415
  quoteAssetAmount: new _1.BN(0),
399
416
  quoteEntryAmount: new _1.BN(0),
400
417
  openOrders: new _1.BN(0),
401
- unsettledPnl: new _1.BN(0),
402
418
  openBids: new _1.BN(0),
403
419
  openAsks: new _1.BN(0),
404
420
  };
405
421
  if (proposedBaseAssetAmount.eq(numericConstants_1.ZERO))
406
422
  return new _1.BN(-1);
407
423
  const market = this.clearingHouse.getMarketAccount(proposedMarketPosition.marketIndex);
408
- const proposedMarketPositionValue = (0, _1.calculateBaseAssetValue)(market, proposedMarketPosition, this.getOracleDataForMarket(market.marketIndex));
424
+ const proposedMarketPositionValue = (0, margin_1.calculateMarginBaseAssetValue)(market, proposedMarketPosition, this.getOracleDataForMarket(market.marketIndex));
409
425
  // total position value after trade
410
426
  const totalPositionValueAfterTrade = totalPositionValueExcludingTargetMarket.add(proposedMarketPositionValue);
411
427
  const marginRequirementExcludingTargetMarket = this.getUserAccount().positions.reduce((totalMarginRequirement, position) => {
412
428
  if (!position.marketIndex.eq(marketPosition.marketIndex)) {
413
429
  const market = this.clearingHouse.getMarketAccount(position.marketIndex);
414
- const positionValue = (0, _1.calculateBaseAssetValue)(market, position, this.getOracleDataForMarket(market.marketIndex));
415
- const marketMarginRequirement = positionValue
416
- .mul(partial
417
- ? new _1.BN(market.marginRatioPartial)
418
- : new _1.BN(market.marginRatioMaintenance))
419
- .div(numericConstants_1.MARGIN_PRECISION);
430
+ const positionValue = (0, margin_1.calculateMarginBaseAssetValue)(market, position, this.getOracleDataForMarket(market.marketIndex));
431
+ const marketMarginRequirement = positionValue;
432
+ new _1.BN((0, _1.calculateMarketMarginRatio)(market, position.baseAssetAmount.abs(), 'Maintenance')).div(numericConstants_1.MARGIN_PRECISION);
420
433
  totalMarginRequirement = totalMarginRequirement.add(marketMarginRequirement);
421
434
  }
422
435
  return totalMarginRequirement;
@@ -428,14 +441,10 @@ class ClearingHouseUser {
428
441
  return new _1.BN(-1);
429
442
  }
430
443
  const marginRequirementAfterTrade = marginRequirementExcludingTargetMarket.add(proposedMarketPositionValue
431
- .mul(partial
432
- ? new _1.BN(market.marginRatioPartial)
433
- : new _1.BN(market.marginRatioMaintenance))
444
+ .mul(new _1.BN((0, _1.calculateMarketMarginRatio)(market, proposedMarketPosition.baseAssetAmount.abs(), 'Maintenance')))
434
445
  .div(numericConstants_1.MARGIN_PRECISION));
435
446
  const freeCollateralAfterTrade = totalCollateral.sub(marginRequirementAfterTrade);
436
- const marketMaxLeverage = partial
437
- ? this.getMaxLeverage(proposedMarketPosition.marketIndex, 'Partial')
438
- : this.getMaxLeverage(proposedMarketPosition.marketIndex, 'Maintenance');
447
+ const marketMaxLeverage = this.getMaxLeverage(proposedMarketPosition.marketIndex, 'Maintenance');
439
448
  let priceDelta;
440
449
  if (proposedBaseAssetAmount.lt(numericConstants_1.ZERO)) {
441
450
  priceDelta = freeCollateralAfterTrade
@@ -479,14 +488,14 @@ class ClearingHouseUser {
479
488
  this.getEmptyPosition(positionMarketIndex);
480
489
  const closeBaseAmount = currentPosition.baseAssetAmount
481
490
  .mul(closeQuoteAmount)
482
- .div(currentPosition.quoteAssetAmount)
491
+ .div(currentPosition.quoteAssetAmount.abs())
483
492
  .add(currentPosition.baseAssetAmount
484
493
  .mul(closeQuoteAmount)
485
- .mod(currentPosition.quoteAssetAmount))
494
+ .mod(currentPosition.quoteAssetAmount.abs()))
486
495
  .neg();
487
496
  return this.liquidationPrice({
488
497
  marketIndex: positionMarketIndex,
489
- }, closeBaseAmount, true);
498
+ }, closeBaseAmount);
490
499
  }
491
500
  /**
492
501
  * Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
package/lib/config.js CHANGED
@@ -7,7 +7,7 @@ exports.configs = {
7
7
  devnet: {
8
8
  ENV: 'devnet',
9
9
  PYTH_ORACLE_MAPPING_ADDRESS: 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2',
10
- CLEARING_HOUSE_PROGRAM_ID: 'GCuH76fb1rXc7bjFXNcnNvWSekLgzpsnMbc1Ng4FsGSs',
10
+ CLEARING_HOUSE_PROGRAM_ID: '7HDuhZ94TVTWpH3vba3dJhGWyHvQuy2zBjniRxE7PU88',
11
11
  USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
12
12
  MARKETS: markets_1.DevnetMarkets,
13
13
  BANKS: banks_1.DevnetBanks,
@@ -1,7 +1,6 @@
1
1
  /// <reference types="bn.js" />
2
- import { BN, OracleSource } from '../';
3
- import { DriftEnv } from '../';
4
2
  import { PublicKey } from '@solana/web3.js';
3
+ import { BN, DriftEnv, OracleSource } from '../';
5
4
  export declare type BankConfig = {
6
5
  symbol: string;
7
6
  bankIndex: BN;
@@ -9,6 +8,7 @@ export declare type BankConfig = {
9
8
  mint: PublicKey;
10
9
  oracleSource: OracleSource;
11
10
  };
11
+ export declare const WRAPPED_SOL_MINT: PublicKey;
12
12
  export declare const DevnetBanks: BankConfig[];
13
13
  export declare const MainnetBanks: BankConfig[];
14
14
  export declare const Banks: {
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Banks = exports.MainnetBanks = exports.DevnetBanks = void 0;
4
- const __1 = require("../");
3
+ exports.Banks = exports.MainnetBanks = exports.DevnetBanks = exports.WRAPPED_SOL_MINT = void 0;
5
4
  const web3_js_1 = require("@solana/web3.js");
5
+ const __1 = require("../");
6
+ exports.WRAPPED_SOL_MINT = new web3_js_1.PublicKey('So11111111111111111111111111111111111111112');
6
7
  exports.DevnetBanks = [
7
8
  {
8
9
  symbol: 'USDC',
@@ -12,11 +13,18 @@ exports.DevnetBanks = [
12
13
  mint: new web3_js_1.PublicKey('8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2'),
13
14
  },
14
15
  {
15
- symbol: 'BTC',
16
+ symbol: 'SOL',
16
17
  bankIndex: new __1.BN(1),
18
+ oracle: new web3_js_1.PublicKey('J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix'),
19
+ oracleSource: __1.OracleSource.PYTH,
20
+ mint: new web3_js_1.PublicKey(exports.WRAPPED_SOL_MINT),
21
+ },
22
+ {
23
+ symbol: 'BTC',
24
+ bankIndex: new __1.BN(2),
17
25
  oracle: new web3_js_1.PublicKey('HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J'),
18
26
  oracleSource: __1.OracleSource.PYTH,
19
- mint: new web3_js_1.PublicKey('Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr'),
27
+ mint: new web3_js_1.PublicKey('3BZPwbcqB5kKScF3TEXxwNfx5ipV13kbRVDvfVp5c6fv'),
20
28
  },
21
29
  ];
22
30
  exports.MainnetBanks = [
@@ -21,6 +21,9 @@ export declare const BANK_RATE_PRECISION: BN;
21
21
  export declare const BANK_WEIGHT_PRECISION: BN;
22
22
  export declare const BANK_BALANCE_PRECISION_EXP: BN;
23
23
  export declare const BANK_BALANCE_PRECISION: BN;
24
+ export declare const BANK_IMF_PRECISION_EXP: BN;
25
+ export declare const BANK_IMF_PRECISION: BN;
26
+ export declare const LIQUIDATION_FEE_PRECISION: BN;
24
27
  export declare const QUOTE_PRECISION: BN;
25
28
  export declare const MARK_PRICE_PRECISION: BN;
26
29
  export declare const FUNDING_PAYMENT_PRECISION: BN;
@@ -29,6 +32,7 @@ export declare const AMM_RESERVE_PRECISION: BN;
29
32
  export declare const BASE_PRECISION: BN;
30
33
  export declare const BASE_PRECISION_EXP: BN;
31
34
  export declare const AMM_TO_QUOTE_PRECISION_RATIO: BN;
35
+ export declare const PRICE_DIV_PEG: BN;
32
36
  export declare const PRICE_TO_QUOTE_PRECISION: BN;
33
37
  export declare const AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO: BN;
34
38
  export declare const MARGIN_PRECISION: BN;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.QUOTE_ASSET_BANK_INDEX = exports.ONE_YEAR = exports.BID_ASK_SPREAD_PRECISION = exports.MARGIN_PRECISION = exports.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO = exports.PRICE_TO_QUOTE_PRECISION = exports.AMM_TO_QUOTE_PRECISION_RATIO = exports.BASE_PRECISION_EXP = exports.BASE_PRECISION = exports.AMM_RESERVE_PRECISION = exports.PEG_PRECISION = exports.FUNDING_PAYMENT_PRECISION = exports.MARK_PRICE_PRECISION = exports.QUOTE_PRECISION = exports.BANK_BALANCE_PRECISION = exports.BANK_BALANCE_PRECISION_EXP = exports.BANK_WEIGHT_PRECISION = exports.BANK_RATE_PRECISION = exports.BANK_UTILIZATION_PRECISION = exports.BANK_CUMULATIVE_INTEREST_PRECISION = exports.BANK_INTEREST_PRECISION = exports.AMM_RESERVE_PRECISION_EXP = exports.PEG_PRECISION_EXP = exports.FUNDING_RATE_PRECISION_EXP = exports.MARK_PRICE_PRECISION_EXP = exports.FUNDING_PAYMENT_PRECISION_EXP = exports.QUOTE_PRECISION_EXP = exports.MAX_LEVERAGE = exports.TEN_MILLION = exports.BN_MAX = exports.TEN_THOUSAND = exports.TEN = exports.TWO = exports.ONE = exports.ZERO = void 0;
3
+ exports.QUOTE_ASSET_BANK_INDEX = exports.ONE_YEAR = exports.BID_ASK_SPREAD_PRECISION = exports.MARGIN_PRECISION = exports.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO = exports.PRICE_TO_QUOTE_PRECISION = exports.PRICE_DIV_PEG = exports.AMM_TO_QUOTE_PRECISION_RATIO = exports.BASE_PRECISION_EXP = exports.BASE_PRECISION = exports.AMM_RESERVE_PRECISION = exports.PEG_PRECISION = exports.FUNDING_PAYMENT_PRECISION = exports.MARK_PRICE_PRECISION = exports.QUOTE_PRECISION = exports.LIQUIDATION_FEE_PRECISION = exports.BANK_IMF_PRECISION = exports.BANK_IMF_PRECISION_EXP = exports.BANK_BALANCE_PRECISION = exports.BANK_BALANCE_PRECISION_EXP = exports.BANK_WEIGHT_PRECISION = exports.BANK_RATE_PRECISION = exports.BANK_UTILIZATION_PRECISION = exports.BANK_CUMULATIVE_INTEREST_PRECISION = exports.BANK_INTEREST_PRECISION = exports.AMM_RESERVE_PRECISION_EXP = exports.PEG_PRECISION_EXP = exports.FUNDING_RATE_PRECISION_EXP = exports.MARK_PRICE_PRECISION_EXP = exports.FUNDING_PAYMENT_PRECISION_EXP = exports.QUOTE_PRECISION_EXP = exports.MAX_LEVERAGE = exports.TEN_MILLION = exports.BN_MAX = exports.TEN_THOUSAND = exports.TEN = exports.TWO = exports.ONE = exports.ZERO = void 0;
4
4
  const __1 = require("../");
5
5
  exports.ZERO = new __1.BN(0);
6
6
  exports.ONE = new __1.BN(1);
@@ -23,6 +23,9 @@ exports.BANK_RATE_PRECISION = new __1.BN(1000000);
23
23
  exports.BANK_WEIGHT_PRECISION = new __1.BN(100);
24
24
  exports.BANK_BALANCE_PRECISION_EXP = new __1.BN(6);
25
25
  exports.BANK_BALANCE_PRECISION = new __1.BN(10).pow(exports.BANK_BALANCE_PRECISION_EXP);
26
+ exports.BANK_IMF_PRECISION_EXP = new __1.BN(6);
27
+ exports.BANK_IMF_PRECISION = new __1.BN(10).pow(exports.BANK_IMF_PRECISION_EXP);
28
+ exports.LIQUIDATION_FEE_PRECISION = new __1.BN(1000000);
26
29
  exports.QUOTE_PRECISION = new __1.BN(10).pow(exports.QUOTE_PRECISION_EXP);
27
30
  exports.MARK_PRICE_PRECISION = new __1.BN(10).pow(exports.MARK_PRICE_PRECISION_EXP);
28
31
  exports.FUNDING_PAYMENT_PRECISION = new __1.BN(10).pow(exports.FUNDING_PAYMENT_PRECISION_EXP);
@@ -31,6 +34,7 @@ exports.AMM_RESERVE_PRECISION = new __1.BN(10).pow(exports.AMM_RESERVE_PRECISION
31
34
  exports.BASE_PRECISION = exports.AMM_RESERVE_PRECISION;
32
35
  exports.BASE_PRECISION_EXP = exports.AMM_RESERVE_PRECISION_EXP;
33
36
  exports.AMM_TO_QUOTE_PRECISION_RATIO = exports.AMM_RESERVE_PRECISION.div(exports.QUOTE_PRECISION); // 10^7
37
+ exports.PRICE_DIV_PEG = exports.MARK_PRICE_PRECISION.div(exports.PEG_PRECISION); //10^7
34
38
  exports.PRICE_TO_QUOTE_PRECISION = exports.MARK_PRICE_PRECISION.div(exports.QUOTE_PRECISION);
35
39
  exports.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO = exports.AMM_RESERVE_PRECISION.mul(exports.PEG_PRECISION).div(exports.QUOTE_PRECISION); // 10^10
36
40
  exports.MARGIN_PRECISION = exports.TEN_THOUSAND;
@@ -40,6 +40,9 @@ class EventList {
40
40
  if (currentNode.next !== undefined) {
41
41
  newNode.next.prev = newNode;
42
42
  }
43
+ else {
44
+ this.tail = newNode;
45
+ }
43
46
  currentNode.next = newNode;
44
47
  newNode.prev = currentNode;
45
48
  }
@@ -1,5 +1,5 @@
1
1
  import { Commitment, TransactionSignature } from '@solana/web3.js';
2
- import { DepositRecord, FundingPaymentRecord, FundingRateRecord, LiquidationRecord, OrderRecord } from '../index';
2
+ import { DepositRecord, FundingPaymentRecord, FundingRateRecord, LiquidationRecord, OrderRecord, SettlePnlRecord } from '../index';
3
3
  export declare type EventSubscriptionOptions = {
4
4
  eventTypes?: EventType[];
5
5
  maxEventsPerType?: number;
@@ -27,6 +27,7 @@ export declare type EventMap = {
27
27
  LiquidationRecord: Event<LiquidationRecord>;
28
28
  FundingRateRecord: Event<FundingRateRecord>;
29
29
  OrderRecord: Event<OrderRecord>;
30
+ SettlePnlRecord: Event<SettlePnlRecord>;
30
31
  };
31
32
  export declare type EventType = keyof EventMap;
32
33
  export interface EventSubscriberEvents {
@@ -6,6 +6,7 @@ export declare class BigNum {
6
6
  static delim: string;
7
7
  static spacer: string;
8
8
  constructor(val: BN | number | string, precisionVal?: BN | number | string);
9
+ private bigNumFromParam;
9
10
  add(bn: BigNum): BigNum;
10
11
  sub(bn: BigNum): BigNum;
11
12
  mul(bn: BigNum | BN): BigNum;
@@ -55,7 +56,7 @@ export declare class BigNum {
55
56
  * @returns
56
57
  */
57
58
  print(): string;
58
- prettyPrint(): string;
59
+ prettyPrint(useTradePrecision?: boolean, precisionOverride?: number): string;
59
60
  /**
60
61
  * Print and remove unnecessary trailing zeroes
61
62
  * @returns
@@ -75,7 +76,13 @@ export declare class BigNum {
75
76
  */
76
77
  toPrecision(fixedPrecision: number, trailingZeroes?: boolean): string;
77
78
  toTradePrecision(): string;
78
- toNotional(): string;
79
+ /**
80
+ * Print dollar formatted value. Defaults to fixed decimals two unless a given precision is given.
81
+ * @param useTradePrecision
82
+ * @param precisionOverride
83
+ * @returns
84
+ */
85
+ toNotional(useTradePrecision?: boolean, precisionOverride?: number): string;
79
86
  toMillified(precision?: number): string;
80
87
  toJSON(): {
81
88
  val: string;