get_funding_rates
Fetch perpetual futures funding rates from 6 venues and identify arbitrage opportunities with annualized carry. Returns per-8h rates, APR, open interest, and next funding time.
Instructions
Get perpetual futures funding rates across 6 venues: Hyperliquid, dYdX v4, Aevo, GMX, Drift, and Vertex. Returns per-8h funding rate, annualized APR, predicted rate, open interest, and next funding time for each venue. Also returns ranked arbitrage opportunities (long low-rate venue, short high-rate venue) with spread in bps and annualized carry. Costs 0.008 USDC per call (x402 micropayment on Base).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| asset | No | Asset symbol (e.g. "BTC", "ETH", "SOL"). Returns all assets if omitted. | |
| min_spread | No | Filter for arbitrage spreads >= N basis points (e.g. 0.5). Omit for no filter. |
Implementation Reference
- src/index.ts:374-393 (schema)Schema/definition for the 'get_funding_rates' tool: describes it as getting perpetual futures funding rates across 6 venues (Hyperliquid, dYdX v4, Aevo, GMX, Drift, Vertex). Accepts optional 'asset' and 'min_spread' parameters. Costs 0.008 USDC.
name: 'get_funding_rates', description: 'Get perpetual futures funding rates across 6 venues: Hyperliquid, dYdX v4, Aevo, GMX, Drift, and Vertex. ' + 'Returns per-8h funding rate, annualized APR, predicted rate, open interest, and next funding time for each venue. ' + 'Also returns ranked arbitrage opportunities (long low-rate venue, short high-rate venue) with spread in bps and annualized carry. ' + 'Costs 0.008 USDC per call (x402 micropayment on Base).', inputSchema: { type: 'object', properties: { asset: { type: 'string', description: 'Asset symbol (e.g. "BTC", "ETH", "SOL"). Returns all assets if omitted.', }, min_spread: { type: 'number', description: 'Filter for arbitrage spreads >= N basis points (e.g. 0.5). Omit for no filter.', }, }, required: [], }, - src/index.ts:246-417 (registration)The tool is registered in the TOOLS array at line 374 and in the TOOLS constant section starting at line 246. It is part of the ListToolsRequestSchema handler (line 434) and the CallToolRequestSchema switch statement (line 498).
const TOOLS = [ { name: 'get_crypto_prices', description: 'Get live cryptocurrency prices and top 24h movers. Returns BTC, ETH, SOL prices plus top gainers/losers. ' + 'Costs 0.001 USDC per call (x402 micropayment on Base). ' + 'Data sourced live from CoinGecko.', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_gas_prices', description: 'Get current gas prices across multiple chains: Ethereum, Base, Polygon, and Arbitrum. ' + 'Returns slow/standard/fast tiers in gwei and estimated USD cost. ' + 'Costs 0.001 USDC per call (x402 micropayment on Base).', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_dex_quotes', description: 'Compare swap quotes across DEXes: Uniswap, SushiSwap, and 1inch. ' + 'Returns best price, price impact, liquidity, and estimated fees for each venue. ' + 'Costs 0.002 USDC per call (x402 micropayment on Base).', inputSchema: { type: 'object', properties: { from: { type: 'string', description: 'Input token symbol or address (e.g. "ETH", "USDC", "0x...")', }, to: { type: 'string', description: 'Output token symbol or address (e.g. "USDC", "DAI", "0x...")', }, amount: { type: 'string', description: 'Amount to swap (e.g. "1.5" for 1.5 ETH)', }, chain: { type: 'string', description: 'Chain to query (e.g. "ethereum", "base", "arbitrum"). Defaults to "ethereum".', }, }, required: ['from', 'to', 'amount'], }, }, { name: 'scan_token', description: 'Perform a security scan on a token contract. Detects rug-pull risks, honeypot patterns, ' + 'ownership concentration, mint authority, and other red flags. ' + 'Costs 0.003 USDC per call (x402 micropayment on Base).', inputSchema: { type: 'object', properties: { token: { type: 'string', description: 'Token contract address (0x...) or symbol (e.g. "PEPE", "UNI")', }, chain: { type: 'string', description: 'Chain to scan on (e.g. "ethereum", "base", "arbitrum", "polygon"). Defaults to "ethereum".', }, }, required: ['token'], }, }, { name: 'track_whales', description: 'Analyze whale activity and holder concentration for a token. Returns top holders, ' + 'Gini coefficient, whale alerts (large recent buys/sells), and distribution breakdown. ' + 'Costs 0.005 USDC per call (x402 micropayment on Base).', inputSchema: { type: 'object', properties: { token: { type: 'string', description: 'Token contract address (0x...) or symbol (e.g. "ETH", "PEPE")', }, chain: { type: 'string', description: 'Chain to query (e.g. "ethereum", "base", "solana", "arbitrum"). Defaults to "ethereum".', }, }, required: ['token'], }, }, { name: 'scan_yields', description: 'Scan top DeFi yield opportunities across protocols: Aave, Compound, Morpho, Lido, Pendle, and more. ' + 'Filter by chain, asset, and minimum TVL. Returns APY, TVL, risk score, and protocol details. ' + 'Costs 0.005 USDC per call (x402 micropayment on Base).', inputSchema: { type: 'object', properties: { chain: { type: 'string', description: 'Blockchain to filter by (e.g. "ethereum", "base", "arbitrum", "polygon"). ' + 'Omit for all chains.', }, asset: { type: 'string', description: 'Filter by asset symbol (e.g. "ETH", "USDC", "stETH"). Omit for all assets.', }, min_tvl: { type: 'number', description: 'Minimum TVL in USD (e.g. 1000000 for $1M). Omit for no minimum.', }, limit: { type: 'number', description: 'Maximum number of results to return (1–50). Defaults to 20.', }, }, required: [], }, }, { name: 'get_funding_rates', description: 'Get perpetual futures funding rates across 6 venues: Hyperliquid, dYdX v4, Aevo, GMX, Drift, and Vertex. ' + 'Returns per-8h funding rate, annualized APR, predicted rate, open interest, and next funding time for each venue. ' + 'Also returns ranked arbitrage opportunities (long low-rate venue, short high-rate venue) with spread in bps and annualized carry. ' + 'Costs 0.008 USDC per call (x402 micropayment on Base).', inputSchema: { type: 'object', properties: { asset: { type: 'string', description: 'Asset symbol (e.g. "BTC", "ETH", "SOL"). Returns all assets if omitted.', }, min_spread: { type: 'number', description: 'Filter for arbitrage spreads >= N basis points (e.g. 0.5). Omit for no filter.', }, }, required: [], }, }, { name: 'profile_wallet', description: 'Generate a full portfolio profile for an Ethereum/Base wallet address. ' + 'Returns token holdings, NFTs, DeFi positions, transaction history summary, ' + 'PnL estimate, and risk profile score. ' + 'Costs 0.008 USDC per call (x402 micropayment on Base).', inputSchema: { type: 'object', properties: { address: { type: 'string', description: 'Ethereum or Base wallet address (0x...)', }, chain: { type: 'string', description: 'Filter by chain (e.g. "ethereum", "base", "arbitrum", "polygon"). Defaults to "all".', }, }, required: ['address'], }, }, ]; - src/index.ts:498-503 (handler)Handler for 'get_funding_rates': calls the backend API at '/api/funding-rates' with optional 'asset' and 'min_spread' query parameters via callApi(). The result is formatted and returned as text content.
case 'get_funding_rates': result = await callApi('/api/funding-rates', { asset: params.asset, min_spread: params.min_spread, }); break; - src/index.ts:114-180 (helper)The callApi() helper function (lines 114-180) is the generic HTTP request helper used by all tool handlers. For get_funding_rates, it sends a GET to '/api/funding-rates?asset=...&min_spread=...'. Handles x402 payment protocol (402 responses), timeouts, and error formatting.
async function callApi( endpoint: string, params: Record<string, string | number | undefined> = {} ): Promise<ApiResponse> { const url = new URL(`${API_BASE_URL}${endpoint}`); for (const [key, value] of Object.entries(params)) { if (value !== undefined && value !== '') { url.searchParams.set(key, String(value)); } } const fetchFn = await getX402Fetch(); let response: Response; const controller = new AbortController(); const fetchTimeout = setTimeout(() => controller.abort(), 30_000); try { response = await fetchFn(url.toString(), { headers: { 'Accept': 'application/json', 'User-Agent': `x402-api-mcp/${SERVER_VERSION}`, }, signal: controller.signal, }); } catch (err) { const isTimeout = err instanceof Error && err.name === 'AbortError'; throw new McpError( ErrorCode.InternalError, isTimeout ? `Request to ${endpoint} timed out after 30 seconds` : `Network error calling ${endpoint}: ${err instanceof Error ? err.message : String(err)}` ); } finally { clearTimeout(fetchTimeout); } if (response.status === 402) { // Clone before reading so we can fall back to text() if JSON parsing fails. // Without the clone, calling response.json() consumes the body; a subsequent // response.text() call then throws "body already used". const cloned = response.clone(); let paymentDetails: unknown; try { paymentDetails = await response.json(); } catch { paymentDetails = await cloned.text(); } return { status: 402, data: null, paymentRequired: true, paymentDetails }; } if (!response.ok) { const errorText = await response.text(); if (response.status === 400 || response.status === 422) { throw new McpError( ErrorCode.InvalidParams, `Invalid request to ${endpoint}: ${errorText}` ); } throw new McpError( ErrorCode.InternalError, `API error ${response.status} from ${endpoint}: ${errorText}` ); } const data = await response.json(); return { status: response.status, data }; }