Files
mindesbunister 4ab7bf58da feat: Drift state verifier double-checking system (WIP - build issues)
CRITICAL: Position Manager stops monitoring randomly
User had to manually close SOL-PERP position after PM stopped at 23:21.

Implemented double-checking system to detect when positions marked
closed in DB are still open on Drift (and vice versa):

1. DriftStateVerifier service (lib/monitoring/drift-state-verifier.ts)
   - Runs every 10 minutes automatically
   - Checks closed trades (24h) vs actual Drift positions
   - Retries close if mismatch found
   - Sends Telegram alerts

2. Manual verification API (app/api/monitoring/verify-drift-state)
   - POST: Force immediate verification check
   - GET: Service status

3. Integrated into startup (lib/startup/init-position-manager.ts)
   - Auto-starts on container boot
   - First check after 2min, then every 10min

STATUS: Build failing due to TypeScript compilation timeout
Need to fix and deploy, then investigate WHY Position Manager stops.

This addresses symptom (stuck positions) but not root cause (PM stopping).
2025-12-07 02:28:10 +01:00

98 lines
2.8 KiB
TypeScript

/**
* Force Drift State Check API Endpoint
*
* Manually trigger Drift state verification and retry closing
* any positions that should be closed but aren't.
*
* POST /api/monitoring/verify-drift-state
* Authorization: Bearer <API_SECRET_KEY>
*/
import { NextRequest, NextResponse } from 'next/server'
import { getDriftStateVerifier } from '@/lib/monitoring/drift-state-verifier'
export async function POST(request: NextRequest) {
try {
// Verify authorization
const authHeader = request.headers.get('authorization')
const expectedAuth = `Bearer ${process.env.API_SECRET_KEY}`
if (!authHeader || authHeader !== expectedAuth) {
return NextResponse.json(
{ success: false, error: 'Unauthorized' },
{ status: 401 }
)
}
console.log('🔍 Manual Drift state verification requested...')
const verifier = getDriftStateVerifier()
const mismatches = await verifier.runVerification()
return NextResponse.json({
success: true,
timestamp: new Date().toISOString(),
mismatchesFound: mismatches.length,
mismatches: mismatches.map(m => ({
tradeId: m.tradeId,
symbol: m.symbol,
expectedState: m.expectedState,
actualState: m.actualState,
driftSize: m.driftSize,
dbExitReason: m.dbExitReason,
timeSinceExit: m.timeSinceExit,
})),
message: mismatches.length === 0
? 'All positions match between database and Drift'
: `Found ${mismatches.length} mismatches - retry close attempted for critical cases`
})
} catch (error) {
console.error('❌ Error in Drift state verification:', error)
return NextResponse.json(
{
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
},
{ status: 500 }
)
}
}
/**
* Get current verification service status
* GET /api/monitoring/verify-drift-state
*/
export async function GET(request: NextRequest) {
try {
const authHeader = request.headers.get('authorization')
const expectedAuth = `Bearer ${process.env.API_SECRET_KEY}`
if (!authHeader || authHeader !== expectedAuth) {
return NextResponse.json(
{ success: false, error: 'Unauthorized' },
{ status: 401 }
)
}
return NextResponse.json({
success: true,
service: 'Drift State Verifier',
status: 'running',
checkInterval: '10 minutes',
description: 'Automatically verifies closed positions are actually closed on Drift. Retries close if mismatches found.',
endpoints: {
manualCheck: 'POST /api/monitoring/verify-drift-state',
status: 'GET /api/monitoring/verify-drift-state'
}
})
} catch (error) {
return NextResponse.json(
{ success: false, error: 'Internal error' },
{ status: 500 }
)
}
}