4

I would like to get the balance of a user formatted using the base unit of the Substrate chain.

When I use toHuman(), I get an opinionated formatting which includes a prefix like so:

let account = await api.query.system.account("EGVQCe73TpFyAZx5uKfE1222XfkT3BSKozjgcqzLBnc5eYo");
account.data.free.toHuman()

2.8320 kKSM

While toNumber() returns the value without any units at all:

account.data.free.toNumber()

2832057009447293

How do I get this value with just the base units using the Polkadot JS API?

Shawn Tabrizi
  • 12,206
  • 1
  • 38
  • 69

1 Answers1

9

You will need to query the chain for the chainDecimals, which will tell you how many places into the raw value you should place the decimal:

api.registry.chainDecimals

12

You can either directly parse the number by dividing by 10chainDecimals, or you can use the Polkadot JS utility function formatBalance to help you format this a bit more easily:

formatBalance(
    accountData.data.free,
    { withSi: false, forceUnit: '-' },
    chainDecimals
);

2,832.057

I ended up making a utility function like this:

function toUnit(balance, decimals) {
    base = new BN(10).pow(new BN(decimals));
    dm = new BN(balance).divmod(base);
    return parseFloat(dm.div.toString() + "." + dm.mod.toString())
}
Shawn Tabrizi
  • 12,206
  • 1
  • 38
  • 69
  • 3
    I don't think `"."+ dm.mod.toString()` works because mod won't print leading zeroes (they're insignificant digits as an integer). `formatBalance` looks useful in my case, although I'm having a hard time finding documentation for it (this post is actually the first search hit for "polkadotjs formatBalance"). The code for `formatBalance` can be found here: https://github.com/polkadot-js/common/blob/master/packages/util/src/format/formatBalance.ts – notlesh Sep 12 '21 at 18:27
  • Currently `chainDecimals` is set using `decimals` in the options object passed to `formatBalance` – datu-puti Jul 10 '23 at 15:46