UNPKG

3.48 kBJavaScriptView Raw
1import { bnToBn } from '../bn/toBn.js';
2import { isBoolean } from '../is/boolean.js';
3import { formatDecimal } from './formatDecimal.js';
4import { getSeparator } from './getSeparator.js';
5import { calcSi, findSi, SI, SI_MID } from './si.js';
6const DEFAULT_DECIMALS = 0;
7const DEFAULT_UNIT = SI[SI_MID].text;
8let defaultDecimals = DEFAULT_DECIMALS;
9let defaultUnit = DEFAULT_UNIT;
10function _formatBalance(input, { decimals = defaultDecimals, forceUnit, locale = 'en', withAll = false, withSi = true, withSiFull = false, withUnit = true, withZero = true } = {}) {
11 // we only work with string inputs here - convert anything
12 // into the string-only value
13 let text = bnToBn(input).toString();
14 if (text.length === 0 || text === '0') {
15 return '0';
16 }
17 // strip the negative sign so we can work with clean groupings, re-add this in the
18 // end when we return the result (from here on we work with positive numbers)
19 let sign = '';
20 if (text[0].startsWith('-')) {
21 sign = '-';
22 text = text.substring(1);
23 }
24 // We start at midpoint (8) minus 1 - this means that values display as
25 // 123.4567 instead of 0.1234 k (so we always have the most relevant).
26 const si = calcSi(text, decimals, forceUnit);
27 const mid = text.length - (decimals + si.power);
28 const pre = mid <= 0 ? '0' : text.substring(0, mid);
29 // get the post from the midpoint onward and then first add max decimals
30 // before trimming to the correct (calculated) amount of decimals again
31 let post = text
32 .padStart(mid < 0 ? decimals : 1, '0')
33 .substring(mid < 0 ? 0 : mid)
34 .padEnd(withAll ? Math.max(decimals, 4) : 4, '0')
35 .substring(0, withAll ? Math.max(4, decimals + si.power) : 4);
36 // remove all trailing 0's (if required via flag)
37 if (!withZero) {
38 let end = post.length - 1;
39 // This looks inefficient, however it is better to do the checks and
40 // only make one final slice than it is to do it in multiples
41 do {
42 if (post[end] === '0') {
43 end--;
44 }
45 } while (post[end] === '0');
46 post = post.substring(0, end + 1);
47 }
48 // the display unit
49 const unit = isBoolean(withUnit)
50 ? SI[SI_MID].text
51 : withUnit;
52 // format the units for display based on the flags
53 const units = withSi || withSiFull
54 ? si.value === '-'
55 ? withUnit
56 ? ` ${unit}`
57 : ''
58 : ` ${withSiFull ? `${si.text}${withUnit ? ' ' : ''}` : si.value}${withUnit ? unit : ''}`
59 : '';
60 const { decimal, thousand } = getSeparator(locale);
61 return `${sign}${formatDecimal(pre, thousand)}${post && `${decimal}${post}`}${units}`;
62}
63export const formatBalance = _formatBalance;
64formatBalance.calcSi = (text, decimals = defaultDecimals) => calcSi(text, decimals);
65formatBalance.findSi = findSi;
66formatBalance.getDefaults = () => {
67 return {
68 decimals: defaultDecimals,
69 unit: defaultUnit
70 };
71};
72formatBalance.getOptions = (decimals = defaultDecimals) => {
73 return SI.filter(({ power }) => power < 0
74 ? (decimals + power) >= 0
75 : true);
76};
77formatBalance.setDefaults = ({ decimals, unit }) => {
78 defaultDecimals = (Array.isArray(decimals)
79 ? decimals[0]
80 : decimals) ?? defaultDecimals;
81 defaultUnit = (Array.isArray(unit)
82 ? unit[0]
83 : unit) ?? defaultUnit;
84 SI[SI_MID].text = defaultUnit;
85};