Fix Drift balance calculation and implement multi-RPC failover system

- Fixed balance calculation: corrected precision factor for Drift scaledBalance (5.69 vs wrong 0,678.76)
- Implemented multi-RPC failover system with 4 endpoints (Helius, Solana official, Alchemy, Ankr)
- Updated automation page with balance sync, leverage-based position sizing, and removed daily trade limits
- Added RPC status monitoring endpoint
- Updated balance and positions APIs to use failover system
- All Drift APIs now working correctly with accurate balance data
This commit is contained in:
mindesbunister
2025-07-22 17:00:46 +02:00
parent 4f553dcfb6
commit 461230d2bc
11 changed files with 1650 additions and 351 deletions

View File

@@ -14,7 +14,6 @@ export interface AutomationConfig {
maxLeverage: number
stopLossPercent: number
takeProfitPercent: number
maxDailyTrades: number
riskPercentage: number
dexProvider: 'JUPITER' | 'DRIFT'
}
@@ -234,10 +233,10 @@ export class AutomationService {
private async executeAutomationCycle(config: AutomationConfig) {
console.log(`🔄 Executing automation cycle for ${config.symbol} ${config.timeframe}`)
// Check if we've reached daily trade limit
const todayTrades = await this.getTodayTradeCount(config.userId)
if (todayTrades >= config.maxDailyTrades) {
console.log(`📊 Daily trade limit reached (${todayTrades}/${config.maxDailyTrades})`)
// Check for open positions first (instead of daily trade limit)
const hasOpenPosition = await this.checkForOpenPositions(config)
if (hasOpenPosition) {
console.log(`📊 Open position detected for ${config.symbol}, monitoring only`)
return
}
@@ -367,6 +366,48 @@ export class AutomationService {
return true
}
private async checkForOpenPositions(config: AutomationConfig): Promise<boolean> {
try {
console.log(`🔍 Checking for open positions for ${config.symbol}`)
// For Jupiter DEX, we don't have persistent positions like in Drift
// This method would need to be implemented based on your specific needs
// For now, return false to allow trading
if (config.dexProvider === 'DRIFT') {
// Check Drift positions via API
const response = await fetch('http://localhost:3000/api/drift/positions')
if (!response.ok) {
console.warn('⚠️ Could not fetch Drift positions, assuming no open positions')
return false
}
const data = await response.json()
if (!data.success || !data.positions) {
return false
}
// Check if there's an open position for the current symbol
const symbolBase = config.symbol.replace('USD', '') // SOLUSD -> SOL
const openPosition = data.positions.find((pos: any) =>
pos.symbol.includes(symbolBase) && pos.size > 0.001
)
if (openPosition) {
console.log(`📊 Found open ${openPosition.side} position: ${openPosition.symbol} ${openPosition.size}`)
return true
}
}
return false
} catch (error) {
console.error('❌ Error checking positions:', error)
// On error, assume no positions to allow trading
return false
}
}
private async executeTrade(config: AutomationConfig, analysis: AnalysisResult, screenshotUrl: string) {
try {
console.log(`🚀 Executing ${config.mode} trade: ${analysis.recommendation} ${config.symbol}`)
@@ -560,27 +601,6 @@ export class AutomationService {
return intervals[timeframe] || intervals['1h'] // Default to 1 hour
}
private async getTodayTradeCount(userId: string): Promise<number> {
const today = new Date()
today.setHours(0, 0, 0, 0)
const tomorrow = new Date(today)
tomorrow.setDate(tomorrow.getDate() + 1)
const count = await prisma.trade.count({
where: {
userId,
isAutomated: true,
createdAt: {
gte: today,
lt: tomorrow
}
}
})
return count
}
private async getRecentPerformance(userId: string): Promise<{
winRate: number
totalTrades: number