> For AI agents: the documentation index is at https://sdk.nimbusprivacy.xyz/llms.txt, and every page is available as Markdown at its URL with .md appended.

# Tokens (/helpers/tokens)

Every amount the SDK takes or returns is a `bigint` in the token's smallest unit. This page shows
where a token's decimals come from, how to format and parse amounts, and how to give tokens names
and logos.

The running example is USDC, which has 6 decimals. 25 USDC is `25_000_000n`.

## The tokens a cluster lists

`sdk.mints` lists the tokens the mainnet preset names, 57
of them. Each `NimbusMint` has:

- **`mint`**, the token's mint address.
- **`tokenProgram`**, the program that owns the mint: SPL Token or Token-2022.
- **`decimals`**, how many decimal places its smallest unit has.

```ts
for (const { mint, decimals, tokenProgram } of sdk.mints) {
  console.log(mint, decimals, tokenProgram);
}
```

Offer only these tokens in your token picker. The SDK names a token in a balance, a held payment or
a history item only when it is in this list.

## Format an amount

Divide by the token's decimals to show an amount. This formatter keeps the full precision of a
`bigint`, drops trailing zeros and groups thousands:

```ts
function formatAmount(value: bigint, decimals: number): string {
  const negative = value < 0n;
  const digits = (negative ? -value : value)
    .toString()
    .padStart(decimals + 1, "0");
  const whole = digits.slice(0, digits.length - decimals);
  const fraction = digits.slice(digits.length - decimals).replace(/0+$/u, "");
  const grouped = whole.replace(/\B(?=(\d{3})+(?!\d))/gu, ",");
  const sign = negative ? "-" : "";
  return fraction === "" ? `${sign}${grouped}` : `${sign}${grouped}.${fraction}`;
}

formatAmount(25_000_000n, 6); // "25"
formatAmount(1_234_567_890n, 6); // "1,234.56789"
```

Avoid `Number` for amounts. A large balance in a token with 9 decimals loses precision as a
`Number`.

## Parse what the user types

Turn what Alice types into the smallest unit the same way, in reverse:

```ts
function parseAmount(text: string, decimals: number): bigint | undefined {
  const match = /^(\d+)(?:\.(\d*))?$/u.exec(text.trim().replace(/,/gu, ""));
  if (match?.[1] === undefined) return undefined;
  const fraction = match[2] ?? "";
  if (fraction.length > decimals) return undefined;
  return BigInt(match[1] + fraction.padEnd(decimals, "0"));
}

parseAmount("25", 6); // 25_000_000n
parseAmount("12.5", 6); // 12_500_000n
```

It refuses more decimal places than the token has. Tell the user why, as the example app does.

## Names and logos

The SDK carries no token names, symbols or logos. Take them from a token list you trust.

The [example app](https://sdk.nimbusprivacy.xyz/resources/example-app) writes its list ahead of time with a script,
`apps/nimbus-example/scripts/fetch-tokens.ts`, which it runs as `pnpm tokens`:

### Ask Jupiter for each token

It sends every mainnet preset address to Jupiter's token search, and reads back each token's symbol,
name and logo URL. It warns when Jupiter's decimals differ from the preset's.

### Save each logo on its own site

It resizes each logo to a 96-pixel WebP through an image proxy. It saves the result under
`public/tokens/`, and skips any logo over 64 KB.

### Write the list

It writes `lib/token-list.json`, one entry per token with its address, symbol, name and logo
path. The app commits this file and reads it at runtime.

Serving logos from your own site matters. A cross-origin isolated page shows an image from another
site only when that site allows it, and many logo hosts do not.

For a token the list lacks, show its shortened address, and draw its initials in place of a logo.

## Unsupported tokens

A deposit of an address that is not a token mint throws a `NimbusSolanaFlowError` with reason
`mint-unsupported`. That covers an address with no account, an account another program owns, and
data that is not a mint.

A Token-2022 token whose transfer fee changes at the next epoch throws `fee-changing` instead. Try
again once the epoch turns.

## Next

- [Balances](https://sdk.nimbusprivacy.xyz/helpers/balances): Show each token's balance with its name and logo.
- [History](https://sdk.nimbusprivacy.xyz/helpers/history): Label past payments and name their tokens.
- [Deposit](https://sdk.nimbusprivacy.xyz/deposit): Deposit USDC into a private balance.
- [API reference](https://sdk.nimbusprivacy.xyz/reference/tokens): findMintByIdentifier: its signature and what it returns.


Last updated 21 October 2026
