Skip to content
Helpers

Tokens

The tokens a cluster lists, their decimals, formatting amounts for display, names and logos, and naming the token in a history item.

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.
for (const { , ,  } of .) {
  .(, , );
}

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:

function (: bigint, : number): string {
  const  =  < 0n;
  const  = ( ? - : )
    .()
    .( + 1, "0");
  const  = .(0, . - );
  const  = .(. - ).(/0+$/u, "");
  const  = .(/\B(?=(\d{3})+(?!\d))/gu, ",");
  const  =  ? "-" : "";
  return  === "" ? `${}${}` : `${}${}.${}`;
}

(25_000_000n, 6); // "25"
(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:

function (: string, : number): bigint | undefined {
  const  = /^(\d+)(?:\.(\d*))?$/u.(.().(/,/gu, ""));
  if (?.[1] === ) return ;
  const  = [2] ?? "";
  if (. > ) return ;
  return ([1] + .(, "0"));
}

("25", 6); // 25_000_000n
("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 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

Last updated

On this page