diff --git a/src/amount.h b/src/amount.h --- a/src/amount.h +++ b/src/amount.h @@ -154,6 +154,24 @@ static constexpr Amount CASH = 100 * SATOSHI; static constexpr Amount COIN = 100000000 * SATOSHI; +class Currency { + Amount m_unit, m_subunit; + uint8_t m_decimals; + +public: + constexpr Currency(Amount unit, Amount subunit, uint8_t decimals) + : m_unit(unit), m_subunit(subunit), m_decimals(decimals) {} + + static const Currency &get(); + + //! the base unit ex: 1 Bitcoin = 100'000'000 satoshis + const Amount &unit() const { return m_unit; } + //! the subunit ex: for Bitcoin, 1 satoshi + const Amount &subunit() const { return m_subunit; } + //! # of decimals ex: 1 Bitcoin can have 8 decimal places + uint8_t decimals() const { return m_decimals; } +}; + /** * No amount larger than this (in satoshi) is valid. * diff --git a/src/amount.cpp b/src/amount.cpp --- a/src/amount.cpp +++ b/src/amount.cpp @@ -11,16 +11,26 @@ #include +static constexpr Currency BCHA{COIN, SATOSHI, 8}; + +const Currency &Currency::get() { + return BCHA; +} + std::string Amount::ToString() const { - return strprintf("%d.%08d %s", *this / COIN, (*this % COIN) / SATOSHI, + const auto currency = Currency::get(); + return strprintf("%d.%0*d %s", *this / currency.unit(), currency.decimals(), + (*this % currency.unit()) / currency.subunit(), CURRENCY_UNIT); } Amount::operator UniValue() const { bool sign = *this < Amount::zero(); Amount n_abs(sign ? -amount : amount); - int64_t quotient = n_abs / COIN; - int64_t remainder = (n_abs % COIN) / SATOSHI; - return UniValue(UniValue::VNUM, strprintf("%s%d.%08d", sign ? "-" : "", - quotient, remainder)); + const auto currency = Currency::get(); + int64_t quotient = n_abs / currency.unit(); + int64_t remainder = (n_abs % currency.unit()) / currency.subunit(); + return UniValue(UniValue::VNUM, + strprintf("%s%d.%0*d", sign ? "-" : "", quotient, + currency.decimals(), remainder)); } diff --git a/src/feerate.cpp b/src/feerate.cpp --- a/src/feerate.cpp +++ b/src/feerate.cpp @@ -57,6 +57,8 @@ } std::string CFeeRate::ToString() const { - return strprintf("%d.%08d %s/kB", nSatoshisPerK / COIN, - (nSatoshisPerK % COIN) / SATOSHI, CURRENCY_UNIT); + const auto currency = Currency::get(); + return strprintf( + "%d.%0*d %s/kB", nSatoshisPerK / currency.unit(), currency.decimals(), + (nSatoshisPerK % currency.unit()) / currency.subunit(), CURRENCY_UNIT); } diff --git a/src/util/moneystr.cpp b/src/util/moneystr.cpp --- a/src/util/moneystr.cpp +++ b/src/util/moneystr.cpp @@ -13,8 +13,10 @@ // Note: not using straight sprintf here because we do NOT want localized // number formatting. Amount amt_abs = amt > Amount::zero() ? amt : -amt; + const auto currency = Currency::get(); std::string str = - strprintf("%d.%08d", amt_abs / COIN, (amt_abs % COIN) / SATOSHI); + strprintf("%d.%0*d", amt_abs / currency.unit(), currency.decimals(), + (amt_abs % currency.unit()) / currency.subunit()); // Right-trim excess zeros before the decimal point: int nTrim = 0; @@ -40,13 +42,14 @@ return false; } + const auto currency = Currency::get(); std::string strWhole; Amount nUnits = Amount::zero(); const char *p = str.c_str(); for (; *p; p++) { if (*p == '.') { p++; - Amount nMult = COIN / 10; + Amount nMult = currency.unit() / 10; while (IsDigit(*p) && (nMult > Amount::zero())) { nUnits += (*p++ - '0') * nMult; nMult /= 10; @@ -68,11 +71,11 @@ if (strWhole.size() > 10) { return false; } - if (nUnits < Amount::zero() || nUnits > COIN) { + if (nUnits < Amount::zero() || nUnits > currency.unit()) { return false; } - Amount nWhole = atoi64(strWhole) * COIN; + Amount nWhole = atoi64(strWhole) * currency.unit(); nRet = nWhole + Amount(nUnits); return true;