From 2a7f9ce9e969d3b7e27f4f66d53974e085467bc4 Mon Sep 17 00:00:00 2001 From: mindesbunister Date: Tue, 9 Dec 2025 20:53:32 +0100 Subject: [PATCH] fix: Database sync for emergency order placement CRITICAL FIX (Dec 9, 2025): Emergency place-exit-orders endpoint now updates database with on-chain order transaction signatures. Problem: - Emergency endpoint placed orders on-chain successfully - But database Trade record showed NULL for order tx fields - Monitoring tools showed false negatives (NULL when orders exist) - User frustrated: 'our database HAS TO reflect whats on chain' Root Cause: - place-exit-orders endpoint called placeExitOrders() directly - Successfully placed orders and returned signatures - But never updated database Trade table with returned tx IDs - Database out of sync with actual on-chain state Solution: - After successful order placement, query database for active trade - Update Trade.tp1OrderTx, tp2OrderTx, slOrderTx with returned signatures - Handle both single SL and dual stop configurations - Log each signature update for verification - Don't fail request if database update fails (orders already on-chain) Impact: - Database now accurately reflects on-chain order state - Monitoring tools (health checks, queries) show correct status - User can trust database as source of truth - Resolves disconnect between user's Drift UI observations and database Testing: - Called endpoint with SOL-PERP position parameters - Received 2 signatures (TP1, TP2) - Bug #76 still present - Database updated: tp1OrderTx and tp2OrderTx now populated - Logs confirm: 'Database updated with on-chain order signatures' Note: Bug #76 (SL order fails silently) still exists but database now accurately reflects whatever orders succeed. Files changed: - app/api/trading/place-exit-orders/route.ts (added database update logic) --- app/api/trading/place-exit-orders/route.ts | 63 +++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/app/api/trading/place-exit-orders/route.ts b/app/api/trading/place-exit-orders/route.ts index 72af36c..7b92ba3 100644 --- a/app/api/trading/place-exit-orders/route.ts +++ b/app/api/trading/place-exit-orders/route.ts @@ -61,10 +61,71 @@ export async function POST(req: NextRequest) { if (result.success) { console.log('✅ Exit orders placed successfully!') + console.log(` Signatures: ${result.signatures?.length || 0} orders placed`) + + // CRITICAL FIX (Dec 9, 2025): Update database with on-chain order signatures + // Without this, database shows NULL even when orders exist on Drift + try { + const { getPrismaClient } = await import('@/lib/database/trades') + const prisma = getPrismaClient() + + // Find the active trade for this symbol + const trade = await prisma.trade.findFirst({ + where: { + symbol, + exitReason: null, // Still open + }, + orderBy: { + createdAt: 'desc', + }, + }) + + if (trade) { + console.log(`💾 Updating database Trade ${trade.id} with order signatures...`) + + // Update with all returned signatures + // placeExitOrders returns: [tp1Sig, tp2Sig, slSig] or [tp1Sig, tp2Sig, softSlSig, hardSlSig] + const updateData: any = {} + + if (result.signatures && result.signatures.length >= 2) { + updateData.tp1OrderTx = result.signatures[0] + updateData.tp2OrderTx = result.signatures[1] + console.log(` TP1 tx: ${result.signatures[0].substring(0, 8)}...`) + console.log(` TP2 tx: ${result.signatures[1].substring(0, 8)}...`) + } + + if (result.signatures && result.signatures.length >= 3) { + updateData.slOrderTx = result.signatures[2] + console.log(` SL tx: ${result.signatures[2].substring(0, 8)}...`) + } + + if (result.signatures && result.signatures.length >= 4) { + // Dual stops: soft (index 2) and hard (index 3) + updateData.softStopOrderTx = result.signatures[2] + updateData.hardStopOrderTx = result.signatures[3] + updateData.slOrderTx = null // Clear single SL when dual stops used + console.log(` Soft SL tx: ${result.signatures[2].substring(0, 8)}...`) + console.log(` Hard SL tx: ${result.signatures[3].substring(0, 8)}...`) + } + + await prisma.trade.update({ + where: { id: trade.id }, + data: updateData, + }) + + console.log('✅ Database updated with on-chain order signatures') + } else { + console.warn('⚠️ No active trade found for symbol, skipping database update') + } + } catch (dbError) { + console.error('❌ Failed to update database with order signatures:', dbError) + // Don't fail the request - orders are already placed on-chain + } + return NextResponse.json({ success: true, signatures: result.signatures, - message: 'Exit orders placed on-chain' + message: 'Exit orders placed on-chain and database updated' }) } else { console.error('❌ Failed to place exit orders:', result.error)