"use client"; import { makeAssistantToolUI } from "@assistant-ui/react"; import { z } from "zod"; import { cn } from "@/lib/utils"; import { Flame, TrendingUp, TrendingDown, Star, ExternalLink } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { ChainIcon } from "@/components/crypto/ChainIcon"; // Schema for trending token const TrendingTokenSchema = z.object({ symbol: z.string(), name: z.string(), chain: z.string(), contractAddress: z.string().optional(), price: z.number(), priceChange24h: z.number(), priceChange1h: z.number().optional(), volume24h: z.number().optional(), liquidity: z.number().optional(), rank: z.number().optional(), }); // Schema for trending tokens tool arguments export const TrendingTokensArgsSchema = z.object({ chain: z.string().optional(), tokens: z.array(TrendingTokenSchema), timeframe: z.string().optional(), }); export type TrendingTokensArgs = z.infer; // Schema for trending tokens result export const TrendingTokensResultSchema = z.object({ success: z.boolean(), message: z.string().optional(), }); export type TrendingTokensResult = z.infer; const formatPrice = (price: number): string => { if (price < 0.00001) return `$${price.toExponential(2)}`; if (price < 1) return `$${price.toFixed(6)}`; return `$${price.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; }; const formatLargeNumber = (num: number): string => { if (num >= 1e9) return `$${(num / 1e9).toFixed(2)}B`; if (num >= 1e6) return `$${(num / 1e6).toFixed(2)}M`; if (num >= 1e3) return `$${(num / 1e3).toFixed(2)}K`; return `$${num.toFixed(2)}`; }; /** * TrendingTokensToolUI - Displays trending/hot tokens inline in chat * Used when AI responds to "what's hot on Solana?" or "show trending tokens" */ export const TrendingTokensToolUI = makeAssistantToolUI({ toolName: "get_trending_tokens", render: ({ args, status }) => { const isLoading = status.type === "running"; const tokens = args.tokens || []; const chain = args.chain || "all chains"; const timeframe = args.timeframe || "24h"; return (
Trending on {chain} {timeframe} {isLoading && Loading...}
{tokens.length === 0 ? (

No trending tokens found

) : (
{tokens.map((token, index) => (
#{token.rank || index + 1}
{token.symbol}
{token.name}

{formatPrice(token.price)}

= 0 ? "text-green-500" : "text-red-500")}> {token.priceChange24h >= 0 ? : } {token.priceChange24h >= 0 ? "+" : ""}{token.priceChange24h.toFixed(1)}%

{token.volume24h && (

Volume

{formatLargeNumber(token.volume24h)}

)}
))}
)}
); }, });