Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2011-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <qt/bitcoinunits.h>7#include <consensus/amount.h>9#include <QStringList>11#include <cassert>13static constexpr auto MAX_DIGITS_BTC = 16;15BitcoinUnits::BitcoinUnits(QObject *parent):16QAbstractListModel(parent),17unitlist(availableUnits())18{19}21QList<BitcoinUnit> BitcoinUnits::availableUnits()22{23QList<BitcoinUnit> unitlist;24unitlist.append(Unit::BTC);25unitlist.append(Unit::mBTC);26unitlist.append(Unit::uBTC);27unitlist.append(Unit::SAT);28return unitlist;29}31QString BitcoinUnits::longName(Unit unit)32{33switch (unit) {34case Unit::BTC: return QString("BTC");35case Unit::mBTC: return QString("mBTC");36case Unit::uBTC: return QString::fromUtf8("µBTC (bits)");37case Unit::SAT: return QString("Satoshi (sat)");38} // no default case, so the compiler can warn about missing cases39assert(false);40}42QString BitcoinUnits::shortName(Unit unit)43{44switch (unit) {45case Unit::BTC: return longName(unit);46case Unit::mBTC: return longName(unit);47case Unit::uBTC: return QString("bits");48case Unit::SAT: return QString("sat");49} // no default case, so the compiler can warn about missing cases50assert(false);51}53QString BitcoinUnits::description(Unit unit)54{55switch (unit) {56case Unit::BTC: return QString("Bitcoins");57case Unit::mBTC: return QString("Milli-Bitcoins (1 / 1" THIN_SP_UTF8 "000)");58case Unit::uBTC: return QString("Micro-Bitcoins (bits) (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");59case Unit::SAT: return QString("Satoshi (sat) (1 / 100" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");60} // no default case, so the compiler can warn about missing cases61assert(false);62}64qint64 BitcoinUnits::factor(Unit unit)65{66switch (unit) {67case Unit::BTC: return 100'000'000;68case Unit::mBTC: return 100'000;69case Unit::uBTC: return 100;70case Unit::SAT: return 1;71} // no default case, so the compiler can warn about missing cases72assert(false);73}75int BitcoinUnits::decimals(Unit unit)76{77switch (unit) {78case Unit::BTC: return 8;79case Unit::mBTC: return 5;80case Unit::uBTC: return 2;81case Unit::SAT: return 0;82} // no default case, so the compiler can warn about missing cases83assert(false);84}86QString BitcoinUnits::format(Unit unit, const CAmount& nIn, bool fPlus, SeparatorStyle separators, bool justify)87{88// Note: not using straight sprintf here because we do NOT want89// localized number formatting.90qint64 n = (qint64)nIn;91qint64 coin = factor(unit);92int num_decimals = decimals(unit);93qint64 n_abs = (n > 0 ? n : -n);94qint64 quotient = n_abs / coin;95QString quotient_str = QString::number(quotient);96if (justify) {97quotient_str = quotient_str.rightJustified(MAX_DIGITS_BTC - num_decimals, ' ');98}100// Use SI-style thin space separators as these are locale independent and can't be101// confused with the decimal marker.102QChar thin_sp(THIN_SP_CP);103int q_size = quotient_str.size();104if (separators == SeparatorStyle::ALWAYS || (separators == SeparatorStyle::STANDARD && q_size > 4))105for (int i = 3; i < q_size; i += 3)106quotient_str.insert(q_size - i, thin_sp);108if (n < 0)109quotient_str.insert(0, '-');110else if (fPlus && n > 0)111quotient_str.insert(0, '+');113if (num_decimals > 0) {114qint64 remainder = n_abs % coin;115QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');116return quotient_str + QString(".") + remainder_str;117} else {118return quotient_str;119}120}123// NOTE: Using formatWithUnit in an HTML context risks wrapping124// quantities at the thousands separator. More subtly, it also results125// in a standard space rather than a thin space, due to a bug in Qt's126// XML whitespace canonicalisation127//128// Please take care to use formatHtmlWithUnit instead, when129// appropriate.131QString BitcoinUnits::formatWithUnit(Unit unit, const CAmount& amount, bool plussign, SeparatorStyle separators)132{133return format(unit, amount, plussign, separators) + QString(" ") + shortName(unit);134}136QString BitcoinUnits::formatHtmlWithUnit(Unit unit, const CAmount& amount, bool plussign, SeparatorStyle separators)137{138QString str(formatWithUnit(unit, amount, plussign, separators));139str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML));140return QString("<span style='white-space: nowrap;'>%1</span>").arg(str);141}143QString BitcoinUnits::formatWithPrivacy(Unit unit, const CAmount& amount, SeparatorStyle separators, bool privacy)144{145assert(amount >= 0);146QString value;147if (privacy) {148value = format(unit, 0, false, separators, true).replace('0', '#');149} else {150value = format(unit, amount, false, separators, true);151}152return value + QString(" ") + shortName(unit);153}155bool BitcoinUnits::parse(Unit unit, const QString& value, CAmount* val_out)156{157if (value.isEmpty()) {158return false; // Refuse to parse invalid unit or empty string159}160int num_decimals = decimals(unit);162// Ignore spaces and thin spaces when parsing163QStringList parts = removeSpaces(value).split(".");165if(parts.size() > 2)166{167return false; // More than one dot168}169const QString& whole = parts[0];170QString decimals;172if(parts.size() > 1)173{174decimals = parts[1];175}176if(decimals.size() > num_decimals)177{178return false; // Exceeds max precision179}180bool ok = false;181QString str = whole + decimals.leftJustified(num_decimals, '0');183if(str.size() > 18)184{185return false; // Longer numbers will exceed 63 bits186}187CAmount retvalue(str.toLongLong(&ok));188if(val_out)189{190*val_out = retvalue;191}192return ok;193}195QString BitcoinUnits::getAmountColumnTitle(Unit unit)196{197return QObject::tr("Amount") + " (" + shortName(unit) + ")";198}200int BitcoinUnits::rowCount(const QModelIndex &parent) const201{202Q_UNUSED(parent);203return unitlist.size();204}206QVariant BitcoinUnits::data(const QModelIndex &index, int role) const207{208int row = index.row();209if(row >= 0 && row < unitlist.size())210{211Unit unit = unitlist.at(row);212switch(role)213{214case Qt::EditRole:215case Qt::DisplayRole:216return QVariant(longName(unit));217case Qt::ToolTipRole:218return QVariant(description(unit));219case UnitRole:220return QVariant::fromValue(unit);221}222}223return QVariant();224}226CAmount BitcoinUnits::maxMoney()227{228return MAX_MONEY;229}231namespace {232qint8 ToQint8(BitcoinUnit unit)233{234switch (unit) {235case BitcoinUnit::BTC: return 0;236case BitcoinUnit::mBTC: return 1;237case BitcoinUnit::uBTC: return 2;238case BitcoinUnit::SAT: return 3;239} // no default case, so the compiler can warn about missing cases240assert(false);241}243BitcoinUnit FromQint8(qint8 num)244{245switch (num) {246case 0: return BitcoinUnit::BTC;247case 1: return BitcoinUnit::mBTC;248case 2: return BitcoinUnit::uBTC;249case 3: return BitcoinUnit::SAT;250}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.