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).
This commit is contained in:
mindesbunister
2025-12-07 02:28:10 +01:00
parent a669058636
commit 4ab7bf58da
3 changed files with 421 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
/**
* 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 }
)
}
}