critical: Bug #82 EMERGENCY FIX - Disable Drift State Verifier automatic close

Problem: Verifier can't distinguish OLD positions from NEW positions at same symbol
- User opened manual trade with SL working
- Verifier detected 6 old closed DB records (150-1064 min ago)
- All showed "15.45 tokens open on Drift" (user's CURRENT trade!)
- Automatic retry close removed user's SL orders

Root Cause: Lines 279-283 call closePosition() for every mismatch
- No verification if Drift position is OLD (should close) or NEW (active trade)
- No position ID/timestamp matching
- Result: Closes ACTIVE trades when cleaning up old database records

Solution: DISABLED automatic retry close (lines 276-298)
- Added BUG #82 warning logs
- Requires manual intervention if true orphan detected
- Will add proper position verification in follow-up fix

Impact: Stops SL removal on active trades
User incident: After Bug #81 fix deployed, THIS bug was killing SLs
Deployment: Dec 10, 2025 11:06 CET
This commit is contained in:
mindesbunister
2025-12-10 11:05:53 +01:00
parent 43bf97d48b
commit e5714e4376

View File

@@ -277,36 +277,51 @@ class DriftStateVerifier {
const attemptTime = Date.now()
this.recentCloseAttempts.set(mismatch.symbol, attemptTime)
const result = await closePosition({
symbol: mismatch.symbol,
percentToClose: 100,
slippageTolerance: 0.05 // 5% slippage tolerance for market order
})
if (result.success) {
console.log(` ✅ Close transaction confirmed: ${result.transactionSignature}`)
console.log(` P&L: $${result.realizedPnL?.toFixed(2) || 0}`)
console.log(` ⏳ Drift API may take up to 5 minutes to reflect closure`)
// Update database with retry close timestamp to prevent loop
await prisma.trade.update({
where: { id: mismatch.tradeId },
data: {
exitOrderTx: result.transactionSignature || 'RETRY_CLOSE',
realizedPnL: result.realizedPnL || 0,
configSnapshot: {
...trade?.configSnapshot as any,
retryCloseAttempted: true,
retryCloseTime: new Date(attemptTime).toISOString(),
}
}
})
console.log(` 📝 Cooldown recorded: ${mismatch.symbol}${new Date(attemptTime).toISOString()}`)
} else {
console.error(` ❌ Failed to close ${mismatch.symbol}: ${result.error}`)
// Keep cooldown even on failure to prevent spam
}
// BUG #82 FIX (Dec 10, 2025): DISABLE automatic retry close
// Problem: Can't distinguish OLD position (should close) from NEW position at same symbol (should NOT touch)
// Result: Closes ACTIVE trades when trying to clean up old database records
// User incident: 6 old closed trades (150-1064 min ago) all showed "15.45 tokens" on Drift
// That was user's CURRENT manual trade, not 6 old ghosts
// Automatic close removed user's SL orders
// Solution: DISABLE automatic close until we add proper position ID/timestamp verification
console.warn(`⚠️ BUG #82 SAFETY: Automatic retry close DISABLED`)
console.warn(` Would have closed ${mismatch.symbol} with 15.45 tokens`)
console.warn(` But can't verify if it's OLD position or NEW active trade`)
console.warn(` Manual intervention required if true orphan detected`)
return
// ORIGINAL CODE (DISABLED):
// const result = await closePosition({
// symbol: mismatch.symbol,
// percentToClose: 100,
// slippageTolerance: 0.05 // 5% slippage tolerance for market order
// })
//
// if (result.success) {
// console.log(` ✅ Close transaction confirmed: ${result.transactionSignature}`)
// console.log(` P&L: $${result.realizedPnL?.toFixed(2) || 0}`)
// console.log(` ⏳ Drift API may take up to 5 minutes to reflect closure`)
//
// // Update database with retry close timestamp to prevent loop
// await prisma.trade.update({
// where: { id: mismatch.tradeId },
// data: {
// exitOrderTx: result.transactionSignature || 'RETRY_CLOSE',
// realizedPnL: result.realizedPnL || 0,
// configSnapshot: {
// ...trade?.configSnapshot as any,
// retryCloseAttempted: true,
// retryCloseTime: new Date(attemptTime).toISOString(),
// }
// }
// })
//
// console.log(` 📝 Cooldown recorded: ${mismatch.symbol} → ${new Date(attemptTime).toISOString()}`)
// } else {
// console.error(` ❌ Failed to close ${mismatch.symbol}: ${result.error}`)
// // Keep cooldown even on failure to prevent spam
// }
} catch (error) {
console.error(` ❌ Error retrying close for ${mismatch.symbol}:`, error)
// On error, still record attempt time to prevent rapid retries