import { NextRequest, NextResponse } from 'next/server'; import { getCachedFirm } from '@/lib/firm-catalog'; import { firmInstruments, isFuturesFirm } from '@/lib/instruments'; import { getClients, isWaking, wakeFirm } from '@/lib/clients'; export async function POST( req: NextRequest, { params }: { params: Promise<{ id: string }> } ) { try { const { id: firmId } = await params; const body = await req.json() as { accountId: number; symbol: string; // product name, e.g. "NQ" qty: number; action: 'Buy' | 'Sell'; orderType?: 'Market' | 'Limit'; price?: number; }; const { accountId, symbol, qty, action, orderType = 'Market', price } = body; if (!accountId || !symbol || !qty || !action) { return NextResponse.json({ error: 'Missing required fields: accountId, symbol, qty, action' }, { status: 400 }); } const clients = getClients(); const client = clients.get(firmId); if (!client) return NextResponse.json({ error: 'Client not found for firm' }, { status: 404 }); // A resting session (lib/clients.ts) holds no login: start one, and // let the caller come back once it's up. if (wakeFirm(firmId, 'manual order') || isWaking(firmId)) { return NextResponse.json({ error: "the firm's session is logging back in — try again in a minute" }, { status: 503 }); } // A futures firm trades only what its instrument list (master Firms // page) names. const firm = getCachedFirm(firmId); if (firm && isFuturesFirm(firm) && !firmInstruments(firm).includes(symbol)) { return NextResponse.json({ error: `${symbol} isn't on ${firm.name}'s instrument list` }, { status: 400 }); } // 1. Find the active contract chosen by the shared resolver const contract = await client.findFrontMonthContract(symbol); if (!contract) { return NextResponse.json({ error: `Could not find an active contract for ${symbol}` }, { status: 404 }); } console.log(`[order] active contract: ${contract.name} (id=${contract.id})`); // 2. Place the order — resolves with the fill event (includes commission/fees) const fill = await client.sendOrder(accountId, contract.name, qty, action, orderType, price); console.log(`[order] fill received: price=${fill.price} qty=${fill.qty} commission=$${fill.commission} perContract=$${fill.perContractFee}`); return NextResponse.json({ contract: { id: contract.id, name: contract.name }, fill }); } catch (err: any) { console.error('[POST /api/firms/[id]/orders]', err); return NextResponse.json({ error: err?.message ?? 'Order failed' }, { status: 500 }); } }