44
55#include < qml/bitcoinamount.h>
66
7+ #include < cassert>
78#include < limits>
89
910#include < QRegularExpression>
@@ -27,9 +28,10 @@ QString BitcoinAmount::sanitize(const QString &text)
2728 result = parts[0 ] + " ." + parts[1 ];
2829 }
2930
30- // Limit decimal places to 8
31- if (parts.size () == 2 && parts[1 ].length () > 8 ) {
32- result = parts[0 ] + " ." + parts[1 ].left (8 );
31+ // Limit decimal places to the selected unit precision.
32+ const int decimals = unitDecimals ();
33+ if (parts.size () == 2 && parts[1 ].length () > decimals) {
34+ result = parts[0 ] + " ." + parts[1 ].left (decimals);
3335 }
3436
3537 return result;
@@ -85,6 +87,8 @@ QString BitcoinAmount::unitLabel() const
8587{
8688 switch (m_unit) {
8789 case Unit::BTC : return QStringLiteral (" ₿" );
90+ case Unit::mBTC : return QStringLiteral (" mBTC" );
91+ case Unit::uBTC: return QStringLiteral (" bits" );
8892 case Unit::SAT :
8993 return (qAbs (m_satoshi) == 1 )
9094 ? tr (" sat" , " unit label, singular" )
@@ -95,10 +99,10 @@ QString BitcoinAmount::unitLabel() const
9599
96100void BitcoinAmount::flipUnit ()
97101{
98- if (m_unit == Unit::BTC ) {
99- m_unit = Unit::SAT ;
100- } else {
102+ if (m_unit == Unit::SAT ) {
101103 m_unit = Unit::BTC ;
104+ } else {
105+ m_unit = Unit::SAT ;
102106 }
103107 Q_EMIT unitChanged ();
104108 Q_EMIT displayChanged ();
@@ -126,11 +130,17 @@ QString BitcoinAmount::toDisplay() const
126130 if (!m_isSet) {
127131 return " " ;
128132 }
129- if (m_unit == Unit::SAT ) {
130- return QString::number (m_satoshi);
131- } else {
132- return satsToBtcString (m_satoshi);
133+ const qint64 factor = unitFactor ();
134+ const int decimals = unitDecimals ();
135+ const bool negative = m_satoshi < 0 ;
136+ const qint64 abs_sat = negative ? -m_satoshi : m_satoshi;
137+ const qint64 whole = abs_sat / factor;
138+ QString result = QString::number (whole);
139+ if (decimals > 0 ) {
140+ result += " ." + QString::number (abs_sat % factor).rightJustified (decimals, ' 0' );
133141 }
142+ if (negative) result.prepend (' -' );
143+ return result;
134144}
135145
136146QString BitcoinAmount::displayWithUnit () const
@@ -139,25 +149,48 @@ QString BitcoinAmount::displayWithUnit() const
139149 return display.isEmpty () ? QString{} : display + QStringLiteral (" " ) + unitLabel ();
140150}
141151
142- qint64 BitcoinAmount::btcToSats ( const QString& btcSanitized)
152+ qint64 BitcoinAmount::unitFactor () const
143153{
144- if (btcSanitized.isEmpty () || btcSanitized == " ." ) return 0 ;
154+ switch (m_unit) {
155+ case Unit::BTC : return COIN ;
156+ case Unit::mBTC : return 100000 ;
157+ case Unit::uBTC: return 100 ;
158+ case Unit::SAT : return 1 ;
159+ }
160+ assert (false );
161+ }
145162
146- QString cleaned = btcSanitized;
163+ int BitcoinAmount::unitDecimals () const
164+ {
165+ switch (m_unit) {
166+ case Unit::BTC : return 8 ;
167+ case Unit::mBTC : return 5 ;
168+ case Unit::uBTC: return 2 ;
169+ case Unit::SAT : return 0 ;
170+ }
171+ assert (false );
172+ }
173+
174+ qint64 BitcoinAmount::displayToSats (const QString& sanitized) const
175+ {
176+ if (sanitized.isEmpty () || sanitized == " ." ) return 0 ;
177+
178+ QString cleaned = sanitized;
147179 if (cleaned.startsWith (' .' )) cleaned.prepend (' 0' );
148180
149181 QStringList parts = cleaned.split (' .' );
150182 const qint64 whole = parts[0 ].isEmpty () ? 0 : parts[0 ].toLongLong ();
151183 qint64 frac = 0 ;
152184 if (parts.size () == 2 ) {
153- frac = parts[1 ].leftJustified (8 , ' 0' ).toLongLong ();
185+ frac = parts[1 ].leftJustified (unitDecimals () , ' 0' ).toLongLong ();
154186 }
155187
156- if (whole > std::numeric_limits<qint64>::max () / COIN ) {
188+ const qint64 factor = unitFactor ();
189+ if (whole > std::numeric_limits<qint64>::max () / factor) {
157190 return std::numeric_limits<qint64>::max ();
158191 }
159192
160- return whole * COIN + frac;
193+ return whole * factor + frac;
161194}
162195
163196void BitcoinAmount::fromDisplay (const QString& text)
@@ -168,13 +201,13 @@ void BitcoinAmount::fromDisplay(const QString& text)
168201 }
169202
170203 qint64 newSat = 0 ;
171- if (m_unit == Unit::BTC ) {
172- QString sanitized = sanitize (text);
173- newSat = btcToSats (sanitized);
174- } else {
204+ if (m_unit == Unit::SAT ) {
175205 QString digitsOnly = text;
176206 digitsOnly.remove (QRegularExpression (" [^0-9]" ));
177207 newSat = digitsOnly.trimmed ().isEmpty () ? 0 : digitsOnly.toLongLong ();
208+ } else {
209+ QString sanitized = sanitize (text);
210+ newSat = displayToSats (sanitized);
178211 }
179212 setSatoshi (newSat);
180213}
0 commit comments