- Add SymbolSettings interface with enabled/positionSize/leverage fields - Implement per-symbol ENV variables (SOLANA_*, ETHEREUM_*) - Add SOL and ETH sections to settings UI with enable/disable toggles - Add symbol-specific test buttons (SOL LONG/SHORT, ETH LONG/SHORT) - Update execute and test endpoints to check symbol enabled status - Add real-time risk/reward calculator per symbol - Rename 'Position Sizing' to 'Global Fallback' for clarity - Fix position manager P&L calculation for externally closed positions - Fix zero P&L bug affecting 12 historical trades - Add SQL scripts for recalculating historical P&L data - Move archive TypeScript files to .archive to fix build Defaults: - SOL: 10 base × 10x leverage = 100 notional (profit trading) - ETH: base × 1x leverage = notional (data collection) - Global: 10 × 10x for BTC and other symbols Configuration priority: Per-symbol ENV > Market config > Global ENV > Defaults
117 lines
3.6 KiB
TypeScript
117 lines
3.6 KiB
TypeScript
/**
|
|
* Query Drift History API
|
|
* GET /api/drift/history
|
|
*
|
|
* Queries Drift Protocol directly to compare with database
|
|
*/
|
|
|
|
import { NextResponse } from 'next/server'
|
|
import { initializeDriftService, getDriftService } from '@/lib/drift/client'
|
|
import { getPrismaClient } from '@/lib/database/trades'
|
|
|
|
export async function GET() {
|
|
try {
|
|
console.log('🔍 Querying Drift Protocol...')
|
|
|
|
// Initialize Drift service if not already done
|
|
console.log('⏳ Calling initializeDriftService()...')
|
|
const driftService = await initializeDriftService()
|
|
console.log('✅ Drift service initialized, got service object')
|
|
|
|
console.log('⏳ Getting Drift client...')
|
|
const driftClient = driftService.getClient()
|
|
console.log('✅ Got Drift client')
|
|
|
|
// Get user account
|
|
const userAccount = driftClient.getUserAccount()
|
|
|
|
if (!userAccount) {
|
|
return NextResponse.json({ error: 'User account not found' }, { status: 404 })
|
|
}
|
|
|
|
// Get account equity and P&L
|
|
const equity = driftClient.getUser().getTotalCollateral()
|
|
const unrealizedPnL = driftClient.getUser().getUnrealizedPNL()
|
|
|
|
// Get settled P&L from perp positions
|
|
const perpPositions = userAccount.perpPositions
|
|
let totalSettledPnL = 0
|
|
const positionDetails: any[] = []
|
|
|
|
for (const position of perpPositions) {
|
|
if (position.marketIndex === 0 || position.marketIndex === 1 || position.marketIndex === 2) {
|
|
const marketName = position.marketIndex === 0 ? 'SOL-PERP' :
|
|
position.marketIndex === 1 ? 'BTC-PERP' : 'ETH-PERP'
|
|
|
|
const settledPnL = Number(position.settledPnl) / 1e6
|
|
const baseAssetAmount = Number(position.baseAssetAmount) / 1e9
|
|
|
|
totalSettledPnL += settledPnL
|
|
|
|
positionDetails.push({
|
|
market: marketName,
|
|
currentPosition: baseAssetAmount,
|
|
settledPnL: settledPnL,
|
|
})
|
|
}
|
|
}
|
|
|
|
// Get spot balance (USDC)
|
|
const spotPositions = userAccount.spotPositions
|
|
let usdcBalance = 0
|
|
let cumulativeDeposits = 0
|
|
|
|
for (const spot of spotPositions) {
|
|
if (spot.marketIndex === 0) { // USDC
|
|
usdcBalance = Number(spot.scaledBalance) / 1e9
|
|
cumulativeDeposits = Number(spot.cumulativeDeposits) / 1e6
|
|
}
|
|
}
|
|
|
|
// Query database for comparison
|
|
const prisma = getPrismaClient()
|
|
|
|
const dbStats = await prisma.trade.aggregate({
|
|
where: {
|
|
exitReason: { not: null },
|
|
entryTime: { gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) }
|
|
},
|
|
_sum: { realizedPnL: true },
|
|
_count: true
|
|
})
|
|
|
|
const dbPnL = Number(dbStats._sum.realizedPnL || 0)
|
|
const dbTrades = dbStats._count
|
|
|
|
const discrepancy = totalSettledPnL - dbPnL
|
|
const estimatedFeePerTrade = dbTrades > 0 ? discrepancy / dbTrades : 0
|
|
|
|
return NextResponse.json({
|
|
drift: {
|
|
totalCollateral: Number(equity) / 1e6,
|
|
unrealizedPnL: Number(unrealizedPnL) / 1e6,
|
|
settledPnL: totalSettledPnL,
|
|
usdcBalance,
|
|
cumulativeDeposits,
|
|
positions: positionDetails,
|
|
},
|
|
database: {
|
|
totalTrades: dbTrades,
|
|
totalPnL: dbPnL,
|
|
},
|
|
comparison: {
|
|
discrepancy,
|
|
estimatedFeePerTrade,
|
|
note: 'Discrepancy includes funding rates, trading fees, and any manual trades not tracked by bot',
|
|
}
|
|
})
|
|
|
|
} catch (error) {
|
|
console.error('❌ Error querying Drift:', error)
|
|
return NextResponse.json(
|
|
{ error: error instanceof Error ? error.message : 'Unknown error' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|