1
- // Copyright (c) 2024 The Bitcoin Core developers
1
+ // Copyright (c) 2024-2025 The Bitcoin Core developers
2
2
// Distributed under the MIT software license, see the accompanying
3
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
4
7
7
#include < QRegExp>
8
8
#include < QStringList>
9
9
10
-
11
- BitcoinAmount::BitcoinAmount (QObject *parent) : QObject(parent)
10
+ BitcoinAmount::BitcoinAmount (QObject* parent)
11
+ : QObject(parent)
12
12
{
13
- m_unit = Unit::BTC;
14
- }
15
-
16
- int BitcoinAmount::decimals (Unit unit)
17
- {
18
- switch (unit) {
19
- case Unit::BTC: return 8 ;
20
- case Unit::SAT: return 0 ;
21
- } // no default case, so the compiler can warn about missing cases
22
- assert (false );
23
13
}
24
14
25
15
QString BitcoinAmount::sanitize (const QString &text)
@@ -43,6 +33,30 @@ QString BitcoinAmount::sanitize(const QString &text)
43
33
return result;
44
34
}
45
35
36
+ qint64 BitcoinAmount::satoshi () const
37
+ {
38
+ return m_satoshi;
39
+ }
40
+
41
+ void BitcoinAmount::setSatoshi (qint64 new_amount)
42
+ {
43
+ m_isSet = true ;
44
+ if (m_satoshi != new_amount) {
45
+ m_satoshi = new_amount;
46
+ Q_EMIT amountChanged ();
47
+ }
48
+ }
49
+
50
+ void BitcoinAmount::clear ()
51
+ {
52
+ if (!m_isSet && m_satoshi == 0 ) {
53
+ return ;
54
+ }
55
+ m_satoshi = 0 ;
56
+ m_isSet = false ;
57
+ Q_EMIT amountChanged ();
58
+ }
59
+
46
60
BitcoinAmount::Unit BitcoinAmount::unit () const
47
61
{
48
62
return m_unit;
@@ -58,97 +72,82 @@ QString BitcoinAmount::unitLabel() const
58
72
{
59
73
switch (m_unit) {
60
74
case Unit::BTC: return " ₿" ;
61
- case Unit::SAT: return " Sat " ;
75
+ case Unit::SAT: return " sat " ;
62
76
}
63
77
assert (false );
64
78
}
65
79
66
- QString BitcoinAmount::amount () const
80
+ void BitcoinAmount::flipUnit ()
67
81
{
68
- return m_amount;
82
+ if (m_unit == Unit::BTC) {
83
+ m_unit = Unit::SAT;
84
+ } else {
85
+ m_unit = Unit::BTC;
86
+ }
87
+ Q_EMIT unitChanged ();
88
+ Q_EMIT amountChanged ();
69
89
}
70
90
71
- QString BitcoinAmount::satoshiAmount () const
91
+ QString BitcoinAmount::satsToBtc (qint64 sat)
72
92
{
73
- return toSatoshis (m_amount) ;
74
- }
93
+ const bool negative = sat < 0 ;
94
+ qint64 absSat = negative ? -sat : sat;
75
95
76
- void BitcoinAmount::setAmount (const QString& new_amount)
77
- {
78
- m_amount = sanitize (new_amount);
79
- Q_EMIT amountChanged ();
96
+ const qint64 wholePart = absSat / COIN;
97
+ const qint64 fracInt = absSat % COIN;
98
+ QString fracPart = QString (" %1" ).arg (fracInt, 8 , 10 , QLatin1Char (' 0' ));
99
+
100
+ QString result = QString::number (wholePart) + ' .' + fracPart;
101
+ if (negative) {
102
+ result.prepend (' -' );
103
+ }
104
+ return result;
80
105
}
81
106
82
- QString BitcoinAmount::toSatoshis ( const QString& text ) const
107
+ QString BitcoinAmount::toDisplay ( ) const
83
108
{
109
+ if (!m_isSet) {
110
+ return " " ;
111
+ }
84
112
if (m_unit == Unit::SAT) {
85
- return text ;
113
+ return QString::number (m_satoshi) ;
86
114
} else {
87
- return convert (text, m_unit );
115
+ return satsToBtc (m_satoshi );
88
116
}
89
117
}
90
118
91
- long long BitcoinAmount::toSatoshis ( QString& amount, const Unit unit )
119
+ qint64 BitcoinAmount::btcToSats ( const QString& btcSanitized )
92
120
{
93
- int num_decimals = decimals (unit);
94
-
95
- QStringList parts = amount.remove (' ' ).split (" ." );
121
+ if (btcSanitized.isEmpty () || btcSanitized == " ." ) return 0 ;
96
122
97
- QString whole = parts[ 0 ] ;
98
- QString decimals ;
123
+ QString cleaned = btcSanitized ;
124
+ if (cleaned. startsWith ( ' . ' )) cleaned. prepend ( ' 0 ' ) ;
99
125
100
- if (parts.size () > 1 )
101
- {
102
- decimals = parts[1 ];
126
+ QStringList parts = cleaned.split (' .' );
127
+ const qint64 whole = parts[0 ].isEmpty () ? 0 : parts[0 ].toLongLong ();
128
+ qint64 frac = 0 ;
129
+ if (parts.size () == 2 ) {
130
+ frac = parts[1 ].leftJustified (8 , ' 0' ).toLongLong ();
103
131
}
104
- QString str = whole + decimals.leftJustified (num_decimals, ' 0' , true );
105
132
106
- return str. toLongLong () ;
133
+ return whole * COIN + frac ;
107
134
}
108
135
109
- QString BitcoinAmount::convert (const QString& amount, Unit unit) const
136
+ void BitcoinAmount::fromDisplay (const QString& text)
110
137
{
111
- if (amount == " " ) {
112
- return amount;
113
- }
114
-
115
- QString result = amount;
116
- int decimalPosition = result.indexOf (" ." );
117
-
118
- if (decimalPosition == -1 ) {
119
- decimalPosition = result.length ();
120
- result.append (" ." );
138
+ if (text.trimmed ().isEmpty ()) {
139
+ clear ();
140
+ return ;
121
141
}
122
142
123
- if (unit == Unit::BTC) {
124
- int numDigitsAfterDecimal = result.length () - decimalPosition - 1 ;
125
- if (numDigitsAfterDecimal < 8 ) {
126
- result.append (QString (8 - numDigitsAfterDecimal, ' 0' ));
127
- }
128
- result.remove (decimalPosition, 1 );
129
-
130
- while (result.startsWith (' 0' ) && result.length () > 1 ) {
131
- result.remove (0 , 1 );
132
- }
133
- } else if (unit == Unit::SAT) {
134
- result.remove (decimalPosition, 1 );
135
- int newDecimalPosition = decimalPosition - 8 ;
136
- if (newDecimalPosition < 1 ) {
137
- result = QString (" 0" ).repeated (-newDecimalPosition) + result;
138
- newDecimalPosition = 0 ;
139
- }
140
- result.insert (newDecimalPosition, " ." );
141
-
142
- while (result.endsWith (' 0' ) && result.contains (' .' )) {
143
- result.chop (1 );
144
- }
145
- if (result.endsWith (' .' )) {
146
- result.chop (1 );
147
- }
148
- if (result.startsWith (' .' )) {
149
- result.insert (0 , " 0" );
150
- }
143
+ qint64 newSat = 0 ;
144
+ if (m_unit == Unit::BTC) {
145
+ QString sanitized = sanitize (text);
146
+ newSat = btcToSats (sanitized);
147
+ } else {
148
+ QString digitsOnly = text;
149
+ digitsOnly.remove (QRegExp (" [^0-9]" ));
150
+ newSat = digitsOnly.trimmed ().isEmpty () ? 0 : digitsOnly.toLongLong ();
151
151
}
152
-
153
- return result;
152
+ setSatoshi (newSat);
154
153
}
0 commit comments