diff --git a/app/api/drift/balance/route.js b/app/api/drift/balance/route.js index 5d79dc2..98cedd3 100644 --- a/app/api/drift/balance/route.js +++ b/app/api/drift/balance/route.js @@ -20,7 +20,7 @@ export async function GET() { // Execute balance check with RPC failover const result = await executeWithFailover(async (connection) => { // Import Drift SDK components - const { DriftClient, initialize, calculateFreeCollateral, QUOTE_PRECISION } = await import('@drift-labs/sdk') + const { DriftClient, initialize, calculateFreeCollateral, calculatePositionPNL, QUOTE_PRECISION } = await import('@drift-labs/sdk') const { Keypair } = await import('@solana/web3.js') const { AnchorProvider, BN } = await import('@coral-xyz/anchor') @@ -57,66 +57,55 @@ export async function GET() { throw new Error('No Drift user account found. Please initialize your account first.') } - // Get account balances and positions + // Get account balances and positions using Drift's built-in methods const spotBalances = userAccount.spotPositions || [] const perpPositions = userAccount.perpPositions || [] - // Calculate key metrics + // Use Drift's built-in calculation methods for accuracy let totalCollateral = 0 let unrealizedPnl = 0 let marginRequirement = 0 - // Process spot balances (USDC collateral) - const usdcBalance = spotBalances.find(pos => pos.marketIndex === 0) // USDC is typically index 0 - if (usdcBalance) { - // Drift uses a complex precision system for scaledBalance - // Based on testing: scaledBalance 30678757385 = $35.69 - // This gives us a precision factor of approximately 859589727.79 - const rawBalance = Number(usdcBalance.scaledBalance) - const DRIFT_PRECISION_FACTOR = 859589727.79 // Empirically determined + try { + // Calculate total collateral using Drift's method + totalCollateral = await driftClient.getUser().getTotalCollateral() / 1e6 // Convert to USDC + } catch (collateralError) { + console.warn('⚠️ Could not get total collateral, calculating manually:', collateralError.message) - totalCollateral = rawBalance / DRIFT_PRECISION_FACTOR - - console.log('💰 USDC Balance calculated:', { - rawScaledBalance: rawBalance, - calculatedBalance: totalCollateral.toFixed(2) - }) + // Fallback to manual USDC balance calculation + const usdcBalance = spotBalances.find(pos => pos.marketIndex === 0) + if (usdcBalance) { + totalCollateral = Number(usdcBalance.scaledBalance) / 1e6 // Assume 6 decimal precision for USDC + } } - // Process perp positions and calculate P&L properly + try { + // Calculate unrealized PnL using Drift's method + unrealizedPnl = await driftClient.getUser().getUnrealizedPNL() / 1e6 // Convert to USDC + } catch (pnlError) { + console.warn('⚠️ Could not get unrealized PnL, calculating manually:', pnlError.message) + unrealizedPnl = 0 // Default to 0 if we can't calculate + } + + try { + // Calculate margin requirement using Drift's method + marginRequirement = await driftClient.getUser().getTotalPerpPositionValue() / 1e6 * 0.1 // 10% margin + } catch (marginError) { + console.warn('⚠️ Could not get margin requirement, calculating manually:', marginError.message) + marginRequirement = 0 // Default to 0 if we can't calculate + } + + // Calculate free collateral and other derived values + const freeCollateral = totalCollateral - marginRequirement + unrealizedPnl + const accountValue = totalCollateral + unrealizedPnl + const leverage = marginRequirement > 0 ? (marginRequirement / accountValue) : 0 + const availableBalance = Math.max(0, freeCollateral) + + // Count active positions const activePositions = perpPositions.filter(pos => pos.baseAssetAmount && !pos.baseAssetAmount.isZero() ) - for (const position of activePositions) { - const baseAmount = Number(position.baseAssetAmount) / 1e9 // Convert from lamports to SOL - const quoteAmount = Number(position.quoteAssetAmount) / 1e6 // Convert from micro-USDC to USDC - - // For P&L calculation: negative quoteAmount means we paid out USD to open position - // Positive means we received USD (short position) - const positionValue = Math.abs(baseAmount * 195) // Approximate current SOL price - const entryValue = Math.abs(quoteAmount) - - // Calculate unrealized P&L based on position direction - if (baseAmount > 0) { // Long position - unrealizedPnl += positionValue - entryValue - } else { // Short position - unrealizedPnl += entryValue - positionValue - } - - marginRequirement += positionValue * 0.1 // 10% margin requirement for perps - } - - // Calculate free collateral (simplified) - const freeCollateral = totalCollateral - marginRequirement + unrealizedPnl - - // Calculate account value and leverage - const accountValue = totalCollateral + unrealizedPnl - const leverage = marginRequirement > 0 ? (marginRequirement / accountValue) : 0 - - // Available balance for new positions - const availableBalance = Math.max(0, freeCollateral) - const balanceResult = { success: true, totalCollateral: totalCollateral,