Bitcoin Core 29.99.0
P2P Digital Currency
transactiontablemodel.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2022 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
6
8#include <qt/bitcoinunits.h>
9#include <qt/clientmodel.h>
10#include <qt/guiconstants.h>
11#include <qt/guiutil.h>
12#include <qt/optionsmodel.h>
13#include <qt/platformstyle.h>
14#include <qt/transactiondesc.h>
16#include <qt/walletmodel.h>
17
18#include <core_io.h>
19#include <interfaces/handler.h>
20#include <tinyformat.h>
21#include <uint256.h>
22
23#include <algorithm>
24#include <functional>
25
26#include <QColor>
27#include <QDateTime>
28#include <QDebug>
29#include <QIcon>
30#include <QLatin1Char>
31#include <QLatin1String>
32#include <QList>
33
34
35// Amount column is right-aligned it contains numbers
36static int column_alignments[] = {
37 Qt::AlignLeft|Qt::AlignVCenter, /*status=*/
38 Qt::AlignLeft|Qt::AlignVCenter, /*date=*/
39 Qt::AlignLeft|Qt::AlignVCenter, /*type=*/
40 Qt::AlignLeft|Qt::AlignVCenter, /*address=*/
41 Qt::AlignRight|Qt::AlignVCenter /* amount */
42 };
43
44// Comparison operator for sort/binary search of model tx list
46{
47 bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
48 {
49 return a.hash < b.hash;
50 }
51 bool operator()(const TransactionRecord &a, const Txid &b) const
52 {
53 return a.hash < b;
54 }
55 bool operator()(const Txid &a, const TransactionRecord &b) const
56 {
57 return a < b.hash;
58 }
59};
60
61// queue notifications to show a non freezing progress dialog e.g. for rescan
63{
64public:
66 TransactionNotification(Txid _hash, ChangeType _status, bool _showTransaction):
67 hash(_hash), status(_status), showTransaction(_showTransaction) {}
68
69 void invoke(QObject *ttm)
70 {
71 QString strHash = QString::fromStdString(hash.GetHex());
72 qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status);
73 bool invoked = QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection,
74 Q_ARG(QString, strHash),
75 Q_ARG(int, status),
76 Q_ARG(bool, showTransaction));
77 assert(invoked);
78 }
79private:
83};
84
85// Private implementation
87{
88public:
90 parent(_parent)
91 {
92 }
93
95
97 QList<TransactionRecord> cachedWallet;
98
100 bool m_loaded = false;
102 bool m_loading = false;
103 std::vector< TransactionNotification > vQueueNotifications;
104
105 void NotifyTransactionChanged(const Txid& hash, ChangeType status);
107
108 /* Query entire wallet anew from core.
109 */
111 {
113 {
114 for (const auto& wtx : wallet.getWalletTxs()) {
117 }
118 }
119 }
120 m_loaded = true;
122 }
123
124 /* Update our model of the wallet incrementally, to synchronize our model of the wallet
125 with that of the core.
126
127 Call with transaction that was added, removed or changed.
128 */
129 void updateWallet(interfaces::Wallet& wallet, const Txid& hash, int status, bool showTransaction)
130 {
131 qDebug() << "TransactionTablePriv::updateWallet: " + QString::fromStdString(hash.ToString()) + " " + QString::number(status);
132
133 // Find bounds of this transaction in model
134 QList<TransactionRecord>::iterator lower = std::lower_bound(
135 cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
136 QList<TransactionRecord>::iterator upper = std::upper_bound(
137 cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
138 int lowerIndex = (lower - cachedWallet.begin());
139 int upperIndex = (upper - cachedWallet.begin());
140 bool inModel = (lower != upper);
141
142 if(status == CT_UPDATED)
143 {
144 if(showTransaction && !inModel)
145 status = CT_NEW; /* Not in model, but want to show, treat as new */
146 if(!showTransaction && inModel)
147 status = CT_DELETED; /* In model, but want to hide, treat as deleted */
148 }
149
150 qDebug() << " inModel=" + QString::number(inModel) +
151 " Index=" + QString::number(lowerIndex) + "-" + QString::number(upperIndex) +
152 " showTransaction=" + QString::number(showTransaction) + " derivedStatus=" + QString::number(status);
153
154 switch(status)
155 {
156 case CT_NEW:
157 if(inModel)
158 {
159 qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is already in model";
160 break;
161 }
162 if(showTransaction)
163 {
164 // Find transaction in wallet
165 interfaces::WalletTx wtx = wallet.getWalletTx(hash);
166 if(!wtx.tx)
167 {
168 qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_NEW, but transaction is not in wallet";
169 break;
170 }
171 // Added -- insert at the right position
172 QList<TransactionRecord> toInsert =
174 if(!toInsert.isEmpty()) /* only if something to insert */
175 {
176 parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1);
177 int insert_idx = lowerIndex;
178 for (const TransactionRecord &rec : toInsert)
179 {
180 cachedWallet.insert(insert_idx, rec);
181 insert_idx += 1;
182 }
183 parent->endInsertRows();
184 }
185 }
186 break;
187 case CT_DELETED:
188 if(!inModel)
189 {
190 qWarning() << "TransactionTablePriv::updateWallet: Warning: Got CT_DELETED, but transaction is not in model";
191 break;
192 }
193 // Removed -- remove entire transaction from table
194 parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
195 cachedWallet.erase(lower, upper);
196 parent->endRemoveRows();
197 break;
198 case CT_UPDATED:
199 // Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for
200 // visible transactions.
201 for (int i = lowerIndex; i < upperIndex; i++) {
203 rec->status.needsUpdate = true;
204 }
205 break;
206 }
207 }
208
209 int size()
210 {
211 return cachedWallet.size();
212 }
213
214 TransactionRecord* index(interfaces::Wallet& wallet, const uint256& cur_block_hash, const int idx)
215 {
216 if (idx >= 0 && idx < cachedWallet.size()) {
217 TransactionRecord *rec = &cachedWallet[idx];
218
219 // If a status update is needed (blocks came in since last check),
220 // try to update the status of this transaction from the wallet.
221 // Otherwise, simply reuse the cached status.
223 int numBlocks;
224 int64_t block_time;
225 if (!cur_block_hash.IsNull() && rec->statusUpdateNeeded(cur_block_hash) && wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, block_time)) {
226 rec->updateStatus(wtx, cur_block_hash, numBlocks, block_time);
227 }
228 return rec;
229 }
230 return nullptr;
231 }
232
234 {
235 return TransactionDesc::toHTML(node, wallet, rec, unit);
236 }
237
239 {
240 auto tx = wallet.getTx(rec->hash);
241 if (tx) {
242 std::string strHex = EncodeHexTx(*tx);
243 return QString::fromStdString(strHex);
244 }
245 return QString();
246 }
247};
248
250 QAbstractTableModel(parent),
251 walletModel(parent),
252 priv(new TransactionTablePriv(this)),
253 platformStyle(_platformStyle)
254{
256
257 columns << QString() << tr("Date") << tr("Type") << tr("Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
259
261}
262
264{
266 delete priv;
267}
268
271{
273 Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount);
274}
275
276void TransactionTableModel::updateTransaction(const QString &hash, int status, bool showTransaction)
277{
278 Txid updated = Txid::FromHex(hash.toStdString()).value();
279
280 priv->updateWallet(walletModel->wallet(), updated, status, showTransaction);
281}
282
284{
285 // Blocks came in since last poll.
286 // Invalidate status (number of confirmations) and (possibly) description
287 // for all rows. Qt is smart enough to only actually request the data for the
288 // visible rows.
289 Q_EMIT dataChanged(index(0, Status), index(priv->size()-1, Status));
290 Q_EMIT dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress));
291}
292
293int TransactionTableModel::rowCount(const QModelIndex &parent) const
294{
295 if (parent.isValid()) {
296 return 0;
297 }
298 return priv->size();
299}
300
301int TransactionTableModel::columnCount(const QModelIndex &parent) const
302{
303 if (parent.isValid()) {
304 return 0;
305 }
306 return columns.length();
307}
308
310{
311 QString status;
312
313 switch(wtx->status.status)
314 {
316 status = tr("Unconfirmed");
317 break;
319 status = tr("Abandoned");
320 break;
322 status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations);
323 break;
325 status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
326 break;
328 status = tr("Conflicted");
329 break;
331 status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in);
332 break;
334 status = tr("Generated but not accepted");
335 break;
336 }
337
338 return status;
339}
340
342{
343 if(wtx->time)
344 {
345 return GUIUtil::dateTimeStr(wtx->time);
346 }
347 return QString();
348}
349
350/* Look up address in address book, if found return label (address)
351 otherwise just return (address)
352 */
353QString TransactionTableModel::lookupAddress(const std::string &address, bool tooltip) const
354{
355 QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(address));
356 QString description;
357 if(!label.isEmpty())
358 {
359 description += label;
360 }
361 if(label.isEmpty() || tooltip)
362 {
363 description += QString(" (") + QString::fromStdString(address) + QString(")");
364 }
365 return description;
366}
367
369{
370 switch(wtx->type)
371 {
373 return tr("Received with");
375 return tr("Received from");
378 return tr("Sent to");
380 return tr("Mined");
381 default:
382 return QString();
383 }
384}
385
387{
388 switch(wtx->type)
389 {
391 return QIcon(":/icons/tx_mined");
394 return QIcon(":/icons/tx_input");
397 return QIcon(":/icons/tx_output");
398 default:
399 return QIcon(":/icons/tx_inout");
400 }
401}
402
403QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
404{
405 switch(wtx->type)
406 {
408 return QString::fromStdString(wtx->address);
412 return lookupAddress(wtx->address, tooltip);
414 return QString::fromStdString(wtx->address);
415 default:
416 return tr("(n/a)");
417 }
418}
419
421{
422 // Show addresses without label in a less visible color
423 switch(wtx->type)
424 {
428 {
429 QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(wtx->address));
430 if(label.isEmpty())
431 return COLOR_BAREADDRESS;
432 } break;
433 default:
434 break;
435 }
436 return QVariant();
437}
438
439QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed, BitcoinUnits::SeparatorStyle separators) const
440{
441 QString str = BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), wtx->credit + wtx->debit, false, separators);
442 if(showUnconfirmed)
443 {
444 if(!wtx->status.countsForBalance)
445 {
446 str = QString("[") + str + QString("]");
447 }
448 }
449 return QString(str);
450}
451
453{
454 switch(wtx->status.status)
455 {
457 return QIcon(":/icons/transaction_0");
459 return QIcon(":/icons/transaction_abandoned");
461 switch(wtx->status.depth)
462 {
463 case 1: return QIcon(":/icons/transaction_1");
464 case 2: return QIcon(":/icons/transaction_2");
465 case 3: return QIcon(":/icons/transaction_3");
466 case 4: return QIcon(":/icons/transaction_4");
467 default: return QIcon(":/icons/transaction_5");
468 };
470 return QIcon(":/icons/transaction_confirmed");
472 return QIcon(":/icons/transaction_conflicted");
474 int total = wtx->status.depth + wtx->status.matures_in;
475 int part = (wtx->status.depth * 4 / total) + 1;
476 return QIcon(QString(":/icons/transaction_%1").arg(part));
477 }
479 return QIcon(":/icons/transaction_0");
480 default:
481 return COLOR_BLACK;
482 }
483}
484
486{
487 QString tooltip = formatTxStatus(rec) + QString("\n") + formatTxType(rec);
490 {
491 tooltip += QString(" ") + formatTxToAddress(rec, true);
492 }
493 return tooltip;
494}
495
496QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
497{
498 if(!index.isValid())
499 return QVariant();
500 TransactionRecord *rec = static_cast<TransactionRecord*>(index.internalPointer());
501
502 const auto column = static_cast<ColumnIndex>(index.column());
503 switch (role) {
505 switch (column) {
506 case Status:
507 return txStatusDecoration(rec);
508 case Date: return {};
509 case Type: return {};
510 case ToAddress:
511 return txAddressDecoration(rec);
512 case Amount: return {};
513 } // no default case, so the compiler can warn about missing cases
514 assert(false);
515 case Qt::DecorationRole:
516 {
517 QIcon icon = qvariant_cast<QIcon>(index.data(RawDecorationRole));
518 return platformStyle->TextColorIcon(icon);
519 }
520 case Qt::DisplayRole:
521 switch (column) {
522 case Status: return {};
523 case Date:
524 return formatTxDate(rec);
525 case Type:
526 return formatTxType(rec);
527 case ToAddress:
528 return formatTxToAddress(rec, false);
529 case Amount:
531 } // no default case, so the compiler can warn about missing cases
532 assert(false);
533 case Qt::EditRole:
534 // Edit role is used for sorting, so return the unformatted values
535 switch (column) {
536 case Status:
537 return QString::fromStdString(rec->status.sortKey);
538 case Date:
539 return QString::fromStdString(strprintf("%020s-%s", rec->time, rec->status.sortKey));
540 case Type:
541 return formatTxType(rec);
542 case ToAddress:
543 return formatTxToAddress(rec, true);
544 case Amount:
545 return qint64(rec->credit + rec->debit);
546 } // no default case, so the compiler can warn about missing cases
547 assert(false);
548 case Qt::ToolTipRole:
549 return formatTooltip(rec);
550 case Qt::TextAlignmentRole:
551 return column_alignments[index.column()];
552 case Qt::ForegroundRole:
553 // Use the "danger" color for abandoned transactions
555 {
557 }
558 // Non-confirmed (but not immature) as transactions are grey
560 {
561 return COLOR_UNCONFIRMED;
562 }
563 if(index.column() == Amount && (rec->credit+rec->debit) < 0)
564 {
565 return COLOR_NEGATIVE;
566 }
567 if(index.column() == ToAddress)
568 {
569 return addressColor(rec);
570 }
571 break;
572 case TypeRole:
573 return rec->type;
574 case DateRole:
575 return QDateTime::fromSecsSinceEpoch(rec->time);
578 case AddressRole:
579 return QString::fromStdString(rec->address);
580 case LabelRole:
581 return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
582 case AmountRole:
583 return qint64(rec->credit + rec->debit);
584 case TxHashRole:
585 return rec->getTxHash();
586 case TxHexRole:
587 return priv->getTxHex(walletModel->wallet(), rec);
588 case TxPlainTextRole:
589 {
590 QString details;
591 QDateTime date = QDateTime::fromSecsSinceEpoch(rec->time);
592 QString txLabel = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
593
594 details.append(date.toString("M/d/yy HH:mm"));
595 details.append(" ");
596 details.append(formatTxStatus(rec));
597 details.append(". ");
598 if(!formatTxType(rec).isEmpty()) {
599 details.append(formatTxType(rec));
600 details.append(" ");
601 }
602 if(!rec->address.empty()) {
603 if(txLabel.isEmpty())
604 details.append(tr("(no label)") + " ");
605 else {
606 details.append("(");
607 details.append(txLabel);
608 details.append(") ");
609 }
610 details.append(QString::fromStdString(rec->address));
611 details.append(" ");
612 }
613 details.append(formatTxAmount(rec, false, BitcoinUnits::SeparatorStyle::NEVER));
614 return details;
615 }
616 case ConfirmedRole:
617 return rec->status.status == TransactionStatus::Status::Confirming || rec->status.status == TransactionStatus::Status::Confirmed;
619 // Used for copy/export, so don't include separators
621 case StatusRole:
622 return rec->status.status;
623 }
624 return QVariant();
625}
626
627QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientation, int role) const
628{
629 if(orientation == Qt::Horizontal)
630 {
631 if(role == Qt::DisplayRole)
632 {
633 return columns[section];
634 }
635 else if (role == Qt::TextAlignmentRole)
636 {
637 return column_alignments[section];
638 } else if (role == Qt::ToolTipRole)
639 {
640 switch(section)
641 {
642 case Status:
643 return tr("Transaction status. Hover over this field to show number of confirmations.");
644 case Date:
645 return tr("Date and time that the transaction was received.");
646 case Type:
647 return tr("Type of transaction.");
648 case ToAddress:
649 return tr("User-defined intent/purpose of the transaction.");
650 case Amount:
651 return tr("Amount removed from or added to balance.");
652 }
653 }
654 }
655 return QVariant();
656}
657
658QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const
659{
660 Q_UNUSED(parent);
662 if(data)
663 {
664 return createIndex(row, column, data);
665 }
666 return QModelIndex();
667}
668
670{
671 // emit dataChanged to update Amount column with the current unit
673 Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount));
674}
675
677{
678 // Find transaction in wallet
679 // Determine whether to show transaction or not (determine this here so that no relocking is needed in GUI thread)
680 bool showTransaction = TransactionRecord::showTransaction();
681
682 TransactionNotification notification(hash, status, showTransaction);
683
684 if (!m_loaded || m_loading)
685 {
686 vQueueNotifications.push_back(notification);
687 return;
688 }
689 notification.invoke(parent);
690}
691
693{
694 if (!m_loaded || m_loading) return;
695
696 if (vQueueNotifications.size() > 10) { // prevent balloon spam, show maximum 10 balloons
697 bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
698 assert(invoked);
699 }
700 for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
701 {
702 if (vQueueNotifications.size() - i <= 10) {
703 bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
704 assert(invoked);
705 }
706
707 vQueueNotifications[i].invoke(parent);
708 }
709 vQueueNotifications.clear();
710}
711
713{
714 // Connect signals to wallet
716 m_handler_show_progress = walletModel->wallet().handleShowProgress([this](const std::string&, int progress) {
717 priv->m_loading = progress < 100;
719 });
720}
721
723{
724 // Disconnect signals from wallet
725 m_handler_transaction_changed->disconnect();
726 m_handler_show_progress->disconnect();
727}
QString labelForAddress(const QString &address) const
Look up label for address in address book, if not found return empty string.
static QString format(Unit unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD, bool justify=false)
Format as string.
static QString getAmountColumnTitle(Unit unit)
Gets title for amount column including current display unit if optionsModel reference available *‍/.
Unit
Bitcoin units.
Definition: bitcoinunits.h:42
void displayUnitChanged(BitcoinUnit unit)
BitcoinUnit getDisplayUnit() const
Definition: optionsmodel.h:103
QIcon TextColorIcon(const QIcon &icon) const
Colorize an icon (given object) with the text color.
static QString toHTML(interfaces::Node &node, interfaces::Wallet &wallet, TransactionRecord *rec, BitcoinUnit unit)
UI model for a transaction.
static QList< TransactionRecord > decomposeTransaction(const interfaces::WalletTx &wtx)
static const int RecommendedNumConfirmations
Number of confirmation recommended for accepting a transaction.
static bool showTransaction()
Decompose CWallet transaction to model transaction records.
TransactionStatus status
Status: can change with block chain update.
QString getTxHash() const
Return the unique identifier for this transaction (part)
bool statusUpdateNeeded(const uint256 &block_hash) const
Return whether a status update is needed.
void updateStatus(const interfaces::WalletTxStatus &wtx, const uint256 &block_hash, int numBlocks, int64_t block_time)
Update status from core wallet tx.
UI model for the transaction table of a wallet.
QVariant txStatusDecoration(const TransactionRecord *wtx) const
TransactionTablePriv * priv
QVariant addressColor(const TransactionRecord *wtx) const
@ TxPlainTextRole
Whole transaction as plain text.
@ LabelRole
Label of address related to transaction.
@ LongDescriptionRole
Long description (HTML format)
@ TypeRole
Type of transaction.
@ StatusRole
Transaction status (TransactionRecord::Status)
@ DateRole
Date and time this transaction was created.
@ TxHashRole
Transaction hash.
@ TxHexRole
Transaction data, hex-encoded.
@ RawDecorationRole
Unprocessed icon.
@ AddressRole
Address of transaction.
@ AmountRole
Net amount of transaction.
@ ConfirmedRole
Is transaction confirmed?
@ FormattedAmountRole
Formatted amount, without brackets when unconfirmed.
QString formatTooltip(const TransactionRecord *rec) const
QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true, BitcoinUnits::SeparatorStyle separators=BitcoinUnits::SeparatorStyle::STANDARD) const
QVariant data(const QModelIndex &index, int role) const override
void updateTransaction(const QString &hash, int status, bool showTransaction)
QString formatTxStatus(const TransactionRecord *wtx) const
std::unique_ptr< interfaces::Handler > m_handler_transaction_changed
int columnCount(const QModelIndex &parent) const override
std::unique_ptr< interfaces::Handler > m_handler_show_progress
TransactionTableModel(const PlatformStyle *platformStyle, WalletModel *parent=nullptr)
int rowCount(const QModelIndex &parent) const override
void updateAmountColumnTitle()
Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table hea...
QString formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
const PlatformStyle * platformStyle
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QString formatTxType(const TransactionRecord *wtx) const
QString lookupAddress(const std::string &address, bool tooltip) const
QVariant txAddressDecoration(const TransactionRecord *wtx) const
QString formatTxDate(const TransactionRecord *wtx) const
QString getTxHex(interfaces::Wallet &wallet, TransactionRecord *rec)
TransactionTablePriv(TransactionTableModel *_parent)
TransactionTableModel * parent
QList< TransactionRecord > cachedWallet
Local cache of wallet sorted by transaction hash.
void refreshWallet(interfaces::Wallet &wallet)
bool m_loading
True when transactions are being notified, for instance when scanning.
void NotifyTransactionChanged(const Txid &hash, ChangeType status)
void updateWallet(interfaces::Wallet &wallet, const Txid &hash, int status, bool showTransaction)
TransactionRecord * index(interfaces::Wallet &wallet, const uint256 &cur_block_hash, const int idx)
std::vector< TransactionNotification > vQueueNotifications
QString describe(interfaces::Node &node, interfaces::Wallet &wallet, TransactionRecord *rec, BitcoinUnit unit)
bool m_loaded
True when model finishes loading all wallet transactions on start.
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:49
interfaces::Node & node() const
Definition: walletmodel.h:138
AddressTableModel * getAddressTableModel() const
interfaces::Wallet & wallet() const
Definition: walletmodel.h:139
OptionsModel * getOptionsModel() const
uint256 getLastBlockProcessed() const
constexpr bool IsNull() const
Definition: uint256.h:48
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:71
Interface for accessing a wallet.
Definition: wallet.h:67
virtual std::unique_ptr< Handler > handleShowProgress(ShowProgressFn fn)=0
virtual std::unique_ptr< Handler > handleTransactionChanged(TransactionChangedFn fn)=0
std::string ToString() const
std::string GetHex() const
static std::optional< transaction_identifier > FromHex(std::string_view hex)
256-bit opaque blob.
Definition: uint256.h:196
std::string EncodeHexTx(const CTransaction &tx)
Definition: core_write.cpp:143
#define COLOR_TX_STATUS_DANGER
Definition: guiconstants.h:37
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:31
#define COLOR_NEGATIVE
Definition: guiconstants.h:33
#define COLOR_BLACK
Definition: guiconstants.h:39
#define COLOR_BAREADDRESS
Definition: guiconstants.h:35
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:90
Definition: messages.h:20
TransactionNotification()=default
TransactionNotification(Txid _hash, ChangeType _status, bool _showTransaction)
bool countsForBalance
Transaction counts towards available balance.
@ Confirmed
Have 6 or more confirmations (normal tx) or fully mature (mined tx)
@ Unconfirmed
Normal (sent/received) transactions.
@ Immature
Generated (mined) transactions.
@ Confirming
Confirmed, but waiting for the recommended number of confirmations.
@ NotAccepted
Mined but not accepted.
@ Conflicted
Conflicts with other transaction or mempool.
@ Abandoned
Abandoned from the wallet.
std::string sortKey
Sorting key based on status.
bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
bool operator()(const Txid &a, const TransactionRecord &b) const
bool operator()(const TransactionRecord &a, const Txid &b) const
CTransactionRef tx
Definition: wallet.h:386
Updated transaction status.
Definition: wallet.h:404
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
static int column_alignments[]
ChangeType
General change type (added, updated, removed).
Definition: ui_change_type.h:9
@ CT_UPDATED
@ CT_DELETED
@ CT_NEW
assert(!tx.IsCoinBase())