Polymarket Whale Wallets
pm_whalesRetrieve top Polymarket wallets ranked by profit and loss, volume, or position size. Access wallet address, total PnL, win rate, and active markets for smart money analysis.
Instructions
Get top Polymarket wallets ranked by PnL, volume, or position size. Shows wallet address, total PnL, win rate, and active markets. Cost: $0.005 per query. Source: Polymarket on-chain data.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| sort | No | Sort order (default: pnl) | |
| market_id | No | Filter by specific market ID | |
| limit | No | Maximum results (default 25) |
Implementation Reference
- src/tools/pm.ts:58-86 (handler)Handler for the pm_whales tool. Calls /api/v1/pm/whales with optional sort, market_id, and limit params, formats response as text.
async ({ sort, market_id, limit }) => { const res = await apiGet<PmQueryResponse>("/api/v1/pm/whales", { sort: sort ?? "pnl", market_id, 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} Polymarket whale(s).`; const json = JSON.stringify(data, null, 2); return { content: [{ type: "text" as const, text: `${summary}\n\n${json}` }], }; }, ); - src/tools/pm.ts:40-56 (schema)Input schema for pm_whales with optional sort (enum pnl/volume/positions), market_id (string), and limit (1-100 integer).
inputSchema: { sort: z .enum(["pnl", "volume", "positions"]) .optional() .describe("Sort order (default: pnl)"), market_id: z .string() .optional() .describe("Filter by specific market ID"), limit: z .number() .int() .min(1) .max(100) .optional() .describe("Maximum results (default 25)"), }, - src/tools/pm.ts:32-86 (registration)Registration of pm_whales tool via server.registerTool() with title, description, inputSchema, and async handler.
server.registerTool( "pm_whales", { title: "Polymarket Whale Wallets", description: "Get top Polymarket wallets ranked by PnL, volume, or position size. " + "Shows wallet address, total PnL, win rate, and active markets. " + "Cost: $0.005 per query. Source: Polymarket on-chain data.", inputSchema: { sort: z .enum(["pnl", "volume", "positions"]) .optional() .describe("Sort order (default: pnl)"), market_id: z .string() .optional() .describe("Filter by specific market ID"), limit: z .number() .int() .min(1) .max(100) .optional() .describe("Maximum results (default 25)"), }, }, async ({ sort, market_id, limit }) => { const res = await apiGet<PmQueryResponse>("/api/v1/pm/whales", { sort: sort ?? "pnl", market_id, 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} Polymarket whale(s).`; const json = JSON.stringify(data, null, 2); return { content: [{ type: "text" as const, text: `${summary}\n\n${json}` }], }; }, ); - src/client.ts:25-76 (helper)Helper functions apiGet and stalenessWarning used by the pm_whales handler to call the Verilex API.
export interface ApiResponse<T = unknown> { ok: boolean; status: number; data: T; stale?: boolean; lastUpdated?: string; ageSeconds?: number; } /** Build a staleness warning string if the data is stale, or empty string. */ export function stalenessWarning(res: ApiResponse): string { if (!res.stale) return ""; const parts = ["[STALE DATA]"]; if (res.lastUpdated) parts.push(`Last updated: ${res.lastUpdated}`); if (res.ageSeconds != null) parts.push(`Age: ${res.ageSeconds}s`); return parts.join(" ") + "\n\n"; } /** Make a GET request to the Verilex API and return parsed JSON. */ 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, }; }