import { NextResponse } from 'next/server' import fs from 'fs' import path from 'path' // Persistent storage for pending orders using JSON file const PENDING_ORDERS_FILE = path.join(process.cwd(), 'data', 'pending-orders.json') // Ensure data directory exists const dataDir = path.join(process.cwd(), 'data') if (!fs.existsSync(dataDir)) { fs.mkdirSync(dataDir, { recursive: true }) } // Helper functions for persistent storage function loadPendingOrders() { try { if (fs.existsSync(PENDING_ORDERS_FILE)) { const data = fs.readFileSync(PENDING_ORDERS_FILE, 'utf8') return JSON.parse(data) } } catch (error) { console.error('Error loading pending orders:', error) } return [] } function savePendingOrders(orders) { try { fs.writeFileSync(PENDING_ORDERS_FILE, JSON.stringify(orders, null, 2)) } catch (error) { console.error('Error saving pending orders:', error) } } // Helper function to map symbols to CoinGecko IDs function getCoinGeckoId(symbol) { const mapping = { 'SOL': 'solana', 'SOLUSD': 'solana', 'BTC': 'bitcoin', 'ETH': 'ethereum', 'USDC': 'usd-coin', 'USDT': 'tether', 'RAY': 'raydium', 'ORCA': 'orca' } return mapping[symbol.replace('USD', '')] || 'solana' } export async function GET() { try { // Load pending orders from persistent storage const pendingOrders = loadPendingOrders() // Check current prices and update order status const updatedOrders = await Promise.all( pendingOrders.filter(order => order.status === 'PENDING').map(async (order) => { try { // Get current price from CoinGecko const priceResponse = await fetch( `https://api.coingecko.com/api/v3/simple/price?ids=${getCoinGeckoId(order.symbol)}&vs_currencies=usd` ) const priceData = await priceResponse.json() const currentPrice = priceData[getCoinGeckoId(order.symbol)]?.usd if (currentPrice) { order.currentPrice = currentPrice // Check if limit order should be filled const shouldFill = ( (order.side === 'BUY' && currentPrice <= order.limitPrice) || (order.side === 'SELL' && currentPrice >= order.limitPrice) ) if (shouldFill) { console.log(`🎯 Limit order ready to fill: ${order.side} ${order.amount} ${order.symbol} at $${order.limitPrice}`) } } return order } catch (error) { console.error(`Error updating order ${order.id}:`, error) return order } }) ) return NextResponse.json({ success: true, orders: updatedOrders, totalOrders: updatedOrders.length }) } catch (error) { console.error('Error fetching pending orders:', error) return NextResponse.json({ success: false, error: 'Failed to fetch pending orders', orders: [] }, { status: 500 }) } } export async function POST(request) { try { const body = await request.json() const { action, orderId, ...orderData } = body if (action === 'add') { // Load existing orders const pendingOrders = loadPendingOrders() // Add new pending order const newOrder = { id: `order_${Date.now()}_${Math.random().toString(36).substr(2, 8)}`, symbol: orderData.symbol, side: orderData.side, amount: parseFloat(orderData.amount), limitPrice: parseFloat(orderData.limitPrice), orderType: 'LIMIT', status: 'PENDING', timestamp: Date.now(), stopLoss: orderData.stopLoss ? parseFloat(orderData.stopLoss) : null, takeProfit: orderData.takeProfit ? parseFloat(orderData.takeProfit) : null, tradingMode: orderData.tradingMode || 'SPOT', fromCoin: orderData.fromCoin, toCoin: orderData.toCoin, expiresAt: orderData.expiresAt || null } pendingOrders.push(newOrder) savePendingOrders(pendingOrders) console.log(`📋 Limit order created: ${newOrder.side} ${newOrder.amount} ${newOrder.symbol} at $${newOrder.limitPrice}`) return NextResponse.json({ success: true, order: newOrder, message: `Limit order created: ${newOrder.side} ${newOrder.amount} ${newOrder.symbol} at $${newOrder.limitPrice}` }) } else if (action === 'cancel') { // Load existing orders const pendingOrders = loadPendingOrders() // Find and cancel order const orderIndex = pendingOrders.findIndex(order => order.id === orderId) if (orderIndex === -1) { return NextResponse.json({ success: false, error: 'Order not found' }, { status: 404 }) } const order = pendingOrders[orderIndex] order.status = 'CANCELLED' order.cancelledAt = Date.now() // Remove from pending orders or mark as cancelled pendingOrders.splice(orderIndex, 1) savePendingOrders(pendingOrders) console.log(`❌ Limit order cancelled: ${order.id}`) return NextResponse.json({ success: true, order: order, message: `Order cancelled: ${order.side} ${order.amount} ${order.symbol}` }) } else if (action === 'fill') { // Fill a limit order (called when price target is reached) const pendingOrders = loadPendingOrders() const orderIndex = pendingOrders.findIndex(order => order.id === orderId) if (orderIndex === -1) { return NextResponse.json({ success: false, error: 'Order not found' }, { status: 404 }) } const order = pendingOrders[orderIndex] const fillPrice = orderData.fillPrice || order.limitPrice try { // Execute the trade by calling the trading API const tradeResponse = await fetch('http://localhost:3000/api/trading', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ symbol: order.symbol, side: order.side.toLowerCase(), amount: order.amount, type: 'limit', price: fillPrice, stopLoss: order.stopLoss, takeProfit: order.takeProfit, tradingMode: order.tradingMode, fromCoin: order.fromCoin, toCoin: order.toCoin, limitOrderId: order.id }) }) if (tradeResponse.ok) { const tradeData = await tradeResponse.json() // Update order status order.status = 'FILLED' order.filledAt = Date.now() order.fillPrice = fillPrice order.tradeId = tradeData.trade?.id // Remove from pending orders pendingOrders.splice(orderIndex, 1) savePendingOrders(pendingOrders) console.log(`✅ Limit order filled: ${order.side} ${order.amount} ${order.symbol} at $${fillPrice}`) return NextResponse.json({ success: true, order: order, trade: tradeData.trade, message: `Order filled: ${order.side} ${order.amount} ${order.symbol} at $${fillPrice}` }) } else { throw new Error('Failed to execute trade for filled order') } } catch (error) { console.error('Error filling limit order:', error) return NextResponse.json({ success: false, error: 'Failed to fill order', message: error.message }, { status: 500 }) } } return NextResponse.json({ success: false, error: 'Invalid action' }, { status: 400 }) } catch (error) { console.error('Error managing pending order:', error) return NextResponse.json({ success: false, error: 'Failed to manage pending order' }, { status: 500 }) } }