X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fqt%2Fwalletmodel.cpp;h=9a7b56d33eca04aa1d2a7d851466ad2b549fb424;hb=ae8adeb90abb334b8e5712124e62461eca77c12f;hp=f962b9a7c7445bc554a10cc66044069199017164;hpb=ebff5c40a234f38429965c391da020bbf8312b1b;p=novacoin.git diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index f962b9a..9a7b56d 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -7,10 +7,13 @@ #include "headers.h" #include +#include -WalletModel::WalletModel(CWallet *wallet, QObject *parent) : - QObject(parent), wallet(wallet), optionsModel(0), addressTableModel(0), - transactionTableModel(0) +WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) : + QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0), + transactionTableModel(0), + cachedBalance(0), cachedUnconfirmedBalance(0), cachedNumTransactions(0), + cachedEncryptionStatus(Unencrypted) { // Until signal notifications is built into the bitcoin core, // simply update everything after polling using a timer. @@ -18,7 +21,6 @@ WalletModel::WalletModel(CWallet *wallet, QObject *parent) : connect(timer, SIGNAL(timeout()), this, SLOT(update())); timer->start(MODEL_UPDATE_DELAY); - optionsModel = new OptionsModel(wallet, this); addressTableModel = new AddressTableModel(wallet, this); transactionTableModel = new TransactionTableModel(wallet, this); } @@ -28,6 +30,11 @@ qint64 WalletModel::getBalance() const return wallet->GetBalance(); } +qint64 WalletModel::getUnconfirmedBalance() const +{ + return wallet->GetUnconfirmedBalance(); +} + int WalletModel::getNumTransactions() const { int numTransactions = 0; @@ -40,72 +47,126 @@ int WalletModel::getNumTransactions() const void WalletModel::update() { - // Plainly emit all signals for now. To be more efficient this should check - // whether the values actually changed first, although it'd be even better if these - // were events coming in from the bitcoin core. - emit balanceChanged(getBalance()); - emit numTransactionsChanged(getNumTransactions()); + qint64 newBalance = getBalance(); + qint64 newUnconfirmedBalance = getUnconfirmedBalance(); + int newNumTransactions = getNumTransactions(); + EncryptionStatus newEncryptionStatus = getEncryptionStatus(); + + if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance) + emit balanceChanged(newBalance, newUnconfirmedBalance); + + if(cachedNumTransactions != newNumTransactions) + emit numTransactionsChanged(newNumTransactions); + + if(cachedEncryptionStatus != newEncryptionStatus) + emit encryptionStatusChanged(newEncryptionStatus); + + cachedBalance = newBalance; + cachedUnconfirmedBalance = newUnconfirmedBalance; + cachedNumTransactions = newNumTransactions; addressTableModel->update(); } -WalletModel::StatusCode WalletModel::sendCoins(const QString &payTo, qint64 payAmount, const QString &addToAddressBookAs) +bool WalletModel::validateAddress(const QString &address) +{ + CBitcoinAddress addressParsed(address.toStdString()); + return addressParsed.IsValid(); +} + +WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList &recipients) { - uint160 hash160 = 0; - bool valid = false; + qint64 total = 0; + QSet setAddress; + QString hex; + + if(recipients.empty()) + { + return OK; + } - if(!AddressToHash160(payTo.toUtf8().constData(), hash160)) + // Pre-check input data for validity + foreach(const SendCoinsRecipient &rcp, recipients) { - return InvalidAddress; + if(!validateAddress(rcp.address)) + { + return InvalidAddress; + } + setAddress.insert(rcp.address); + + if(rcp.amount <= 0) + { + return InvalidAmount; + } + total += rcp.amount; } - if(payAmount <= 0) + if(recipients.size() > setAddress.size()) { - return InvalidAmount; + return DuplicateAddress; } - if(payAmount > getBalance()) + if(total > getBalance()) { return AmountExceedsBalance; } - if((payAmount + nTransactionFee) > getBalance()) + if((total + nTransactionFee) > getBalance()) { - return AmountWithFeeExceedsBalance; + return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee); } CRITICAL_BLOCK(cs_main) + CRITICAL_BLOCK(wallet->cs_mapWallet) { - // Send to bitcoin address + // Sendmany + std::vector > vecSend; + foreach(const SendCoinsRecipient &rcp, recipients) + { + CScript scriptPubKey; + scriptPubKey.SetBitcoinAddress(rcp.address.toStdString()); + vecSend.push_back(make_pair(scriptPubKey, rcp.amount)); + } + CWalletTx wtx; - CScript scriptPubKey; - scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG; + CReserveKey keyChange(wallet); + int64 nFeeRequired = 0; + bool fCreated = wallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired); - std::string strError = wallet->SendMoney(scriptPubKey, payAmount, wtx, true); - if (strError == "") + if(!fCreated) { - // OK + if((total + nFeeRequired) > wallet->GetBalance()) + { + return SendCoinsReturn(AmountWithFeeExceedsBalance, nFeeRequired); + } + return TransactionCreationFailed; } - else if (strError == "ABORTED") + if(!ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString(), NULL)) { return Aborted; } - else + if(!wallet->CommitTransaction(wtx, keyChange)) { - emit error(tr("Sending..."), QString::fromStdString(strError)); - return MiscError; + return TransactionCommitFailed; } + hex = QString::fromStdString(wtx.GetHash().GetHex()); } // Add addresses that we've sent to to the address book - std::string strAddress = payTo.toStdString(); - CRITICAL_BLOCK(wallet->cs_mapAddressBook) + foreach(const SendCoinsRecipient &rcp, recipients) { - if (!wallet->mapAddressBook.count(strAddress)) - wallet->SetAddressBookName(strAddress, addToAddressBookAs.toStdString()); + std::string strAddress = rcp.address.toStdString(); + CRITICAL_BLOCK(wallet->cs_mapAddressBook) + { + if (!wallet->mapAddressBook.count(strAddress)) + wallet->SetAddressBookName(strAddress, rcp.label.toStdString()); + } } - return OK; + // Update our model of the address table + addressTableModel->updateList(); + + return SendCoinsReturn(OK, 0, hex); } OptionsModel *WalletModel::getOptionsModel() @@ -123,18 +184,18 @@ TransactionTableModel *WalletModel::getTransactionTableModel() return transactionTableModel; } -/* Look up label for address in address book, if not found return empty string. - */ -QString WalletModel::labelForAddress(const QString &address) const +WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const { - CRITICAL_BLOCK(wallet->cs_mapAddressBook) + if(!wallet->IsCrypted()) { - std::map::iterator mi = wallet->mapAddressBook.find(address.toStdString()); - if (mi != wallet->mapAddressBook.end()) - { - return QString::fromStdString(mi->second); - } + return Unencrypted; + } + else if(wallet->IsLocked()) + { + return Locked; + } + else + { + return Unlocked; } - return QString(); } -