erc20_getTokenInfo
Retrieve ERC20 token details like name, symbol, decimals, and total supply by providing the contract address on Ethereum networks.
Instructions
Get detailed information about an ERC20 token including its name, symbol, decimals, and total supply. Alternative naming for compatibility with MCP client tests.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| contractAddress | Yes | The address of the ERC20 token contract | |
| tokenAddress | No | DEPRECATED: Use contractAddress instead. The address of the ERC20 token contract | |
| provider | No | Optional. Either a network name or custom RPC URL. Use getAllNetworks to see available networks and their details, or getNetwork to get info about a specific network. You can use any network name returned by these tools as a provider value. | |
| chainId | No | Optional. The chain ID to use. If provided with a named network and they don't match, the RPC's chain ID will be used. |
Implementation Reference
- src/tools/erc20.ts:110-154 (registration)Registration of the 'erc20_getTokenInfo' tool using server.tool, including schema and handler function. This is the primary location where the tool is defined and registered with the MCP server.server.tool( "erc20_getTokenInfo", "Get detailed information about an ERC20 token including its name, symbol, decimals, and total supply. Alternative naming for compatibility with MCP client tests.", { contractAddress: contractAddressSchema, tokenAddress: tokenAddressSchema.optional(), // Deprecated provider: providerSchema, chainId: chainIdSchema }, async (params) => { // Map deprecated parameters const mapped = mapParameters(params); try { const contractAddr = mapped.contractAddress || params.tokenAddress; if (!contractAddr) { throw new Error('Either contractAddress or tokenAddress must be provided'); } const tokenInfo = await ethersService.getERC20TokenInfo( contractAddr, mapped.provider, mapped.chainId ); return { content: [{ type: "text", text: `Token Information: Name: ${tokenInfo.name} Symbol: ${tokenInfo.symbol} Decimals: ${tokenInfo.decimals} Total Supply: ${tokenInfo.totalSupply}` }] }; } catch (error) { return { isError: true, content: [{ type: "text", text: `Error getting token information: ${error instanceof Error ? error.message : String(error)}` }] }; } } );
- src/tools/erc20.ts:119-154 (handler)The handler function for erc20_getTokenInfo tool that processes parameters, calls EthersService.getERC20TokenInfo, and returns formatted token information or error.async (params) => { // Map deprecated parameters const mapped = mapParameters(params); try { const contractAddr = mapped.contractAddress || params.tokenAddress; if (!contractAddr) { throw new Error('Either contractAddress or tokenAddress must be provided'); } const tokenInfo = await ethersService.getERC20TokenInfo( contractAddr, mapped.provider, mapped.chainId ); return { content: [{ type: "text", text: `Token Information: Name: ${tokenInfo.name} Symbol: ${tokenInfo.symbol} Decimals: ${tokenInfo.decimals} Total Supply: ${tokenInfo.totalSupply}` }] }; } catch (error) { return { isError: true, content: [{ type: "text", text: `Error getting token information: ${error instanceof Error ? error.message : String(error)}` }] }; } } );
- src/tools/erc20.ts:113-118 (schema)Input schema definition for the erc20_getTokenInfo tool, referencing shared Zod schemas for parameters.{ contractAddress: contractAddressSchema, tokenAddress: tokenAddressSchema.optional(), // Deprecated provider: providerSchema, chainId: chainIdSchema },
- src/services/erc/erc20.ts:34-102 (helper)Low-level helper function getTokenInfo that implements the core logic for fetching ERC20 token information, likely wrapped by EthersService.getERC20TokenInfo.export async function getTokenInfo( ethersService: EthersService, tokenAddress: string, provider?: string, chainId?: number ): Promise<ERC20Info> { metrics.incrementCounter('erc20.getTokenInfo'); return timeAsync('erc20.getTokenInfo', async () => { try { // Check rate limiting const identity = `${tokenAddress}:${provider || 'default'}`; if (!rateLimiter.consume('token', identity)) { throw new ERC20Error('Rate limit exceeded for token operations'); } // Create cache key const cacheKey = createTokenCacheKey( CACHE_KEYS.ERC20_INFO, tokenAddress, chainId ); // Check cache first const cachedInfo = contractCache.get(cacheKey); if (cachedInfo) { return cachedInfo as ERC20Info; } // Get provider from ethers service const ethersProvider = ethersService['getProvider'](provider, chainId); // Create contract instance const contract = new ethers.Contract(tokenAddress, ERC20_ABI, ethersProvider); // Fetch token information const [name, symbol, decimals, totalSupply] = await Promise.all([ contract.name(), contract.symbol(), contract.decimals(), contract.totalSupply() ]); // Format data const tokenInfo: ERC20Info = { name, symbol, decimals, totalSupply: totalSupply.toString() }; // Cache result for future use (1 day TTL) contractCache.set(cacheKey, tokenInfo, { ttl: 86400000 }); return tokenInfo; } catch (error) { logger.debug('Error getting ERC20 token info', { tokenAddress, error }); if (error instanceof Error && ( error.message.includes('contract not deployed') || error.message.includes('invalid address') )) { throw new TokenNotFoundError(tokenAddress); } throw handleTokenError(error, 'Failed to get token information'); } }); }