# Chains, tokens, prices and balances

> Build chain and token pickers from every chain and token LayerHop routes, and show USD prices and wallet balances — endpoints, parameters, caching and SDK calls.

Source: https://docs.layerhop.com/guides/tokens-and-balances

LayerHop serves the asset data a swap UI needs through five public endpoints: `GET /v1/chains` (the 70 chains its providers route), `GET /v1/tokens` and `GET /v1/tokens/lookup` (token search and metadata), `GET /v1/prices` (USD prices) and `GET /v1/balances` (a wallet's holdings). The LayerHop swap app uses the same calls.

## Which endpoints are there?

| Endpoint | Returns | Server cache | SDK |
|---|---|---|---|
| [`GET /v1/chains`](/api-reference#list-chains) | Every routable chain, popular first | Registry refreshed every 6 h | `lh.chains()` |
| [`GET /v1/tokens`](/api-reference#list-tokens) | One chain's tokens, searchable and paged | Token lists refreshed hourly | `lh.tokens({ chain, q, limit, cursor })` |
| [`GET /v1/tokens/lookup`](/api-reference#look-up-a-token) | One token by address or mint, even if unlisted | 1 h | `lh.lookupToken(chain, address)` |
| [`GET /v1/prices`](/api-reference#get-usd-prices) | USD prices for up to 100 tokens | 60 s | `lh.prices(ids)` |
| [`GET /v1/balances`](/api-reference#get-wallet-balances) | A wallet's non-zero balances with USD values | 20 s per address and chain | `lh.balances(address, chains?)` |

All five count toward your [rate limit](/guides/dashboard-and-api-keys#what-are-the-rate-limits). Responses from `/chains` and `/tokens` are also cacheable by browsers and CDNs for 5 minutes.

## How do I list chains?

[`GET /v1/chains`](/api-reference#list-chains) returns every chain at least one provider can quote from or to. The registry merges the chain lists of Relay, LI.FI, deBridge, KyberSwap, Mayan, 0x and Jupiter, refreshes every 6 hours, and falls back to a built-in snapshot when providers are unreachable. Popular chains (`popular: true`) come first, then the rest alphabetically.

```ts
const chains = await lh.chains();
const bera = chains.find((c) => c.slug === "berachain");
// { id: 80094, slug: "berachain", name: "Berachain", vm: "evm", nativeSymbol: "BERA", nativeDecimals: 18,
//   logoURI: "https://…", explorerTx: "https://berascan.com/tx/", explorerAddress: "https://berascan.com/address/",
//   providers: ["kyberswap", "lifi", "relay", "zerox"], popular: true }
```

| Field | Meaning |
|---|---|
| `id` | EVM chain id, or `7565164` for Solana |
| `slug` | Stable name such as `base`, `hyperevm`, `robinhood` |
| `vm` | `evm` or `svm` |
| `nativeSymbol`, `nativeDecimals` | The gas coin |
| `explorerTx`, `explorerAddress` | Prefixes; append a hash or an address |
| `providers` | Providers that route from or to the chain |
| `popular` | Shown first in pickers |

Use the `id` or the `slug` anywhere a chain is expected. [Supported chains & tokens](/chains) lists the current snapshot.

## How do I search tokens?

[`GET /v1/tokens`](/api-reference#list-tokens) lists and searches one chain's tokens. It merges LI.FI's token list (with prices), Jupiter's verified list on Solana and LayerHop's curated tokens.

| Param | Required | Meaning |
|---|---|---|
| `chain` | Yes | Chain id or slug |
| `q` | No | Symbol or name, or an exact address / mint |
| `limit` | No | 1–200, default 50 |
| `cursor` | No | `nextCursor` from the previous page |

```ts
const { tokens, nextCursor } = await lh.tokens({ chain: "berachain", q: "HONEY", limit: 20 });
```

Results rank exact symbol matches first, then `popular` tokens (native coin, stablecoins, wrapped native, majors), then `verified` ones, then by liquidity. Page with `cursor: nextCursor` until `nextCursor` is `null`.

## How do I handle a token that is on no list?

A pasted address that no list knows can still be traded. Read it with [`GET /v1/tokens/lookup`](/api-reference#look-up-a-token):

```ts
const token = await lh.lookupToken("base", "0x…");
if (!token.verified) showWarning(`${token.symbol} is not on any token list. Check the address.`);
```

Unknown EVM tokens are read on chain (`symbol`, `name`, `decimals`). Unknown Solana mints get their decimals from the mint account and their name from Jupiter. Both come back with `verified: false`, and with `priceUsd` when a price source knows the token.

## Can I quote any token?

Yes. [`GET /v1/quote`](/api-reference#get-quotes) accepts any chain from `/v1/chains` and any token address or mint. Symbols work as shortcuts for the curated tokens (`USDC`) and for each chain's native coin (`ETH`, `BERA`, `SOL`):

```ts
const { best } = await lh.quote({
  srcChain: "base", srcToken: "USDC", amount: "10000000",   // 10 USDC
  dstChain: "berachain", dstToken: "BERA",
  sender: evmAddress, recipient: evmAddress,
});
```

Each provider decides support from its own chain list, so `quotes` contains every provider that serves the pair. A symbol that is not on the curated list returns [`UNSUPPORTED_TOKEN`](/errors/UNSUPPORTED_TOKEN); pass the address instead.

## How do I get USD prices?

[`GET /v1/prices`](/api-reference#get-usd-prices) takes `ids`, a comma-separated list of up to 100 `chainId:address` entries. Prices come from LI.FI for EVM chains and Jupiter for Solana, cached for 60 seconds. The response is keyed by the ids exactly as you sent them; ids without a price are left out.

```ts
const prices = await lh.prices([
  "8453:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  { chainId: 7565164, address: "So11111111111111111111111111111111111111112" },
]);
// { "8453:0x8335…2913": <usd>, "7565164:So11…112": <usd> }: keys as sent, values are USD numbers
```

## How do I read a wallet's balances?

[`GET /v1/balances`](/api-reference#get-wallet-balances) returns a wallet's non-zero balances with token metadata, `priceUsd` and `valueUsd`, highest value first, plus `totalUsd`.

| Param | Required | Meaning |
|---|---|---|
| `address` | Yes | An EVM address or a Solana address |
| `chains` | No | Comma-separated ids or slugs. Default: the popular chains of the address's VM |

```ts
const { balances, totalUsd, errors } = await lh.balances("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", ["base", "arbitrum", "berachain"]);
```

- EVM chains report the native coin plus the top 200 popular and verified tokens of each chain (one Multicall3 read per chain). Solana reports SOL and every token account.
- A chain that fails or times out is listed in `errors`; the other chains are still returned.
- Results are cached for 20 seconds per address and chain. Amounts are integer strings in base units.
