Skip to main content
Glama

read.wallet.balances

Read-onlyIdempotent

Check wallet balances for native ETH and ERC20 tokens on supported chains to verify token availability before executing transactions.

Instructions

Get native ETH and ERC20 token balances for a wallet address. Reads directly from chain via RPC multicall. Use before write.account.add_liquidity or write.account.deposit to verify the wallet has sufficient tokens. Returns both raw balance (smallest unit/wei) and formatted (human-readable) per token.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
wallet_addressYesWallet address to check balances for
token_addressesYesERC20 token contract addresses to check
chain_idNoChain ID: 8453 (Base) or 130 (Unichain)

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
nativeYes
tokensYes

Implementation Reference

  • Handler implementation for the "read.wallet.balances" tool, which uses viem to get native ETH balance and ERC20 token balances via multicall.
    async ({ wallet_address, token_addresses, chain_id }) => {
      try {
        const validChainId = validateChainId(chain_id);
        const wallet = validateAddress(wallet_address, "wallet_address");
        const client = getPublicClient(validChainId, chains);
    
        // Build multicall: for each token get balanceOf, decimals, symbol
        const calls = token_addresses.flatMap((addr) => [
          {
            address: addr as `0x${string}`,
            abi: erc20Abi,
            functionName: "balanceOf" as const,
            args: [wallet],
          },
          { address: addr as `0x${string}`, abi: erc20Abi, functionName: "decimals" as const },
          { address: addr as `0x${string}`, abi: erc20Abi, functionName: "symbol" as const },
        ]);
    
        const [nativeBalance, ...multicallResults] = await Promise.all([
          client.getBalance({ address: wallet }),
          ...(calls.length > 0 ? [client.multicall({ contracts: calls, allowFailure: true })] : []),
        ]);
    
        const results = (multicallResults[0] ?? []) as { status: string; result?: unknown }[];
        const tokens = token_addresses.map((addr, i) => {
          const balRes = results[i * 3];
          const decRes = results[i * 3 + 1];
          const symRes = results[i * 3 + 2];
    
          const balance = balRes?.status === "success" ? String(balRes.result) : "0";
          const decimals = decRes?.status === "success" ? Number(decRes.result) : 18;
          const symbol = symRes?.status === "success" ? String(symRes.result) : "???";
    
          return {
            address: addr,
            symbol,
            decimals,
            balance,
            formatted: formatUnits(BigInt(balance), decimals),
          };
        });
    
        const result = {
          native: {
            symbol: "ETH",
            balance: String(nativeBalance),
            formatted: formatUnits(nativeBalance, 18),
          },
          tokens,
        };
    
        return {
          content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
          structuredContent: result,
        };
      } catch (err) {
        return {
          content: [
            {
              type: "text" as const,
              text: `Error: ${err instanceof Error ? err.message : String(err)}`,
            },
          ],
          isError: true,
        };
      }
    },
  • Registration of the "read.wallet.balances" tool with its description, input schema, and annotations.
    server.registerTool(
      "read.wallet.balances",
      {
        annotations: {
          title: "Get Wallet Balances",
          readOnlyHint: true,
          destructiveHint: false,
          idempotentHint: true,
          openWorldHint: true,
        },
        description:
          "Get native ETH and ERC20 token balances for a wallet address. Reads directly from chain via RPC multicall. Use before write.account.add_liquidity or write.account.deposit to verify the wallet has sufficient tokens. Returns both raw balance (smallest unit/wei) and formatted (human-readable) per token.",
        inputSchema: {
          wallet_address: z.string().describe("Wallet address to check balances for"),
          token_addresses: z.array(z.string()).describe("ERC20 token contract addresses to check"),
          chain_id: z.number().default(8453).describe("Chain ID: 8453 (Base) or 130 (Unichain)"),
        },
        outputSchema: WalletBalancesOutput,
      },

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/arcadia-finance/arcadia-finance-mcp-server'

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