diff --git a/src/policy/feerate.cpp b/src/policy/feerate.cpp index f62835acbcf..7cc07099daa 100644 --- a/src/policy/feerate.cpp +++ b/src/policy/feerate.cpp @@ -7,6 +7,7 @@ #include #include +#include CFeeRate::CFeeRate(const CAmount& nFeePaid, int32_t virtual_bytes) { @@ -29,9 +30,16 @@ CAmount CFeeRate::GetFee(int32_t virtual_bytes) const std::string CFeeRate::ToString(FeeRateFormat fee_rate_format) const { const CAmount feerate_per_kvb{GetFeePerK()}; + const auto format_feerate = [](const CAmount fee_rate, const CAmount divisor, const int decimals, const std::string& currency_unit, const std::string& size_unit) { + Assert(divisor > 0); + const char* sign{fee_rate < 0 ? "-" : ""}; + const CAmount quotient{std::abs(fee_rate / divisor)}; + const CAmount remainder{std::abs(fee_rate % divisor)}; + return strprintf("%s%d.%0*d %s/%s", sign, quotient, decimals, remainder, currency_unit, size_unit); + }; switch (fee_rate_format) { - case FeeRateFormat::BTC_KVB: return strprintf("%d.%08d %s/kvB", feerate_per_kvb / COIN, feerate_per_kvb % COIN, CURRENCY_UNIT); - case FeeRateFormat::SAT_VB: return strprintf("%d.%03d %s/vB", feerate_per_kvb / 1000, feerate_per_kvb % 1000, CURRENCY_ATOM); + case FeeRateFormat::BTC_KVB: return format_feerate(feerate_per_kvb, COIN, /*decimals=*/8, CURRENCY_UNIT, "kvB"); + case FeeRateFormat::SAT_VB: return format_feerate(feerate_per_kvb, 1000, /*decimals=*/3, CURRENCY_ATOM, "vB"); } // no default case, so the compiler can warn about missing cases assert(false); } diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index 0a273a21e74..24c4e93f9be 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -144,6 +144,24 @@ BOOST_AUTO_TEST_CASE(ToStringTest) BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kvB"); BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::BTC_KVB), "0.00000001 BTC/kvB"); BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::SAT_VB), "0.001 sat/vB"); + + feeRate = CFeeRate(0); + BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000000 BTC/kvB"); + BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::BTC_KVB), "0.00000000 BTC/kvB"); + BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::SAT_VB), "0.000 sat/vB"); + + feeRate = CFeeRate(-1); + BOOST_CHECK_EQUAL(feeRate.ToString(), "-0.00000001 BTC/kvB"); + BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::BTC_KVB), "-0.00000001 BTC/kvB"); + BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::SAT_VB), "-0.001 sat/vB"); + + feeRate = CFeeRate(-1000); + BOOST_CHECK_EQUAL(feeRate.ToString(), "-0.00001000 BTC/kvB"); + BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::SAT_VB), "-1.000 sat/vB"); + + feeRate = CFeeRate(-COIN - 1); + BOOST_CHECK_EQUAL(feeRate.ToString(), "-1.00000001 BTC/kvB"); + BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::SAT_VB), "-100000.001 sat/vB"); } BOOST_AUTO_TEST_SUITE_END()