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:
97
app/api/monitoring/verify-drift-state/route.ts
Normal file
97
app/api/monitoring/verify-drift-state/route.ts
Normal 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 }
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user