Implement pure Drift Protocol automation system

- Remove Jupiter DEX completely from automation system
- Implement exclusive Drift Protocol integration with up to 100x leverage
- Update executeLiveTrade method to use only Drift API endpoints
- Change default DEX provider from Jupiter to Drift
- Create minimal professional UI without promotional banners
- Add comprehensive leverage options (1x-100x) with risk indicators
- Update automation service to route all trades through /api/automation/trade
- Fix type definitions to support Drift-only configuration
- Add multiple trading pairs support (SOL, BTC, ETH, APT, AVAX, DOGE)
- Implement clean configuration interface with essential controls
- Remove excessive marketing text and promotional elements
- Maintain full automation functionality while simplifying UX
This commit is contained in:
mindesbunister
2025-07-22 16:05:29 +02:00
parent fb194f1b12
commit 4f553dcfb6
34 changed files with 7133 additions and 2221 deletions

View File

@@ -1,56 +1,29 @@
// Analysis completion flag manager
// This ensures cleanup only happens after the entire analysis cycle is complete
class AnalysisCompletionFlag {
private static instance: AnalysisCompletionFlag
private isAnalysisComplete = false
private currentSessionId: string | null = null
private constructor() {}
static getInstance(): AnalysisCompletionFlag {
if (!AnalysisCompletionFlag.instance) {
AnalysisCompletionFlag.instance = new AnalysisCompletionFlag()
// Analysis completion flag utility
export const analysisCompletionFlag = {
isComplete: false,
currentSession: null as string | null,
setComplete: (value: boolean) => {
analysisCompletionFlag.isComplete = value
},
getComplete: () => analysisCompletionFlag.isComplete,
startAnalysisCycle: (sessionId: string) => {
analysisCompletionFlag.currentSession = sessionId
analysisCompletionFlag.isComplete = false
},
endAnalysisCycle: () => {
analysisCompletionFlag.isComplete = true
analysisCompletionFlag.currentSession = null
},
markAnalysisComplete: (sessionId: string) => {
if (analysisCompletionFlag.currentSession === sessionId) {
analysisCompletionFlag.isComplete = true
}
return AnalysisCompletionFlag.instance
}
// Called at the start of each analysis cycle
startAnalysisCycle(sessionId: string) {
console.log(`🚀 Starting analysis cycle: ${sessionId}`)
this.isAnalysisComplete = false
this.currentSessionId = sessionId
}
// Called at the end of each analysis cycle
markAnalysisComplete(sessionId: string) {
if (sessionId === this.currentSessionId) {
console.log(`✅ Analysis cycle complete: ${sessionId}`)
this.isAnalysisComplete = true
} else {
console.log(`⚠️ Session ID mismatch: expected ${this.currentSessionId}, got ${sessionId}`)
}
}
// Check if analysis is complete and cleanup can proceed
canCleanup(): boolean {
return this.isAnalysisComplete
}
// Get current session info
getCurrentSession(): { sessionId: string | null; isComplete: boolean } {
return {
sessionId: this.currentSessionId,
isComplete: this.isAnalysisComplete
}
}
// Reset flag (for manual cleanup or new cycles)
reset() {
console.log(`🔄 Resetting analysis completion flag`)
this.isAnalysisComplete = false
this.currentSessionId = null
}
}
export const analysisCompletionFlag = AnalysisCompletionFlag.getInstance()
export default analysisCompletionFlag

View File

@@ -805,7 +805,7 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
if (tradeResult.status !== 'FAILED') {
setTimeout(async () => {
try {
await aggressiveCleanup.forceCleanupAfterTrade()
await aggressiveCleanup.runPostAnalysisCleanup()
} catch (error) {
console.error('Error in post-trade cleanup:', error)
}
@@ -852,52 +852,53 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r.
}
private async executeLiveTrade(decision: any): Promise<any> {
// Execute real trade via Jupiter DEX
const inputToken = decision.direction === 'BUY' ? 'USDC' : 'SOL'
const outputToken = decision.direction === 'BUY' ? 'SOL' : 'USDC'
const tokens = {
SOL: 'So11111111111111111111111111111111111111112',
USDC: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
}
try {
console.log(`🚀 Executing DRIFT trade: ${decision.direction} ${decision.positionSize} ${this.config!.symbol} with ${this.config!.maxLeverage}x leverage`)
const response = await fetch("http://localhost:3000/api/automation/trade", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
dexProvider: "DRIFT",
action: decision.direction.toLowerCase() === "buy" ? "open_long" : "open_short",
symbol: this.config!.symbol.replace("USD", ""), // Convert SOLUSD to SOL
amount: this.config!.tradingAmount,
side: decision.direction,
leverage: this.config!.maxLeverage,
stopLoss: decision.stopLoss,
takeProfit: decision.takeProfit,
mode: "LIVE"
})
})
// Calculate proper amount for Jupiter API
let swapAmount
if (decision.direction === 'BUY') {
// BUY: Use trading amount in USDC (convert to 6 decimals)
swapAmount = Math.floor(this.config!.tradingAmount * 1e6) // USDC has 6 decimals
console.log(`💱 BUY: Converting $${this.config!.tradingAmount} USDC to ${swapAmount} USDC tokens`)
} else {
// SELL: Use SOL amount (convert to 9 decimals)
swapAmount = Math.floor(decision.positionSize * 1e9) // SOL has 9 decimals
console.log(`💱 SELL: Converting ${decision.positionSize} SOL to ${swapAmount} SOL tokens`)
}
console.log(`🔄 Executing Jupiter swap with corrected amount: ${swapAmount}`)
const swapResult = await jupiterDEXService.executeSwap(
tokens[inputToken as keyof typeof tokens],
tokens[outputToken as keyof typeof tokens],
swapAmount,
50 // 0.5% slippage
)
// Convert Jupiter result to standard trade result format
if (swapResult.success) {
return {
transactionId: swapResult.txId,
executionPrice: swapResult.executionPrice,
amount: swapResult.outputAmount, // Amount of tokens received
direction: decision.direction,
status: 'COMPLETED',
timestamp: new Date(),
fees: swapResult.fees || 0,
slippage: swapResult.slippage || 0,
inputAmount: swapResult.inputAmount, // Amount of tokens spent
tradingAmount: this.config!.tradingAmount // Original USD amount
if (!response.ok) {
throw new Error(`Drift trade request failed: ${response.statusText}`)
}
} else {
throw new Error(swapResult.error || 'Jupiter swap failed')
const result = await response.json()
if (result.success) {
return {
transactionId: result.result?.transactionId || result.txId,
executionPrice: result.result?.executionPrice || decision.currentPrice,
amount: result.result?.amount || decision.positionSize,
direction: decision.direction,
status: "COMPLETED",
timestamp: new Date(),
fees: result.result?.fees || 0,
slippage: result.result?.slippage || 0,
leverage: this.config!.maxLeverage,
dexProvider: "DRIFT",
tradingAmount: this.config!.tradingAmount
}
} else {
throw new Error(result.error || "Drift trade execution failed")
}
} catch (error) {
console.error("Live trade execution error:", error)
throw error
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -16,6 +16,7 @@ export interface AutomationConfig {
takeProfitPercent: number
maxDailyTrades: number
riskPercentage: number
dexProvider: 'JUPITER' | 'DRIFT'
}
export interface AutomationStatus {
@@ -388,13 +389,15 @@ export class AutomationService {
leverage
})
} else {
// Execute real trade via Jupiter DEX
tradeResult = await jupiterDEXService.executeTrade({
// Execute real trade via unified trading endpoint
tradeResult = await this.executeUnifiedTrade({
symbol: config.symbol,
side,
amount,
stopLoss: analysis.stopLoss?.price,
takeProfit: analysis.takeProfits?.tp1?.price
takeProfit: analysis.takeProfits?.tp1?.price,
leverage,
dexProvider: config.dexProvider
})
}
@@ -449,6 +452,50 @@ export class AutomationService {
}
}
private async executeUnifiedTrade(params: {
symbol: string
side: string
amount: number
stopLoss?: number
takeProfit?: number
leverage?: number
dexProvider: 'JUPITER' | 'DRIFT'
}): Promise<{ success: boolean; txId?: string }> {
try {
console.log(`🚀 Executing ${params.dexProvider} trade: ${params.side} ${params.amount} ${params.symbol}`)
const response = await fetch('http://localhost:3000/api/automation/trade', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
symbol: params.symbol,
side: params.side,
amount: params.amount,
leverage: params.leverage,
stopLoss: params.stopLoss,
takeProfit: params.takeProfit,
dexProvider: params.dexProvider,
mode: 'LIVE'
})
})
if (!response.ok) {
throw new Error(`Trade request failed: ${response.statusText}`)
}
const result = await response.json()
return {
success: result.success,
txId: result.txId || result.transactionId
}
} catch (error) {
console.error('Unified trade execution error:', error)
return { success: false }
}
}
private async simulateTrade(params: {
symbol: string
side: string