Add Net USD Value display to dashboard
- Updated AccountBalance interface to include netUsdValue and unrealizedPnl - Enhanced getAccountBalance() to calculate Net USD Value (collateral + unrealized PnL) - Added Net USD Value calculation from all position unrealized PnL - Updated Dashboard.tsx to display Net USD Value as primary metric - Added new stats card with emerald styling for Net USD Value - Reorganized stats grid to 6 columns to accommodate new metric - Net USD Value = Total Collateral + Total Unrealized PnL from all positions
This commit is contained in:
@@ -50,6 +50,8 @@ export interface AccountBalance {
|
||||
accountValue: number
|
||||
leverage: number
|
||||
availableBalance: number
|
||||
netUsdValue: number
|
||||
unrealizedPnl: number
|
||||
}
|
||||
|
||||
export interface TradeHistory {
|
||||
@@ -181,8 +183,11 @@ export class DriftTradingService {
|
||||
async getAccountBalance(): Promise<AccountBalance> {
|
||||
try {
|
||||
if (this.isInitialized && this.driftClient) {
|
||||
// Try to use SDK without subscription
|
||||
// Subscribe to user account to access balance data
|
||||
try {
|
||||
console.log('🔍 Subscribing to user account for balance...')
|
||||
await this.driftClient.subscribe()
|
||||
|
||||
const user = this.driftClient.getUser()
|
||||
|
||||
// Get account equity and collateral information using proper SDK methods
|
||||
@@ -213,17 +218,67 @@ export class DriftTradingService {
|
||||
const leverage = marginRequirement > 0 ? totalCollateral / marginRequirement : 1
|
||||
const availableBalance = freeCollateral
|
||||
|
||||
// Calculate unrealized PnL from all positions
|
||||
let totalUnrealizedPnl = 0
|
||||
try {
|
||||
// Get all perp positions to calculate total unrealized PnL
|
||||
const mainMarkets = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] // Check more markets for PnL
|
||||
|
||||
for (const marketIndex of mainMarkets) {
|
||||
try {
|
||||
const position = user.getPerpPosition(marketIndex)
|
||||
if (!position || position.baseAssetAmount.isZero()) continue
|
||||
|
||||
// Calculate unrealized PnL manually
|
||||
const marketData = this.driftClient.getPerpMarketAccount(marketIndex)
|
||||
const markPrice = convertToNumber(marketData?.amm.lastMarkPriceTwap || new BN(0), PRICE_PRECISION)
|
||||
|
||||
const entryPrice = convertToNumber(position.quoteEntryAmount.abs(), PRICE_PRECISION) /
|
||||
convertToNumber(position.baseAssetAmount.abs(), BASE_PRECISION)
|
||||
const size = convertToNumber(position.baseAssetAmount.abs(), BASE_PRECISION)
|
||||
const isLong = position.baseAssetAmount.gt(new BN(0))
|
||||
|
||||
const unrealizedPnl = isLong ?
|
||||
(markPrice - entryPrice) * size :
|
||||
(entryPrice - markPrice) * size
|
||||
|
||||
totalUnrealizedPnl += unrealizedPnl
|
||||
} catch (e) {
|
||||
// Skip markets that don't exist
|
||||
continue
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Could not calculate unrealized PnL:', e)
|
||||
}
|
||||
|
||||
// Net USD Value = Total Collateral + Unrealized PnL
|
||||
const netUsdValue = totalCollateral + totalUnrealizedPnl
|
||||
|
||||
console.log(`💰 Account balance: $${accountValue.toFixed(2)}, Net USD: $${netUsdValue.toFixed(2)}, PnL: $${totalUnrealizedPnl.toFixed(2)}`)
|
||||
|
||||
return {
|
||||
totalCollateral,
|
||||
freeCollateral,
|
||||
marginRequirement,
|
||||
accountValue,
|
||||
leverage,
|
||||
availableBalance
|
||||
availableBalance,
|
||||
netUsdValue,
|
||||
unrealizedPnl: totalUnrealizedPnl
|
||||
}
|
||||
} catch (sdkError: any) {
|
||||
console.log('⚠️ SDK method failed, using fallback:', sdkError.message)
|
||||
console.log('⚠️ SDK balance method failed, using fallback:', sdkError.message)
|
||||
// Fall through to fallback method
|
||||
} finally {
|
||||
// Always unsubscribe to clean up
|
||||
if (this.driftClient) {
|
||||
try {
|
||||
await this.driftClient.unsubscribe()
|
||||
} catch (e) {
|
||||
// Ignore unsubscribe errors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +292,9 @@ export class DriftTradingService {
|
||||
marginRequirement: 0,
|
||||
accountValue: balance / 1e9, // SOL balance
|
||||
leverage: 0,
|
||||
availableBalance: 0
|
||||
availableBalance: 0,
|
||||
netUsdValue: balance / 1e9, // Use SOL balance as fallback
|
||||
unrealizedPnl: 0
|
||||
}
|
||||
|
||||
} catch (error: any) {
|
||||
@@ -281,8 +338,11 @@ export class DriftTradingService {
|
||||
async getPositions(): Promise<Position[]> {
|
||||
try {
|
||||
if (this.isInitialized && this.driftClient) {
|
||||
// Try to use SDK without subscription
|
||||
// Subscribe to user account to access positions
|
||||
try {
|
||||
console.log('🔍 Subscribing to user account for positions...')
|
||||
await this.driftClient.subscribe()
|
||||
|
||||
const user = this.driftClient.getUser()
|
||||
|
||||
// Get all available markets
|
||||
@@ -296,7 +356,7 @@ export class DriftTradingService {
|
||||
const p = user.getPerpPosition(marketIndex)
|
||||
if (!p || p.baseAssetAmount.isZero()) continue
|
||||
|
||||
// Get market price without subscription
|
||||
// Get market price
|
||||
const marketData = this.driftClient.getPerpMarketAccount(marketIndex)
|
||||
const markPrice = convertToNumber(marketData?.amm.lastMarkPriceTwap || new BN(0), PRICE_PRECISION)
|
||||
|
||||
@@ -319,16 +379,29 @@ export class DriftTradingService {
|
||||
marketIndex,
|
||||
marketType: 'PERP'
|
||||
})
|
||||
|
||||
console.log(`✅ Found position: ${this.getSymbolFromMarketIndex(marketIndex)} ${isLong ? 'LONG' : 'SHORT'} ${size}`)
|
||||
} catch (error) {
|
||||
// Skip markets that don't exist or have errors
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`📊 Found ${positions.length} total positions`)
|
||||
return positions
|
||||
|
||||
} catch (sdkError: any) {
|
||||
console.log('⚠️ SDK positions method failed, using fallback:', sdkError.message)
|
||||
// Fall through to fallback method
|
||||
} finally {
|
||||
// Always unsubscribe to clean up
|
||||
if (this.driftClient) {
|
||||
try {
|
||||
await this.driftClient.unsubscribe()
|
||||
} catch (e) {
|
||||
// Ignore unsubscribe errors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user