/** * 24k feed - Watch activity feed */ import { Command } from "commander"; import chalk from "chalk"; import ora from "ora"; import { api } from "../api.js"; const eventColors: Record string> = { purchase: chalk.green, listing: chalk.blue, haggle_offer: chalk.yellow, haggle_accepted: chalk.greenBright, trade_offer: chalk.magenta, trade_accepted: chalk.magentaBright, comment: chalk.cyan, storefront_opened: chalk.white, deal: chalk.yellowBright, }; function formatEvent(event: { type: string; actor: { name: string } | null; metadata: Record; coordinates: { x: number; y: number }; timestamp: number; }): string { const color = eventColors[event.type] || chalk.dim; const actor = event.actor?.name || "Unknown"; const coords = `(${event.coordinates.x},${event.coordinates.y})`; const time = new Date(event.timestamp).toLocaleTimeString(); let action = ""; const meta = event.metadata; switch (event.type) { case "purchase": action = `bought "${meta.itemName}" for ◆${meta.price} from ${meta.sellerName}`; break; case "listing": action = `listed "${meta.itemName}" for ◆${meta.price}`; break; case "haggle_offer": if (meta.isCounter) { action = `countered with ◆${meta.counterPrice} on "${meta.itemName}"`; } else { action = `offered ◆${meta.offerPrice} for "${meta.itemName}" (asking ◆${meta.originalPrice})`; } break; case "haggle_accepted": action = `accepted ◆${meta.finalPrice} for "${meta.itemName}" (saved ◆${meta.savings})`; break; case "trade_offer": action = `proposed trade to ${meta.targetName}`; break; case "trade_accepted": action = `completed trade with ${meta.offererName}`; break; case "comment": action = `"${(meta.content as string)?.slice(0, 40)}..."`; break; case "storefront_opened": action = `opened "${meta.storefrontName}"`; break; default: action = event.type; } return `${chalk.dim(time)} ${chalk.dim(coords)} ${color(actor)} ${action}`; } export const feedCommand = new Command("feed") .description("Watch the marketplace activity feed") .option("-l, --limit ", "Number of events to show", "20") .option("-t, --types ", "Filter by types (comma-separated)") .action(async (options) => { const limit = parseInt(options.limit); const types = options.types?.split(","); const spinner = ora("Loading feed...").start(); const result = await api.getFeed(limit, types); if (result.error) { spinner.fail(chalk.red(`Failed: ${result.error}`)); return; } spinner.stop(); console.log(""); console.log(chalk.bold("📡 24K Live Feed")); console.log(chalk.dim("─".repeat(60))); console.log(""); const events = result.data!.events; if (events.length === 0) { console.log(chalk.dim(" No activity yet. Be the first!")); } else { for (const event of events) { console.log(` ${formatEvent(event)}`); } } console.log(""); console.log(chalk.dim("─".repeat(60))); console.log(chalk.dim(`Showing ${events.length} events. Use --limit to see more.`)); });