3
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
4
5
5
#include < qt/bitcoinunits.h>
6
+ #include < qt/tonalutils.h>
6
7
7
8
#include < consensus/amount.h>
8
9
11
12
#include < cassert>
12
13
13
14
static constexpr auto MAX_DIGITS_BTC = 16 ;
15
+ static constexpr auto MAX_DIGITS_TBC = 13 ;
14
16
15
17
BitcoinUnits::BitcoinUnits (QObject *parent):
16
18
QAbstractListModel(parent),
@@ -25,6 +27,12 @@ QList<BitcoinUnit> BitcoinUnits::availableUnits()
25
27
unitlist.append (Unit::mBTC );
26
28
unitlist.append (Unit::uBTC);
27
29
unitlist.append (Unit::SAT);
30
+ if (TonalUtils::Supported ())
31
+ {
32
+ unitlist.append (Unit::bTBC);
33
+ unitlist.append (Unit::sTBC );
34
+ unitlist.append (Unit::TBC);
35
+ }
28
36
return unitlist;
29
37
}
30
38
@@ -35,6 +43,9 @@ QString BitcoinUnits::longName(Unit unit)
35
43
case Unit::mBTC : return QString (" mBTC" );
36
44
case Unit::uBTC: return QString::fromUtf8 (" µBTC (bits)" );
37
45
case Unit::SAT: return QString (" Satoshi (sat)" );
46
+ case Unit::bTBC: return QString::fromUtf8 (" ᵇTBC" );
47
+ case Unit::sTBC : return QString::fromUtf8 (" ˢTBC" );
48
+ case Unit::TBC: return QString (" TBC" );
38
49
} // no default case, so the compiler can warn about missing cases
39
50
assert (false );
40
51
}
@@ -46,17 +57,23 @@ QString BitcoinUnits::shortName(Unit unit)
46
57
case Unit::mBTC : return longName (unit);
47
58
case Unit::uBTC: return QString (" bits" );
48
59
case Unit::SAT: return QString (" sat" );
60
+ case Unit::bTBC: return QString::fromUtf8 (" ᵇTBC" );
61
+ case Unit::sTBC : return QString::fromUtf8 (" ˢTBC" );
62
+ case Unit::TBC: return QString (" TBC" );
49
63
} // no default case, so the compiler can warn about missing cases
50
64
assert (false );
51
65
}
52
66
53
67
QString BitcoinUnits::description (Unit unit)
54
68
{
55
69
switch (unit) {
56
- case Unit::BTC: return QString (" Bitcoins" );
70
+ case Unit::BTC: return QString (" Bitcoins (decimal) " );
57
71
case Unit::mBTC : return QString (" Milli-Bitcoins (1 / 1" THIN_SP_UTF8 " 000)" );
58
72
case Unit::uBTC: return QString (" Micro-Bitcoins (bits) (1 / 1" THIN_SP_UTF8 " 000" THIN_SP_UTF8 " 000)" );
59
73
case Unit::SAT: return QString (" Satoshi (sat) (1 / 100" THIN_SP_UTF8 " 000" THIN_SP_UTF8 " 000)" );
74
+ case Unit::bTBC: return QString (" Bong-Bitcoins (1,0000 tonal)" );
75
+ case Unit::sTBC : return QString (" San-Bitcoins (100 tonal)" );
76
+ case Unit::TBC: return QString (" Bitcoins (tonal)" );
60
77
} // no default case, so the compiler can warn about missing cases
61
78
assert (false );
62
79
}
@@ -68,6 +85,9 @@ qint64 BitcoinUnits::factor(Unit unit)
68
85
case Unit::mBTC : return 100'000 ;
69
86
case Unit::uBTC: return 100 ;
70
87
case Unit::SAT: return 1 ;
88
+ case Unit::bTBC: return 0x100000000LL ;
89
+ case Unit::sTBC : return 0x1000000 ;
90
+ case Unit::TBC: return 0x10000 ;
71
91
} // no default case, so the compiler can warn about missing cases
72
92
assert (false );
73
93
}
@@ -79,10 +99,57 @@ int BitcoinUnits::decimals(Unit unit)
79
99
case Unit::mBTC : return 5 ;
80
100
case Unit::uBTC: return 2 ;
81
101
case Unit::SAT: return 0 ;
102
+ case Unit::bTBC: return 8 ;
103
+ case Unit::sTBC : return 6 ;
104
+ case Unit::TBC: return 4 ;
82
105
} // no default case, so the compiler can warn about missing cases
83
106
assert (false );
84
107
}
85
108
109
+ int BitcoinUnits::radix (Unit unit)
110
+ {
111
+ switch (unit) {
112
+ case Unit::bTBC:
113
+ case Unit::sTBC :
114
+ case Unit::TBC:
115
+ return 0x10 ;
116
+ default :
117
+ return 10 ;
118
+ }
119
+ }
120
+
121
+ BitcoinUnit BitcoinUnits::numsys (Unit unit)
122
+ {
123
+ switch (unit) {
124
+ case Unit::bTBC:
125
+ case Unit::sTBC :
126
+ case Unit::TBC:
127
+ return Unit::TBC;
128
+ default :
129
+ return Unit::BTC;
130
+ }
131
+ }
132
+
133
+ qint64 BitcoinUnits::max_digits (Unit unit)
134
+ {
135
+ switch (numsys (unit)) {
136
+ case Unit::TBC:
137
+ return MAX_DIGITS_TBC;
138
+ default :
139
+ return MAX_DIGITS_BTC;
140
+ }
141
+ }
142
+
143
+ qint64 BitcoinUnits::singlestep (Unit unit)
144
+ {
145
+ switch (numsys (unit)) {
146
+ case Unit::TBC:
147
+ return 0x10000 ;
148
+ default :
149
+ return 100000 ;
150
+ }
151
+ }
152
+
86
153
QString BitcoinUnits::format (Unit unit, const CAmount& nIn, bool fPlus , SeparatorStyle separators, bool justify)
87
154
{
88
155
// Note: not using straight sprintf here because we do NOT want
@@ -92,11 +159,22 @@ QString BitcoinUnits::format(Unit unit, const CAmount& nIn, bool fPlus, Separato
92
159
int num_decimals = decimals (unit);
93
160
qint64 n_abs = (n > 0 ? n : -n);
94
161
qint64 quotient = n_abs / coin;
95
- QString quotient_str = QString::number (quotient);
162
+ int uradix = radix (unit);
163
+ QString quotient_str = QString::number (quotient, uradix);
96
164
if (justify) {
97
- quotient_str = quotient_str.rightJustified (MAX_DIGITS_BTC - num_decimals, ' ' );
165
+ quotient_str = quotient_str.rightJustified (max_digits (unit) - num_decimals, ' ' );
98
166
}
99
167
168
+ QString remainder_str;
169
+ if (num_decimals > 0 ) {
170
+ const qint64 remainder = n_abs % coin;
171
+ remainder_str = QString::number (remainder, uradix).rightJustified (num_decimals, ' 0' );
172
+ }
173
+
174
+ switch (numsys (unit)) {
175
+ case Unit::BTC:
176
+ {
177
+
100
178
// Use SI-style thin space separators as these are locale independent and can't be
101
179
// confused with the decimal marker.
102
180
QChar thin_sp (THIN_SP_CP);
@@ -105,18 +183,28 @@ QString BitcoinUnits::format(Unit unit, const CAmount& nIn, bool fPlus, Separato
105
183
for (int i = 3 ; i < q_size; i += 3 )
106
184
quotient_str.insert (q_size - i, thin_sp);
107
185
186
+ break ;
187
+ }
188
+ case Unit::TBC:
189
+ {
190
+ // Right-trim excess zeros after the decimal point
191
+ static const QRegExp tail_zeros (" 0+$" );
192
+ remainder_str.remove (tail_zeros);
193
+ TonalUtils::ConvertFromHex (quotient_str);
194
+ TonalUtils::ConvertFromHex (remainder_str);
195
+ break ;
196
+ }
197
+ default : assert (false );
198
+ }
199
+
108
200
if (n < 0 )
109
201
quotient_str.insert (0 , ' -' );
110
202
else if (fPlus && n > 0 )
111
203
quotient_str.insert (0 , ' +' );
112
204
113
- if (num_decimals > 0 ) {
114
- qint64 remainder = n_abs % coin;
115
- QString remainder_str = QString::number (remainder).rightJustified (num_decimals, ' 0' );
116
- return quotient_str + QString (" ." ) + remainder_str;
117
- } else {
118
- return quotient_str;
119
- }
205
+ if (!remainder_str.isEmpty ())
206
+ quotient_str += QString (" ." ) + remainder_str;
207
+ return quotient_str;
120
208
}
121
209
122
210
@@ -180,11 +268,18 @@ bool BitcoinUnits::parse(Unit unit, const QString& value, CAmount* val_out)
180
268
bool ok = false ;
181
269
QString str = whole + decimals.leftJustified (num_decimals, ' 0' );
182
270
271
+ Unit unumsys = numsys (unit);
272
+ if (unumsys == Unit::TBC) {
273
+ if (str.size () > 15 )
274
+ return false ; // Longer numbers may exceed 63 bits
275
+ TonalUtils::ConvertToHex (str);
276
+ } else
183
277
if (str.size () > 18 )
184
278
{
185
279
return false ; // Longer numbers will exceed 63 bits
186
280
}
187
- CAmount retvalue (str.toLongLong (&ok));
281
+
282
+ CAmount retvalue (str.toLongLong (&ok, radix (unit)));
188
283
if (val_out)
189
284
{
190
285
*val_out = retvalue;
@@ -228,18 +323,21 @@ CAmount BitcoinUnits::maxMoney()
228
323
return MAX_MONEY;
229
324
}
230
325
231
- namespace {
232
- qint8 ToQint8 (BitcoinUnit unit)
326
+ std::variant<qint8, QString> BitcoinUnits::ToSetting (BitcoinUnit unit)
233
327
{
234
328
switch (unit) {
235
- case BitcoinUnit::BTC: return 0 ;
236
- case BitcoinUnit::mBTC : return 1 ;
237
- case BitcoinUnit::uBTC: return 2 ;
238
- case BitcoinUnit::SAT: return 3 ;
329
+ case BitcoinUnit::BTC: return qint8{0 };
330
+ case BitcoinUnit::mBTC : return qint8{1 };
331
+ case BitcoinUnit::uBTC: return qint8{2 };
332
+ case BitcoinUnit::SAT: return qint8{3 };
333
+ case BitcoinUnit::bTBC: return QString (" bTBC" );
334
+ case BitcoinUnit::sTBC : return QString (" sTBC" );
335
+ case BitcoinUnit::TBC: return QString (" TBC" );
239
336
} // no default case, so the compiler can warn about missing cases
240
337
assert (false );
241
338
}
242
339
340
+ namespace {
243
341
BitcoinUnit FromQint8 (qint8 num)
244
342
{
245
343
switch (num) {
@@ -248,19 +346,43 @@ BitcoinUnit FromQint8(qint8 num)
248
346
case 2 : return BitcoinUnit::uBTC;
249
347
case 3 : return BitcoinUnit::SAT;
250
348
}
251
- assert ( false ) ;
349
+ return BitcoinUnit::BTC ;
252
350
}
253
351
} // namespace
254
352
353
+ BitcoinUnit BitcoinUnits::FromSetting (const QString& s, BitcoinUnit def)
354
+ {
355
+ if (s == " 0" ) return BitcoinUnit::BTC;
356
+ if (s == " 1" ) return BitcoinUnit::mBTC ;
357
+ if (s == " 2" ) return BitcoinUnit::uBTC;
358
+ if (s == " 3" ) return BitcoinUnit::SAT;
359
+ if (s == " 4" ) return BitcoinUnit::sTBC ;
360
+ if (s == " 5" ) return BitcoinUnit::TBC;
361
+ if (s == " bTBC" ) return BitcoinUnit::bTBC;
362
+ if (s == " sTBC" ) return BitcoinUnit::sTBC ;
363
+ if (s == " TBC" ) return BitcoinUnit::TBC;
364
+ return def;
365
+ }
366
+
255
367
QDataStream& operator <<(QDataStream& out, const BitcoinUnit& unit)
256
368
{
257
- return out << ToQint8 (unit);
369
+ auto setting_val = BitcoinUnits::ToSetting (unit);
370
+ if (const QString* setting_str = std::get_if<QString>(&setting_val)) {
371
+ return out << qint8{0 } << *setting_str;
372
+ } else {
373
+ return out << std::get<qint8>(setting_val);
374
+ }
258
375
}
259
376
260
377
QDataStream& operator >>(QDataStream& in, BitcoinUnit& unit)
261
378
{
262
379
qint8 input;
263
380
in >> input;
264
381
unit = FromQint8 (input);
382
+ if (!in.atEnd ()) {
383
+ QString setting_str;
384
+ in >> setting_str;
385
+ unit = BitcoinUnits::FromSetting (setting_str, unit);
386
+ }
265
387
return in;
266
388
}
0 commit comments