diff --git a/app/api/drift/account-state/route.ts b/app/api/drift/account-state/route.ts deleted file mode 100644 index 66b5fde..0000000 --- a/app/api/drift/account-state/route.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { NextResponse } from 'next/server' -import { getDriftService } from '@/lib/drift/client' - -export async function GET() { - try { - const driftService = getDriftService() - - // Get account health and equity - const health = await driftService.getAccountHealth() - const equity = await driftService.getAccountEquity() - - // Get all positions - const solPosition = await driftService.getPosition(0) // SOL-PERP - const ethPosition = await driftService.getPosition(1) // ETH-PERP - const btcPosition = await driftService.getPosition(2) // BTC-PERP - - const positions = [] - if (solPosition && Math.abs(solPosition.size) > 0.01) { - positions.push({ - market: 'SOL-PERP', - direction: solPosition.side, - size: solPosition.size, - entryPrice: solPosition.entryPrice, - unrealizedPnL: solPosition.unrealizedPnL - }) - } - if (ethPosition && Math.abs(ethPosition.size) > 0.01) { - positions.push({ - market: 'ETH-PERP', - direction: ethPosition.side, - size: ethPosition.size, - entryPrice: ethPosition.entryPrice, - unrealizedPnL: ethPosition.unrealizedPnL - }) - } - if (btcPosition && Math.abs(btcPosition.size) > 0.01) { - positions.push({ - market: 'BTC-PERP', - direction: btcPosition.side, - size: btcPosition.size, - entryPrice: btcPosition.entryPrice, - unrealizedPnL: btcPosition.unrealizedPnL - }) - } - - return NextResponse.json({ - success: true, - accountHealth: health, - equity: equity, - positions: positions, - timestamp: new Date().toISOString() - }) - } catch (error: any) { - console.error('Error getting account state:', error) - return NextResponse.json({ - success: false, - error: error.message - }, { status: 500 }) - } -} diff --git a/app/api/trading/execute/route.ts b/app/api/trading/execute/route.ts index 56105ce..b06b8dd 100644 --- a/app/api/trading/execute/route.ts +++ b/app/api/trading/execute/route.ts @@ -253,41 +253,83 @@ export async function POST(request: NextRequest): Promise setTimeout(resolve, checkInterval)) + waitTime += checkInterval - await updateTradeExit({ - positionId: oppositePosition.positionId, - exitPrice: closeResult.closePrice!, - exitReason: 'manual', // Manually closed for flip - realizedPnL: realizedPnL, - exitOrderTx: closeResult.transactionSignature || 'FLIP_CLOSE', - holdTimeSeconds, - maxDrawdown: Math.abs(Math.min(0, oppositePosition.maxAdverseExcursion)), - maxGain: Math.max(0, oppositePosition.maxFavorableExcursion), - maxFavorableExcursion: oppositePosition.maxFavorableExcursion, - maxAdverseExcursion: oppositePosition.maxAdverseExcursion, - maxFavorablePrice: oppositePosition.maxFavorablePrice, - maxAdversePrice: oppositePosition.maxAdversePrice, - }) - console.log(`💾 Saved opposite position closure to database`) - } catch (dbError) { - console.error('❌ Failed to save opposite position closure:', dbError) + const position = await driftService.getPosition((await import('@/config/trading')).getMarketConfig(driftSymbol).driftMarketIndex) + if (!position || Math.abs(position.size) < 0.01) { + console.log(`✅ Position confirmed closed on Drift after ${waitTime/1000}s`) + break + } + console.log(`⏳ Still waiting for Drift closure (${waitTime/1000}s elapsed)...`) + } + + if (waitTime >= maxWait) { + console.error(`❌ CRITICAL: Position still on Drift after ${maxWait/1000}s!`) + return NextResponse.json( + { + success: false, + error: 'Flip failed - position did not close', + message: `Close transaction confirmed but position still exists on Drift after ${maxWait/1000}s. Not opening new position to avoid hedge.`, + }, + { status: 500 } + ) } } - // Small delay to ensure position is fully closed on-chain - await new Promise(resolve => setTimeout(resolve, 2000)) + // Save the closure to database + try { + const holdTimeSeconds = Math.floor((Date.now() - oppositePosition.entryTime) / 1000) + const priceProfitPercent = oppositePosition.direction === 'long' + ? ((closeResult.closePrice! - oppositePosition.entryPrice) / oppositePosition.entryPrice) * 100 + : ((oppositePosition.entryPrice - closeResult.closePrice!) / oppositePosition.entryPrice) * 100 + const realizedPnL = closeResult.realizedPnL ?? (oppositePosition.currentSize * priceProfitPercent) / 100 + + await updateTradeExit({ + positionId: oppositePosition.positionId, + exitPrice: closeResult.closePrice!, + exitReason: 'manual', // Manually closed for flip + realizedPnL: realizedPnL, + exitOrderTx: closeResult.transactionSignature || 'FLIP_CLOSE', + holdTimeSeconds, + maxDrawdown: Math.abs(Math.min(0, oppositePosition.maxAdverseExcursion)), + maxGain: Math.max(0, oppositePosition.maxFavorableExcursion), + maxFavorableExcursion: oppositePosition.maxFavorableExcursion, + maxAdverseExcursion: oppositePosition.maxAdverseExcursion, + maxFavorablePrice: oppositePosition.maxFavorablePrice, + maxAdversePrice: oppositePosition.maxAdversePrice, + }) + console.log(`💾 Saved opposite position closure to database`) + } catch (dbError) { + console.error('❌ Failed to save opposite position closure:', dbError) + } + + console.log(`✅ Flip sequence complete - ready to open ${body.direction} position`) } // Calculate position size with leverage