pulse_recent_trades
Retrieve the largest trades on Hyperliquid within a specified time window, sorted by absolute profit and loss to identify market movers. Filter by coin or limit results for targeted insights.
Instructions
Get the biggest trades on Hyperliquid in the last N minutes/hours. Returns trades sorted by absolute PnL — the largest movers. Use this to see what's happening right now on the exchange.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| useToonFormat | No | Return data in compact toon format (default: true). Set to false for standard JSON. | |
| since | No | Time window: e.g. '10m' (minutes), '1h' (hours), '1d' (days) | 10m |
| limit | No | Number of trades to return | |
| coin | No | Filter by coin symbol (e.g. BTC, ETH, SOL). For builder dex: prefix:COIN (e.g. xyz:SILVER) |
Implementation Reference
- src/index.ts:485-501 (registration)Registration of the 'pulse_recent_trades' tool via server.registerTool with its input schema (useToonFormat, since, limit, coin) and handler. The tool is conditionally registered based on API key availability via shouldRegister().
if (shouldRegister("pulse_recent_trades")) server.registerTool( "pulse_recent_trades", { description: "Get the biggest trades on Hyperliquid in the last N minutes/hours. Returns trades sorted by absolute PnL — the largest movers. Use this to see what's happening right now on the exchange.", inputSchema: { useToonFormat: useToonFormatSchema, since: sinceSchema.default("10m"), limit: z.number().min(1).max(100).default(20).describe("Number of trades to return"), coin: z.string().optional().describe("Filter by coin symbol (e.g. BTC, ETH, SOL). For builder dex: prefix:COIN (e.g. xyz:SILVER)"), }, }, async ({ useToonFormat, since, limit, coin }) => { const params: Record<string, string> = { since, limit: String(limit) }; if (coin) params.coin = normalizeCoin(coin); return toolResult(await callAPI(useToonFormat, "/pulse/trades/recent", params)); } ); - src/index.ts:496-501 (handler)Handler function for pulse_recent_trades: builds params object with 'since' and 'limit', optionally normalizes the 'coin' parameter, then calls the API at endpoint '/pulse/trades/recent' via the callAPI helper.
async ({ useToonFormat, since, limit, coin }) => { const params: Record<string, string> = { since, limit: String(limit) }; if (coin) params.coin = normalizeCoin(coin); return toolResult(await callAPI(useToonFormat, "/pulse/trades/recent", params)); } ); - src/index.ts:487-495 (schema)Input schema definition for pulse_recent_trades: useToonFormat (boolean, default true), since (regex-validated time window, default '10m'), limit (1-100, default 20), and optional coin filter.
{ description: "Get the biggest trades on Hyperliquid in the last N minutes/hours. Returns trades sorted by absolute PnL — the largest movers. Use this to see what's happening right now on the exchange.", inputSchema: { useToonFormat: useToonFormatSchema, since: sinceSchema.default("10m"), limit: z.number().min(1).max(100).default(20).describe("Number of trades to return"), coin: z.string().optional().describe("Filter by coin symbol (e.g. BTC, ETH, SOL). For builder dex: prefix:COIN (e.g. xyz:SILVER)"), }, }, - src/index.ts:84-91 (helper)The normalizeCoin helper function used by the handler to normalize coin/symbol strings (uppercasing the ticker while preserving builder dex prefix case).
function normalizeCoin(raw: string): string { const idx = raw.indexOf(':'); if (idx !== -1) { // Builder dex format — keep prefix lowercase, uppercase the coin return raw.slice(0, idx).toLowerCase() + ':' + raw.slice(idx + 1).toUpperCase(); } return raw.toUpperCase(); } - src/index.ts:94-166 (helper)The callAPI helper function used by the handler to make HTTP requests to the backend API with timeout, retries, and error handling.
async function callAPI(useToon: boolean, path: string, params?: Record<string, string>): Promise<any> { const url = new URL(`${BASE}${path}`); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== "") { url.searchParams.set(key, value); } }); } let lastError: Error | null = null; for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) { try { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS); const headers: Record<string, string> = {}; if (API_KEY) headers["X-API-Key"] = API_KEY; const response = await fetch(url.toString(), { headers, signal: controller.signal, }); clearTimeout(timeout); if (response.status === 429) { // Rate limited — retry after delay if (attempt < MAX_RETRIES) { await new Promise((r) => setTimeout(r, RETRY_DELAY_MS * (attempt + 1))); continue; } throw new Error("Rate limit exceeded. Please wait a moment and try again."); } if (response.status === 404) { throw new Error("Not found. The requested resource does not exist — check the address or symbol."); } if (response.status === 401) { throw new Error("Invalid API key. Check your COINVERSAA_API_KEY environment variable."); } if (!response.ok) { const body = await response.json().catch(() => null); const msg = body?.error || response.statusText; throw new Error(`Request failed (${response.status}): ${msg}`); } const data = await response.json(); return useToon ? toonEncode(data) : data; } catch (err: any) { if (err.name === "AbortError") { lastError = new Error("Request timed out after 30 seconds. The server may be under heavy load — try again."); } else if (err.cause?.code === "ECONNREFUSED" || err.cause?.code === "ENOTFOUND") { lastError = new Error("Cannot connect to the Coinversa API. Check your COINVERSAA_API_URL setting and network connection."); } else { lastError = err; } // Retry on transient network errors if (attempt < MAX_RETRIES && (err.name === "AbortError" || err.cause?.code === "ECONNRESET")) { await new Promise((r) => setTimeout(r, RETRY_DELAY_MS * (attempt + 1))); continue; } throw lastError; } } throw lastError || new Error("Request failed after retries"); }