Add Real-Time Crypto Trading to Any Next.js App
The Vercel AI SDK's streamText function and useChat hook make it trivially easy to add streaming AI interactions to any Next.js application. Combined with Purple Flea's trading tools, you can build a complete crypto trading interface in an afternoon — with real-time streaming responses as trades are executed.
This tutorial uses Next.js App Router, the Vercel AI SDK ai package, Zod for schema validation, and Purple Flea for actual on-chain trading via Hyperliquid's 275+ perpetual markets.
What We're Building
A chat interface where users can type natural language commands like "Open a $100 long on ETH" and the AI executes the trade, streaming back confirmation with position ID, entry price, and current P&L. The interface handles tool calls transparently — the user just sees a conversational response.
Installation
# Install dependencies npm install ai @purpleflea/vercel-ai-sdk zod @ai-sdk/openai # Set environment variables in .env.local OPENAI_API_KEY=sk-... PURPLE_FLEA_API_KEY=pf_...
Define the Trading Tools
Vercel AI SDK tools use Zod schemas for automatic type validation. Define all Purple Flea tools in a separate file so you can reuse them across API routes.
// lib/crypto-tools.ts import { tool } from 'ai'; import { z } from 'zod'; import { PurpleFleas } from '@purpleflea/vercel-ai-sdk'; const flea = new PurpleFleas({ apiKey: process.env.PURPLE_FLEA_API_KEY! }); export const cryptoTools = { createWallet: tool({ description: 'Create a new non-custodial BIP-39 crypto wallet', parameters: z.object({}), execute: async () => flea.wallet.create(), }), walletBalance: tool({ description: 'Get the balance of a crypto wallet on a specific chain', parameters: z.object({ address: z.string().describe('The wallet address'), chain: z.enum(['eth', 'btc', 'sol', 'bnb', 'matic', 'trx']).default('eth'), }), execute: async ({ address, chain }) => flea.wallet.balance(address, chain), }), openTrade: tool({ description: 'Open a perpetual futures position on Hyperliquid. 275+ markets available.', parameters: z.object({ market: z.string().describe("e.g. 'ETH-PERP', 'BTC-PERP', 'SOL-PERP'"), sizeUsd: z.number().min(10).max(100_000), side: z.enum(['long', 'short']), leverage: z.number().min(1).max(50).default(1), }), execute: async (params) => flea.trading.openPosition(params), }), closeTrade: tool({ description: 'Close an open position and realize P&L', parameters: z.object({ positionId: z.string(), }), execute: async ({ positionId }) => flea.trading.closePosition(positionId), }), listPositions: tool({ description: 'List all open positions with P&L', parameters: z.object({}), execute: async () => flea.trading.getPositions(), }), };
The API Route
Create an App Router route handler that uses streamText with our tools. The toDataStreamResponse() method formats the response for useChat on the client.
// app/api/chat/route.ts import { streamText } from 'ai'; import { openai } from '@ai-sdk/openai'; import { cryptoTools } from '@/lib/crypto-tools'; export const runtime = 'edge'; // Works on Vercel Edge Runtime export async function POST(req: Request) { const { messages } = await req.json(); const result = streamText({ model: openai('gpt-4o'), system: `You are a crypto trading assistant. You can open/close trades, create wallets, and check balances using the provided tools. Always confirm trade details before executing. Show position IDs so users can reference them in follow-up commands.`, messages, tools: cryptoTools, maxSteps: 5, // Allow multi-step tool use }); return result.toDataStreamResponse(); }
The Chat Interface
The client component is minimal — useChat handles all the streaming complexity. Tool results are automatically incorporated into the conversation flow.
// app/page.tsx 'use client'; import { useChat } from 'ai/react'; export default function TradingChat() { const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({ api: '/api/chat', }); return ( <div style={{ maxWidth: '640px', margin: '0 auto', padding: '2rem' }}> <h1>Crypto Trading Agent</h1> <div style={{ minHeight: '400px', marginBottom: '1rem' }}> {messages.map(m => ( <div key={m.id} style={{ marginBottom: '1rem' }}> <strong>{m.role === 'user' ? 'You' : 'Agent'}:</strong> <p>{m.content}</p> </div> ))} {isLoading && <p>Executing...</p>} </div> <form onSubmit={handleSubmit}> <input value={input} onChange={handleInputChange} placeholder="Open a $100 long on ETH-PERP..." style={{ width: '80%', marginRight: '0.5rem' }} /> <button type="submit" disabled={isLoading}>Send</button> </form> </div> ); }
Works with Any Model
Vercel AI SDK's provider abstraction means you can swap GPT-4o for Claude, Gemini, or any other model by changing one line:
// Use Anthropic Claude instead import { anthropic } from '@ai-sdk/anthropic'; // model: anthropic('claude-sonnet-4-6') // Use Google Gemini import { google } from '@ai-sdk/google'; // model: google('gemini-2.0-flash') // Use a self-hosted Llama model via Ollama import { ollama } from 'ollama-ai-provider'; // model: ollama('llama3.3')
The Purple Flea tools work identically regardless of which model you use — tool calling is handled at the framework level.
Deploying to Vercel
Because the route uses export const runtime = 'edge', it deploys to Vercel's Edge Network automatically. Add your environment variables in the Vercel dashboard, and you're live globally with millisecond cold starts.
# Deploy to production
vercel --prod
Earn 20% Referral Commissions
Every Purple Flea API key includes a referral code. When your app's users open trades through Purple Flea, you earn 20% of all trading fees they generate — forever. For a trading app with active users, this becomes significant passive income.
20% trading fee referral · 10% casino wager referral · 10% wallet swap referral · 15% domain registration referral
Next Steps
Add position monitoring with WebSocket streaming from Hyperliquid, portfolio analytics charts, or expand to the full Purple Flea suite with casino games and domain registration.
Explore more: Purple Flea for Vercel AI SDK · Trading API reference · Mastra trading agent tutorial · LangChain integration