Skip to content
IC Reactor

formatTokenAmount

formatTokenAmount(value, decimals, options?): string

Defined in: core/src/utils/token-amount.ts:229

Show an amount of a token’s base units as decimal text, exactly.

value is what a ledger returns: a bigint from a Reactor, or the integer text a DisplayReactor gives for a nat. decimals is the token’s, as icrc1_decimals returns it, in any of those forms. No digit passes through a JavaScript Number, so an 18-decimal balance of any size shows as it is.

By default every significant fraction digit is shown and zeros at the end are dropped. maxFractionDigits shortens the fraction, cutting the rest unless roundingMode is "halfExpand"; minFractionDigits or trimTrailingZeros: false pads it. A negative amount (an int) is written with a leading -, except where the digits shown are all zero.

string | number | bigint

The amount in base units (e8s for ICP).

string | number | bigint

The token’s decimals, from 0 to 255.

FormatTokenAmountOptions = {}

Fraction digits, rounding, locale and grouping.

string

The amount as decimal text, "1.5" for 150000000 e8s.

TypeError when value is not an integer amount, or decimals is not a whole number.

RangeError when decimals or a digit option is outside 0-255, minFractionDigits exceeds maxFractionDigits, roundingMode is not one of the two, or Intl.NumberFormat refuses locale.

import { formatTokenAmount } from "@ic-reactor/core"
formatTokenAmount(150_000_000n, 8) // "1.5"
formatTokenAmount("123456789", 8, { maxFractionDigits: 2 }) // "1.23"
formatTokenAmount(100_000_000n, 8, { minFractionDigits: 2 }) // "1.00"
formatTokenAmount(123_456_789_000n, 8, { locale: "de-DE" }) // "1.234,56789"
// A DisplayReactor returns both as display values
const [balance, decimals] = await Promise.all([
ledger.fetchQuery({ functionName: "icrc1_balance_of", args: [{ owner }] }),
ledger.fetchQuery({ functionName: "icrc1_decimals" }),
])
formatTokenAmount(balance, decimals, { maxFractionDigits: 4 })