Skip to content

Commit

Permalink
feat(core/strings): use thousands separator (fixes #2394)
Browse files Browse the repository at this point in the history
  • Loading branch information
matejcik committed Aug 2, 2022
1 parent 8ca7859 commit 635d4fd
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 66 deletions.
1 change: 1 addition & 0 deletions core/.changelog.d/2394.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Show thousands separator when displaying large amounts.
7 changes: 6 additions & 1 deletion core/src/apps/bitcoin/sign_tx/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,12 @@ async def confirm_total(
fee_rate_str: str | None = None

if fee_rate >= 0:
fee_rate_str = f"({fee_rate:.1f} sat/{'v' if coin.segwit else ''}B)"
# Use format_amount to get correct thousands separator -- micropython's built-in
# formatting doesn't add thousands sep to floating point numbers.
# We multiply by 10 to get a fixed-point integer with one decimal place,
# and add 0.5 to round to the nearest integer.
fee_rate_formatted = format_amount(int(fee_rate * 10 + 0.5), 1)
fee_rate_str = f"({fee_rate_formatted} sat/{'v' if coin.segwit else ''}B)"

await layouts.confirm_total(
ctx,
Expand Down
10 changes: 8 additions & 2 deletions core/src/trezor/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ def format_amount(amount: int, decimals: int) -> str:
sign = "-"
else:
sign = ""
d = pow(10, decimals)
s = f"{sign}{amount // d}.{amount % d:0{decimals}}".rstrip("0").rstrip(".")
d = 10**decimals
integer = amount // d
decimal = amount % d

# TODO: bug in mpz: https://github.com/micropython/micropython/issues/8984
grouped_integer = f"{integer:,}".lstrip(",")

s = f"{sign}{grouped_integer}.{decimal:0{decimals}}".rstrip("0").rstrip(".")
return s


Expand Down
4 changes: 2 additions & 2 deletions core/tests/test_apps.bitcoin.signtx.omni.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ def test_parse(self):
VECTORS = {
"6f6d6e69000000000000001f000000002b752ee0": "Simple send of 7.291 USDT",
"6f6d6e69000000000000001f0000000020c85580": "Simple send of 5.5 USDT",
"6f6d6e690000000000000003000000002b752ee0": "Simple send of 729100000 MAID",
"6f6d6e690000000000000000000000002b752ee0": "Simple send of 729100000 UNKN",
"6f6d6e690000000000000003000000002b752ee0": "Simple send of 729,100,000 MAID",
"6f6d6e690000000000000000000000002b752ee0": "Simple send of 729,100,000 UNKN",
"6f6d6e6901000000": "Unknown transaction",
}
for k, v in VECTORS.items():
Expand Down
12 changes: 6 additions & 6 deletions core/tests/test_apps.ethereum.layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ def test_format(self):
text = format_ethereum_amount(1, None, 1)
self.assertEqual(text, '1 Wei ETH')
text = format_ethereum_amount(1000, None, 1)
self.assertEqual(text, '1000 Wei ETH')
self.assertEqual(text, '1,000 Wei ETH')
text = format_ethereum_amount(1000000, None, 1)
self.assertEqual(text, '1000000 Wei ETH')
self.assertEqual(text, '1,000,000 Wei ETH')
text = format_ethereum_amount(10000000, None, 1)
self.assertEqual(text, '10000000 Wei ETH')
self.assertEqual(text, '10,000,000 Wei ETH')
text = format_ethereum_amount(100000000, None, 1)
self.assertEqual(text, '100000000 Wei ETH')
self.assertEqual(text, '100,000,000 Wei ETH')
text = format_ethereum_amount(1000000000, None, 1)
self.assertEqual(text, '0.000000001 ETH')
text = format_ethereum_amount(10000000000, None, 1)
Expand All @@ -44,7 +44,7 @@ def test_format(self):
text = format_ethereum_amount(100000000000000000000, None, 1)
self.assertEqual(text, '100 ETH')
text = format_ethereum_amount(1000000000000000000000, None, 1)
self.assertEqual(text, '1000 ETH')
self.assertEqual(text, '1,000 ETH')

text = format_ethereum_amount(1000000000000000000, None, 61)
self.assertEqual(text, '1 ETC')
Expand Down Expand Up @@ -97,7 +97,7 @@ def test_unknown_token(self):
self.assertEqual(text, '0 Wei UNKN')
# unknown token has 0 decimals so is always wei
text = format_ethereum_amount(1000000000000000000, unknown_token, 1)
self.assertEqual(text, '1000000000000000000 Wei UNKN')
self.assertEqual(text, '1,000,000,000,000,000,000 Wei UNKN')


if __name__ == '__main__':
Expand Down
11 changes: 9 additions & 2 deletions core/tests/test_trezor.strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@


class TestStrings(unittest.TestCase):

def test_format_amount(self):
VECTORS = [
(123456, 3, "123.456"),
(4242, 7, "0.0004242"),
(-123456, 3, "-123.456"),
(-4242, 7, "-0.0004242"),
(123, 5, "0.00123"),
(100, 5, "0.001"),
(123456789, 0, "123,456,789"),
(100000000, 5, "1,000"),
(100000001, 5, "1,000.00001"),
(100001000, 5, "1,000.01"),
(-100001000, 5, "-1,000.01"),
(123_456_789_123_456_789_123_456_789, 18, "123,456,789.123456789123456789"),
]
for v in VECTORS:
self.assertEqual(strings.format_amount(v[0], v[1]), v[2])
Expand Down Expand Up @@ -151,5 +158,5 @@ def test_format_timestamp(self):
strings.format_timestamp(1616057224)


if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()
Loading

0 comments on commit 635d4fd

Please sign in to comment.