diff --git a/lib/drift/orders.ts b/lib/drift/orders.ts index 39c1315..55a0347 100644 --- a/lib/drift/orders.ts +++ b/lib/drift/orders.ts @@ -628,13 +628,44 @@ export async function closePosition( console.log(` Closed notional: $${closedNotional.toFixed(2)}`) console.log(` Realized P&L: $${realizedPnL.toFixed(2)}`) - // If closing 100%, cancel all remaining orders for this market + // If closing 100%, verify position actually closed and cancel remaining orders if (params.percentToClose === 100) { console.log('🗑️ Position fully closed, cancelling remaining orders...') const cancelResult = await cancelAllOrders(params.symbol) if (cancelResult.success && cancelResult.cancelledCount! > 0) { console.log(`✅ Cancelled ${cancelResult.cancelledCount} orders`) } + + // CRITICAL: Verify position actually closed on Drift (Nov 16, 2025) + // Transaction confirmed ≠ Drift state updated immediately + // Wait 5 seconds for Drift internal state to propagate + console.log('⏳ Waiting 5s for Drift state to propagate...') + await new Promise(resolve => setTimeout(resolve, 5000)) + + try { + const verifyPosition = await driftService.getPosition(marketConfig.driftMarketIndex) + if (verifyPosition && Math.abs(verifyPosition.size) >= 0.01) { + console.error(`🔴 CRITICAL: Close transaction confirmed BUT position still exists on Drift!`) + console.error(` Transaction: ${txSig}`) + console.error(` Drift size: ${verifyPosition.size}`) + console.error(` This indicates Drift state propagation delay or partial fill`) + console.error(` Position Manager will continue monitoring until Drift confirms closure`) + // Return success but flag that monitoring should continue + return { + success: true, + transactionSignature: txSig, + closePrice: oraclePrice, + closedSize: sizeToClose, + realizedPnL, + needsVerification: true, // Flag for Position Manager + } + } else { + console.log('✅ Position verified closed on Drift') + } + } catch (verifyError) { + console.warn('⚠️ Could not verify position closure:', verifyError) + // Continue anyway - transaction was confirmed + } } return { diff --git a/lib/trading/position-manager.ts b/lib/trading/position-manager.ts index 8b920fe..47f4f4b 100644 --- a/lib/trading/position-manager.ts +++ b/lib/trading/position-manager.ts @@ -1202,6 +1202,17 @@ export class PositionManager { console.error(`❌ Failed to close ${trade.symbol}:`, errorMsg) return } + + // CRITICAL: Check if position needs verification (Nov 16, 2025) + // If close transaction confirmed but Drift still shows position open, + // DON'T mark as closed yet - keep monitoring until Drift confirms + if ((result as any).needsVerification) { + console.log(`⚠️ Close transaction confirmed but position still exists on Drift`) + console.log(` Keeping ${trade.symbol} in monitoring until Drift confirms closure`) + console.log(` Ghost detection will handle final cleanup once Drift updates`) + // Keep monitoring - ghost detection will eventually see it's closed + return + } // Update trade state if (percentToClose >= 100) {