get_token_balance
Retrieve the ERC20 token balance for a specific wallet address on any EVM-compatible network using blockchain data. Input wallet and token addresses to get accurate results.
Instructions
Get the balance of an ERC20 token for an address
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| network | No | Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', etc.) or chain ID. Supports all EVM-compatible networks. Defaults to Ethereum mainnet. | |
| ownerAddress | Yes | The wallet address or ENS name to check the balance for (e.g., '0x1234...' or 'vitalik.eth') | |
| tokenAddress | Yes | The contract address or ENS name of the ERC20 token (e.g., '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' for USDC or 'uniswap.eth') |
Implementation Reference
- src/core/services/balance.ts:98-136 (handler)Core helper function that executes the ERC20 balance query: resolves ENS if needed, creates viem contract, reads balanceOf, symbol, and decimals in parallel, formats the balance.export async function getERC20Balance( tokenAddressOrEns: string, ownerAddressOrEns: string, network = 'ethereum' ): Promise<{ raw: bigint; formatted: string; token: { symbol: string; decimals: number; } }> { // Resolve ENS names to addresses if needed const tokenAddress = await resolveAddress(tokenAddressOrEns, network); const ownerAddress = await resolveAddress(ownerAddressOrEns, network); const publicClient = getPublicClient(network); const contract = getContract({ address: tokenAddress, abi: erc20Abi, client: publicClient, }); const [balance, symbol, decimals] = await Promise.all([ contract.read.balanceOf([ownerAddress]), contract.read.symbol(), contract.read.decimals() ]); return { raw: balance, formatted: formatUnits(balance, decimals), token: { symbol, decimals } }; }
- src/core/tools.ts:380-423 (registration)MCP tool registration for get_token_balance, including Zod input schema, annotations, and thin handler that calls services.getERC20Balance and formats MCP response.server.registerTool( "get_token_balance", { description: "Get the ERC20 token balance for an address", inputSchema: { address: z.string().describe("The wallet address or ENS name"), tokenAddress: z.string().describe("The ERC20 token contract address"), network: z.string().optional().describe("Network name or chain ID. Defaults to Ethereum mainnet.") }, annotations: { title: "Get ERC20 Token Balance", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true } }, async ({ address, tokenAddress, network = "ethereum" }) => { try { const balance = await services.getERC20Balance(tokenAddress as Address, address as Address, network); return { content: [{ type: "text", text: JSON.stringify({ network, tokenAddress, address, balance: { raw: balance.raw.toString(), formatted: balance.formatted, symbol: balance.token.symbol, decimals: balance.token.decimals } }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error fetching token balance: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } );
- src/core/services/balance.ts:13-35 (schema)ERC20 ABI schema used by the balance helper for contract reads (symbol, decimals, balanceOf).const erc20Abi = [ { inputs: [], name: 'symbol', outputs: [{ type: 'string' }], stateMutability: 'view', type: 'function' }, { inputs: [], name: 'decimals', outputs: [{ type: 'uint8' }], stateMutability: 'view', type: 'function' }, { inputs: [{ type: 'address', name: 'account' }], name: 'balanceOf', outputs: [{ type: 'uint256' }], stateMutability: 'view', type: 'function' } ] as const;