DEV Community

Cover image for Asset Resolution in Claude: From Token Symbols to Contract Addresses
Wallet Guy
Wallet Guy

Posted on

Asset Resolution in Claude: From Token Symbols to Contract Addresses

Asset Resolution in Claude: From Token Symbols to Contract Addresses

MCP tools for onchain actions sound great until your Claude agent confidently tries to send USDC to a token symbol instead of a contract address — and the whole thing breaks before it starts. If you're building with Claude's Model Context Protocol and want your agent to actually execute DeFi actions, token resolution is the silent problem sitting between "Claude knows what to do" and "Claude can actually do it." Here's how WAIaaS handles it, and how one line in your claude_desktop_config.json gives your agent the tools to get this right.

Why Token Resolution Is Harder Than It Looks

When you tell Claude "swap 0.1 SOL for USDC on Jupiter," Claude understands the intent perfectly. But executing that swap requires a specific contract address for USDC on Solana (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v), the correct mint address for SOL's wrapped version, and the right amount in lamports — not in human-readable form. There's a wide gap between what a language model understands semantically and what a blockchain transaction needs structurally.

Most developers hit this wall when they try to wire up an LLM to onchain actions directly. The model hallucinates addresses, uses mainnet addresses on testnets, or gets the decimals wrong. You end up spending more time writing address resolution and validation logic than actually building the agent behavior you care about.

The stakes here go beyond broken transactions. A misresolved token address in a DeFi context — say, a lending position or a token approval — isn't just a failed call. It's potentially a transaction that goes through against the wrong contract. Building a proper resolution layer that handles symbols, chain context, and address validation is genuinely non-trivial.

WAIaaS as an MCP Server: The One-Line Setup

WAIaaS is a self-hosted Wallet-as-a-Service built specifically for AI agents. It exposes 45 MCP tools that Claude can call directly through the Model Context Protocol — covering wallet operations, token transfers, DeFi protocol actions, NFTs, and the x402 HTTP payment protocol.

To give Claude access to all of these, you add one server block to your Claude Desktop config:

{
  "mcpServers": {
    "waiaas": {
      "command": "npx",
      "args": ["-y", "@waiaas/mcp"],
      "env": {
        "WAIAAS_BASE_URL": "http://127.0.0.1:3100",
        "WAIAAS_SESSION_TOKEN": "wai_sess_<your-token>",
        "WAIAAS_DATA_DIR": "~/.waiaas"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

That's the one line (okay, one block) that changes the situation. Claude now has a session-authenticated wallet with tools for resolving assets, checking balances, executing swaps, querying DeFi positions, and more. The WAIAAS_SESSION_TOKEN scopes Claude's access to a specific wallet — the agent can't do anything the session isn't permitted to do.

The resolve-asset and get-tokens Tools

Among the 45 MCP tools WAIaaS provides, two are specifically relevant to the token resolution problem: resolve-asset and get-tokens.

When Claude needs to go from a human-readable symbol like "USDC" to the actual mint address needed for a Jupiter swap, it calls resolve-asset. The tool understands chain context — it knows that USDC on Solana has a different address than USDC on Ethereum mainnet, and it handles that disambiguation based on the wallet's configured network.

The get-tokens tool gives Claude a list of tokens available in the current wallet context, with their addresses, symbols, and chain information already attached. This means Claude doesn't have to guess or recall addresses from training data — it can look them up against the live configuration of the WAIaaS daemon.

Here's what the actual flow looks like after the MCP setup is in place:

User: "Swap 0.1 SOL for USDC on Jupiter"

→ Claude calls get-tokens to confirm USDC address on Solana
→ Claude calls action-provider with jupiter-swap
→ WAIaaS executes the swap through the Jupiter protocol integration
→ Claude reports the transaction result
Enter fullscreen mode Exit fullscreen mode

Claude is doing the orchestration. WAIaaS is doing the resolution, policy enforcement, signing, and execution. The two parts stay cleanly separated.

Getting Your Daemon Running First

Before the MCP config does anything useful, you need a WAIaaS daemon running locally. The fastest path:

npm install -g @waiaas/cli
waiaas init
waiaas start
waiaas quickset --mode mainnet
Enter fullscreen mode Exit fullscreen mode

quickset creates wallets and MCP sessions in one step, and prints the MCP config JSON you need to paste into Claude Desktop. Or, if you prefer Docker:

git clone https://github.com/waiaas/WAIaaS.git
cd WAIaaS
docker compose up -d
Enter fullscreen mode Exit fullscreen mode

The Docker image (ghcr.io/minhoyoo-iotrust/waiaas:latest) binds to 127.0.0.1:3100 by default, which is exactly where the MCP server config points.

If you want auto-provisioning so you're not prompted for a master password on first start:

docker run -d \
  --name waiaas \
  -p 127.0.0.1:3100:3100 \
  -v waiaas-data:/data \
  -e WAIAAS_AUTO_PROVISION=true \
  ghcr.io/minhoyoo-iotrust/waiaas:latest

docker exec waiaas cat /data/recovery.key
Enter fullscreen mode Exit fullscreen mode

That last command retrieves the auto-generated master password. Save it somewhere safe.

What Claude Can Actually Do After Setup

The 45 MCP tools span several categories that go well beyond token resolution. Here's a practical view of what's available once your agent has a session:

Wallet and balance operations:

  • get-balance — native token balance
  • get-assets — all token balances
  • get-address — wallet address
  • get-wallet-info — full wallet metadata

Transactions:

  • send-token — native or token transfer
  • send-batch — multiple transfers in one call
  • transfer-nft — ERC-721, ERC-1155, or Metaplex NFTs
  • simulate-transaction — dry-run before executing
  • get-transaction, list-transactions — history and status

DeFi actions:

  • action-provider — entry point for all 15 integrated DeFi protocols
  • get-defi-positions — lending and staking positions across protocols
  • get-health-factor — lending health for Aave and similar
  • hyperliquid — perpetuals, spot trading, sub-accounts
  • polymarket — prediction market positions

Asset resolution:

  • resolve-asset — symbol to address with chain context
  • get-tokens — available tokens for the current wallet

Onchain verification:

  • erc8004-get-agent-info — agent reputation lookup
  • erc8004-get-reputation — reputation score
  • erc8004-get-validation-status — validation state

The DeFi coverage comes from 15 integrated protocol providers: Aave v3, Across, D'CENT Swap, Drift, ERC-8004, Hyperliquid, Jito staking, Jupiter swap, Kamino, Lido staking, LI.FI, Pendle, Polymarket, XRPL DEX, and 0x swap. Claude can call any of these through the action-provider tool once the session is established.

Policies Keep Claude From Doing Too Much

Token resolution being correct is one part of the equation. The other part is making sure Claude's agent doesn't do more than it should — especially in a DeFi context where a single transaction can move significant value.

WAIaaS has a policy engine with 21 policy types and 4 security tiers: INSTANT, NOTIFY, DELAY, and APPROVAL. When you create a session for Claude, you configure policies on that session's wallet. A simple spending limit looks like this:

curl -X POST http://127.0.0.1:3100/v1/policies \
  -H "Content-Type: application/json" \
  -H "X-Master-Password: my-secret-password" \
  -d '{
    "walletId": "<wallet-uuid>",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'
Enter fullscreen mode Exit fullscreen mode

With this in place, Claude can execute small swaps immediately (under $100), gets a notification sent for medium ones (up to $500), larger transactions are queued for 15 minutes before executing (up to $2000), and anything above that requires your explicit approval. Claude doesn't control any of this — the policy engine runs server-side on every transaction that comes through the 7-stage pipeline.

The default-deny behavior for tokens is also worth knowing about: unless you configure an ALLOWED_TOKENS policy, token transfers are blocked. This means a misconfigured agent that resolves the wrong token can't accidentally send it — the policy layer catches it first.

If you want a domain-level allowlist for DeFi protocols Claude can interact with, the CONTRACT_WHITELIST policy handles that:

curl -X POST http://127.0.0.1:3100/v1/policies \
  -H "Content-Type: application/json" \
  -H "X-Master-Password: my-secret-password" \
  -d '{
    "walletId": "<wallet-uuid>",
    "type": "CONTRACT_WHITELIST",
    "rules": {
      "contracts": [
        {
          "address": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
          "name": "Jupiter",
          "chain": "solana"
        }
      ]
    }
  }'
Enter fullscreen mode Exit fullscreen mode

Multi-Wallet Setup for Separate Agent Contexts

If you're running multiple Claude agents — say, one for trading and one for a Solana-specific workflow — you can run separate MCP server instances pointing to different wallet sessions:

{
  "mcpServers": {
    "waiaas-trading": {
      "command": "npx",
      "args": ["-y", "@waiaas/mcp"],
      "env": {
        "WAIAAS_BASE_URL": "http://127.0.0.1:3100",
        "WAIAAS_AGENT_ID": "019c47d6-51ef-7f43-a76b-d50e875d95f4",
        "WAIAAS_AGENT_NAME": "trading-agent",
        "WAIAAS_DATA_DIR": "~/.waiaas"
      }
    },
    "waiaas-solana": {
      "command": "npx",
      "args": ["-y", "@waiaas/mcp"],
      "env": {
        "WAIAAS_BASE_URL": "http://127.0.0.1:3100",
        "WAIAAS_AGENT_ID": "019c4cd2-86e8-758f-a61e-9c560307c788",
        "WAIAAS_AGENT_NAME": "solana-wallet",
        "WAIAAS_DATA_DIR": "~/.waiaas"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Each wallet has its own session, its own policies, and its own token allowlists. The asset resolution context stays correct per-wallet — USDC on the trading wallet's Ethereum session won't be confused with USDC on the Solana wallet's session.

Quick Start: Four Steps to a Working Setup

  1. Install the CLI and initialize: npm install -g @waiaas/cli && waiaas init && waiaas start
  2. Create wallets and sessions: waiaas quickset --mode mainnet (prints the MCP config JSON)
  3. Paste the config into ~/Library/Application Support/Claude/claude_desktop_config.json
  4. Restart Claude Desktop and ask: "What's my wallet balance?"

If you hit any issues, the OpenAPI spec is available at http://127.0.0.1:3100/doc and the interactive API reference is at http://127.0.0.1:3100/reference.

What's Next

WAIaaS is open source and self-hosted, so your wallet keys and transaction data stay on your infrastructure. The GitHub repo has the full codebase, Docker setup, and documentation: https://github.com/waiaas/WAIaaS. For the project site and additional guides, visit https://waiaas.ai. If you're building something with Claude and onchain actions, the 45 MCP tools and policy engine are worth an afternoon to explore — the gap between "Claude understands the intent" and "Claude executes correctly and safely" is exactly what this is designed to close.

Top comments (0)