@drift-labs/sdk 2.38.1-beta.8 → 2.39.1-beta.0
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/VERSION +1 -1
- package/lib/adminClient.d.ts +1 -0
- package/lib/adminClient.js +11 -0
- package/lib/driftClient.d.ts +22 -2
- package/lib/driftClient.js +94 -13
- package/lib/idl/drift.json +37 -2
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -0
- package/lib/math/spotBalance.d.ts +6 -5
- package/lib/math/spotBalance.js +29 -12
- package/lib/math/spotMarket.d.ts +1 -1
- package/lib/math/spotMarket.js +2 -2
- package/lib/math/spotPosition.d.ts +16 -3
- package/lib/math/spotPosition.js +53 -9
- package/lib/oracles/strictOraclePrice.d.ts +8 -0
- package/lib/oracles/strictOraclePrice.js +17 -0
- package/lib/tx/priorityFeeCalculator.d.ts +44 -0
- package/lib/tx/priorityFeeCalculator.js +85 -0
- package/lib/types.d.ts +1 -0
- package/lib/user.d.ts +5 -4
- package/lib/user.js +71 -105
- package/package.json +1 -1
- package/src/adminClient.ts +23 -0
- package/src/driftClient.ts +170 -13
- package/src/idl/drift.json +37 -2
- package/src/index.ts +3 -0
- package/src/math/spotBalance.ts +38 -12
- package/src/math/spotMarket.ts +7 -1
- package/src/math/spotPosition.ts +133 -18
- package/src/oracles/strictOraclePrice.ts +19 -0
- package/src/tx/priorityFeeCalculator.ts +117 -0
- package/src/types.ts +1 -0
- package/src/user.ts +171 -228
- package/tests/dlob/helpers.ts +10 -7
- package/tests/tx/priorityFeeCalculator.ts +77 -0
- package/tests/user/test.ts +77 -4
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PriorityFeeCalculator = void 0;
|
|
4
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
5
|
+
/**
|
|
6
|
+
* This class determines whether a priority fee needs to be included in a transaction based on
|
|
7
|
+
* a recent history of timed out transactions.
|
|
8
|
+
*/
|
|
9
|
+
class PriorityFeeCalculator {
|
|
10
|
+
/**
|
|
11
|
+
* Constructor for the PriorityFeeCalculator class.
|
|
12
|
+
* @param currentTimeMs - The current time in milliseconds.
|
|
13
|
+
* @param priorityFeeLatchDurationMs - The duration for how long to stay in triggered state before resetting. Default value is 10 seconds.
|
|
14
|
+
*/
|
|
15
|
+
constructor(currentTimeMs, priorityFeeLatchDurationMs = 10 * 1000) {
|
|
16
|
+
this.lastTxTimeoutCount = 0;
|
|
17
|
+
this.priorityFeeTriggered = false;
|
|
18
|
+
this.lastTxTimeoutCountTriggered = currentTimeMs;
|
|
19
|
+
this.priorityFeeLatchDurationMs = priorityFeeLatchDurationMs;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Update the priority fee state based on the current time and the current timeout count.
|
|
23
|
+
* @param currentTimeMs current time in milliseconds
|
|
24
|
+
* @returns true if priority fee should be included in the next transaction
|
|
25
|
+
*/
|
|
26
|
+
updatePriorityFee(currentTimeMs, txTimeoutCount) {
|
|
27
|
+
let triggerPriorityFee = false;
|
|
28
|
+
if (txTimeoutCount > this.lastTxTimeoutCount) {
|
|
29
|
+
this.lastTxTimeoutCount = txTimeoutCount;
|
|
30
|
+
this.lastTxTimeoutCountTriggered = currentTimeMs;
|
|
31
|
+
triggerPriorityFee = true;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
if (!this.priorityFeeTriggered) {
|
|
35
|
+
triggerPriorityFee = false;
|
|
36
|
+
}
|
|
37
|
+
else if (currentTimeMs - this.lastTxTimeoutCountTriggered <
|
|
38
|
+
this.priorityFeeLatchDurationMs) {
|
|
39
|
+
triggerPriorityFee = true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
this.priorityFeeTriggered = triggerPriorityFee;
|
|
43
|
+
return triggerPriorityFee;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* This method returns a transaction instruction list that sets the compute limit on the ComputeBudget program.
|
|
47
|
+
* @param computeUnitLimit - The maximum number of compute units that can be used by the transaction.
|
|
48
|
+
* @returns An array of transaction instructions.
|
|
49
|
+
*/
|
|
50
|
+
generateComputeBudgetIxs(computeUnitLimit) {
|
|
51
|
+
const ixs = [
|
|
52
|
+
web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
|
|
53
|
+
units: computeUnitLimit,
|
|
54
|
+
}),
|
|
55
|
+
];
|
|
56
|
+
return ixs;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Calculates the compute unit price to use based on the desired additional fee to pay and the compute unit limit.
|
|
60
|
+
* @param computeUnitLimit desired CU to use
|
|
61
|
+
* @param additionalFeeMicroLamports desired additional fee to pay, in micro lamports
|
|
62
|
+
* @returns the compute unit price to use, in micro lamports
|
|
63
|
+
*/
|
|
64
|
+
calculateComputeUnitPrice(computeUnitLimit, additionalFeeMicroLamports) {
|
|
65
|
+
return additionalFeeMicroLamports / computeUnitLimit;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* This method generates a list of transaction instructions for the ComputeBudget program, and includes a priority fee if it's required
|
|
69
|
+
* @param computeUnitLimit - The maximum number of compute units that can be used by the transaction.
|
|
70
|
+
* @param usePriorityFee - A boolean indicating whether to include a priority fee in the transaction, this should be from `this.updatePriorityFee()` or `this.priorityFeeTriggered()`.
|
|
71
|
+
* @param additionalFeeMicroLamports - The additional fee to be paid, in micro lamports, the actual price will be calculated.
|
|
72
|
+
* @returns An array of transaction instructions.
|
|
73
|
+
*/
|
|
74
|
+
generateComputeBudgetWithPriorityFeeIx(computeUnitLimit, usePriorityFee, additionalFeeMicroLamports) {
|
|
75
|
+
const ixs = this.generateComputeBudgetIxs(computeUnitLimit);
|
|
76
|
+
if (usePriorityFee) {
|
|
77
|
+
const computeUnitPrice = this.calculateComputeUnitPrice(computeUnitLimit, additionalFeeMicroLamports);
|
|
78
|
+
ixs.push(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
|
|
79
|
+
microLamports: computeUnitPrice,
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
return ixs;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.PriorityFeeCalculator = PriorityFeeCalculator;
|
package/lib/types.d.ts
CHANGED
package/lib/user.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { UserAccountSubscriber, UserAccountEvents, DataAndSlot } from './account
|
|
|
8
8
|
import { PositionDirection, BN, SpotMarketAccount, MarketType } from '.';
|
|
9
9
|
import { OraclePriceData } from './oracles/types';
|
|
10
10
|
import { UserConfig } from './userConfig';
|
|
11
|
+
import { StrictOraclePrice } from './oracles/strictOraclePrice';
|
|
11
12
|
export declare class User {
|
|
12
13
|
driftClient: DriftClient;
|
|
13
14
|
userAccountPublicKey: PublicKey;
|
|
@@ -138,9 +139,9 @@ export declare class User {
|
|
|
138
139
|
totalLiabilityValue: BN;
|
|
139
140
|
};
|
|
140
141
|
getSpotMarketLiabilityValue(marketIndex?: number, marginCategory?: MarginCategory, liquidationBuffer?: BN, includeOpenOrders?: boolean, strict?: boolean, now?: BN): BN;
|
|
141
|
-
getSpotLiabilityValue(tokenAmount: BN,
|
|
142
|
+
getSpotLiabilityValue(tokenAmount: BN, strictOraclePrice: StrictOraclePrice, spotMarketAccount: SpotMarketAccount, marginCategory?: MarginCategory, liquidationBuffer?: BN): BN;
|
|
142
143
|
getSpotMarketAssetValue(marketIndex?: number, marginCategory?: MarginCategory, includeOpenOrders?: boolean, strict?: boolean, now?: BN): BN;
|
|
143
|
-
getSpotAssetValue(tokenAmount: BN,
|
|
144
|
+
getSpotAssetValue(tokenAmount: BN, strictOraclePrice: StrictOraclePrice, spotMarketAccount: SpotMarketAccount, marginCategory?: MarginCategory): BN;
|
|
144
145
|
getSpotPositionValue(marketIndex: number, marginCategory?: MarginCategory, includeOpenOrders?: boolean, strict?: boolean, now?: BN): BN;
|
|
145
146
|
getNetSpotMarketValue(withWeightMarginCategory?: MarginCategory): BN;
|
|
146
147
|
/**
|
|
@@ -306,8 +307,8 @@ export declare class User {
|
|
|
306
307
|
leverage: BN;
|
|
307
308
|
};
|
|
308
309
|
cloneAndUpdateSpotPosition(position: SpotPosition, tokenAmount: BN, market: SpotMarketAccount): SpotPosition;
|
|
309
|
-
calculateSpotPositionFreeCollateralContribution(spotPosition: SpotPosition): BN;
|
|
310
|
-
calculateSpotPositionLeverageContribution(spotPosition: SpotPosition): {
|
|
310
|
+
calculateSpotPositionFreeCollateralContribution(spotPosition: SpotPosition, strictOraclePrice: StrictOraclePrice): BN;
|
|
311
|
+
calculateSpotPositionLeverageContribution(spotPosition: SpotPosition, strictOraclePrice: StrictOraclePrice): {
|
|
311
312
|
totalAssetValue: BN;
|
|
312
313
|
totalLiabilityValue: BN;
|
|
313
314
|
};
|
package/lib/user.js
CHANGED
|
@@ -13,6 +13,7 @@ const webSocketUserAccountSubscriber_1 = require("./accounts/webSocketUserAccoun
|
|
|
13
13
|
const spotPosition_1 = require("./math/spotPosition");
|
|
14
14
|
const oracles_1 = require("./math/oracles");
|
|
15
15
|
const tiers_1 = require("./math/tiers");
|
|
16
|
+
const strictOraclePrice_1 = require("./oracles/strictOraclePrice");
|
|
16
17
|
class User {
|
|
17
18
|
get isSubscribed() {
|
|
18
19
|
return this._isSubscribed && this.accountSubscriber.isSubscribed;
|
|
@@ -543,15 +544,21 @@ class User {
|
|
|
543
544
|
}
|
|
544
545
|
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
545
546
|
const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
|
|
547
|
+
let twap5min;
|
|
548
|
+
if (strict) {
|
|
549
|
+
twap5min = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
const strictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(oraclePriceData.price, twap5min);
|
|
546
553
|
if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX &&
|
|
547
554
|
countForQuote) {
|
|
548
555
|
const tokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
|
|
549
556
|
if ((0, types_1.isVariant)(spotPosition.balanceType, 'borrow')) {
|
|
550
|
-
const weightedTokenValue = this.getSpotLiabilityValue(tokenAmount,
|
|
557
|
+
const weightedTokenValue = this.getSpotLiabilityValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory, liquidationBuffer).abs();
|
|
551
558
|
netQuoteValue = netQuoteValue.sub(weightedTokenValue);
|
|
552
559
|
}
|
|
553
560
|
else {
|
|
554
|
-
const weightedTokenValue = this.getSpotAssetValue(tokenAmount,
|
|
561
|
+
const weightedTokenValue = this.getSpotAssetValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory);
|
|
555
562
|
netQuoteValue = netQuoteValue.add(weightedTokenValue);
|
|
556
563
|
}
|
|
557
564
|
continue;
|
|
@@ -559,24 +566,24 @@ class User {
|
|
|
559
566
|
if (!includeOpenOrders && countForBase) {
|
|
560
567
|
if ((0, types_1.isVariant)(spotPosition.balanceType, 'borrow')) {
|
|
561
568
|
const tokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), _1.SpotBalanceType.BORROW);
|
|
562
|
-
const liabilityValue = this.getSpotLiabilityValue(tokenAmount,
|
|
569
|
+
const liabilityValue = this.getSpotLiabilityValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory, liquidationBuffer).abs();
|
|
563
570
|
totalLiabilityValue = totalLiabilityValue.add(liabilityValue);
|
|
564
571
|
continue;
|
|
565
572
|
}
|
|
566
573
|
else {
|
|
567
574
|
const tokenAmount = (0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
|
|
568
|
-
const assetValue = this.getSpotAssetValue(tokenAmount,
|
|
575
|
+
const assetValue = this.getSpotAssetValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory);
|
|
569
576
|
totalAssetValue = totalAssetValue.add(assetValue);
|
|
570
577
|
continue;
|
|
571
578
|
}
|
|
572
579
|
}
|
|
573
|
-
const
|
|
580
|
+
const { tokenAmount: worstCaseTokenAmount, ordersValue: worstCaseQuoteTokenAmount, } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory !== null && marginCategory !== void 0 ? marginCategory : 'Initial');
|
|
574
581
|
if (worstCaseTokenAmount.gt(numericConstants_1.ZERO) && countForBase) {
|
|
575
|
-
const baseAssetValue = this.getSpotAssetValue(worstCaseTokenAmount,
|
|
582
|
+
const baseAssetValue = this.getSpotAssetValue(worstCaseTokenAmount, strictOraclePrice, spotMarketAccount, marginCategory);
|
|
576
583
|
totalAssetValue = totalAssetValue.add(baseAssetValue);
|
|
577
584
|
}
|
|
578
585
|
if (worstCaseTokenAmount.lt(numericConstants_1.ZERO) && countForBase) {
|
|
579
|
-
const baseLiabilityValue = this.getSpotLiabilityValue(worstCaseTokenAmount,
|
|
586
|
+
const baseLiabilityValue = this.getSpotLiabilityValue(worstCaseTokenAmount, strictOraclePrice, spotMarketAccount, marginCategory, liquidationBuffer).abs();
|
|
580
587
|
totalLiabilityValue = totalLiabilityValue.add(baseLiabilityValue);
|
|
581
588
|
}
|
|
582
589
|
if (worstCaseQuoteTokenAmount.gt(numericConstants_1.ZERO) && countForQuote) {
|
|
@@ -609,16 +616,8 @@ class User {
|
|
|
609
616
|
const { totalLiabilityValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict, now);
|
|
610
617
|
return totalLiabilityValue;
|
|
611
618
|
}
|
|
612
|
-
getSpotLiabilityValue(tokenAmount,
|
|
613
|
-
let liabilityValue =
|
|
614
|
-
if (strict) {
|
|
615
|
-
const estOracleTwap = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
|
|
616
|
-
);
|
|
617
|
-
liabilityValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, oraclePriceData, estOracleTwap);
|
|
618
|
-
}
|
|
619
|
-
else {
|
|
620
|
-
liabilityValue = (0, _1.getTokenValue)(tokenAmount, spotMarketAccount.decimals, oraclePriceData);
|
|
621
|
-
}
|
|
619
|
+
getSpotLiabilityValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory, liquidationBuffer) {
|
|
620
|
+
let liabilityValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
|
|
622
621
|
if (marginCategory !== undefined) {
|
|
623
622
|
let weight = (0, spotBalance_1.calculateLiabilityWeight)(tokenAmount, spotMarketAccount, marginCategory);
|
|
624
623
|
if (marginCategory === 'Initial') {
|
|
@@ -637,18 +636,10 @@ class User {
|
|
|
637
636
|
const { totalAssetValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, undefined, includeOpenOrders, strict, now);
|
|
638
637
|
return totalAssetValue;
|
|
639
638
|
}
|
|
640
|
-
getSpotAssetValue(tokenAmount,
|
|
641
|
-
let assetValue =
|
|
642
|
-
if (strict) {
|
|
643
|
-
const estOracleTwap = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
|
|
644
|
-
);
|
|
645
|
-
assetValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, oraclePriceData, estOracleTwap);
|
|
646
|
-
}
|
|
647
|
-
else {
|
|
648
|
-
assetValue = (0, _1.getTokenValue)(tokenAmount, spotMarketAccount.decimals, oraclePriceData);
|
|
649
|
-
}
|
|
639
|
+
getSpotAssetValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory) {
|
|
640
|
+
let assetValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
|
|
650
641
|
if (marginCategory !== undefined) {
|
|
651
|
-
const weight = (0, spotBalance_1.calculateAssetWeight)(tokenAmount, spotMarketAccount, marginCategory);
|
|
642
|
+
const weight = (0, spotBalance_1.calculateAssetWeight)(tokenAmount, strictOraclePrice.current, spotMarketAccount, marginCategory);
|
|
652
643
|
assetValue = assetValue.mul(weight).div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
653
644
|
}
|
|
654
645
|
return assetValue;
|
|
@@ -1157,7 +1148,7 @@ class User {
|
|
|
1157
1148
|
calculateFreeCollateralDeltaForSpot(market, signedTokenAmount) {
|
|
1158
1149
|
const tokenPrecision = new _1.BN(Math.pow(10, market.decimals));
|
|
1159
1150
|
if (signedTokenAmount.gt(numericConstants_1.ZERO)) {
|
|
1160
|
-
const assetWeight = (0, spotBalance_1.calculateAssetWeight)(signedTokenAmount, market, 'Maintenance');
|
|
1151
|
+
const assetWeight = (0, spotBalance_1.calculateAssetWeight)(signedTokenAmount, this.driftClient.getOraclePriceDataAndSlot(market.oracle).data.price, market, 'Maintenance');
|
|
1161
1152
|
return numericConstants_1.QUOTE_PRECISION.mul(assetWeight)
|
|
1162
1153
|
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
|
|
1163
1154
|
.mul(signedTokenAmount)
|
|
@@ -1279,11 +1270,12 @@ class User {
|
|
|
1279
1270
|
*/
|
|
1280
1271
|
getMaxTradeSizeUSDCForSpot(targetMarketIndex, direction, currentQuoteAssetValue, currentSpotMarketNetValue) {
|
|
1281
1272
|
const market = this.driftClient.getSpotMarketAccount(targetMarketIndex);
|
|
1273
|
+
const oraclePrice = this.driftClient.getOraclePriceDataAndSlot(market.oracle).data.price;
|
|
1282
1274
|
currentQuoteAssetValue = this.getSpotMarketAssetValue(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
1283
1275
|
currentSpotMarketNetValue =
|
|
1284
1276
|
currentSpotMarketNetValue !== null && currentSpotMarketNetValue !== void 0 ? currentSpotMarketNetValue : this.getSpotPositionValue(targetMarketIndex);
|
|
1285
1277
|
let freeCollateral = this.getFreeCollateral();
|
|
1286
|
-
const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, 'Initial', numericConstants_1.ZERO, (0, types_1.isVariant)(direction, 'long')
|
|
1278
|
+
const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', numericConstants_1.ZERO, (0, types_1.isVariant)(direction, 'long')
|
|
1287
1279
|
? _1.SpotBalanceType.DEPOSIT
|
|
1288
1280
|
: _1.SpotBalanceType.BORROW);
|
|
1289
1281
|
let tradeAmount = numericConstants_1.ZERO;
|
|
@@ -1291,13 +1283,13 @@ class User {
|
|
|
1291
1283
|
// if the user is buying/selling and already short/long, need to account for closing out short/long
|
|
1292
1284
|
if ((0, types_1.isVariant)(direction, 'long') && currentSpotMarketNetValue.lt(numericConstants_1.ZERO)) {
|
|
1293
1285
|
tradeAmount = currentSpotMarketNetValue.abs();
|
|
1294
|
-
const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, 'Initial', this.getTokenAmount(targetMarketIndex).abs(), _1.SpotBalanceType.BORROW);
|
|
1286
|
+
const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', this.getTokenAmount(targetMarketIndex).abs(), _1.SpotBalanceType.BORROW);
|
|
1295
1287
|
freeCollateral = freeCollateral.add(tradeAmount.mul(new _1.BN(marginRatio)).div(numericConstants_1.MARGIN_PRECISION));
|
|
1296
1288
|
}
|
|
1297
1289
|
else if ((0, types_1.isVariant)(direction, 'short') &&
|
|
1298
1290
|
currentSpotMarketNetValue.gt(numericConstants_1.ZERO)) {
|
|
1299
1291
|
tradeAmount = currentSpotMarketNetValue;
|
|
1300
|
-
const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, 'Initial', this.getTokenAmount(targetMarketIndex), _1.SpotBalanceType.DEPOSIT);
|
|
1292
|
+
const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', this.getTokenAmount(targetMarketIndex), _1.SpotBalanceType.DEPOSIT);
|
|
1301
1293
|
freeCollateral = freeCollateral.add(tradeAmount.mul(new _1.BN(marginRatio)).div(numericConstants_1.MARGIN_PRECISION));
|
|
1302
1294
|
}
|
|
1303
1295
|
tradeAmount = tradeAmount.add(freeCollateral.mul(numericConstants_1.MARGIN_PRECISION).div(new _1.BN(marginRatio)));
|
|
@@ -1322,8 +1314,12 @@ class User {
|
|
|
1322
1314
|
getMaxSwapAmount({ inMarketIndex, outMarketIndex, calculateSwap, iterationLimit = 1000, }) {
|
|
1323
1315
|
const inMarket = this.driftClient.getSpotMarketAccount(inMarketIndex);
|
|
1324
1316
|
const outMarket = this.driftClient.getSpotMarketAccount(outMarketIndex);
|
|
1325
|
-
const
|
|
1326
|
-
const
|
|
1317
|
+
const inOraclePriceData = this.getOracleDataForSpotMarket(inMarketIndex);
|
|
1318
|
+
const inOraclePrice = inOraclePriceData.price;
|
|
1319
|
+
const outOraclePriceData = this.getOracleDataForSpotMarket(outMarketIndex);
|
|
1320
|
+
const outOraclePrice = outOraclePriceData.price;
|
|
1321
|
+
const inStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(inOraclePrice);
|
|
1322
|
+
const outStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(outOraclePrice);
|
|
1327
1323
|
const inPrecision = new _1.BN(10 ** inMarket.decimals);
|
|
1328
1324
|
const outPrecision = new _1.BN(10 ** outMarket.decimals);
|
|
1329
1325
|
const inSpotPosition = this.getSpotPosition(inMarketIndex) ||
|
|
@@ -1331,10 +1327,10 @@ class User {
|
|
|
1331
1327
|
const outSpotPosition = this.getSpotPosition(outMarketIndex) ||
|
|
1332
1328
|
this.getEmptySpotPosition(outMarketIndex);
|
|
1333
1329
|
const freeCollateral = this.getFreeCollateral();
|
|
1334
|
-
const inContributionInitial = this.calculateSpotPositionFreeCollateralContribution(inSpotPosition);
|
|
1335
|
-
const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition);
|
|
1336
|
-
const outContributionInitial = this.calculateSpotPositionFreeCollateralContribution(outSpotPosition);
|
|
1337
|
-
const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition);
|
|
1330
|
+
const inContributionInitial = this.calculateSpotPositionFreeCollateralContribution(inSpotPosition, inStrictOraclePrice);
|
|
1331
|
+
const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition, inStrictOraclePrice);
|
|
1332
|
+
const outContributionInitial = this.calculateSpotPositionFreeCollateralContribution(outSpotPosition, outStrictOraclePrice);
|
|
1333
|
+
const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outStrictOraclePrice);
|
|
1338
1334
|
const initialContribution = inContributionInitial.add(outContributionInitial);
|
|
1339
1335
|
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
|
|
1340
1336
|
if (!calculateSwap) {
|
|
@@ -1374,8 +1370,8 @@ class User {
|
|
|
1374
1370
|
outSwap = calculateSwap(inSwap);
|
|
1375
1371
|
const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inSwap.neg(), inMarket);
|
|
1376
1372
|
const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outSwap, outMarket);
|
|
1377
|
-
const inContributionAfter = this.calculateSpotPositionFreeCollateralContribution(inPositionAfter);
|
|
1378
|
-
const outContributionAfter = this.calculateSpotPositionFreeCollateralContribution(outPositionAfter);
|
|
1373
|
+
const inContributionAfter = this.calculateSpotPositionFreeCollateralContribution(inPositionAfter, inStrictOraclePrice);
|
|
1374
|
+
const outContributionAfter = this.calculateSpotPositionFreeCollateralContribution(outPositionAfter, outStrictOraclePrice);
|
|
1379
1375
|
const contributionAfter = inContributionAfter.add(outContributionAfter);
|
|
1380
1376
|
const contributionDelta = contributionAfter.sub(initialContribution);
|
|
1381
1377
|
freeCollateralAfter = freeCollateral.add(contributionDelta);
|
|
@@ -1395,8 +1391,8 @@ class User {
|
|
|
1395
1391
|
}
|
|
1396
1392
|
const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inSwap.neg(), inMarket);
|
|
1397
1393
|
const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outSwap, outMarket);
|
|
1398
|
-
const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter);
|
|
1399
|
-
const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter);
|
|
1394
|
+
const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter, inStrictOraclePrice);
|
|
1395
|
+
const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter, outStrictOraclePrice);
|
|
1400
1396
|
const spotAssetValueDelta = inTotalAssetValueAfter
|
|
1401
1397
|
.add(outTotalAssetValueAfter)
|
|
1402
1398
|
.sub(inTotalAssetValueInitial)
|
|
@@ -1441,45 +1437,28 @@ class User {
|
|
|
1441
1437
|
}
|
|
1442
1438
|
return clonedPosition;
|
|
1443
1439
|
}
|
|
1444
|
-
calculateSpotPositionFreeCollateralContribution(spotPosition) {
|
|
1445
|
-
let freeCollateralContribution = numericConstants_1.ZERO;
|
|
1446
|
-
const now = new _1.BN(new Date().getTime() / 1000);
|
|
1447
|
-
const strict = true;
|
|
1440
|
+
calculateSpotPositionFreeCollateralContribution(spotPosition, strictOraclePrice) {
|
|
1448
1441
|
const marginCategory = 'Initial';
|
|
1449
1442
|
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1450
|
-
const
|
|
1451
|
-
const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, oraclePriceData);
|
|
1452
|
-
if (worstCaseTokenAmount.gt(numericConstants_1.ZERO)) {
|
|
1453
|
-
const baseAssetValue = this.getSpotAssetValue(worstCaseTokenAmount, oraclePriceData, spotMarketAccount, marginCategory, strict, now);
|
|
1454
|
-
freeCollateralContribution =
|
|
1455
|
-
freeCollateralContribution.add(baseAssetValue);
|
|
1456
|
-
}
|
|
1457
|
-
else {
|
|
1458
|
-
const baseLiabilityValue = this.getSpotLiabilityValue(worstCaseTokenAmount, oraclePriceData, spotMarketAccount, marginCategory, undefined, strict, now).abs();
|
|
1459
|
-
freeCollateralContribution =
|
|
1460
|
-
freeCollateralContribution.sub(baseLiabilityValue);
|
|
1461
|
-
}
|
|
1462
|
-
freeCollateralContribution.add(worstCaseQuoteTokenAmount);
|
|
1443
|
+
const { freeCollateralContribution } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory);
|
|
1463
1444
|
return freeCollateralContribution;
|
|
1464
1445
|
}
|
|
1465
|
-
calculateSpotPositionLeverageContribution(spotPosition) {
|
|
1446
|
+
calculateSpotPositionLeverageContribution(spotPosition, strictOraclePrice) {
|
|
1466
1447
|
let totalAssetValue = numericConstants_1.ZERO;
|
|
1467
1448
|
let totalLiabilityValue = numericConstants_1.ZERO;
|
|
1468
|
-
const now = new _1.BN(new Date().getTime() / 1000);
|
|
1469
1449
|
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1470
|
-
const
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
totalAssetValue = this.getSpotAssetValue(worstCaseTokenAmount, oraclePriceData, spotMarketAccount, undefined, false, now);
|
|
1450
|
+
const { tokenValue, ordersValue } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, 'Initial');
|
|
1451
|
+
if (tokenValue.gte(numericConstants_1.ZERO)) {
|
|
1452
|
+
totalAssetValue = tokenValue;
|
|
1474
1453
|
}
|
|
1475
1454
|
else {
|
|
1476
|
-
totalLiabilityValue =
|
|
1455
|
+
totalLiabilityValue = tokenValue.abs();
|
|
1477
1456
|
}
|
|
1478
|
-
if (
|
|
1479
|
-
totalAssetValue = totalAssetValue.add(
|
|
1457
|
+
if (ordersValue.gt(numericConstants_1.ZERO)) {
|
|
1458
|
+
totalAssetValue = totalAssetValue.add(ordersValue);
|
|
1480
1459
|
}
|
|
1481
1460
|
else {
|
|
1482
|
-
totalLiabilityValue = totalLiabilityValue.add(
|
|
1461
|
+
totalLiabilityValue = totalLiabilityValue.add(ordersValue.abs());
|
|
1483
1462
|
}
|
|
1484
1463
|
return {
|
|
1485
1464
|
totalAssetValue,
|
|
@@ -1496,17 +1475,23 @@ class User {
|
|
|
1496
1475
|
accountLeverageAfterSwap({ inMarketIndex, outMarketIndex, inAmount, outAmount, }) {
|
|
1497
1476
|
const inMarket = this.driftClient.getSpotMarketAccount(inMarketIndex);
|
|
1498
1477
|
const outMarket = this.driftClient.getSpotMarketAccount(outMarketIndex);
|
|
1478
|
+
const inOraclePriceData = this.getOracleDataForSpotMarket(inMarketIndex);
|
|
1479
|
+
const inOraclePrice = inOraclePriceData.price;
|
|
1480
|
+
const outOraclePriceData = this.getOracleDataForSpotMarket(outMarketIndex);
|
|
1481
|
+
const outOraclePrice = outOraclePriceData.price;
|
|
1482
|
+
const inStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(inOraclePrice);
|
|
1483
|
+
const outStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(outOraclePrice);
|
|
1499
1484
|
const inSpotPosition = this.getSpotPosition(inMarketIndex) ||
|
|
1500
1485
|
this.getEmptySpotPosition(inMarketIndex);
|
|
1501
1486
|
const outSpotPosition = this.getSpotPosition(outMarketIndex) ||
|
|
1502
1487
|
this.getEmptySpotPosition(outMarketIndex);
|
|
1503
|
-
const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition);
|
|
1504
|
-
const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition);
|
|
1488
|
+
const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition, inStrictOraclePrice);
|
|
1489
|
+
const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outStrictOraclePrice);
|
|
1505
1490
|
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
|
|
1506
1491
|
const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inAmount.abs().neg(), inMarket);
|
|
1507
1492
|
const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outAmount.abs(), outMarket);
|
|
1508
|
-
const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter);
|
|
1509
|
-
const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter);
|
|
1493
|
+
const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter, inStrictOraclePrice);
|
|
1494
|
+
const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter, outStrictOraclePrice);
|
|
1510
1495
|
const spotAssetValueDelta = inTotalAssetValueAfter
|
|
1511
1496
|
.add(outTotalAssetValueAfter)
|
|
1512
1497
|
.sub(inTotalAssetValueInitial)
|
|
@@ -1634,7 +1619,7 @@ class User {
|
|
|
1634
1619
|
if (canBypass) {
|
|
1635
1620
|
withdrawLimit = _1.BN.max(withdrawLimit, userDepositAmount);
|
|
1636
1621
|
}
|
|
1637
|
-
const assetWeight = (0, spotBalance_1.calculateAssetWeight)(userDepositAmount, spotMarket, 'Initial');
|
|
1622
|
+
const assetWeight = (0, spotBalance_1.calculateAssetWeight)(userDepositAmount, oracleData.price, spotMarket, 'Initial');
|
|
1638
1623
|
const amountWithdrawable = assetWeight.eq(numericConstants_1.ZERO)
|
|
1639
1624
|
? userDepositAmount
|
|
1640
1625
|
: freeCollateral
|
|
@@ -1816,26 +1801,17 @@ class User {
|
|
|
1816
1801
|
for (const spotPosition of this.getActiveSpotPositions()) {
|
|
1817
1802
|
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1818
1803
|
const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
|
|
1804
|
+
const strictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(oraclePriceData.price);
|
|
1819
1805
|
if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
|
|
1820
1806
|
const tokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
|
|
1821
1807
|
netQuoteValue = netQuoteValue.add(tokenAmount);
|
|
1822
1808
|
continue;
|
|
1823
1809
|
}
|
|
1824
|
-
const
|
|
1825
|
-
netQuoteValue = netQuoteValue.add(
|
|
1826
|
-
const baseAssetValue =
|
|
1827
|
-
const
|
|
1828
|
-
|
|
1829
|
-
if (isLiability) {
|
|
1830
|
-
weight = (0, spotBalance_1.calculateLiabilityWeight)(worstCaseTokenAmount.abs(), spotMarketAccount, marginCategory);
|
|
1831
|
-
}
|
|
1832
|
-
else {
|
|
1833
|
-
weight = (0, spotBalance_1.calculateAssetWeight)(worstCaseTokenAmount, spotMarketAccount, marginCategory);
|
|
1834
|
-
}
|
|
1835
|
-
const weightedValue = baseAssetValue
|
|
1836
|
-
.mul(weight)
|
|
1837
|
-
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
1838
|
-
if (isLiability) {
|
|
1810
|
+
const { tokenAmount: worstCaseTokenAmount, tokenValue: tokenValue, weight, weightedTokenValue: weightedTokenValue, ordersValue: ordersValue, } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory);
|
|
1811
|
+
netQuoteValue = netQuoteValue.add(ordersValue);
|
|
1812
|
+
const baseAssetValue = tokenValue.abs();
|
|
1813
|
+
const weightedValue = weightedTokenValue.abs();
|
|
1814
|
+
if (weightedTokenValue.lt(numericConstants_1.ZERO)) {
|
|
1839
1815
|
healthComponents.borrows.push({
|
|
1840
1816
|
marketIndex: spotMarketAccount.marketIndex,
|
|
1841
1817
|
size: worstCaseTokenAmount,
|
|
@@ -1857,25 +1833,15 @@ class User {
|
|
|
1857
1833
|
if (!netQuoteValue.eq(numericConstants_1.ZERO)) {
|
|
1858
1834
|
const spotMarketAccount = this.driftClient.getQuoteSpotMarketAccount();
|
|
1859
1835
|
const oraclePriceData = this.getOracleDataForSpotMarket(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
1860
|
-
const baseAssetValue = (0, _1.getTokenValue)(netQuoteValue
|
|
1861
|
-
const
|
|
1862
|
-
|
|
1863
|
-
if (isLiability) {
|
|
1864
|
-
weight = (0, spotBalance_1.calculateLiabilityWeight)(netQuoteValue.abs(), spotMarketAccount, marginCategory);
|
|
1865
|
-
}
|
|
1866
|
-
else {
|
|
1867
|
-
weight = (0, spotBalance_1.calculateAssetWeight)(netQuoteValue, spotMarketAccount, marginCategory);
|
|
1868
|
-
}
|
|
1869
|
-
const weightedValue = baseAssetValue
|
|
1870
|
-
.mul(weight)
|
|
1871
|
-
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
1872
|
-
if (isLiability) {
|
|
1836
|
+
const baseAssetValue = (0, _1.getTokenValue)(netQuoteValue, spotMarketAccount.decimals, oraclePriceData);
|
|
1837
|
+
const { weight, weightedTokenValue } = (0, spotPosition_1.calculateWeightedTokenValue)(netQuoteValue, baseAssetValue, oraclePriceData.price, spotMarketAccount, marginCategory);
|
|
1838
|
+
if (netQuoteValue.lt(numericConstants_1.ZERO)) {
|
|
1873
1839
|
healthComponents.borrows.push({
|
|
1874
1840
|
marketIndex: spotMarketAccount.marketIndex,
|
|
1875
1841
|
size: netQuoteValue,
|
|
1876
|
-
value: baseAssetValue,
|
|
1842
|
+
value: baseAssetValue.abs(),
|
|
1877
1843
|
weight: weight,
|
|
1878
|
-
weightedValue:
|
|
1844
|
+
weightedValue: weightedTokenValue.abs(),
|
|
1879
1845
|
});
|
|
1880
1846
|
}
|
|
1881
1847
|
else {
|
|
@@ -1884,7 +1850,7 @@ class User {
|
|
|
1884
1850
|
size: netQuoteValue,
|
|
1885
1851
|
value: baseAssetValue,
|
|
1886
1852
|
weight: weight,
|
|
1887
|
-
weightedValue:
|
|
1853
|
+
weightedValue: weightedTokenValue,
|
|
1888
1854
|
});
|
|
1889
1855
|
}
|
|
1890
1856
|
}
|
package/package.json
CHANGED
package/src/adminClient.ts
CHANGED
|
@@ -909,6 +909,29 @@ export class AdminClient extends DriftClient {
|
|
|
909
909
|
return txSig;
|
|
910
910
|
}
|
|
911
911
|
|
|
912
|
+
public async updateSpotMarketScaleInitialAssetWeightStart(
|
|
913
|
+
spotMarketIndex: number,
|
|
914
|
+
scaleInitialAssetWeightStart: BN
|
|
915
|
+
): Promise<TransactionSignature> {
|
|
916
|
+
const tx =
|
|
917
|
+
this.program.transaction.updateSpotMarketScaleInitialAssetWeightStart(
|
|
918
|
+
scaleInitialAssetWeightStart,
|
|
919
|
+
{
|
|
920
|
+
accounts: {
|
|
921
|
+
admin: this.wallet.publicKey,
|
|
922
|
+
state: await this.getStatePublicKey(),
|
|
923
|
+
spotMarket: await getSpotMarketPublicKey(
|
|
924
|
+
this.program.programId,
|
|
925
|
+
spotMarketIndex
|
|
926
|
+
),
|
|
927
|
+
},
|
|
928
|
+
}
|
|
929
|
+
);
|
|
930
|
+
|
|
931
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
932
|
+
return txSig;
|
|
933
|
+
}
|
|
934
|
+
|
|
912
935
|
public async updateInsuranceFundUnstakingPeriod(
|
|
913
936
|
spotMarketIndex: number,
|
|
914
937
|
insuranceWithdrawEscrowPeriod: BN
|