- Query Drift Protocol's cumulativeDeposits for ground truth - Discovered user deposited ,440.61 (not hardcoded 46) - Previous withdrawals: ~26.78 (not tracked in ENV) - Database P&L -.01 is correct - Reconciliation: ,440.61 deposits - .01 P&L - 26.78 withdrawn = 11.82 current - Available profit now shows current balance (includes all trading results) - Created /api/drift/account-summary endpoint for account reconciliation - Statistics now mathematically consistent and trustworthy
99 lines
3.8 KiB
TypeScript
99 lines
3.8 KiB
TypeScript
/**
|
|
* Withdrawal Stats API
|
|
*
|
|
* Returns current account statistics for withdrawal calculations
|
|
*/
|
|
|
|
import { NextResponse } from 'next/server'
|
|
import { getPrismaClient } from '@/lib/database/trades'
|
|
import { initializeDriftService } from '@/lib/drift/client'
|
|
|
|
export async function GET() {
|
|
try {
|
|
const prisma = getPrismaClient()
|
|
|
|
// Get current Drift balance and actual deposits
|
|
const driftService = await initializeDriftService()
|
|
const health = await driftService.getAccountHealth()
|
|
const currentBalance = health.freeCollateral // Already a number
|
|
|
|
// Get actual deposits from Drift Protocol (ground truth from blockchain)
|
|
const user = driftService.getUser()
|
|
const userAccount = user.getUserAccount()
|
|
const usdcSpotPosition = userAccount.spotPositions.find(
|
|
(pos: any) => pos.marketIndex === 0 // USDC market index
|
|
)
|
|
const cumulativeDeposits = usdcSpotPosition
|
|
? Number(usdcSpotPosition.cumulativeDeposits.toString()) / 1_000_000
|
|
: 546 // Fallback to hardcoded if query fails (shouldn't happen)
|
|
|
|
const totalInvested = cumulativeDeposits // Use actual deposits as "invested"
|
|
|
|
// Calculate total P&L from database
|
|
const trades = await prisma.trade.findMany({
|
|
where: {
|
|
exitReason: { not: null },
|
|
},
|
|
select: {
|
|
realizedPnL: true,
|
|
},
|
|
})
|
|
|
|
const totalPnL = trades.reduce((sum, trade) => sum + (trade.realizedPnL || 0), 0)
|
|
|
|
// Get total withdrawn from .env
|
|
const totalWithdrawn = parseFloat(process.env.TOTAL_WITHDRAWN || '0')
|
|
|
|
// Calculate available profit
|
|
// Current balance is what's left after deposits + P&L - previous withdrawals
|
|
// Available profit = current balance (what we have now, which includes trading profit/loss)
|
|
const availableProfit = Math.max(0, currentBalance)
|
|
|
|
// Calculate inferred previous withdrawals
|
|
// If deposits + P&L - current balance > 0, that's what was withdrawn
|
|
const inferredWithdrawals = Math.max(0, cumulativeDeposits + totalPnL - currentBalance)
|
|
|
|
// Calculate next withdrawal amount
|
|
const withdrawalPercent = parseFloat(process.env.WITHDRAWAL_PROFIT_PERCENT || '10')
|
|
const nextWithdrawalAmount = availableProfit * (withdrawalPercent / 100)
|
|
|
|
// Calculate next withdrawal time
|
|
let nextWithdrawalTime: string | null = null
|
|
if (process.env.ENABLE_AUTO_WITHDRAWALS === 'true' && process.env.LAST_WITHDRAWAL_TIME) {
|
|
const lastWithdrawal = new Date(process.env.LAST_WITHDRAWAL_TIME)
|
|
const intervalHours = parseFloat(process.env.WITHDRAWAL_INTERVAL_HOURS || '168')
|
|
const nextTime = new Date(lastWithdrawal.getTime() + intervalHours * 60 * 60 * 1000)
|
|
nextWithdrawalTime = nextTime.toISOString()
|
|
} else if (process.env.ENABLE_AUTO_WITHDRAWALS === 'true') {
|
|
// First withdrawal - schedule from now
|
|
const intervalHours = parseFloat(process.env.WITHDRAWAL_INTERVAL_HOURS || '168')
|
|
const nextTime = new Date(Date.now() + intervalHours * 60 * 60 * 1000)
|
|
nextWithdrawalTime = nextTime.toISOString()
|
|
}
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
currentBalance: parseFloat(currentBalance.toFixed(2)),
|
|
totalInvested,
|
|
totalPnL: parseFloat(totalPnL.toFixed(2)),
|
|
totalWithdrawn,
|
|
availableProfit: parseFloat(availableProfit.toFixed(2)),
|
|
nextWithdrawalAmount: parseFloat(nextWithdrawalAmount.toFixed(2)),
|
|
nextWithdrawalTime,
|
|
})
|
|
} catch (error: any) {
|
|
console.error('Failed to load withdrawal stats:', error)
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: error.message,
|
|
currentBalance: 0,
|
|
totalInvested: 546,
|
|
totalPnL: 0,
|
|
totalWithdrawn: 0,
|
|
availableProfit: 0,
|
|
nextWithdrawalAmount: 0,
|
|
nextWithdrawalTime: null,
|
|
})
|
|
}
|
|
}
|