--- title: Token catalog description: Discovering quotable tokens, their decimals, and which ones support permit. --- Token support is runtime state. `ListTokens` returns every token that can appear on a quote, on every chain, in one call. ```ts const { tokens } = await hular.listTokens({}); ``` | Field | Use | | --- | --- | | `chain` | Lowercase chain name. | | `chain_id` | EVM chain id. Absent for Solana. | | `address` | Token address. The zero address means the chain's native asset on EVM. | | `symbol` | Display symbol. Optional. | | `decimals` | Base-unit exponent. Required to parse and format amounts. | | `tier` | Liquidity classification used for slippage defaults. | | `permit` | True when the token supports EIP-2612, so approval can be replaced by a signature. | | `logo_url` | Icon for display. Optional. | Cache the response for the lifetime of a page load rather than calling it per quote, and refresh it when your app reloads. It changes when the operator lists or delists a token, not on a schedule. ## Amount handling `decimals` from the catalog is the only correct source for converting user input into `amount`: the source token's decimals for an exact-input quote, the destination token's for an expected-output one. ```ts import { parseAmount, formatAmount } from "@mayanfinance/hular-sdk"; parseAmount("25.5", 6); // 25500000n formatAmount("25500000", 6); // "25.5" ``` Never round-trip an amount through a float. Parse once at the input boundary, keep it as a string or bigint everywhere else. ## Building a token picker Pair the catalog with `GetChains` so the picker only offers what is currently quotable: ```ts const [{ tokens }, { chains }] = await Promise.all([ hular.listTokens({}), hular.getChains({}), ]); const open = new Set(chains.filter((c) => c.quoteEnabled).map((c) => c.chain)); const selectable = tokens.filter((t) => open.has(t.chain)); ``` The two calls are independent, so issue them together on load. ## Single token lookup `GetTokenInfo` resolves one token by chain and address, for cases where you have an address from elsewhere, such as a deep link, a user paste, or a stored preference. ```ts const token = await hular.getTokenInfo({ chain: "arbitrum", address }); ``` It returns the symbol, decimals, chain id, and logo, read live from the token contract or mint on chain, so it also resolves addresses outside the catalog, though those still cannot be quoted. If the chain read fails, the call returns `UNAVAILABLE` rather than inventing metadata. ## Tiers and slippage `tier` classifies a token's liquidity and feeds the default slippage applied when you omit `slippage_bps`. Stable assets get tighter defaults than long-tail ones. You can always override per quote; see [Slippage](/concepts/slippage).