Skip to content

Commit

Permalink
fix: handle account balance abbreviation (#494)
Browse files Browse the repository at this point in the history
* fix: handle account balance abbreviation

* fix: handle values less than 1

* fix: do not round decimals

* chore: clean up test suite

* chore: remove redundant tests
  • Loading branch information
estrattonbailey authored Jun 15, 2022
1 parent e82caf0 commit 11ed088
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/clever-ghosts-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rainbow-me/rainbowkit': patch
---

Abbreviate large account balances using standard k/m/b units, fixes cases where balances appeared in exponential notation.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
useRainbowKitChainsById,
} from '../RainbowKitProvider/RainbowKitChainContext';
import { ShowRecentTransactionsContext } from '../RainbowKitProvider/ShowRecentTransactionsContext';
import { abbreviateETHBalance } from './abbreviateETHBalance';
import { formatAddress } from './formatAddress';
import { formatENS } from './formatENS';

Expand Down Expand Up @@ -158,7 +159,9 @@ export function ConnectButtonRenderer({
}, [preloadImages]);

const displayBalance = balanceData
? `${Number(balanceData.formatted).toPrecision(3)} ${balanceData.symbol}`
? `${abbreviateETHBalance(parseFloat(balanceData.formatted))} ${
balanceData.symbol
}`
: undefined;

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { describe, expect, it } from 'vitest';
import { abbreviateETHBalance } from './abbreviateETHBalance';

const K = 1000;
const M = 1000 * K;
const B = 1000 * M;

describe('abbreviateETHBalance', () => {
it('truncates to 3 decimal places for numbers under 1', () => {
expect(abbreviateETHBalance(0.002)).toEqual('0.002');
expect(abbreviateETHBalance(0.9009)).toEqual('0.9');
expect(abbreviateETHBalance(0.0009)).toEqual('0');
expect(abbreviateETHBalance(0.5194)).toEqual('0.519');
expect(abbreviateETHBalance(0.5199)).toEqual('0.519');
expect(abbreviateETHBalance(0.5499)).toEqual('0.549');
expect(abbreviateETHBalance(0.5999)).toEqual('0.599');
});

it('truncates to 2 decimal places for numbers under 100', () => {
expect(abbreviateETHBalance(1)).toEqual('1');
expect(abbreviateETHBalance(1.002)).toEqual('1');
expect(abbreviateETHBalance(1.04)).toEqual('1.04');
expect(abbreviateETHBalance(1.09)).toEqual('1.09');
expect(abbreviateETHBalance(1.1)).toEqual('1.1');
expect(abbreviateETHBalance(10)).toEqual('10');
expect(abbreviateETHBalance(10.0)).toEqual('10');
expect(abbreviateETHBalance(12)).toEqual('12');
});

it('truncates to 1 decimal place and adds commas for numbers under 10k', () => {
expect(abbreviateETHBalance(123)).toEqual('123');
expect(abbreviateETHBalance(1234)).toEqual('1,234');
expect(abbreviateETHBalance(1234.22)).toEqual('1,234.2');
expect(abbreviateETHBalance(1234.02)).toEqual('1,234');
expect(abbreviateETHBalance(9999)).toEqual('9,999');
expect(abbreviateETHBalance(9999.1)).toEqual('9,999.1');
expect(abbreviateETHBalance(9999.99)).toEqual('9,999.9'); // no round
});

it('abbreviates past 10k', () => {
expect(abbreviateETHBalance(10 * K)).toEqual('10k');
expect(abbreviateETHBalance(12.3 * K)).toEqual('12.3k');
expect(abbreviateETHBalance(123.4 * K)).toEqual('123.4k');
expect(abbreviateETHBalance(999.99 * K)).toEqual('999.9k'); // no rounds
});

it('abbreviates past 1m', () => {
expect(abbreviateETHBalance(1 * M)).toEqual('1m');
expect(abbreviateETHBalance(1.23 * M)).toEqual('1.2m');
expect(abbreviateETHBalance(10 * M)).toEqual('10m');
expect(abbreviateETHBalance(12.3 * M)).toEqual('12.3m');
expect(abbreviateETHBalance(123.4 * M)).toEqual('123.4m');
expect(abbreviateETHBalance(999.99 * M)).toEqual('999.9m'); // no rounds
});

it('abbreviates past 1b', () => {
expect(abbreviateETHBalance(1 * B)).toEqual('1b');
expect(abbreviateETHBalance(1.23 * B)).toEqual('1.2b');
expect(abbreviateETHBalance(10 * B)).toEqual('10b');
expect(abbreviateETHBalance(12.3 * B)).toEqual('12.3b');
expect(abbreviateETHBalance(123.4 * B)).toEqual('123.4b');
expect(abbreviateETHBalance(999.99 * B)).toEqual('999.9b'); // no rounds
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Adapted from https://github.com/domharrington/js-number-abbreviate
*/
const units = ['k', 'm', 'b', 't'];

export function toPrecision(number: number, precision: number = 1) {
return number
.toString()
.replace(new RegExp(`(.+\\.\\d{${precision}})\\d+`), '$1')
.replace(/(\.[1-9]*)0+$/, '$1')
.replace(/\.$/, '');
}

export function abbreviateETHBalance(number: number): string {
if (number < 1) return toPrecision(number, 3);
if (number < 10 ** 2) return toPrecision(number, 2);
if (number < 10 ** 4)
return new Intl.NumberFormat().format(parseFloat(toPrecision(number, 1)));

const decimalsDivisor = 10 ** 1; // 1 decimal place

let result = String(number);

for (let i = units.length - 1; i >= 0; i--) {
const size = 10 ** ((i + 1) * 3);

if (size <= number) {
number = (number * decimalsDivisor) / size / decimalsDivisor;

result = toPrecision(number, 1) + units[i];

break;
}
}

return result;
}

2 comments on commit 11ed088

@vercel
Copy link

@vercel vercel bot commented on 11ed088 Jun 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 11ed088 Jun 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.