@drift-labs/sdk 0.2.0-master.10 → 0.2.0-master.13
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.
- package/lib/admin.d.ts +3 -3
- package/lib/admin.js +6 -6
- package/lib/clearingHouse.d.ts +22 -6
- package/lib/clearingHouse.js +357 -74
- package/lib/clearingHouseUser.d.ts +12 -17
- package/lib/clearingHouseUser.js +97 -88
- package/lib/config.js +1 -1
- package/lib/constants/banks.d.ts +2 -2
- package/lib/constants/banks.js +5 -4
- package/lib/constants/numericConstants.d.ts +3 -0
- package/lib/constants/numericConstants.js +4 -1
- package/lib/events/eventList.js +3 -0
- package/lib/events/types.d.ts +2 -1
- package/lib/factory/bigNum.d.ts +1 -0
- package/lib/factory/bigNum.js +37 -11
- package/lib/idl/clearing_house.json +611 -146
- package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/lib/index.d.ts +2 -1
- package/lib/index.js +2 -1
- package/lib/math/amm.js +2 -2
- package/lib/math/bankBalance.d.ts +3 -1
- package/lib/math/bankBalance.js +54 -1
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +72 -0
- package/lib/math/market.d.ts +4 -1
- package/lib/math/market.js +35 -1
- package/lib/math/position.d.ts +8 -0
- package/lib/math/position.js +42 -12
- package/lib/orders.d.ts +1 -2
- package/lib/orders.js +2 -77
- package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
- package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
- package/lib/tx/retryTxSender.js +9 -2
- package/lib/types.d.ts +86 -16
- package/lib/types.js +18 -1
- package/lib/util/computeUnits.js +1 -1
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +1 -1
- package/src/admin.ts +7 -7
- package/src/clearingHouse.ts +636 -94
- package/src/clearingHouseConfig.js +2 -0
- package/src/clearingHouseUser.ts +219 -121
- package/src/clearingHouseUserConfig.js +2 -0
- package/src/config.ts +1 -1
- package/src/constants/banks.js +42 -0
- package/src/constants/banks.ts +7 -4
- package/src/constants/markets.js +42 -0
- package/src/constants/numericConstants.js +41 -0
- package/src/constants/numericConstants.ts +4 -0
- package/src/events/eventList.ts +3 -0
- package/src/events/types.ts +2 -0
- package/src/factory/bigNum.js +37 -11
- package/src/factory/bigNum.ts +43 -13
- package/src/idl/clearing_house.json +611 -146
- package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/src/index.js +1 -1
- package/src/index.ts +2 -1
- package/src/math/amm.ts +8 -5
- package/src/math/bankBalance.ts +98 -1
- package/src/math/margin.ts +124 -0
- package/src/math/market.ts +66 -1
- package/src/math/position.ts +59 -9
- package/src/mockUSDCFaucet.js +276 -167
- package/src/orders.ts +4 -157
- package/src/tokenFaucet.js +189 -0
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
- package/src/tx/retryTxSender.ts +11 -3
- package/src/types.js +12 -1
- package/src/types.ts +88 -16
- package/src/{accounts/fetch.js → util/computeUnits.js} +11 -13
- package/src/util/computeUnits.ts +1 -1
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/tests/bn/test.ts +2 -0
- package/src/addresses/pda.js +0 -104
- package/src/math/bankBalance.js +0 -75
- package/src/math/market.js +0 -57
- package/src/math/orders.js +0 -110
- package/src/math/position.js +0 -140
- package/src/orders.js +0 -134
- package/src/tx/retryTxSender.js +0 -188
package/lib/clearingHouseUser.js
CHANGED
|
@@ -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
|
-
|
|
118
|
-
.positions.reduce((marginRequirement, marketPosition) => {
|
|
117
|
+
const postionMarginRequirement = this.getUserAccount().positions.reduce((marginRequirement, marketPosition) => {
|
|
119
118
|
const market = this.clearingHouse.getMarketAccount(marketPosition.marketIndex);
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
.
|
|
123
|
-
|
|
124
|
-
|
|
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
|
|
131
|
+
* @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
|
|
128
132
|
*/
|
|
129
|
-
|
|
133
|
+
getMaintenanceMarginRequirement() {
|
|
130
134
|
return this.getUserAccount()
|
|
131
135
|
.positions.reduce((marginRequirement, marketPosition) => {
|
|
132
136
|
const market = this.clearingHouse.getMarketAccount(marketPosition.marketIndex);
|
|
133
|
-
|
|
134
|
-
|
|
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.
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
|
|
175
|
-
return this.getUserAccount().bankBalances.reduce((
|
|
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
|
-
|
|
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
|
-
|
|
190
|
+
let liabilityValue = tokenAmount
|
|
184
191
|
.mul(this.getOracleDataForBank(bankAccount.bankIndex).price)
|
|
185
|
-
.
|
|
186
|
-
.div(numericConstants_1.
|
|
187
|
-
|
|
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
|
-
|
|
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
|
-
|
|
199
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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.
|
|
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
|
|
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,
|
|
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,
|
|
415
|
-
const marketMarginRequirement = positionValue
|
|
416
|
-
|
|
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(
|
|
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 =
|
|
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
|
|
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: '
|
|
10
|
+
CLEARING_HOUSE_PROGRAM_ID: '7HDuhZ94TVTWpH3vba3dJhGWyHvQuy2zBjniRxE7PU88',
|
|
11
11
|
USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
|
|
12
12
|
MARKETS: markets_1.DevnetMarkets,
|
|
13
13
|
BANKS: banks_1.DevnetBanks,
|
package/lib/constants/banks.d.ts
CHANGED
|
@@ -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: {
|
package/lib/constants/banks.js
CHANGED
|
@@ -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',
|
|
@@ -16,14 +17,14 @@ exports.DevnetBanks = [
|
|
|
16
17
|
bankIndex: new __1.BN(1),
|
|
17
18
|
oracle: new web3_js_1.PublicKey('J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix'),
|
|
18
19
|
oracleSource: __1.OracleSource.PYTH,
|
|
19
|
-
mint: new web3_js_1.PublicKey(
|
|
20
|
+
mint: new web3_js_1.PublicKey(exports.WRAPPED_SOL_MINT),
|
|
20
21
|
},
|
|
21
22
|
{
|
|
22
23
|
symbol: 'BTC',
|
|
23
24
|
bankIndex: new __1.BN(2),
|
|
24
25
|
oracle: new web3_js_1.PublicKey('HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J'),
|
|
25
26
|
oracleSource: __1.OracleSource.PYTH,
|
|
26
|
-
mint: new web3_js_1.PublicKey('
|
|
27
|
+
mint: new web3_js_1.PublicKey('3BZPwbcqB5kKScF3TEXxwNfx5ipV13kbRVDvfVp5c6fv'),
|
|
27
28
|
},
|
|
28
29
|
];
|
|
29
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;
|
|
@@ -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.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.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);
|
package/lib/events/eventList.js
CHANGED
package/lib/events/types.d.ts
CHANGED
|
@@ -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 {
|
package/lib/factory/bigNum.d.ts
CHANGED
|
@@ -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;
|
package/lib/factory/bigNum.js
CHANGED
|
@@ -10,6 +10,9 @@ class BigNum {
|
|
|
10
10
|
this.val = new anchor_1.BN(val);
|
|
11
11
|
this.precision = new anchor_1.BN(precisionVal);
|
|
12
12
|
}
|
|
13
|
+
bigNumFromParam(bn) {
|
|
14
|
+
return anchor_1.BN.isBN(bn) ? BigNum.from(bn) : bn;
|
|
15
|
+
}
|
|
13
16
|
add(bn) {
|
|
14
17
|
(0, assert_1.assert)(bn.precision.eq(this.precision), 'Adding unequal precisions');
|
|
15
18
|
return BigNum.from(this.val.add(bn.val), this.precision);
|
|
@@ -19,7 +22,7 @@ class BigNum {
|
|
|
19
22
|
return BigNum.from(this.val.sub(bn.val), this.precision);
|
|
20
23
|
}
|
|
21
24
|
mul(bn) {
|
|
22
|
-
const mulVal =
|
|
25
|
+
const mulVal = this.bigNumFromParam(bn);
|
|
23
26
|
return BigNum.from(this.val.mul(mulVal.val), this.precision.add(mulVal.precision));
|
|
24
27
|
}
|
|
25
28
|
/**
|
|
@@ -28,12 +31,12 @@ class BigNum {
|
|
|
28
31
|
* @returns
|
|
29
32
|
*/
|
|
30
33
|
scalarMul(bn) {
|
|
31
|
-
if (
|
|
34
|
+
if (anchor_1.BN.isBN(bn))
|
|
32
35
|
return BigNum.from(this.val.mul(bn), this.precision);
|
|
33
36
|
return BigNum.from(this.val.mul(bn.val), this.precision.add(bn.precision)).shift(bn.precision.neg());
|
|
34
37
|
}
|
|
35
38
|
div(bn) {
|
|
36
|
-
if (
|
|
39
|
+
if (anchor_1.BN.isBN(bn))
|
|
37
40
|
return BigNum.from(this.val.div(bn), this.precision);
|
|
38
41
|
return BigNum.from(this.val.div(bn.val), this.precision.sub(bn.precision));
|
|
39
42
|
}
|
|
@@ -73,35 +76,35 @@ class BigNum {
|
|
|
73
76
|
.toPrecision(precision);
|
|
74
77
|
}
|
|
75
78
|
gt(bn, ignorePrecision) {
|
|
76
|
-
const comparisonVal =
|
|
79
|
+
const comparisonVal = this.bigNumFromParam(bn);
|
|
77
80
|
if (!ignorePrecision && !comparisonVal.eq(numericConstants_1.ZERO)) {
|
|
78
81
|
(0, assert_1.assert)(comparisonVal.precision.eq(this.precision), 'Trying to compare numbers with different precision. Yo can opt to ignore precision using the ignorePrecision parameter');
|
|
79
82
|
}
|
|
80
83
|
return this.val.gt(comparisonVal.val);
|
|
81
84
|
}
|
|
82
85
|
lt(bn, ignorePrecision) {
|
|
83
|
-
const comparisonVal =
|
|
86
|
+
const comparisonVal = this.bigNumFromParam(bn);
|
|
84
87
|
if (!ignorePrecision && !comparisonVal.val.eq(numericConstants_1.ZERO)) {
|
|
85
88
|
(0, assert_1.assert)(comparisonVal.precision.eq(this.precision), 'Trying to compare numbers with different precision. Yo can opt to ignore precision using the ignorePrecision parameter');
|
|
86
89
|
}
|
|
87
90
|
return this.val.lt(comparisonVal.val);
|
|
88
91
|
}
|
|
89
92
|
gte(bn, ignorePrecision) {
|
|
90
|
-
const comparisonVal =
|
|
93
|
+
const comparisonVal = this.bigNumFromParam(bn);
|
|
91
94
|
if (!ignorePrecision && !comparisonVal.val.eq(numericConstants_1.ZERO)) {
|
|
92
95
|
(0, assert_1.assert)(comparisonVal.precision.eq(this.precision), 'Trying to compare numbers with different precision. Yo can opt to ignore precision using the ignorePrecision parameter');
|
|
93
96
|
}
|
|
94
97
|
return this.val.gte(comparisonVal.val);
|
|
95
98
|
}
|
|
96
99
|
lte(bn, ignorePrecision) {
|
|
97
|
-
const comparisonVal =
|
|
100
|
+
const comparisonVal = this.bigNumFromParam(bn);
|
|
98
101
|
if (!ignorePrecision && !comparisonVal.val.eq(numericConstants_1.ZERO)) {
|
|
99
102
|
(0, assert_1.assert)(comparisonVal.precision.eq(this.precision), 'Trying to compare numbers with different precision. Yo can opt to ignore precision using the ignorePrecision parameter');
|
|
100
103
|
}
|
|
101
104
|
return this.val.lte(comparisonVal.val);
|
|
102
105
|
}
|
|
103
106
|
eq(bn, ignorePrecision) {
|
|
104
|
-
const comparisonVal =
|
|
107
|
+
const comparisonVal = this.bigNumFromParam(bn);
|
|
105
108
|
if (!ignorePrecision && !comparisonVal.val.eq(numericConstants_1.ZERO)) {
|
|
106
109
|
(0, assert_1.assert)(comparisonVal.precision.eq(this.precision), 'Trying to compare numbers with different precision. Yo can opt to ignore precision using the ignorePrecision parameter');
|
|
107
110
|
}
|
|
@@ -149,8 +152,14 @@ class BigNum {
|
|
|
149
152
|
// remove leading zeroes
|
|
150
153
|
printString = printString.replace(/^0+/, '');
|
|
151
154
|
// add zero if leading delim
|
|
152
|
-
if (
|
|
153
|
-
printString
|
|
155
|
+
if (this.isNeg()) {
|
|
156
|
+
if (printString[1] === BigNum.delim)
|
|
157
|
+
printString = printString.replace('-.', '-0.');
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
if (printString[0] === BigNum.delim)
|
|
161
|
+
printString = `0${printString}`;
|
|
162
|
+
}
|
|
154
163
|
// remove trailing delim
|
|
155
164
|
if (printString[printString.length - 1] === BigNum.delim)
|
|
156
165
|
printString = printString.slice(0, printString.length - 1);
|
|
@@ -261,10 +270,27 @@ class BigNum {
|
|
|
261
270
|
* @returns
|
|
262
271
|
*/
|
|
263
272
|
toNotional(useTradePrecision, precisionOverride) {
|
|
273
|
+
var _a;
|
|
264
274
|
const prefix = `${this.lt(BigNum.zero()) ? `-` : ``}$`;
|
|
265
|
-
const
|
|
275
|
+
const usingCustomPrecision = true && (useTradePrecision || precisionOverride);
|
|
276
|
+
let val = usingCustomPrecision
|
|
266
277
|
? this.prettyPrint(useTradePrecision, precisionOverride)
|
|
267
278
|
: BigNum.fromPrint(this.toFixed(2), new anchor_1.BN(2)).prettyPrint();
|
|
279
|
+
// Append two trailing zeroes if not using custom precision
|
|
280
|
+
if (!usingCustomPrecision) {
|
|
281
|
+
const [_, rightSide] = val.split(BigNum.delim);
|
|
282
|
+
const trailingLength = (_a = rightSide === null || rightSide === void 0 ? void 0 : rightSide.length) !== null && _a !== void 0 ? _a : 0;
|
|
283
|
+
if (trailingLength < 2) {
|
|
284
|
+
const numHasDecimals = this.print().includes(BigNum.delim);
|
|
285
|
+
// Handle case where pretty print won't include the decimal point
|
|
286
|
+
if (trailingLength === 0 && numHasDecimals) {
|
|
287
|
+
val = `${val}.00`;
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
val = `${val}${new Array(2 - trailingLength).fill('0').join('')}`;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
268
294
|
return `${prefix}${val.replace('-', '')}`;
|
|
269
295
|
}
|
|
270
296
|
toMillified(precision = 3) {
|