From 9e6de772f2763efb9610d16627be401339c0ca8a Mon Sep 17 00:00:00 2001 From: mindesbunister Date: Thu, 24 Jul 2025 11:14:22 +0200 Subject: [PATCH] CRITICAL FIX: Replace Jupiter with Drift Protocol in automation service - Remove Jupiter DEX import and dependencies from automation-service-simple.ts - Replace executeLiveTrade method to use Drift Protocol via /api/automation/trade - Add dexProvider field to AutomationConfig interface - Update AI risk management to use calculateAIStopLoss/calculateAITakeProfit methods - Fix all Jupiter references to use Drift Protocol instead - Ensure automation uses proper Drift leverage trading instead of Jupiter spot trading - Route trades through unified API that defaults to DRIFT provider This resolves the issue where automation was incorrectly using Jupiter DEX instead of the configured Drift Protocol for leveraged trading. --- lib/automation-service-simple.ts | 89 ++++++++++++++++--------------- prisma/prisma/dev.db | Bin 962560 -> 978944 bytes 2 files changed, 46 insertions(+), 43 deletions(-) diff --git a/lib/automation-service-simple.ts b/lib/automation-service-simple.ts index 46d0bf5..a6bc305 100644 --- a/lib/automation-service-simple.ts +++ b/lib/automation-service-simple.ts @@ -1,6 +1,5 @@ import { PrismaClient } from '@prisma/client' import { aiAnalysisService, AnalysisResult } from './ai-analysis' -import { jupiterDEXService } from './jupiter-dex-service' import { enhancedScreenshotService } from './enhanced-screenshot-simple' import { TradingViewCredentials } from './tradingview-automation' import { progressTracker, ProgressStatus } from './progress-tracker' @@ -21,6 +20,7 @@ export interface AutomationConfig { // stopLossPercent and takeProfitPercent removed - AI calculates these automatically maxDailyTrades: number riskPercentage: number + dexProvider?: string // DEX provider (DRIFT or JUPITER) } export interface AutomationStatus { @@ -850,7 +850,7 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r. // Execute simulation trade tradeResult = await this.executeSimulationTrade(decision) } else { - // Execute live trade via Jupiter + // Execute live trade via Drift Protocol console.log(`💰 LIVE TRADE: $${this.config!.tradingAmount} trading amount configured`) tradeResult = await this.executeLiveTrade(decision) @@ -859,7 +859,7 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r. console.log('⚠️ Live trade failed, falling back to simulation for record keeping') tradeResult = await this.executeSimulationTrade(decision) tradeResult.status = 'FAILED' - tradeResult.error = 'Jupiter DEX execution failed' + tradeResult.error = 'Drift Protocol execution failed' } } @@ -922,52 +922,55 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r. } private async executeLiveTrade(decision: any): Promise { - // Execute real trade via Jupiter DEX - const inputToken = decision.direction === 'BUY' ? 'USDC' : 'SOL' - const outputToken = decision.direction === 'BUY' ? 'SOL' : 'USDC' + // Execute real trade via Drift Protocol + console.log(`🌊 Executing Drift trade: ${decision.direction} ${this.config!.symbol}`) - const tokens = { - SOL: 'So11111111111111111111111111111111111111112', - USDC: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', - } + // Calculate AI-generated stop loss and take profit from analysis + const stopLossPercent = decision.stopLoss || this.calculateAIStopLoss(decision) + const takeProfitPercent = decision.takeProfit || this.calculateAITakeProfit(decision) + + console.log(`🎯 AI Risk Management: SL=${stopLossPercent}%, TP=${takeProfitPercent}%`) - // 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`) - } + // Call the unified trading API endpoint that routes to Drift + const tradeResponse = await fetch(`${process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'}/api/automation/trade`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + dexProvider: this.config!.dexProvider || 'DRIFT', + action: 'place_order', + symbol: this.config!.symbol, + amount: this.config!.tradingAmount, + side: decision.direction.toLowerCase(), + leverage: this.config!.maxLeverage || 2, + stopLoss: true, + takeProfit: true, + stopLossPercent: stopLossPercent, + takeProfitPercent: takeProfitPercent, + mode: this.config!.mode || 'SIMULATION' + }) + }) - console.log(`🔄 Executing Jupiter swap with corrected amount: ${swapAmount}`) + const tradeResult = await tradeResponse.json() - 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) { + // Convert Drift result to standard trade result format + if (tradeResult.success) { return { - transactionId: swapResult.txId, - executionPrice: swapResult.executionPrice, - amount: swapResult.outputAmount, // Amount of tokens received + transactionId: tradeResult.result?.transactionId || tradeResult.result?.txId, + executionPrice: tradeResult.result?.executionPrice, + amount: tradeResult.result?.amount, 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 + leverage: tradeResult.leverageUsed || this.config!.maxLeverage, + stopLoss: stopLossPercent, + takeProfit: takeProfitPercent, + tradingAmount: this.config!.tradingAmount, + dexProvider: 'DRIFT' } } else { - throw new Error(swapResult.error || 'Jupiter swap failed') + throw new Error(tradeResult.error || 'Drift trade execution failed') } } @@ -982,7 +985,7 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r. return } - // For live trades, use the actual amounts from Jupiter + // For live trades, use the actual amounts from Drift const tradeAmount = result.tradingAmount ? this.config!.tradingAmount : decision.positionSize const actualAmount = result.amount || decision.positionSize @@ -1005,11 +1008,11 @@ ${validResults.map(r => `• ${r.timeframe}: ${r.analysis?.recommendation} (${r. confidence: decision.confidence, marketSentiment: decision.marketSentiment, createdAt: new Date(), - // Add Jupiter-specific fields for live trades + // Add Drift-specific fields for live trades ...(this.config!.mode === 'LIVE' && result.tradingAmount && { realTradingAmount: this.config!.tradingAmount, - inputAmount: result.inputAmount, - slippage: result.slippage + leverage: result.leverage, + driftTxId: result.transactionId }) } }) diff --git a/prisma/prisma/dev.db b/prisma/prisma/dev.db index 3b46605475dd5d8f3c8a23eca397240a342fbf65..b3738bcf1f12f0e78236131c93f48a17bef38176 100644 GIT binary patch delta 1997 zcmaKs4NMbf7{~9u>$Ug69aQ-cKcFBVabUd`xYDBF{8$tfh^PxPM;R1)7D_7=#W#VP8HE}G4~JwBER@sj7sB~R|2 z_x=6<&(k*OXdBGym_|P(2x4fTsQ^64=gTkT1LF3TlFyLU+GrQQiDaZ?Si2aEXi^Mr%l<*K9d@n?+ ze}&jWoYE7UDNDZz%P$}bk+QRpgrN$O_i#0%8{IBe(c8A$(7&ceB8w36T z(LYv}l`J1F+r!e-RavtA9-B;D7%OLcYZ}8p*UJ88Pfb92hd7VR+kGcl92^cFM}+D- zDRewMKEQX9=H<}^sRYquZ=Z~BjR<4B5sNZxgb98J{#z)-+RfHXORj9TfWLx@hP{VH z9*m2~L}-0R1=RKwF&{xFl`IEm4igWdU#UG1B~vLd_!+04R%!CO0!rB3eMx{w< z@MfCoDyuw-w-zqy4GYx)nK^?xcNpqG_!(P>wo~V*?5?DKrcX97aa{H z2ZS`Z-X$6!z=;`9Tu3=+yTzPqgG-yaR3OXg^^|PR0^?m4U?9Vg52o|%8YsDDFu>M2 ziiHJkLmYHOkY9kZBBBNQE(pi4$Aeya3k+SSq9}Y*KsT5;NbIJUz4G3Zps!V&YOy;c z*^w=oEppDK_y`)#!;4!%7ZI3A-d=3jHJHT1RrRj5JEJhCaPf@Y74Zq^^H>Ybz6S?nT?Y8h>GiPpHlv5TSNNGQ8@MNs;O5KV&=USJ_~Q9Z7zT2X8J$=8 zLh!B^Q=pAwm%#51F$o5raT}rF9Crnr%XuGM+rsYz=igi@99<#&g1__UGgb(RVlsXo ze4AYiX$|5`nEwNpKJkey8bApH%*71NIU@jTMgfLLK6Efu%V`=v@)1Ek!u))1)bE=2WBR91V%8z{AlrJOm3r7bZi*2|)yBESmy8o48xOZ4j*p=A00& z(s*RDEP%Si02TIVuuE{O*u5u^`tg^7fM@1j#AVo4#5-W%J~so|;AWBVhEDTyQh~7e zl}8=(pG9(5?dEKotohG5icj-j@7Ze1ulKBLm>)xs4CeO_k`6Wni#2}7%G%j+{KhY> zFuxvcI{YuVDbR6P)FV5fQk@AZZZV@fz!bx1JAi{C7aIw_X08H!X`BLmPYlt}nr0|b z2RaQ)5%kBg9jedGrXXFI5f}@}d5}4kNd|E}l@2$$M16R|r@$cxDMDKzO+(&PHZsQK z+N3m@lp2$7gHq)(RlBO{6faax)n`KfIW7hsT-EIySqMgt4!f_MEP*zUE2?R!CEJSiw`sbp{l6~HcZYR(zUN=|4SQYy delta 402 zcmZp8VBPS*YJxQDQw9cx*Ao@&8J{*LY)xR?7|+_zEyyjnS$1iSk9D3oWGWGGk|Oy8f*n8Ibf zaGM%fPIdc&EXH$8j4IRfa~b6<^U@l%FfDCV1bTpj0cL4gO0o&i(j<_jX=x=USw=~v za7+C;SFAGy8Vw}3+vG8t3yPXzRo_w1Si^CW`vlNrhS%G98W<-r0>i_TWBc<+#)pjU zC%QqH35c12m<5PgftU@5*@2j2`-yH&8x_W^>8u+#uTPiR$f>rSX(OitHxrZY_T^I; ZHJRFT_i+L-7Z7s;G0*ngeY}%D0szg%fgAt;