azeth_balance
Check ETH, USDC, and WETH balances with USD values for your EOA and Azeth smart accounts to view total portfolio value before transactions.
Instructions
Check all balances with USD values for your EOA and all Azeth smart accounts.
Use this when: You need to know how much ETH, USDC, or WETH your accounts hold, or you want a total portfolio value in USD before making a transfer or payment.
Returns: Multi-account breakdown with per-token USD values and grand total. EOA is shown first (index 0), followed by smart accounts in deployment order.
Optionally filter to a single smart account by providing its address.
Note: This is a read-only, single-RPC-call operation and safe to call repeatedly. The owner is determined by the AZETH_PRIVATE_KEY environment variable.
Example: {} or { "smartAccount": "#1" }
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| chain | No | Target chain. Defaults to AZETH_CHAIN env var or "baseSepolia". Accepts "base", "baseSepolia", "ethereumSepolia", "ethereum" (and aliases like "base-sepolia", "eth-sepolia", "sepolia", "eth", "mainnet"). | |
| smartAccount | No | Smart account address, name, or "#N" (account index). If omitted, shows all accounts. |
Implementation Reference
- src/tools/account.ts:220-322 (handler)The azeth_balance handler which checks account balances and USD values, with optional filtering for smart accounts and integration with the trust registry for labels.
server.registerTool( 'azeth_balance', { description: [ 'Check all balances with USD values for your EOA and all Azeth smart accounts.', '', 'Use this when: You need to know how much ETH, USDC, or WETH your accounts hold,', 'or you want a total portfolio value in USD before making a transfer or payment.', '', 'Returns: Multi-account breakdown with per-token USD values and grand total.', 'EOA is shown first (index 0), followed by smart accounts in deployment order.', '', 'Optionally filter to a single smart account by providing its address.', '', 'Note: This is a read-only, single-RPC-call operation and safe to call repeatedly.', 'The owner is determined by the AZETH_PRIVATE_KEY environment variable.', '', 'Example: {} or { "smartAccount": "#1" }', ].join('\n'), inputSchema: z.object({ chain: z.string().optional().describe('Target chain. Defaults to AZETH_CHAIN env var or "baseSepolia". Accepts "base", "baseSepolia", "ethereumSepolia", "ethereum" (and aliases like "base-sepolia", "eth-sepolia", "sepolia", "eth", "mainnet").'), smartAccount: z.string().optional().describe('Smart account address, name, or "#N" (account index). If omitted, shows all accounts.'), }), }, async (args) => { let client; try { client = await createClient(args.chain); // Resolve smartAccount: address, name, "#N", or undefined let targetAddress: `0x${string}` | undefined; if (args.smartAccount) { try { targetAddress = await resolveSmartAccount(args.smartAccount, client); } catch (resolveErr) { return handleError(resolveErr); } } const allBalances = await client.getAllBalances(); let accounts = allBalances.accounts; if (targetAddress) { const target = targetAddress.toLowerCase(); accounts = accounts.filter((ab) => ab.account.toLowerCase() === target); } // Enrich smart account labels with names from the trust registry. // Skip index 0 (EOA). Non-fatal: falls back to default label on any failure. const chain = resolveChain(args.chain); const trustRegistryAddr = AZETH_CONTRACTS[chain].trustRegistryModule; const identityRegistryAddr = ERC8004_REGISTRY[chain]; for (let i = 0; i < accounts.length; i++) { const ab = accounts[i]!; // EOA label is always "EOA Wallet" — skip if (i === 0 && !targetAddress) continue; try { const tokenId = await client.publicClient.readContract({ address: trustRegistryAddr, abi: TrustRegistryModuleAbi, functionName: 'getTokenId', args: [ab.account as `0x${string}`], }); if (tokenId > 0n) { const uri = await client.publicClient.readContract({ address: identityRegistryAddr, abi: ERC8004_TOKEN_URI_ABI, functionName: 'tokenURI', args: [tokenId], }); const name = parseAgentMetadata(uri).name; if (name !== '(unknown)') { // Extract the #N index from the existing label if present const indexMatch = ab.label.match(/#(\d+)/); ab.label = indexMatch ? `${name} (#${indexMatch[1]})` : name; } } } catch { // Non-fatal — keep existing label } } return success({ owner: client.address, grandTotalUSD: allBalances.grandTotalUSDFormatted, accounts: accounts.map((ab) => ({ account: ab.account, label: ab.label, totalUSD: ab.totalUSDFormatted, balances: ab.balances.map((tb) => ({ token: tb.symbol, balance: tb.balanceFormatted, usdValue: tb.usdFormatted, })), })), }); } catch (err) { return handleError(err); } finally { try { await client?.destroy(); } catch (e) { process.stderr.write(`[azeth-mcp] destroy error: ${e instanceof Error ? e.message : String(e)}\n`); } } }, ); - src/tools/account.ts:221-221 (registration)Registration of the azeth_balance tool within the registerAccountTools function.
'azeth_balance',