From c7b2626d6e7af61a29a57d4efe0293b5c3a9e789 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Sat, 15 Mar 2025 18:24:53 +0000 Subject: [PATCH] amt.py: reimplement CoinAmt.to_unit(), add test --- mmgen/amt.py | 9 ++++++- test/modtest_d/ut_amt.py | 56 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100755 test/modtest_d/ut_amt.py diff --git a/mmgen/amt.py b/mmgen/amt.py index 004acab1..e066d1b8 100755 --- a/mmgen/amt.py +++ b/mmgen/amt.py @@ -65,7 +65,12 @@ class CoinAmt(Decimal, Hilite, InitErrors): # abstract class return cls.init_fail(e, num) def to_unit(self, unit): - return int(Decimal(self) // getattr(self, unit)) + if (u := getattr(self, unit)) == self.atomic: + return int(Decimal(self) // u) + else: + return Decimal('{:0.{w}f}'.format( + self / u, + w = (u/self.atomic).as_tuple().exponent)) @classmethod def fmtc(cls, *args, **kwargs): @@ -165,6 +170,7 @@ class BTCAmt(CoinAmt): max_prec = 8 max_amt = 21000000 satoshi = Decimal('0.00000001') + atomic = satoshi units = ('satoshi',) class BCHAmt(BTCAmt): @@ -190,6 +196,7 @@ class ETHAmt(CoinAmt): Gwei = Decimal('0.000000001') szabo = Decimal('0.000001') finney = Decimal('0.001') + atomic = wei units = ('wei', 'Kwei', 'Mwei', 'Gwei', 'szabo', 'finney') def toWei(self): diff --git a/test/modtest_d/ut_amt.py b/test/modtest_d/ut_amt.py new file mode 100755 index 00000000..9cf236be --- /dev/null +++ b/test/modtest_d/ut_amt.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 + +""" +test.modtest_d.ut_amt: CoinAmt unit tests for the MMGen suite +""" + +from decimal import Decimal + +from mmgen.protocol import init_proto +from mmgen.cfg import Config + +from ..include.common import cfg, vmsg + +def get_protos(data): + return {coin: init_proto(cfg, coin, need_amt=True) for coin in set(d[0] for d in data)} + +def test_to_unit(data): + protos = get_protos(data) + for proto, amt, unit, chk in data: + amt = protos[proto].coin_amt(amt) + res = amt.to_unit(unit) + vmsg(f' {proto.upper()} {amt.fmt(8)} => {res:<14} {unit}') + if '.' in chk: + assert res == Decimal(chk), f'{res} != {Decimal(chk)}' + else: + assert res == int(chk), f'{res} != {int(chk)}' + return True + +class unit_tests: + + altcoin_deps = ('to_unit_alt',) + + def to_unit(self, name, ut, desc='CoinAmt.to_unit() (BTC)'): + return test_to_unit(( + ('btc', '0.00000001', 'satoshi', '1'), + ('btc', '1.23456789', 'satoshi', '123456789'))) + + def to_unit_alt(self, name, ut, desc='CoinAmt.to_unit() (LTC, BCH, ETH, XMR)'): + return test_to_unit(( + ('ltc', '0.00000001', 'satoshi', '1'), + ('ltc', '1.23456789', 'satoshi', '123456789'), + ('bch', '0.00000001', 'satoshi', '1'), + ('bch', '1.23456789', 'satoshi', '123456789'), + ('eth', '1.234567890123456789', 'wei', '1234567890123456789'), + ('eth', '1.234567890123456789', 'Kwei', '1234567890123456.789'), + ('eth', '1.234567890123456789', 'Mwei', '1234567890123.456789'), + ('eth', '1.234567890123456789', 'finney', '1234.567890123456789'), + ('eth', '0.000000012345678901', 'Mwei', '12345.678901'), + ('eth', '0.000000000000000001', 'Kwei', '0.001'), + ('eth', '0.000000000000000001', 'Gwei', '0.000000001'), + ('eth', '0.00000001', 'Gwei', '10'), + ('eth', '1', 'Gwei', '1000000000'), + ('eth', '1', 'finney', '1000'), + ('xmr', '1', 'atomic', '1000000000000'), + ('xmr', '0.000000000001', 'atomic', '1'), + ('xmr', '1.234567890123', 'atomic', '1234567890123')))