diff --git a/web/cashtab/src/components/Common/BalanceHeaderToken.js b/web/cashtab/src/components/Common/BalanceHeaderToken.js
new file mode 100644
--- /dev/null
+++ b/web/cashtab/src/components/Common/BalanceHeaderToken.js
@@ -0,0 +1,21 @@
+import * as React from 'react';
+import PropTypes from 'prop-types';
+import { formatTokenBalance } from 'utils/formatting';
+import { BalanceHeaderWrap } from 'components/Common/Atoms';
+
+const BalanceHeaderToken = ({ balance, ticker, tokenDecimals }) => {
+ return (
+
+ {formatTokenBalance(balance, tokenDecimals)} {ticker}
+
+ );
+};
+
+// balance may be a string (XEC balance) or a BigNumber object (token balance)
+BalanceHeaderToken.propTypes = {
+ balance: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
+ ticker: PropTypes.string,
+ tokenDecimals: PropTypes.number,
+};
+
+export default BalanceHeaderToken;
diff --git a/web/cashtab/src/components/Home/TokenList.js b/web/cashtab/src/components/Home/TokenList.js
--- a/web/cashtab/src/components/Home/TokenList.js
+++ b/web/cashtab/src/components/Home/TokenList.js
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types';
import TokenListItem from './TokenListItem';
import { Link } from 'react-router-dom';
-import { formatBalance } from 'utils/formatting';
+import { formatTokenBalance } from 'utils/formatting';
const TokenList = ({ tokens }) => {
return (
@@ -12,7 +12,10 @@
))}
diff --git a/web/cashtab/src/components/Home/__tests__/__snapshots__/Home.test.js.snap b/web/cashtab/src/components/Home/__tests__/__snapshots__/Home.test.js.snap
--- a/web/cashtab/src/components/Home/__tests__/__snapshots__/Home.test.js.snap
+++ b/web/cashtab/src/components/Home/__tests__/__snapshots__/Home.test.js.snap
@@ -398,9 +398,7 @@
TBS
-
- 6.001
-
+
diff --git a/web/cashtab/src/components/Send/SendToken.js b/web/cashtab/src/components/Send/SendToken.js
--- a/web/cashtab/src/components/Send/SendToken.js
+++ b/web/cashtab/src/components/Send/SendToken.js
@@ -24,7 +24,7 @@
} from 'components/Common/EnhancedInputs';
import useBCH from 'hooks/useBCH';
import { SidePaddingCtn } from 'components/Common/Atoms';
-import BalanceHeader from 'components/Common/BalanceHeader';
+import BalanceHeaderToken from 'components/Common/BalanceHeaderToken';
import { Redirect } from 'react-router-dom';
import useWindowDimensions from 'hooks/useWindowDimensions';
import usePrevious from 'hooks/usePrevious';
@@ -494,10 +494,11 @@
-
diff --git a/web/cashtab/src/components/Send/__tests__/__snapshots__/SendToken.test.js.snap b/web/cashtab/src/components/Send/__tests__/__snapshots__/SendToken.test.js.snap
--- a/web/cashtab/src/components/Send/__tests__/__snapshots__/SendToken.test.js.snap
+++ b/web/cashtab/src/components/Send/__tests__/__snapshots__/SendToken.test.js.snap
@@ -9,15 +9,8 @@
-
-
- 6.001
-
- TBS
-
-
+
+ TBS
{
@@ -137,4 +139,23 @@
it(`test formatFiatBalance with undefined input`, () => {
expect(formatFiatBalance(undefined, 'en-US')).toBe(undefined);
});
+ it(`returns undefined formatTokenBalance with undefined inputs`, () => {
+ expect(formatTokenBalance(undefined, undefined)).toBe(undefined);
+ });
+ it(`test formatTokenBalance with valid balance & decimal inputs`, () => {
+ const testBalance = new BigNumber(100.00000001);
+ expect(formatTokenBalance(testBalance, 8)).toBe('100.00000001');
+ });
+ it(`returns undefined when passed invalid decimals parameter`, () => {
+ const testBalance = new BigNumber(100.00000001);
+ expect(formatTokenBalance(testBalance, 'cheese')).toBe(undefined);
+ });
+ it(`returns undefined when passed invalid balance parameter`, () => {
+ const testBalance = '100.000010122';
+ expect(formatTokenBalance(testBalance, 9)).toBe(undefined);
+ });
+ it(`maintains trailing zeros in balance per tokenDecimal parameter`, () => {
+ const testBalance = new BigNumber(10000);
+ expect(formatTokenBalance(testBalance, 8)).toBe('10,000.00000000');
+ });
});
diff --git a/web/cashtab/src/utils/formatting.js b/web/cashtab/src/utils/formatting.js
--- a/web/cashtab/src/utils/formatting.js
+++ b/web/cashtab/src/utils/formatting.js
@@ -1,5 +1,5 @@
import { currency } from 'components/Common/Ticker.js';
-
+import BigNumber from 'bignumber.js';
export const formatDate = (dateString, userLocale = 'en') => {
const options = { month: 'short', day: 'numeric', year: 'numeric' };
const dateFormattingError = 'Unable to format date.';
@@ -70,3 +70,44 @@
return unformattedBalance;
}
};
+
+// unformattedBalance will always be a BigNumber, tokenDecimal will always be a number
+export const formatTokenBalance = (
+ unformattedBalance,
+ tokenDecimal,
+ defaultLocale = 'en',
+) => {
+ let formattedTokenBalance;
+ let convertedTokenBalance;
+ let locale = defaultLocale;
+ try {
+ if (
+ tokenDecimal === undefined ||
+ unformattedBalance === undefined ||
+ typeof tokenDecimal !== 'number' ||
+ !BigNumber.isBigNumber(unformattedBalance)
+ ) {
+ return undefined;
+ }
+ if (navigator && navigator.language) {
+ locale = navigator.language;
+ }
+
+ // Use toFixed to get a string with the correct decimal places
+ formattedTokenBalance = new BigNumber(unformattedBalance).toFixed(
+ tokenDecimal,
+ );
+ // formattedTokenBalance is converted into a number as toLocaleString does not work with a string
+ convertedTokenBalance = parseFloat(
+ formattedTokenBalance,
+ ).toLocaleString(locale, {
+ minimumFractionDigits: tokenDecimal,
+ });
+
+ return convertedTokenBalance;
+ } catch (err) {
+ console.log(`Error in formatTokenBalance for ${unformattedBalance}`);
+ console.log(err);
+ return unformattedBalance;
+ }
+};