Whale Movements
whale_movementsMonitor whale wallets for large balance changes across multiple blockchains to detect significant inflows, outflows, and transfers that may signal market moves.
Instructions
Get large balance changes across whale wallets. Shows significant inflows, outflows, and transfers that may signal market moves. Cost: $0.04 per query. Source: On-chain analytics.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| chain | No | Filter by blockchain network | |
| min_usd | No | Minimum movement size in USD | |
| token | No | Filter by token symbol | |
| hours | No | Lookback period in hours (default 24, max 168) | |
| limit | No | Maximum results (default 25) |
Implementation Reference
- src/tools/whales.ts:139-207 (handler)The handler for the 'whale_movements' tool. Calls GET /api/v1/whales/movements with optional filters (chain, min_usd, token, hours, limit) and returns the response as text.
// ── Whale movements ─────────────────────────────────────────────────── server.registerTool( "whale_movements", { title: "Whale Movements", description: "Get large balance changes across whale wallets. Shows significant inflows, " + "outflows, and transfers that may signal market moves. " + "Cost: $0.04 per query. Source: On-chain analytics.", inputSchema: { chain: z .enum(["ethereum", "arbitrum", "polygon", "base", "bsc"]) .optional() .describe("Filter by blockchain network"), min_usd: z .number() .optional() .describe("Minimum movement size in USD"), token: z .string() .optional() .describe("Filter by token symbol"), hours: z .number() .int() .min(1) .max(168) .optional() .describe("Lookback period in hours (default 24, max 168)"), limit: z .number() .int() .min(1) .max(100) .optional() .describe("Maximum results (default 25)"), }, }, async ({ chain, min_usd, token, hours, limit }) => { const res = await apiGet<WhaleQueryResponse>("/api/v1/whales/movements", { chain, min_usd, token, hours: hours ?? 24, limit: limit ?? 25, }); if (!res.ok) { return { content: [ { type: "text" as const, text: `API error (${res.status}): ${JSON.stringify(res.data)}`, }, ], isError: true, }; } const { count, data } = res.data; const warn = stalenessWarning(res); const summary = `${warn}Found ${count} whale movement(s).`; const json = JSON.stringify(data, null, 2); return { content: [{ type: "text" as const, text: `${summary}\n\n${json}` }], }; }, - src/tools/whales.ts:149-176 (schema)Zod input schema for whale_movements: optional chain (enum), min_usd (number), token (string), hours (int 1-168), limit (int 1-100).
inputSchema: { chain: z .enum(["ethereum", "arbitrum", "polygon", "base", "bsc"]) .optional() .describe("Filter by blockchain network"), min_usd: z .number() .optional() .describe("Minimum movement size in USD"), token: z .string() .optional() .describe("Filter by token symbol"), hours: z .number() .int() .min(1) .max(168) .optional() .describe("Lookback period in hours (default 24, max 168)"), limit: z .number() .int() .min(1) .max(100) .optional() .describe("Maximum results (default 25)"), }, - src/tools/whales.ts:141-208 (registration)Registration of 'whale_movements' tool via server.registerTool() within registerWhaleTools() function.
server.registerTool( "whale_movements", { title: "Whale Movements", description: "Get large balance changes across whale wallets. Shows significant inflows, " + "outflows, and transfers that may signal market moves. " + "Cost: $0.04 per query. Source: On-chain analytics.", inputSchema: { chain: z .enum(["ethereum", "arbitrum", "polygon", "base", "bsc"]) .optional() .describe("Filter by blockchain network"), min_usd: z .number() .optional() .describe("Minimum movement size in USD"), token: z .string() .optional() .describe("Filter by token symbol"), hours: z .number() .int() .min(1) .max(168) .optional() .describe("Lookback period in hours (default 24, max 168)"), limit: z .number() .int() .min(1) .max(100) .optional() .describe("Maximum results (default 25)"), }, }, async ({ chain, min_usd, token, hours, limit }) => { const res = await apiGet<WhaleQueryResponse>("/api/v1/whales/movements", { chain, min_usd, token, hours: hours ?? 24, limit: limit ?? 25, }); if (!res.ok) { return { content: [ { type: "text" as const, text: `API error (${res.status}): ${JSON.stringify(res.data)}`, }, ], isError: true, }; } const { count, data } = res.data; const warn = stalenessWarning(res); const summary = `${warn}Found ${count} whale movement(s).`; const json = JSON.stringify(data, null, 2); return { content: [{ type: "text" as const, text: `${summary}\n\n${json}` }], }; }, ); - src/index.ts:49-49 (registration)Top-level registration of all whale tools (including whale_movements) in the MCP server.
registerWhaleTools(server); - src/client.ts:44-76 (helper)HTTP GET helper that the handler uses to call /api/v1/whales/movements on the Verilex API.
export async function apiGet<T = unknown>( path: string, params?: Record<string, string | number | undefined>, ): Promise<ApiResponse<T>> { const url = buildUrl(path, params); const headers: Record<string, string> = { Accept: "application/json", "User-Agent": "verilex-mcp-server/0.1.0", }; // Forward x402 payment token if present in env (for paid endpoints) const paymentToken = process.env.VERILEX_PAYMENT_TOKEN; if (paymentToken) { headers["X-Payment-Token"] = paymentToken; } const res = await fetch(url, { headers }); const data = (await res.json()) as T; const stale = res.headers.get("X-Data-Stale"); const lastUpdated = res.headers.get("X-Data-Last-Updated"); const ageSeconds = res.headers.get("X-Data-Age-Seconds"); return { ok: res.ok, status: res.status, data, stale: stale === "true", lastUpdated: lastUpdated ?? undefined, ageSeconds: ageSeconds ? Number(ageSeconds) : undefined, }; }