From 6ca9ed8c81bf30ce36de9095ee29fba3fd3192ac Mon Sep 17 00:00:00 2001 From: Time Markov Date: Thu, 16 Nov 2017 07:44:54 -0800 Subject: [PATCH] Add zero token address receiver option --- src/qt/addressfield.cpp | 58 +++++++++++++++++++++++++++++++---- src/qt/addressfield.h | 9 ++++++ src/qt/addtokenpage.cpp | 15 +++++++++ src/qt/addtokenpage.h | 1 + src/qt/forms/optionsdialog.ui | 7 +++++ src/qt/optionsdialog.cpp | 1 + src/qt/optionsmodel.cpp | 11 +++++++ src/qt/optionsmodel.h | 4 ++- src/wallet/wallet.cpp | 12 +++++--- src/wallet/wallet.h | 3 ++ 10 files changed, 109 insertions(+), 12 deletions(-) diff --git a/src/qt/addressfield.cpp b/src/qt/addressfield.cpp index 4fb2cb3fd8..6f1bc3b12e 100644 --- a/src/qt/addressfield.cpp +++ b/src/qt/addressfield.cpp @@ -16,7 +16,9 @@ using namespace std; AddressField::AddressField(QWidget *parent) : QComboBox(parent), - m_addressType(AddressField::UTXO) + m_addressType(AddressField::UTXO), + m_addressTableModel(0), + m_addressColumn(0) { setComboBoxEditable(false); @@ -81,7 +83,26 @@ void AddressField::on_refresh() { // Fill the list with UTXO LOCK2(cs_main, pwalletMain->cs_wallet); - pwalletMain->AvailableCoins(vecOutputs); + + // Add all available addresses if 0 address ballance for token is enabled + if(m_addressTableModel) + { + // Fill the list with user defined address + for(int row = 0; row < m_addressTableModel->rowCount(); row++) + { + QModelIndex index = m_addressTableModel->index(row, m_addressColumn); + QString strAddress = m_addressTableModel->data(index).toString(); + appendAddress(strAddress); + } + + // Include zero or unconfirmed coins too + pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); + } + else + { + // List only the spendable coins + pwalletMain->AvailableCoins(vecOutputs); + } BOOST_FOREACH(const COutput& out, vecOutputs) { CTxDestination address; @@ -91,10 +112,7 @@ void AddressField::on_refresh() if (fValidAddress) { QString strAddress = QString::fromStdString(CBitcoinAddress(address).ToString()); - if(!m_stringList.contains(strAddress)) - { - m_stringList.append(strAddress); - } + appendAddress(strAddress); } } } @@ -116,3 +134,31 @@ void AddressField::on_editingFinished() { Q_EMIT editTextChanged(QComboBox::currentText()); } + +void AddressField::appendAddress(const QString &strAddress) +{ + if(!m_stringList.contains(strAddress)) + { + m_stringList.append(strAddress); + } +} + +void AddressField::setAddressColumn(int addressColumn) +{ + m_addressColumn = addressColumn; +} + +void AddressField::setAddressTableModel(QAbstractItemModel *addressTableModel) +{ + if(m_addressTableModel) + { + disconnect(m_addressTableModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(on_refresh())); + disconnect(m_addressTableModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(on_refresh())); + } + + m_addressTableModel = addressTableModel; + connect(m_addressTableModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(on_refresh())); + connect(m_addressTableModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(on_refresh())); + + on_refresh(); +} diff --git a/src/qt/addressfield.h b/src/qt/addressfield.h index 00871be3db..0e9150f707 100644 --- a/src/qt/addressfield.h +++ b/src/qt/addressfield.h @@ -59,6 +59,10 @@ class AddressField: public QComboBox bool isValidAddress(); void setComboBoxEditable(bool editable); + void setAddressTableModel(QAbstractItemModel *addressTableModel); + + void setAddressColumn(int addressColumn); + Q_SIGNALS: /** * @brief addressTypeChanged Signal that the address type is changed @@ -81,10 +85,15 @@ public Q_SLOTS: */ void on_editingFinished(); +private: + void appendAddress(const QString& strAddress); + private: QStringList m_stringList; QStringListModel m_stringModel; AddressType m_addressType; + QAbstractItemModel* m_addressTableModel; + int m_addressColumn; }; #endif // ADDRESSFIELD_H diff --git a/src/qt/addtokenpage.cpp b/src/qt/addtokenpage.cpp index 765fa33a58..b4d8133c5b 100755 --- a/src/qt/addtokenpage.cpp +++ b/src/qt/addtokenpage.cpp @@ -8,6 +8,8 @@ #include "qvalidatedlineedit.h" #include "contractabi.h" #include "validation.h" +#include "addresstablemodel.h" +#include "optionsmodel.h" #include #include @@ -37,6 +39,7 @@ AddTokenPage::AddTokenPage(QWidget *parent) : connect(ui->lineEditTokenName, SIGNAL(textChanged(const QString &)), SLOT(on_updateConfirmButton())); connect(ui->lineEditTokenSymbol, SIGNAL(textChanged(const QString &)), SLOT(on_updateConfirmButton())); + ui->lineEditSenderAddress->setAddressColumn(AddressTableModel::Address); if(ui->lineEditSenderAddress->isEditable()) ((QValidatedLineEdit*)ui->lineEditSenderAddress->lineEdit())->setEmptyIsValid(false); m_validTokenAddress = false; @@ -73,6 +76,8 @@ void AddTokenPage::clearAll() void AddTokenPage::setModel(WalletModel *_model) { m_model = _model; + on_zeroBalanceAddressToken(bZeroBalanceAddressToken); + connect(m_model->getOptionsModel(), SIGNAL(zeroBalanceAddressTokenChanged(bool)), this, SLOT(on_zeroBalanceAddressToken(bool))); } void AddTokenPage::on_clearButton_clicked() @@ -149,3 +154,13 @@ void AddTokenPage::on_updateConfirmButton() enabled &= m_validTokenAddress; ui->confirmButton->setEnabled(enabled); } + +void AddTokenPage::on_zeroBalanceAddressToken(bool enable) +{ + QAbstractItemModel *addressTableModel = 0; + if(enable && m_model) + { + addressTableModel = m_model->getAddressTableModel(); + } + ui->lineEditSenderAddress->setAddressTableModel(addressTableModel); +} diff --git a/src/qt/addtokenpage.h b/src/qt/addtokenpage.h index 0cbe23f1b3..4dad3322fa 100755 --- a/src/qt/addtokenpage.h +++ b/src/qt/addtokenpage.h @@ -27,6 +27,7 @@ private Q_SLOTS: void on_addressChanged(); void on_numBlocksChanged(); void on_updateConfirmButton(); + void on_zeroBalanceAddressToken(bool enable); Q_SIGNALS: diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index d651133521..da6d39ab0c 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -203,6 +203,13 @@ + + + + Enable &zero balance for receiver token address + + + diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 260a972b3e..9fe1d2b524 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -186,6 +186,7 @@ void OptionsDialog::setMapper() /* Wallet */ mapper->addMapping(ui->spendZeroConfChange, OptionsModel::SpendZeroConfChange); mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures); + mapper->addMapping(ui->zeroBalanceAddressToken, OptionsModel::ZeroBalanceAddressToken); /* Network */ mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index fa4c92fc59..dea30bd70d 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -125,6 +125,10 @@ void OptionsModel::Init(bool resetSettings) if (!SoftSetBoolArg("-spendzeroconfchange", settings.value("bSpendZeroConfChange").toBool())) addOverriddenOption("-spendzeroconfchange"); #endif + if (!settings.contains("bZeroBalanceAddressToken")) + settings.setValue("bZeroBalanceAddressToken", true); + if (!SoftSetBoolArg("-zerobalanceaddresstoken", settings.value("bZeroBalanceAddressToken").toBool())) + addOverriddenOption("-zerobalanceaddresstoken"); // Network if (!settings.contains("fUseUPnP")) @@ -248,6 +252,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const case SpendZeroConfChange: return settings.value("bSpendZeroConfChange"); #endif + case ZeroBalanceAddressToken: + return settings.value("bZeroBalanceAddressToken"); case ReserveBalance: return (qint64) nReserveBalance; case DisplayUnit: @@ -375,6 +381,11 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in } break; #endif + case ZeroBalanceAddressToken: + bZeroBalanceAddressToken = value.toBool(); + settings.setValue("bZeroBalanceAddressToken", bZeroBalanceAddressToken); + Q_EMIT zeroBalanceAddressTokenChanged(bZeroBalanceAddressToken); + break; case DisplayUnit: setDisplayUnit(value); break; diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index ee860bfd6c..986eb38ce6 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -44,8 +44,9 @@ class OptionsModel : public QAbstractListModel CoinControlFeatures, // bool ThreadsScriptVerif, // int DatabaseCache, // int - LogEvents, // bool + LogEvents, // bool SpendZeroConfChange, // bool + ZeroBalanceAddressToken,// bool Listen, // bool ReserveBalance, // CAmount OptionIDRowCount, @@ -96,6 +97,7 @@ class OptionsModel : public QAbstractListModel void coinControlFeaturesChanged(bool); void hideTrayIconChanged(bool); void reserveBalanceChanged(CAmount); + void zeroBalanceAddressTokenChanged(bool); }; #endif // BITCOIN_QT_OPTIONSMODEL_H diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e57d460dc6..34cfb911e1 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -41,6 +41,7 @@ CWallet* pwalletMain = NULL; CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE; +bool bZeroBalanceAddressToken = DEFAULT_ZERO_BALANCE_ADDRESS_TOKEN; bool fSendFreeTransactions = DEFAULT_SEND_FREE_TRANSACTIONS; bool fWalletRbf = DEFAULT_WALLET_RBF; @@ -4491,6 +4492,7 @@ bool CWallet::ParameterInteraction() } nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); + bZeroBalanceAddressToken = GetBoolArg("-zerobalanceaddresstoken", DEFAULT_SPEND_ZEROCONF_CHANGE); fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS); fWalletRbf = GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF); @@ -4558,7 +4560,7 @@ bool CWallet::LoadTokenTx(const CTokenTx &tokenTx) bool CWallet::AddTokenEntry(const CTokenInfo &token, bool fFlushOnClose) { - LOCK(cs_wallet); + LOCK2(cs_main, cs_wallet); CWalletDB walletdb(strWalletFile, "r+", fFlushOnClose); @@ -4607,7 +4609,7 @@ bool CWallet::AddTokenEntry(const CTokenInfo &token, bool fFlushOnClose) bool CWallet::AddTokenTxEntry(const CTokenTx &tokenTx, bool fFlushOnClose) { - LOCK(cs_wallet); + LOCK2(cs_main, cs_wallet); CWalletDB walletdb(strWalletFile, "r+", fFlushOnClose); @@ -4718,7 +4720,7 @@ uint256 CTokenTx::GetHash() const bool CWallet::GetTokenTxDetails(const CTokenTx &wtx, uint256 &credit, uint256 &debit, string &tokenSymbol, uint8_t &decimals) const { - LOCK(cs_wallet); + LOCK2(cs_main, cs_wallet); bool ret = false; for(auto it = mapToken.begin(); it != mapToken.end(); it++) @@ -4749,7 +4751,7 @@ bool CWallet::GetTokenTxDetails(const CTokenTx &wtx, uint256 &credit, uint256 &d bool CWallet::IsTokenTxMine(const CTokenTx &wtx) const { - LOCK(cs_wallet); + LOCK2(cs_main, cs_wallet); bool ret = false; for(auto it = mapToken.begin(); it != mapToken.end(); it++) @@ -4770,7 +4772,7 @@ bool CWallet::IsTokenTxMine(const CTokenTx &wtx) const bool CWallet::RemoveTokenEntry(const uint256 &tokenHash, bool fFlushOnClose) { - LOCK(cs_wallet); + LOCK2(cs_main, cs_wallet); CWalletDB walletdb(strWalletFile, "r+", fFlushOnClose); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 579ea1f0d2..dc28a81dd4 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -41,6 +41,7 @@ extern CAmount nReserveBalance; extern CFeeRate payTxFee; extern unsigned int nTxConfirmTarget; extern bool bSpendZeroConfChange; +extern bool bZeroBalanceAddressToken; extern bool fSendFreeTransactions; extern bool fWalletRbf; extern bool fWalletUnlockStakingOnly; @@ -60,6 +61,8 @@ static const CAmount MIN_CHANGE = CENT; static const CAmount MIN_FINAL_CHANGE = MIN_CHANGE/2; //! Default for -spendzeroconfchange static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true; +//! Default for -zerobalanceaddresstoken +static const bool DEFAULT_ZERO_BALANCE_ADDRESS_TOKEN = true; //! Default for -sendfreetransactions static const bool DEFAULT_SEND_FREE_TRANSACTIONS = false; //! Default for -walletrejectlongchains