Skip to main content
Skip to main content

Token Resolver

The token resolver maps token symbols and names to their on-chain addresses across all supported chains. It's the layer that lets you write "USDC" instead of "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" when calling tools.

Tools: resolve_token, list_chain_tokens

How Resolution Works

The resolver has two layers:

  1. Canonical registry — a curated list of well-known tokens (USDC, WETH, WBTC, DAI, etc.) with verified addresses for each supported chain. No network call required.

  2. DexScreener fallback — if the symbol isn't in the registry, the resolver queries DexScreener to find the token by name or symbol. This covers long-tail assets that aren't in the canonical list.

resolve_token("USDC", chainId: 8453)
  → check canonical registry → found → return address
  
resolve_token("PEPE", chainId: 1)
  → check canonical registry → not found
  → query DexScreener → found → return address

Canonical Registry

The canonical registry contains tokens that are:

  • Widely used across DeFi
  • Verified to have the correct address on each chain
  • Consistent across all web3agent tools

Canonical tokens include: USDC, USDT, DAI, WETH, WBTC, MATIC, BNB, AVAX, OP, ARB, LINK, UNI, AAVE, CRV, and others.

The registry is chain-aware. USDC on Base has a different address than USDC on Ethereum. The resolver returns the correct address for the requested chain.

Tools

resolve_token

Resolves a token symbol or name to its address on a specific chain. Uses the canonical registry first, then falls back to DexScreener.

// Via MCP tool
resolve_token({
  symbol: "USDC",
  chainId: 8453,
})

// Returns:
// {
//   address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
//   symbol: "USDC",
//   name: "USD Coin",
//   decimals: 6,
//   chainId: 8453,
//   source: "canonical"  // or "dexscreener"
// }
// Long-tail token via DexScreener
resolve_token({
  symbol: "PEPE",
  chainId: 1,
})

// Returns:
// {
//   address: "0x6982508145454Ce325dDbE47a25d4ec3d2311933",
//   symbol: "PEPE",
//   name: "Pepe",
//   decimals: 18,
//   chainId: 1,
//   source: "dexscreener"
// }

list_chain_tokens

Returns all tokens in the canonical registry for a specific chain.

list_chain_tokens({
  chainId: 8453,
})

// Returns array of token objects:
// [
//   { address: "0x833589...", symbol: "USDC", name: "USD Coin", decimals: 6 },
//   { address: "0x4200000000000000000000000000000000000006", symbol: "WETH", ... },
//   ...
// ]

This is useful for building token pickers or validating that a token is supported before attempting a swap.

SDK Functions

import {
  resolveToken,
  resolveCanonicalToken,
  resolveCanonicalTokenSync,
  listChainTokens,
} from "web3agent";

resolveToken

Full resolution with DexScreener fallback. Makes a network call if the token isn't in the canonical registry.

import { resolveToken } from "web3agent";

const token = await resolveToken({
  symbol: "USDC",
  chainId: 8453,
});

console.log(token.address);  // "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
console.log(token.decimals); // 6

resolveCanonicalToken

Registry-only lookup. Returns null if the token isn't in the canonical list. No network call.

import { resolveCanonicalToken } from "web3agent";

const token = await resolveCanonicalToken({
  symbol: "WETH",
  chainId: 8453,
});

if (!token) {
  // Token not in canonical registry
}

resolveCanonicalTokenSync

Synchronous version of resolveCanonicalToken. Useful in contexts where async isn't available.

import { resolveCanonicalTokenSync } from "web3agent";

const token = resolveCanonicalTokenSync("WETH", 8453);
// Returns token object or null

listChainTokens

Returns all canonical tokens for a chain.

import { listChainTokens } from "web3agent";

const tokens = await listChainTokens({ chainId: 8453 });

for (const token of tokens) {
  console.log(`${token.symbol}: ${token.address}`);
}

Canonical Token Addresses

Common tokens across the most-used chains:

USDC

ChainChain IDAddress
Ethereum10xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Base84530x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Arbitrum421610xaf88d065e77c8cC2239327C5EDb3A432268e5831
Optimism100x0b2C639c533813f4Aa9D7837CAf62653d097Ff85
Polygon1370x3c499c542cEF5E3811e1192ce70d8cC03d5c3359

WETH

ChainChain IDAddress
Ethereum10xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Base84530x4200000000000000000000000000000000000006
Arbitrum421610x82aF49447D8a07e3bd95BD0d56f35241523fBab1
Optimism100x4200000000000000000000000000000000000006
Polygon1370x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619

Naming Conventions

web3agent uses consistent parameter names across all tools and SDK functions. This matters when passing token addresses between tools:

CorrectIncorrect
fromTokensrcToken, tokenIn, inputToken
toTokendstToken, tokenOut, outputToken
fromAmountamountIn, inputAmount, srcAmount

All tools and SDK functions follow this convention. If you're building on top of web3agent, use the same names to avoid confusion.

DexScreener Fallback Behavior

When a token isn't in the canonical registry, the resolver queries DexScreener and picks the result with the highest liquidity on the requested chain. This works well for established tokens but can return unexpected results for tokens with very low liquidity or multiple pools.

For production use cases where address accuracy is critical, prefer resolveCanonicalToken and handle the null case explicitly rather than relying on the DexScreener fallback.

Adding Tokens to the Registry

The canonical registry is part of the web3agent source code. To add a token, open a pull request to github.com/Apegurus/web3agent with the token address verified against the official contract deployment.