@drift-labs/sdk 2.37.1-beta.6 → 2.37.1-beta.7
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/types.d.ts +13 -0
- package/lib/user.d.ts +4 -1
- package/lib/user.js +142 -2
- package/package.json +1 -1
- package/src/types.ts +15 -0
- package/src/user.ts +250 -2
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.37.1-beta.
|
|
1
|
+
2.37.1-beta.7
|
package/lib/types.d.ts
CHANGED
|
@@ -1117,3 +1117,16 @@ export type PerpMarketExtendedInfo = {
|
|
|
1117
1117
|
pnlPoolValue: BN;
|
|
1118
1118
|
contractTier: ContractTier;
|
|
1119
1119
|
};
|
|
1120
|
+
export type HealthComponents = {
|
|
1121
|
+
deposits: HealthComponent[];
|
|
1122
|
+
borrows: HealthComponent[];
|
|
1123
|
+
perpPositions: HealthComponent[];
|
|
1124
|
+
perpPnl: HealthComponent[];
|
|
1125
|
+
};
|
|
1126
|
+
export type HealthComponent = {
|
|
1127
|
+
marketIndex: number;
|
|
1128
|
+
size: BN;
|
|
1129
|
+
value: BN;
|
|
1130
|
+
weight: BN;
|
|
1131
|
+
weightedValue: BN;
|
|
1132
|
+
};
|
package/lib/user.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { PublicKey } from '@solana/web3.js';
|
|
|
3
3
|
import { EventEmitter } from 'events';
|
|
4
4
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
5
|
import { DriftClient } from './driftClient';
|
|
6
|
-
import { MarginCategory, Order, UserAccount, PerpPosition, SpotPosition, PerpMarketAccount } from './types';
|
|
6
|
+
import { MarginCategory, Order, UserAccount, PerpPosition, SpotPosition, PerpMarketAccount, HealthComponents } from './types';
|
|
7
7
|
import { UserAccountSubscriber, UserAccountEvents, DataAndSlot } from './accounts/types';
|
|
8
8
|
import { PositionDirection, BN, SpotMarketAccount, MarketType } from '.';
|
|
9
9
|
import { OraclePriceData } from './oracles/types';
|
|
@@ -358,6 +358,9 @@ export declare class User {
|
|
|
358
358
|
perpTier: number;
|
|
359
359
|
spotTier: number;
|
|
360
360
|
};
|
|
361
|
+
getHealthComponents({ marginCategory, }: {
|
|
362
|
+
marginCategory: MarginCategory;
|
|
363
|
+
}): HealthComponents;
|
|
361
364
|
/**
|
|
362
365
|
* Get the total position value, excluding any position coming from the given target market
|
|
363
366
|
* @param marketToIgnore
|
package/lib/user.js
CHANGED
|
@@ -464,7 +464,7 @@ class User {
|
|
|
464
464
|
}
|
|
465
465
|
positionUnrealizedPnl = positionUnrealizedPnl
|
|
466
466
|
.mul(quotePrice)
|
|
467
|
-
.div(
|
|
467
|
+
.div(numericConstants_1.PRICE_PRECISION);
|
|
468
468
|
if (withWeightMarginCategory !== undefined) {
|
|
469
469
|
if (positionUnrealizedPnl.gt(numericConstants_1.ZERO)) {
|
|
470
470
|
positionUnrealizedPnl = positionUnrealizedPnl
|
|
@@ -676,7 +676,7 @@ class User {
|
|
|
676
676
|
let baseAssetValue = baseAssetAmount
|
|
677
677
|
.abs()
|
|
678
678
|
.mul(valuationPrice)
|
|
679
|
-
.div(numericConstants_1.
|
|
679
|
+
.div(numericConstants_1.BASE_PRECISION);
|
|
680
680
|
if (marginCategory) {
|
|
681
681
|
let marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(market, baseAssetAmount.abs(), marginCategory));
|
|
682
682
|
if (marginCategory === 'Initial') {
|
|
@@ -1722,6 +1722,146 @@ class User {
|
|
|
1722
1722
|
spotTier: safestSpotTier,
|
|
1723
1723
|
};
|
|
1724
1724
|
}
|
|
1725
|
+
getHealthComponents({ marginCategory, }) {
|
|
1726
|
+
const healthComponents = {
|
|
1727
|
+
deposits: [],
|
|
1728
|
+
borrows: [],
|
|
1729
|
+
perpPositions: [],
|
|
1730
|
+
perpPnl: [],
|
|
1731
|
+
};
|
|
1732
|
+
for (const perpPosition of this.getActivePerpPositions()) {
|
|
1733
|
+
const perpMarket = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
|
|
1734
|
+
const oraclePriceData = this.driftClient.getOraclePriceDataAndSlot(perpMarket.amm.oracle).data;
|
|
1735
|
+
const oraclePrice = oraclePriceData.price;
|
|
1736
|
+
const worstCaseBaseAmount = (0, margin_1.calculateWorstCaseBaseAssetAmount)(perpPosition);
|
|
1737
|
+
const marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(perpMarket, worstCaseBaseAmount.abs(), marginCategory));
|
|
1738
|
+
const quoteSpotMarket = this.driftClient.getSpotMarketAccount(perpMarket.quoteSpotMarketIndex);
|
|
1739
|
+
const quoteOraclePriceData = this.driftClient.getOraclePriceDataAndSlot(quoteSpotMarket.oracle).data;
|
|
1740
|
+
const baseAssetValue = worstCaseBaseAmount
|
|
1741
|
+
.abs()
|
|
1742
|
+
.mul(oraclePrice)
|
|
1743
|
+
.div(numericConstants_1.BASE_PRECISION);
|
|
1744
|
+
let marginRequirement = baseAssetValue
|
|
1745
|
+
.mul(quoteOraclePriceData.price)
|
|
1746
|
+
.div(numericConstants_1.PRICE_PRECISION)
|
|
1747
|
+
.mul(marginRatio)
|
|
1748
|
+
.div(numericConstants_1.MARGIN_PRECISION);
|
|
1749
|
+
marginRequirement = marginRequirement.add(new _1.BN(perpPosition.openOrders).mul(numericConstants_1.OPEN_ORDER_MARGIN_REQUIREMENT));
|
|
1750
|
+
if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
|
|
1751
|
+
marginRequirement = marginRequirement.add(_1.BN.max(numericConstants_1.QUOTE_PRECISION, oraclePrice
|
|
1752
|
+
.mul(perpMarket.amm.orderStepSize)
|
|
1753
|
+
.mul(numericConstants_1.QUOTE_PRECISION)
|
|
1754
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
1755
|
+
.div(numericConstants_1.PRICE_PRECISION)));
|
|
1756
|
+
}
|
|
1757
|
+
healthComponents.perpPositions.push({
|
|
1758
|
+
marketIndex: perpMarket.marketIndex,
|
|
1759
|
+
size: worstCaseBaseAmount,
|
|
1760
|
+
value: baseAssetValue,
|
|
1761
|
+
weight: marginRatio,
|
|
1762
|
+
weightedValue: marginRequirement,
|
|
1763
|
+
});
|
|
1764
|
+
const settledPerpPosition = this.getPerpPositionWithLPSettle(perpPosition.marketIndex, perpPosition)[0];
|
|
1765
|
+
const positionUnrealizedPnl = (0, _1.calculatePositionPNL)(perpMarket, settledPerpPosition, true, oraclePriceData);
|
|
1766
|
+
let pnlWeight;
|
|
1767
|
+
if (positionUnrealizedPnl.gt(numericConstants_1.ZERO)) {
|
|
1768
|
+
pnlWeight = (0, _1.calculateUnrealizedAssetWeight)(perpMarket, quoteSpotMarket, positionUnrealizedPnl, marginCategory, oraclePriceData);
|
|
1769
|
+
}
|
|
1770
|
+
else {
|
|
1771
|
+
pnlWeight = numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION;
|
|
1772
|
+
}
|
|
1773
|
+
const pnlValue = positionUnrealizedPnl
|
|
1774
|
+
.mul(quoteOraclePriceData.price)
|
|
1775
|
+
.div(numericConstants_1.PRICE_PRECISION);
|
|
1776
|
+
const wegithedPnlValue = pnlValue
|
|
1777
|
+
.mul(pnlWeight)
|
|
1778
|
+
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
1779
|
+
healthComponents.perpPnl.push({
|
|
1780
|
+
marketIndex: perpMarket.marketIndex,
|
|
1781
|
+
size: positionUnrealizedPnl,
|
|
1782
|
+
value: wegithedPnlValue,
|
|
1783
|
+
weight: pnlWeight,
|
|
1784
|
+
weightedValue: wegithedPnlValue,
|
|
1785
|
+
});
|
|
1786
|
+
}
|
|
1787
|
+
let netQuoteValue = numericConstants_1.ZERO;
|
|
1788
|
+
for (const spotPosition of this.getActiveSpotPositions()) {
|
|
1789
|
+
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1790
|
+
const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
|
|
1791
|
+
if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
|
|
1792
|
+
const tokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
|
|
1793
|
+
netQuoteValue = netQuoteValue.add(tokenAmount);
|
|
1794
|
+
continue;
|
|
1795
|
+
}
|
|
1796
|
+
const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, oraclePriceData);
|
|
1797
|
+
netQuoteValue = netQuoteValue.add(worstCaseQuoteTokenAmount);
|
|
1798
|
+
const baseAssetValue = (0, _1.getTokenValue)(worstCaseTokenAmount.abs(), spotMarketAccount.decimals, oraclePriceData);
|
|
1799
|
+
const isLiability = (0, types_1.isVariant)(spotPosition.balanceType, 'borrow');
|
|
1800
|
+
let weight;
|
|
1801
|
+
if (isLiability) {
|
|
1802
|
+
weight = (0, spotBalance_1.calculateLiabilityWeight)(worstCaseTokenAmount.abs(), spotMarketAccount, marginCategory);
|
|
1803
|
+
}
|
|
1804
|
+
else {
|
|
1805
|
+
weight = (0, spotBalance_1.calculateAssetWeight)(worstCaseTokenAmount, spotMarketAccount, marginCategory);
|
|
1806
|
+
}
|
|
1807
|
+
const weightedValue = baseAssetValue
|
|
1808
|
+
.mul(weight)
|
|
1809
|
+
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
1810
|
+
if (isLiability) {
|
|
1811
|
+
healthComponents.borrows.push({
|
|
1812
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
1813
|
+
size: worstCaseTokenAmount,
|
|
1814
|
+
value: baseAssetValue,
|
|
1815
|
+
weight: weight,
|
|
1816
|
+
weightedValue: weightedValue,
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
1819
|
+
else {
|
|
1820
|
+
healthComponents.deposits.push({
|
|
1821
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
1822
|
+
size: worstCaseTokenAmount,
|
|
1823
|
+
value: weightedValue,
|
|
1824
|
+
weight: weight,
|
|
1825
|
+
weightedValue: weightedValue,
|
|
1826
|
+
});
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
if (!netQuoteValue.eq(numericConstants_1.ZERO)) {
|
|
1830
|
+
const spotMarketAccount = this.driftClient.getQuoteSpotMarketAccount();
|
|
1831
|
+
const oraclePriceData = this.getOracleDataForSpotMarket(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
1832
|
+
const baseAssetValue = (0, _1.getTokenValue)(netQuoteValue.abs(), spotMarketAccount.decimals, oraclePriceData);
|
|
1833
|
+
const isLiability = netQuoteValue.lt(numericConstants_1.ZERO);
|
|
1834
|
+
let weight;
|
|
1835
|
+
if (isLiability) {
|
|
1836
|
+
weight = (0, spotBalance_1.calculateLiabilityWeight)(netQuoteValue.abs(), spotMarketAccount, marginCategory);
|
|
1837
|
+
}
|
|
1838
|
+
else {
|
|
1839
|
+
weight = (0, spotBalance_1.calculateAssetWeight)(netQuoteValue, spotMarketAccount, marginCategory);
|
|
1840
|
+
}
|
|
1841
|
+
const weightedValue = baseAssetValue
|
|
1842
|
+
.mul(weight)
|
|
1843
|
+
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
1844
|
+
if (isLiability) {
|
|
1845
|
+
healthComponents.borrows.push({
|
|
1846
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
1847
|
+
size: netQuoteValue,
|
|
1848
|
+
value: baseAssetValue,
|
|
1849
|
+
weight: weight,
|
|
1850
|
+
weightedValue: weightedValue,
|
|
1851
|
+
});
|
|
1852
|
+
}
|
|
1853
|
+
else {
|
|
1854
|
+
healthComponents.deposits.push({
|
|
1855
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
1856
|
+
size: netQuoteValue,
|
|
1857
|
+
value: weightedValue,
|
|
1858
|
+
weight: weight,
|
|
1859
|
+
weightedValue: weightedValue,
|
|
1860
|
+
});
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
return healthComponents;
|
|
1864
|
+
}
|
|
1725
1865
|
/**
|
|
1726
1866
|
* Get the total position value, excluding any position coming from the given target market
|
|
1727
1867
|
* @param marketToIgnore
|
package/package.json
CHANGED
package/src/types.ts
CHANGED
|
@@ -1100,3 +1100,18 @@ export type PerpMarketExtendedInfo = {
|
|
|
1100
1100
|
pnlPoolValue: BN;
|
|
1101
1101
|
contractTier: ContractTier;
|
|
1102
1102
|
};
|
|
1103
|
+
|
|
1104
|
+
export type HealthComponents = {
|
|
1105
|
+
deposits: HealthComponent[];
|
|
1106
|
+
borrows: HealthComponent[];
|
|
1107
|
+
perpPositions: HealthComponent[];
|
|
1108
|
+
perpPnl: HealthComponent[];
|
|
1109
|
+
};
|
|
1110
|
+
|
|
1111
|
+
export type HealthComponent = {
|
|
1112
|
+
marketIndex: number;
|
|
1113
|
+
size: BN;
|
|
1114
|
+
value: BN;
|
|
1115
|
+
weight: BN;
|
|
1116
|
+
weightedValue: BN;
|
|
1117
|
+
};
|
package/src/user.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
SpotPosition,
|
|
12
12
|
isOneOfVariant,
|
|
13
13
|
PerpMarketAccount,
|
|
14
|
+
HealthComponents,
|
|
14
15
|
} from './types';
|
|
15
16
|
import { calculateEntryPrice, positionIsAvailable } from './math/position';
|
|
16
17
|
import {
|
|
@@ -749,7 +750,7 @@ export class User {
|
|
|
749
750
|
|
|
750
751
|
positionUnrealizedPnl = positionUnrealizedPnl
|
|
751
752
|
.mul(quotePrice)
|
|
752
|
-
.div(
|
|
753
|
+
.div(PRICE_PRECISION);
|
|
753
754
|
|
|
754
755
|
if (withWeightMarginCategory !== undefined) {
|
|
755
756
|
if (positionUnrealizedPnl.gt(ZERO)) {
|
|
@@ -1231,7 +1232,7 @@ export class User {
|
|
|
1231
1232
|
let baseAssetValue = baseAssetAmount
|
|
1232
1233
|
.abs()
|
|
1233
1234
|
.mul(valuationPrice)
|
|
1234
|
-
.div(
|
|
1235
|
+
.div(BASE_PRECISION);
|
|
1235
1236
|
|
|
1236
1237
|
if (marginCategory) {
|
|
1237
1238
|
let marginRatio = new BN(
|
|
@@ -3117,6 +3118,253 @@ export class User {
|
|
|
3117
3118
|
};
|
|
3118
3119
|
}
|
|
3119
3120
|
|
|
3121
|
+
public getHealthComponents({
|
|
3122
|
+
marginCategory,
|
|
3123
|
+
}: {
|
|
3124
|
+
marginCategory: MarginCategory;
|
|
3125
|
+
}): HealthComponents {
|
|
3126
|
+
const healthComponents: HealthComponents = {
|
|
3127
|
+
deposits: [],
|
|
3128
|
+
borrows: [],
|
|
3129
|
+
perpPositions: [],
|
|
3130
|
+
perpPnl: [],
|
|
3131
|
+
};
|
|
3132
|
+
|
|
3133
|
+
for (const perpPosition of this.getActivePerpPositions()) {
|
|
3134
|
+
const perpMarket = this.driftClient.getPerpMarketAccount(
|
|
3135
|
+
perpPosition.marketIndex
|
|
3136
|
+
);
|
|
3137
|
+
const oraclePriceData = this.driftClient.getOraclePriceDataAndSlot(
|
|
3138
|
+
perpMarket.amm.oracle
|
|
3139
|
+
).data;
|
|
3140
|
+
const oraclePrice = oraclePriceData.price;
|
|
3141
|
+
const worstCaseBaseAmount =
|
|
3142
|
+
calculateWorstCaseBaseAssetAmount(perpPosition);
|
|
3143
|
+
|
|
3144
|
+
const marginRatio = new BN(
|
|
3145
|
+
calculateMarketMarginRatio(
|
|
3146
|
+
perpMarket,
|
|
3147
|
+
worstCaseBaseAmount.abs(),
|
|
3148
|
+
marginCategory
|
|
3149
|
+
)
|
|
3150
|
+
);
|
|
3151
|
+
|
|
3152
|
+
const quoteSpotMarket = this.driftClient.getSpotMarketAccount(
|
|
3153
|
+
perpMarket.quoteSpotMarketIndex
|
|
3154
|
+
);
|
|
3155
|
+
const quoteOraclePriceData = this.driftClient.getOraclePriceDataAndSlot(
|
|
3156
|
+
quoteSpotMarket.oracle
|
|
3157
|
+
).data;
|
|
3158
|
+
|
|
3159
|
+
const baseAssetValue = worstCaseBaseAmount
|
|
3160
|
+
.abs()
|
|
3161
|
+
.mul(oraclePrice)
|
|
3162
|
+
.div(BASE_PRECISION);
|
|
3163
|
+
|
|
3164
|
+
let marginRequirement = baseAssetValue
|
|
3165
|
+
.mul(quoteOraclePriceData.price)
|
|
3166
|
+
.div(PRICE_PRECISION)
|
|
3167
|
+
.mul(marginRatio)
|
|
3168
|
+
.div(MARGIN_PRECISION);
|
|
3169
|
+
|
|
3170
|
+
marginRequirement = marginRequirement.add(
|
|
3171
|
+
new BN(perpPosition.openOrders).mul(OPEN_ORDER_MARGIN_REQUIREMENT)
|
|
3172
|
+
);
|
|
3173
|
+
|
|
3174
|
+
if (perpPosition.lpShares.gt(ZERO)) {
|
|
3175
|
+
marginRequirement = marginRequirement.add(
|
|
3176
|
+
BN.max(
|
|
3177
|
+
QUOTE_PRECISION,
|
|
3178
|
+
oraclePrice
|
|
3179
|
+
.mul(perpMarket.amm.orderStepSize)
|
|
3180
|
+
.mul(QUOTE_PRECISION)
|
|
3181
|
+
.div(AMM_RESERVE_PRECISION)
|
|
3182
|
+
.div(PRICE_PRECISION)
|
|
3183
|
+
)
|
|
3184
|
+
);
|
|
3185
|
+
}
|
|
3186
|
+
|
|
3187
|
+
healthComponents.perpPositions.push({
|
|
3188
|
+
marketIndex: perpMarket.marketIndex,
|
|
3189
|
+
size: worstCaseBaseAmount,
|
|
3190
|
+
value: baseAssetValue,
|
|
3191
|
+
weight: marginRatio,
|
|
3192
|
+
weightedValue: marginRequirement,
|
|
3193
|
+
});
|
|
3194
|
+
|
|
3195
|
+
const settledPerpPosition = this.getPerpPositionWithLPSettle(
|
|
3196
|
+
perpPosition.marketIndex,
|
|
3197
|
+
perpPosition
|
|
3198
|
+
)[0];
|
|
3199
|
+
|
|
3200
|
+
const positionUnrealizedPnl = calculatePositionPNL(
|
|
3201
|
+
perpMarket,
|
|
3202
|
+
settledPerpPosition,
|
|
3203
|
+
true,
|
|
3204
|
+
oraclePriceData
|
|
3205
|
+
);
|
|
3206
|
+
|
|
3207
|
+
let pnlWeight;
|
|
3208
|
+
if (positionUnrealizedPnl.gt(ZERO)) {
|
|
3209
|
+
pnlWeight = calculateUnrealizedAssetWeight(
|
|
3210
|
+
perpMarket,
|
|
3211
|
+
quoteSpotMarket,
|
|
3212
|
+
positionUnrealizedPnl,
|
|
3213
|
+
marginCategory,
|
|
3214
|
+
oraclePriceData
|
|
3215
|
+
);
|
|
3216
|
+
} else {
|
|
3217
|
+
pnlWeight = SPOT_MARKET_WEIGHT_PRECISION;
|
|
3218
|
+
}
|
|
3219
|
+
|
|
3220
|
+
const pnlValue = positionUnrealizedPnl
|
|
3221
|
+
.mul(quoteOraclePriceData.price)
|
|
3222
|
+
.div(PRICE_PRECISION);
|
|
3223
|
+
|
|
3224
|
+
const wegithedPnlValue = pnlValue
|
|
3225
|
+
.mul(pnlWeight)
|
|
3226
|
+
.div(SPOT_MARKET_WEIGHT_PRECISION);
|
|
3227
|
+
|
|
3228
|
+
healthComponents.perpPnl.push({
|
|
3229
|
+
marketIndex: perpMarket.marketIndex,
|
|
3230
|
+
size: positionUnrealizedPnl,
|
|
3231
|
+
value: wegithedPnlValue,
|
|
3232
|
+
weight: pnlWeight,
|
|
3233
|
+
weightedValue: wegithedPnlValue,
|
|
3234
|
+
});
|
|
3235
|
+
}
|
|
3236
|
+
|
|
3237
|
+
let netQuoteValue = ZERO;
|
|
3238
|
+
for (const spotPosition of this.getActiveSpotPositions()) {
|
|
3239
|
+
const spotMarketAccount: SpotMarketAccount =
|
|
3240
|
+
this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
3241
|
+
|
|
3242
|
+
const oraclePriceData = this.getOracleDataForSpotMarket(
|
|
3243
|
+
spotPosition.marketIndex
|
|
3244
|
+
);
|
|
3245
|
+
|
|
3246
|
+
if (spotPosition.marketIndex === QUOTE_SPOT_MARKET_INDEX) {
|
|
3247
|
+
const tokenAmount = getSignedTokenAmount(
|
|
3248
|
+
getTokenAmount(
|
|
3249
|
+
spotPosition.scaledBalance,
|
|
3250
|
+
spotMarketAccount,
|
|
3251
|
+
spotPosition.balanceType
|
|
3252
|
+
),
|
|
3253
|
+
spotPosition.balanceType
|
|
3254
|
+
);
|
|
3255
|
+
|
|
3256
|
+
netQuoteValue = netQuoteValue.add(tokenAmount);
|
|
3257
|
+
continue;
|
|
3258
|
+
}
|
|
3259
|
+
|
|
3260
|
+
const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] =
|
|
3261
|
+
getWorstCaseTokenAmounts(
|
|
3262
|
+
spotPosition,
|
|
3263
|
+
spotMarketAccount,
|
|
3264
|
+
oraclePriceData
|
|
3265
|
+
);
|
|
3266
|
+
|
|
3267
|
+
netQuoteValue = netQuoteValue.add(worstCaseQuoteTokenAmount);
|
|
3268
|
+
|
|
3269
|
+
const baseAssetValue = getTokenValue(
|
|
3270
|
+
worstCaseTokenAmount.abs(),
|
|
3271
|
+
spotMarketAccount.decimals,
|
|
3272
|
+
oraclePriceData
|
|
3273
|
+
);
|
|
3274
|
+
const isLiability = isVariant(spotPosition.balanceType, 'borrow');
|
|
3275
|
+
|
|
3276
|
+
let weight;
|
|
3277
|
+
if (isLiability) {
|
|
3278
|
+
weight = calculateLiabilityWeight(
|
|
3279
|
+
worstCaseTokenAmount.abs(),
|
|
3280
|
+
spotMarketAccount,
|
|
3281
|
+
marginCategory
|
|
3282
|
+
);
|
|
3283
|
+
} else {
|
|
3284
|
+
weight = calculateAssetWeight(
|
|
3285
|
+
worstCaseTokenAmount,
|
|
3286
|
+
spotMarketAccount,
|
|
3287
|
+
marginCategory
|
|
3288
|
+
);
|
|
3289
|
+
}
|
|
3290
|
+
|
|
3291
|
+
const weightedValue = baseAssetValue
|
|
3292
|
+
.mul(weight)
|
|
3293
|
+
.div(SPOT_MARKET_WEIGHT_PRECISION);
|
|
3294
|
+
|
|
3295
|
+
if (isLiability) {
|
|
3296
|
+
healthComponents.borrows.push({
|
|
3297
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
3298
|
+
size: worstCaseTokenAmount,
|
|
3299
|
+
value: baseAssetValue,
|
|
3300
|
+
weight: weight,
|
|
3301
|
+
weightedValue: weightedValue,
|
|
3302
|
+
});
|
|
3303
|
+
} else {
|
|
3304
|
+
healthComponents.deposits.push({
|
|
3305
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
3306
|
+
size: worstCaseTokenAmount,
|
|
3307
|
+
value: weightedValue,
|
|
3308
|
+
weight: weight,
|
|
3309
|
+
weightedValue: weightedValue,
|
|
3310
|
+
});
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
|
|
3314
|
+
if (!netQuoteValue.eq(ZERO)) {
|
|
3315
|
+
const spotMarketAccount = this.driftClient.getQuoteSpotMarketAccount();
|
|
3316
|
+
const oraclePriceData = this.getOracleDataForSpotMarket(
|
|
3317
|
+
QUOTE_SPOT_MARKET_INDEX
|
|
3318
|
+
);
|
|
3319
|
+
|
|
3320
|
+
const baseAssetValue = getTokenValue(
|
|
3321
|
+
netQuoteValue.abs(),
|
|
3322
|
+
spotMarketAccount.decimals,
|
|
3323
|
+
oraclePriceData
|
|
3324
|
+
);
|
|
3325
|
+
const isLiability = netQuoteValue.lt(ZERO);
|
|
3326
|
+
|
|
3327
|
+
let weight;
|
|
3328
|
+
if (isLiability) {
|
|
3329
|
+
weight = calculateLiabilityWeight(
|
|
3330
|
+
netQuoteValue.abs(),
|
|
3331
|
+
spotMarketAccount,
|
|
3332
|
+
marginCategory
|
|
3333
|
+
);
|
|
3334
|
+
} else {
|
|
3335
|
+
weight = calculateAssetWeight(
|
|
3336
|
+
netQuoteValue,
|
|
3337
|
+
spotMarketAccount,
|
|
3338
|
+
marginCategory
|
|
3339
|
+
);
|
|
3340
|
+
}
|
|
3341
|
+
|
|
3342
|
+
const weightedValue = baseAssetValue
|
|
3343
|
+
.mul(weight)
|
|
3344
|
+
.div(SPOT_MARKET_WEIGHT_PRECISION);
|
|
3345
|
+
|
|
3346
|
+
if (isLiability) {
|
|
3347
|
+
healthComponents.borrows.push({
|
|
3348
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
3349
|
+
size: netQuoteValue,
|
|
3350
|
+
value: baseAssetValue,
|
|
3351
|
+
weight: weight,
|
|
3352
|
+
weightedValue: weightedValue,
|
|
3353
|
+
});
|
|
3354
|
+
} else {
|
|
3355
|
+
healthComponents.deposits.push({
|
|
3356
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
3357
|
+
size: netQuoteValue,
|
|
3358
|
+
value: weightedValue,
|
|
3359
|
+
weight: weight,
|
|
3360
|
+
weightedValue: weightedValue,
|
|
3361
|
+
});
|
|
3362
|
+
}
|
|
3363
|
+
}
|
|
3364
|
+
|
|
3365
|
+
return healthComponents;
|
|
3366
|
+
}
|
|
3367
|
+
|
|
3120
3368
|
/**
|
|
3121
3369
|
* Get the total position value, excluding any position coming from the given target market
|
|
3122
3370
|
* @param marketToIgnore
|