get_erc20_balance
Retrieve the ERC20 token balance for a specified Ethereum address by providing the wallet address and token contract address. Works across multiple Ethereum-compatible networks.
Instructions
Get the ERC20 token balance of an Ethereum address
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | The Ethereum address to check | |
| network | No | Network name or chain ID. Defaults to Ethereum mainnet. | |
| tokenAddress | Yes | The ERC20 token contract address |
Implementation Reference
- src/core/tools.ts:397-422 (handler)Handler function for the 'get_token_balance' MCP tool that invokes the getERC20Balance service, formats the response, and handles errors.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/tools.ts:384-388 (schema)Zod input schema defining parameters for the ERC20 balance tool: address (wallet/ENS), tokenAddress (ERC20 contract), and optional network.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.") },
- src/core/tools.ts:380-423 (registration)Registration of the MCP tool 'get_token_balance' (functionally equivalent to get_erc20_balance) including description, schema, annotations, and handler reference.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:98-136 (helper)Core helper function getERC20Balance that resolves ENS names, fetches balance, symbol, and decimals from the ERC20 contract using viem, and 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 } }; }