Skip to main content
Glama

get_address_balances

Retrieve cryptocurrency balances for an Ethereum address across multiple blockchain networks simultaneously, including Ethereum, Arbitrum, and Polygon.

Instructions

Get balances for a specific address across all chains (concurrent execution).

Args:
    address: Ethereum address to check balances for
    timeout_seconds: Timeout for the entire operation (default: 30 seconds)

Returns:
    JSON string with balance information across all chains.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
addressYes
timeout_secondsNo

Implementation Reference

  • The primary handler function for the 'get_address_balances' tool. It validates the input address, creates concurrent tasks to fetch native and PUSD balances across all supported chains using Web3 clients, combines results, and returns formatted JSON.
    @mcp.tool()
    async def get_address_balances(ctx: Context, address: str, timeout_seconds: float = 30.0) -> str:
        """Get balances for a specific address across all chains (concurrent execution).
        
        Args:
            address: Ethereum address to check balances for
            timeout_seconds: Timeout for the entire operation (default: 30 seconds)
        
        Returns:
            JSON string with balance information across all chains.
        """
        try:
            paloma_ctx = ctx.request_context.lifespan_context
            
            # Validate address
            if not Web3.is_address(address):
                return f"Error: Invalid address format: {address}"
            
            address = Web3.to_checksum_address(address)
            
            # Create tasks for concurrent execution
            tasks = []
            chain_names = []
            
            for chain_id, config in CHAIN_CONFIGS.items():
                if chain_id in paloma_ctx.web3_clients:
                    web3 = paloma_ctx.web3_clients[chain_id]
                    task = _get_chain_balance(web3, address, config, chain_id)
                    tasks.append(task)
                    chain_names.append(config.name)
            
            # Execute all balance checks concurrently (no overall timeout, individual chains handle their own timeouts)
            results = await asyncio.gather(*tasks, return_exceptions=True)
            
            # Combine results
            balances = {}
            for result in results:
                if isinstance(result, dict):
                    balances.update(result)
                elif isinstance(result, Exception):
                    logger.error(f"Chain balance check failed: {result}")
            
            result = {
                "address": address,
                "balances": balances,
                "chains_checked": len(tasks),
                "timeout_seconds": timeout_seconds,
                "timestamp": asyncio.get_event_loop().time()
            }
            
            return json.dumps(result, indent=2)
            
        except Exception as e:
            logger.error(f"Error getting address balances: {e}")
            return f"Error getting address balances: {str(e)}"
  • Supporting helper function used by get_address_balances to retrieve native token balance and optional PUSD token balance for a single chain, with per-chain timeouts to prevent hanging.
    async def _get_chain_balance(web3: Web3, address: str, config: ChainConfig, chain_id: str) -> Dict[str, Any]:
        """Helper function to get balance for a single chain with individual timeout."""
        try:
            # Get native balance with individual timeout (5 seconds per chain)
            native_balance_wei = await asyncio.wait_for(
                asyncio.get_event_loop().run_in_executor(
                    None, lambda: web3.eth.get_balance(address)
                ),
                timeout=5.0
            )
            native_balance = web3.from_wei(native_balance_wei, 'ether')
            
            chain_balances = {
                "native_balance": str(native_balance),
                "native_symbol": "ETH" if chain_id == ChainID.ETHEREUM_MAIN else config.name.split()[0]
            }
            
            # Get PUSD balance if configured (with individual timeout)
            if config.pusd_token:
                try:
                    pusd_contract = web3.eth.contract(
                        address=config.pusd_token,
                        abi=ERC20_ABI
                    )
                    
                    # Wrap contract calls in timeout
                    pusd_balance_wei = await asyncio.wait_for(
                        asyncio.get_event_loop().run_in_executor(
                            None, lambda: pusd_contract.functions.balanceOf(address).call()
                        ),
                        timeout=5.0
                    )
                    pusd_decimals = await asyncio.wait_for(
                        asyncio.get_event_loop().run_in_executor(
                            None, lambda: pusd_contract.functions.decimals().call()
                        ),
                        timeout=5.0
                    )
                    pusd_balance = pusd_balance_wei / (10 ** pusd_decimals)
                    chain_balances["pusd_balance"] = str(pusd_balance)
                except asyncio.TimeoutError:
                    chain_balances["pusd_balance"] = "Timeout"
                except Exception as e:
                    chain_balances["pusd_balance"] = f"Error: {str(e)}"
            
            return {config.name: chain_balances}
            
        except asyncio.TimeoutError:
            return {config.name: {"error": "Timeout (5s)"}}
        except Exception as e:
            return {config.name: {"error": str(e)}}
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden. It discloses key behavioral traits: concurrent execution across chains, timeout parameter with default, and JSON return format. However, it lacks details on error handling, rate limits, authentication needs, or what 'balance information' specifically includes (e.g., token types, amounts).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with core purpose, followed by structured Args and Returns sections. Every sentence adds value: the first states purpose and concurrency, Args explain parameters, Returns specifies output format. No wasted words, efficiently organized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description provides basic completeness for a read operation with 2 parameters. It covers purpose, parameters, and return format, but lacks details on output structure (e.g., chain-specific balances), error cases, or performance considerations, leaving gaps for agent invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It adds meaningful semantics: 'address' is an Ethereum address for balance checking, and 'timeout_seconds' defines operation timeout with a default. This clarifies beyond schema types, though it could specify address format (e.g., 0x-prefixed) or timeout implications.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Get balances') and resource ('for a specific address across all chains'), with the parenthetical 'concurrent execution' adding operational detail. It distinguishes from sibling 'get_address_balance_single_chain' by specifying 'across all chains' versus single-chain focus.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context by specifying 'across all chains' and 'concurrent execution,' which helps differentiate from the single-chain sibling tool. However, it lacks explicit guidance on when to use this versus alternatives like 'get_account_info' or 'get_etf_balance,' and does not mention prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/VolumeFi/mcpPADEX'

If you have feedback or need assistance with the MCP directory API, please join our Discord server