import { NextResponse } from 'next/server' export async function POST(request) { try { const body = await request.json() const { symbol, side, amount, leverage = 1, stopLoss, takeProfit, useRealDEX = false } = body console.log('🔥 Drift Perpetuals trade request:', { symbol, side, amount, leverage, stopLoss, takeProfit, useRealDEX }) // Validate inputs if (!symbol || !side || !amount) { return NextResponse.json( { success: false, error: 'Missing required fields: symbol, side, amount' }, { status: 400 } ) } if (!['BUY', 'SELL', 'LONG', 'SHORT'].includes(side.toUpperCase())) { return NextResponse.json( { success: false, error: 'Invalid side. Must be LONG/SHORT or BUY/SELL' }, { status: 400 } ) } if (amount <= 0) { return NextResponse.json( { success: false, error: 'Amount must be greater than 0' }, { status: 400 } ) } if (leverage < 1 || leverage > 10) { return NextResponse.json( { success: false, error: 'Leverage must be between 1x and 10x' }, { status: 400 } ) } if (!useRealDEX) { // Simulation mode console.log('🎮 Executing SIMULATED Drift perpetual trade') const currentPrice = symbol === 'SOL' ? 166.75 : symbol === 'BTC' ? 121819 : 3041.66 const leveragedAmount = amount * leverage const entryFee = leveragedAmount * 0.001 // 0.1% opening fee const liquidationPrice = side.toUpperCase().includes('LONG') || side.toUpperCase() === 'BUY' ? currentPrice * (1 - 0.9 / leverage) // Approximate liquidation price : currentPrice * (1 + 0.9 / leverage) await new Promise(resolve => setTimeout(resolve, 1200)) return NextResponse.json({ success: true, trade: { txId: `drift_sim_${Date.now()}_${Math.random().toString(36).substr(2, 8)}`, orderId: `drift_order_${Date.now()}`, symbol: symbol.toUpperCase(), side: side.toUpperCase(), positionSize: amount, leverage: leverage, leveragedAmount: leveragedAmount, entryPrice: currentPrice, liquidationPrice: liquidationPrice, entryFee: entryFee, timestamp: Date.now(), status: 'OPEN', platform: 'Drift Protocol (Simulation)', stopLoss: stopLoss, takeProfit: takeProfit, monitoring: !!(stopLoss || takeProfit), pnl: 0 }, message: `${side.toUpperCase()} perpetual position opened: $${amount} at ${leverage}x leverage - SIMULATED` }) } // Real Drift trading implementation console.log('💰 Executing REAL Drift perpetual trade') // Import Drift SDK components const { DriftClient, initialize, MarketType, PositionDirection, OrderType } = await import('@drift-labs/sdk') const { Connection, Keypair } = await import('@solana/web3.js') const { Wallet } = await import('@coral-xyz/anchor') // Initialize connection and wallet const connection = new Connection( process.env.SOLANA_RPC_URL || 'https://api.mainnet-beta.solana.com', 'confirmed' ) if (!process.env.SOLANA_PRIVATE_KEY) { return NextResponse.json({ success: false, error: 'Drift trading not configured - missing SOLANA_PRIVATE_KEY' }, { status: 400 }) } const privateKeyArray = JSON.parse(process.env.SOLANA_PRIVATE_KEY) const keypair = Keypair.fromSecretKey(new Uint8Array(privateKeyArray)) const wallet = new Wallet(keypair) console.log('🚀 Initializing Drift client...') // Initialize Drift SDK const env = 'mainnet-beta' const sdkConfig = initialize({ env }) const driftClient = new DriftClient({ connection, wallet, programID: sdkConfig.DRIFT_PROGRAM_ID, opts: { commitment: 'confirmed', }, }) await driftClient.subscribe() try { // Get market index for the symbol const marketIndex = symbol === 'SOL' ? 0 : symbol === 'BTC' ? 1 : 0 // SOL-PERP is typically index 0 // Determine position direction const direction = side.toUpperCase().includes('LONG') || side.toUpperCase() === 'BUY' ? PositionDirection.LONG : PositionDirection.SHORT // Calculate position size in base asset units const currentPrice = 166.75 // Get from oracle in production const baseAssetAmount = (amount * leverage) / currentPrice * 1e9 // Convert to lamports for SOL console.log('📊 Trade parameters:', { marketIndex, direction: direction === PositionDirection.LONG ? 'LONG' : 'SHORT', baseAssetAmount: baseAssetAmount.toString(), leverage }) // Place market order const orderParams = { orderType: OrderType.MARKET, marketType: MarketType.PERP, direction, baseAssetAmount: Math.floor(baseAssetAmount), marketIndex, } console.log('🎯 Placing Drift market order...') const txSig = await driftClient.placeOrder(orderParams) console.log('✅ Drift order placed:', txSig) // Set up stop loss and take profit if specified let stopLossOrderId = null let takeProfitOrderId = null if (stopLoss) { try { const stopLossParams = { orderType: OrderType.LIMIT, marketType: MarketType.PERP, direction: direction === PositionDirection.LONG ? PositionDirection.SHORT : PositionDirection.LONG, baseAssetAmount: Math.floor(baseAssetAmount), price: stopLoss * 1e6, // Price in 6 decimal format marketIndex, triggerPrice: stopLoss * 1e6, triggerCondition: direction === PositionDirection.LONG ? 'below' : 'above', } const slTxSig = await driftClient.placeOrder(stopLossParams) stopLossOrderId = slTxSig console.log('🛑 Stop loss order placed:', slTxSig) } catch (slError) { console.warn('⚠️ Stop loss order failed:', slError.message) } } if (takeProfit) { try { const takeProfitParams = { orderType: OrderType.LIMIT, marketType: MarketType.PERP, direction: direction === PositionDirection.LONG ? PositionDirection.SHORT : PositionDirection.LONG, baseAssetAmount: Math.floor(baseAssetAmount), price: takeProfit * 1e6, // Price in 6 decimal format marketIndex, triggerPrice: takeProfit * 1e6, triggerCondition: direction === PositionDirection.LONG ? 'above' : 'below', } const tpTxSig = await driftClient.placeOrder(takeProfitParams) takeProfitOrderId = tpTxSig console.log('🎯 Take profit order placed:', tpTxSig) } catch (tpError) { console.warn('⚠️ Take profit order failed:', tpError.message) } } // Calculate liquidation price const liquidationPrice = direction === PositionDirection.LONG ? currentPrice * (1 - 0.9 / leverage) : currentPrice * (1 + 0.9 / leverage) const result = { success: true, trade: { txId: txSig, orderId: `drift_${Date.now()}`, symbol: symbol.toUpperCase(), side: direction === PositionDirection.LONG ? 'LONG' : 'SHORT', positionSize: amount, leverage: leverage, leveragedAmount: amount * leverage, entryPrice: currentPrice, liquidationPrice: liquidationPrice, entryFee: (amount * leverage) * 0.001, timestamp: Date.now(), status: 'PENDING', platform: 'Drift Protocol', dex: 'DRIFT_REAL', stopLoss: stopLoss, takeProfit: takeProfit, stopLossOrderId: stopLossOrderId, takeProfitOrderId: takeProfitOrderId, monitoring: !!(stopLoss || takeProfit), pnl: 0 }, message: `${direction === PositionDirection.LONG ? 'LONG' : 'SHORT'} perpetual position opened: $${amount} at ${leverage}x leverage`, warnings: [ `⚠️ Liquidation risk at $${liquidationPrice.toFixed(4)}`, '📊 Position requires active monitoring', '💰 Real funds at risk' ] } return NextResponse.json(result) } finally { // Clean up try { await driftClient.unsubscribe() } catch (e) { console.warn('⚠️ Cleanup warning:', e.message) } } } catch (error) { console.error('❌ Drift perpetual trade execution error:', error) return NextResponse.json( { success: false, error: 'Internal server error', message: `Failed to execute Drift perpetual trade: ${error.message}`, details: error.message }, { status: 500 } ) } } export async function GET() { return NextResponse.json({ message: 'Drift Protocol Perpetuals Trading API', endpoints: { 'POST /api/trading/execute-drift': 'Execute real perpetual trades via Drift Protocol', }, status: 'Active', features: [ 'Real leveraged perpetual trading (1x-10x)', 'Long/Short positions with liquidation risk', 'Stop Loss & Take Profit orders', 'Real-time position tracking', 'Automatic margin management' ], requirements: [ 'SOLANA_PRIVATE_KEY environment variable', 'Sufficient USDC collateral in Drift account', 'Active Drift user account' ], note: 'This API executes real trades with real money and liquidation risk. Use with caution.' }) }