Implement working Drift leverage trading

Key Features:
-  Drift SDK v2.126.0-beta.14 integration with Helius RPC
-  User account initialization and balance reading
-  Leverage trading API with real trades executed
-  Support for SOL, BTC, ETH, APT, AVAX, BNB, MATIC, ARB, DOGE, OP
-  Transaction confirmed: gNmaWVqcE4qNK31ksoUsK6pcHqdDTaUtJXY52ZoXRF

API Endpoints:
- POST /api/drift/trade - Main trading endpoint
- Actions: get_balance, place_order
- Successfully tested with 0.01 SOL buy order at 2x leverage

Technical Fixes:
- Fixed RPC endpoint blocking with Helius API key
- Resolved wallet signing compatibility issues
- Implemented proper BigNumber handling for amounts
- Added comprehensive error handling and logging

Trading Bot Status: 🚀 FULLY OPERATIONAL with leverage trading!
This commit is contained in:
mindesbunister
2025-07-22 12:23:51 +02:00
parent 491ff51ba9
commit fb194f1b12
28 changed files with 7285 additions and 198 deletions

View File

@@ -9,7 +9,6 @@ class AggressiveCleanup {
private cleanupInterval: NodeJS.Timeout | null = null
private isRunning = false
private isInitialized = false
private lastApiCallTime = Date.now()
private constructor() {
// Don't auto-start - let startup.ts control it
@@ -31,11 +30,10 @@ class AggressiveCleanup {
this.isInitialized = true
console.log('🚀 Starting aggressive cleanup system')
// In development, completely disable automatic cleanup to prevent interference
// In development, use on-demand cleanup instead of periodic
if (process.env.NODE_ENV === 'development') {
console.log('🔧 Development mode: Automatic cleanup DISABLED to prevent analysis interference')
console.log('💡 Use manual cleanup via runPostAnalysisCleanup() or forceCleanup() when needed')
console.log('✅ Manual cleanup system ready')
console.log('🔧 Development mode: Using on-demand cleanup (triggered after analysis)')
console.log('✅ On-demand cleanup system ready')
return
}
@@ -57,7 +55,16 @@ class AggressiveCleanup {
}
async cleanupOrphanedProcesses(): Promise<void> {
if (this.isRunning) return
if (this.isRunning) {
console.log('🔒 Cleanup already in progress, skipping...')
return
}
// Check if auto cleanup is disabled (for development)
if (process.env.DISABLE_AUTO_CLEANUP === 'true') {
console.log('🚫 Auto cleanup disabled via DISABLE_AUTO_CLEANUP environment variable')
return
}
this.isRunning = true
const isDevelopment = process.env.NODE_ENV === 'development'
@@ -66,62 +73,69 @@ class AggressiveCleanup {
console.log(`🧹 Running ${cleanupType} cleanup for orphaned processes...`)
try {
// Multiple checks for active analysis sessions
let hasActiveSessions = false
// Check 1: Progress tracker
// Check for active analysis sessions
try {
const { progressTracker } = await import('./progress-tracker')
const activeSessions = progressTracker.getActiveSessions()
if (activeSessions.length > 0) {
console.log(`⚠️ Found ${activeSessions.length} active progress sessions: ${activeSessions.join(', ')}`)
hasActiveSessions = true
console.log(`⚠️ Skipping cleanup - ${activeSessions.length} active analysis sessions detected:`)
activeSessions.forEach(session => {
const progress = progressTracker.getProgress(session)
if (progress) {
const activeStep = progress.steps.find(step => step.status === 'active')
const currentStep = activeStep ? activeStep.title : 'Unknown'
console.log(` - ${session}: ${currentStep} (Step ${progress.currentStep}/${progress.totalSteps})`)
} else {
console.log(` - ${session}: Session info not available`)
}
})
console.log(' Will retry cleanup after analysis completes')
return
}
console.log('✅ No active analysis sessions detected, proceeding with cleanup')
} catch (importError) {
console.log('⚠️ Could not check progress tracker, being conservative')
hasActiveSessions = true // Be conservative if we can't check
}
// Check 2: Recent browser activity (processes less than 2 minutes old)
const chromiumProcesses = await this.findChromiumProcesses()
if (chromiumProcesses.length > 0) {
const recentProcesses = await this.checkProcessAge(chromiumProcesses)
if (recentProcesses.length > 0) {
console.log(`⚠️ Found ${recentProcesses.length} recent browser processes (< 2 min old)`)
hasActiveSessions = true
console.warn('⚠️ Could not check active sessions, proceeding cautiously with cleanup')
console.warn('Import error:', importError)
// In case of import errors, be extra cautious - only clean very old processes
if (isDevelopment) {
console.log('🔧 Development mode with import issues - using aggressive cleanup to clear stuck processes')
// In development, if we can't check sessions, assume they're stuck and clean aggressively
}
}
// Check 3: In development, be extra conservative - only cleanup if no recent API calls
if (isDevelopment) {
const lastApiCall = this.getLastApiCallTime()
const timeSinceLastApi = Date.now() - lastApiCall
if (timeSinceLastApi < 30000) { // 30 seconds
console.log(`⚠️ Recent API activity detected (${Math.round(timeSinceLastApi/1000)}s ago), skipping cleanup`)
hasActiveSessions = true
}
}
if (hasActiveSessions) {
console.log(`⚠️ Skipping cleanup - active analysis detected`)
return
}
console.log('✅ No active analysis sessions detected, proceeding with cleanup')
// Find and kill orphaned chromium processes
const chromiumProcesses = await this.findChromiumProcesses()
if (chromiumProcesses.length > 0) {
console.log(`Found ${chromiumProcesses.length} chromium processes, cleaning up...`)
console.log(`🔍 Found ${chromiumProcesses.length} chromium processes, evaluating for cleanup...`)
for (const pid of chromiumProcesses) {
// In development, be more selective about which processes to kill
let processesToKill = chromiumProcesses
if (isDevelopment) {
// Only kill processes that are likely orphaned (older than 5 minutes)
const oldProcesses = await this.filterOldProcesses(chromiumProcesses, 5 * 60 * 1000) // 5 minutes
processesToKill = oldProcesses
if (processesToKill.length === 0) {
console.log('✅ All chromium processes appear to be recent and potentially active - skipping cleanup')
return
}
console.log(`🔧 Development mode: Cleaning only ${processesToKill.length} old processes (older than 5 minutes)`)
}
for (const pid of processesToKill) {
try {
if (isDevelopment) {
// In development, use gentler SIGTERM first
console.log(`🔧 Dev mode: Gentle shutdown of process ${pid}`)
await execAsync(`kill -TERM ${pid}`)
// Give process 5 seconds to shut down gracefully (increased from 3)
await new Promise(resolve => setTimeout(resolve, 5000))
// Give process 3 seconds to shut down gracefully
await new Promise(resolve => setTimeout(resolve, 3000))
// Check if process is still running
try {
@@ -167,6 +181,7 @@ class AggressiveCleanup {
console.error(`Error in ${cleanupType} cleanup:`, error)
} finally {
this.isRunning = false
console.log(`🏁 ${cleanupType} cleanup completed`)
}
}
@@ -179,31 +194,41 @@ class AggressiveCleanup {
}
}
private async checkProcessAge(pids: string[]): Promise<string[]> {
const recentProcesses: string[] = []
const twoMinutesAgo = Date.now() - (2 * 60 * 1000)
private async filterOldProcesses(pids: string[], maxAgeMs: number): Promise<string[]> {
const oldProcesses: string[] = []
for (const pid of pids) {
try {
const { stdout } = await execAsync(`ps -o lstart= -p ${pid}`)
const startTime = new Date(stdout.trim()).getTime()
if (startTime > twoMinutesAgo) {
recentProcesses.push(pid)
// Get process start time
const { stdout } = await execAsync(`ps -o pid,lstart -p ${pid} | tail -1`)
const processInfo = stdout.trim()
if (processInfo) {
// Parse the process start time
const parts = processInfo.split(/\s+/)
if (parts.length >= 6) {
// Format: PID Mon DD HH:MM:SS YYYY
const startTimeStr = parts.slice(1).join(' ')
const startTime = new Date(startTimeStr)
const now = new Date()
const processAge = now.getTime() - startTime.getTime()
if (processAge > maxAgeMs) {
console.log(`🕐 Process ${pid} is ${Math.round(processAge / 60000)} minutes old - marked for cleanup`)
oldProcesses.push(pid)
} else {
console.log(`🕐 Process ${pid} is ${Math.round(processAge / 60000)} minutes old - keeping alive`)
}
}
}
} catch (error) {
// Process might not exist anymore, skip
// If we can't get process info, assume it's old and safe to clean
console.log(`❓ Could not get age info for process ${pid} - assuming it's old`)
oldProcesses.push(pid)
}
}
return recentProcesses
}
private getLastApiCallTime(): number {
return this.lastApiCallTime
}
updateApiCallTime(): void {
this.lastApiCallTime = Date.now()
return oldProcesses
}
async forceCleanup(): Promise<void> {
@@ -227,22 +252,236 @@ class AggressiveCleanup {
}
}
// New method for on-demand cleanup after analysis
// New method for on-demand cleanup after complete automation cycle
async runPostAnalysisCleanup(): Promise<void> {
const isDevelopment = process.env.NODE_ENV === 'development'
if (isDevelopment) {
console.log('🔧 Development mode: Skipping post-analysis cleanup to prevent interference')
console.log('💡 Manual cleanup available via forceCleanup() if needed')
// Check if auto cleanup is disabled (for development)
if (process.env.DISABLE_AUTO_CLEANUP === 'true') {
console.log('🚫 Post-analysis cleanup disabled via DISABLE_AUTO_CLEANUP environment variable')
return
}
console.log('🧹 Post-analysis cleanup triggered...')
console.log('🧹 Post-cycle cleanup triggered (analysis + decision complete)...')
// Small delay to ensure analysis processes are fully closed
await new Promise(resolve => setTimeout(resolve, 2000))
// Wait for all browser processes to fully close
console.log('⏳ Waiting 3 seconds for all processes to close gracefully...')
await new Promise(resolve => setTimeout(resolve, 3000))
await this.cleanupOrphanedProcesses()
// Always run cleanup after complete automation cycle - don't check for active sessions
// since the analysis is complete and we need to ensure all processes are cleaned up
console.log('🧹 Running comprehensive post-cycle cleanup (ignoring session status)...')
try {
// Find all chromium processes
const chromiumProcesses = await this.findChromiumProcesses()
if (chromiumProcesses.length === 0) {
console.log('✅ No chromium processes found to clean up')
return
}
console.log(`🔍 Found ${chromiumProcesses.length} chromium processes for post-analysis cleanup`)
// In post-analysis cleanup, we're more aggressive since analysis is complete
// Try graceful shutdown first
for (const pid of chromiumProcesses) {
try {
console.log(`🔧 Attempting graceful shutdown of process ${pid}`)
await execAsync(`kill -TERM ${pid}`)
} catch (error) {
console.log(` Process ${pid} may already be terminated`)
}
}
// Wait for graceful shutdown
await new Promise(resolve => setTimeout(resolve, 5000))
// Check which processes are still running and force kill them
const stillRunning = await this.findStillRunningProcesses(chromiumProcesses)
if (stillRunning.length > 0) {
console.log(`🗡️ Force killing ${stillRunning.length} stubborn processes`)
for (const pid of stillRunning) {
try {
await execAsync(`kill -9 ${pid}`)
console.log(`💀 Force killed process ${pid}`)
} catch (error) {
console.log(` Process ${pid} already terminated`)
}
}
} else {
console.log('✅ All processes shut down gracefully')
}
// Clean up temp directories and shared memory
try {
await execAsync('rm -rf /tmp/puppeteer_dev_chrome_profile-* 2>/dev/null || true')
await execAsync('rm -rf /dev/shm/.org.chromium.* 2>/dev/null || true')
await execAsync('rm -rf /tmp/.org.chromium.* 2>/dev/null || true')
console.log('✅ Cleaned up temporary files and shared memory')
} catch (error) {
console.error('Warning: Could not clean up temporary files:', error)
}
console.log('✅ Post-analysis cleanup completed successfully')
} catch (error) {
console.error('Error in post-analysis cleanup:', error)
}
// Clear any stuck progress sessions
try {
const { progressTracker } = await import('./progress-tracker')
const activeSessions = progressTracker.getActiveSessions()
if (activeSessions.length > 0) {
console.log(`🧹 Force clearing ${activeSessions.length} potentially stuck sessions`)
activeSessions.forEach(session => {
console.log(`🧹 Force clearing session: ${session}`)
progressTracker.deleteSession(session)
})
}
} catch (error) {
console.warn('Could not clear progress sessions:', error)
}
}
// Signal that an analysis cycle is complete and all processes should be cleaned up
async signalAnalysisCycleComplete(): Promise<void> {
console.log('🎯 Analysis cycle completion signal received')
// Wait for graceful shutdown of analysis-related processes
console.log('⏳ Waiting 5 seconds for graceful process shutdown...')
await new Promise(resolve => setTimeout(resolve, 5000))
// Check if there are any active progress sessions first
const activeSessions = await this.checkActiveAnalysisSessions()
if (activeSessions > 0) {
console.log(`⚠️ Found ${activeSessions} active analysis sessions, skipping aggressive cleanup`)
return
}
// Only run cleanup if no active sessions
console.log('🧹 No active sessions detected, running post-analysis cleanup...')
await this.cleanupPostAnalysisProcesses()
}
private async checkActiveAnalysisSessions(): Promise<number> {
// Check if progress tracker has any active sessions
try {
// This is a simple check - in a real scenario you might want to check actual session state
const { stdout } = await execAsync('pgrep -f "automation-.*-.*" | wc -l')
return parseInt(stdout.trim()) || 0
} catch (error) {
return 0
}
}
private async cleanupPostAnalysisProcesses(): Promise<void> {
console.log('🚨 Post-analysis cleanup - targeting orphaned browser processes')
try {
// Find all chromium processes
const chromiumProcesses = await this.findChromiumProcesses()
if (chromiumProcesses.length === 0) {
console.log('✅ No chromium processes found to clean up')
return
}
console.log(`🔍 Found ${chromiumProcesses.length} chromium processes`)
// Filter out processes that are too new (less than 2 minutes old)
const oldProcesses = await this.filterOldProcesses(chromiumProcesses, 2 * 60) // 2 minutes
if (oldProcesses.length === 0) {
console.log('✅ All chromium processes are recent, not cleaning up')
return
}
console.log(`🧹 Cleaning up ${oldProcesses.length} old chromium processes`)
// Try graceful shutdown first
for (const pid of oldProcesses) {
try {
console.log(`<EFBFBD> Attempting graceful shutdown of process ${pid}`)
await execAsync(`kill -TERM ${pid}`)
} catch (error) {
console.log(` Process ${pid} may already be terminated`)
}
}
// Wait for graceful shutdown
await new Promise(resolve => setTimeout(resolve, 3000))
// Check which processes are still running and force kill only those
const stillRunning = await this.findStillRunningProcesses(oldProcesses)
if (stillRunning.length > 0) {
console.log(`🗡️ Force killing ${stillRunning.length} stubborn processes`)
for (const pid of stillRunning) {
try {
await execAsync(`kill -9 ${pid}`)
console.log(`💀 Force killed process ${pid}`)
} catch (error) {
console.log(` Process ${pid} already terminated`)
}
}
}
console.log('✅ Post-analysis cleanup completed')
} catch (error) {
console.error('Error in post-analysis cleanup:', error)
}
}
private async findStillRunningProcesses(pids: string[]): Promise<string[]> {
const stillRunning: string[] = []
for (const pid of pids) {
try {
await execAsync(`kill -0 ${pid}`) // Check if process exists
stillRunning.push(pid)
} catch (error) {
// Process is already dead
}
}
return stillRunning
}
// Method to get detailed process information for debugging
async getProcessInfo(): Promise<void> {
try {
console.log('🔍 Current browser process information:')
// Get all chromium processes with detailed info
const { stdout } = await execAsync('ps aux | grep -E "(chromium|chrome)" | grep -v grep')
const processes = stdout.trim().split('\n').filter(line => line.length > 0)
if (processes.length === 0) {
console.log('✅ No browser processes currently running')
return
}
console.log(`📊 Found ${processes.length} browser processes:`)
processes.forEach((process, index) => {
const parts = process.split(/\s+/)
const pid = parts[1]
const cpu = parts[2]
const mem = parts[3]
const command = parts.slice(10).join(' ')
console.log(` ${index + 1}. PID: ${pid}, CPU: ${cpu}%, MEM: ${mem}%, CMD: ${command.substring(0, 100)}...`)
})
// Get memory usage
const { stdout: memInfo } = await execAsync('free -h')
console.log('💾 Memory usage:')
console.log(memInfo)
} catch (error) {
console.error('Error getting process info:', error)
}
}
stop(): void {