X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fqt%2Fwalletmodel.cpp;h=ee8affea2dab9ad2109c9a34539332649211ce4e;hb=1c4fc9052a444c114d9c1501d2c6d1305de650d0;hp=e3e68b3206799c2f97c173474cb49ee387161dcd;hpb=0d98e3fb36c86b7f7c78d072fbcf14aefea41fc2;p=novacoin.git diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index e3e68b3..ee8affe 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -7,17 +7,33 @@ #include "ui_interface.h" #include "wallet.h" #include "walletdb.h" // for BackupWallet +#include "base58.h" #include +#include 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) + cachedBalance(0), cachedStake(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0), + cachedNumTransactions(0), + cachedEncryptionStatus(Unencrypted), + cachedNumBlocks(0) { addressTableModel = new AddressTableModel(wallet, this); transactionTableModel = new TransactionTableModel(wallet, this); + + // This timer will be fired repeatedly to update the balance + pollTimer = new QTimer(this); + connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged())); + pollTimer->start(MODEL_UPDATE_DELAY); + + subscribeToCoreSignals(); +} + +WalletModel::~WalletModel() +{ + unsubscribeFromCoreSignals(); } qint64 WalletModel::getBalance() const @@ -25,9 +41,9 @@ qint64 WalletModel::getBalance() const return wallet->GetBalance(); } -qint64 WalletModel::getStake() const +qint64 WalletModel::getBalanceWatchOnly() const { - return wallet->GetStake(); + return wallet->GetBalanceWatchOnly(); } qint64 WalletModel::getUnconfirmedBalance() const @@ -35,6 +51,16 @@ qint64 WalletModel::getUnconfirmedBalance() const return wallet->GetUnconfirmedBalance(); } +qint64 WalletModel::getStake() const +{ + return wallet->GetStake(); +} + +qint64 WalletModel::getImmatureBalance() const +{ + return wallet->GetImmatureBalance(); +} + int WalletModel::getNumTransactions() const { int numTransactions = 0; @@ -45,30 +71,61 @@ int WalletModel::getNumTransactions() const return numTransactions; } -void WalletModel::update() +void WalletModel::updateStatus() { - qint64 newBalance = getBalance(); - qint64 newUnconfirmedBalance = getUnconfirmedBalance(); - int newNumTransactions = getNumTransactions(); EncryptionStatus newEncryptionStatus = getEncryptionStatus(); - if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance) - emit balanceChanged(newBalance, getStake(), newUnconfirmedBalance); - - if(cachedNumTransactions != newNumTransactions) - emit numTransactionsChanged(newNumTransactions); - if(cachedEncryptionStatus != newEncryptionStatus) emit encryptionStatusChanged(newEncryptionStatus); +} + +void WalletModel::pollBalanceChanged() +{ + if(nBestHeight != cachedNumBlocks) + { + // Balance and number of transactions might have changed + cachedNumBlocks = nBestHeight; + checkBalanceChanged(); + } +} - cachedBalance = newBalance; - cachedUnconfirmedBalance = newUnconfirmedBalance; - cachedNumTransactions = newNumTransactions; +void WalletModel::checkBalanceChanged() +{ + qint64 newBalanceTotal=getBalance(), newBalanceWatchOnly=getBalanceWatchOnly(); + qint64 newStake = getStake(); + qint64 newUnconfirmedBalance = getUnconfirmedBalance(); + qint64 newImmatureBalance = getImmatureBalance(); + + if(cachedBalance != newBalanceTotal || cachedStake != newStake || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance) + { + cachedBalance = newBalanceTotal; + cachedStake = newStake; + cachedUnconfirmedBalance = newUnconfirmedBalance; + cachedImmatureBalance = newImmatureBalance; + emit balanceChanged(newBalanceTotal, newBalanceWatchOnly, newStake, newUnconfirmedBalance, newImmatureBalance); + } } -void WalletModel::updateAddressList() +void WalletModel::updateTransaction(const QString &hash, int status) { - addressTableModel->update(); + if(transactionTableModel) + transactionTableModel->updateTransaction(hash, status); + + // Balance and number of transactions might have changed + checkBalanceChanged(); + + int newNumTransactions = getNumTransactions(); + if(cachedNumTransactions != newNumTransactions) + { + cachedNumTransactions = newNumTransactions; + emit numTransactionsChanged(newNumTransactions); + } +} + +void WalletModel::updateAddressBook(const QString &address, const QString &label, bool isMine, int status) +{ + if(addressTableModel) + addressTableModel->updateEntry(address, label, isMine, status); } bool WalletModel::validateAddress(const QString &address) @@ -77,7 +134,7 @@ bool WalletModel::validateAddress(const QString &address) return addressParsed.IsValid(); } -WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList &recipients) +WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList &recipients, const CCoinControl *coinControl) { qint64 total = 0; QSet setAddress; @@ -109,12 +166,20 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList getBalance()) + int64 nBalance = 0; + std::vector vCoins; + wallet->AvailableCoins(vCoins, true, coinControl); + + BOOST_FOREACH(const COutput& out, vCoins) + if(out.fSpendable) + nBalance += out.tx->vout[out.i].nValue; + + if(total > nBalance) { return AmountExceedsBalance; } - if((total + nTransactionFee) > getBalance()) + if((total + nTransactionFee) > nBalance) { return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee); } @@ -127,24 +192,24 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QListCreateTransaction(vecSend, wtx, keyChange, nFeeRequired); + bool fCreated = wallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, coinControl); if(!fCreated) { - if((total + nFeeRequired) > wallet->GetBalance()) + if((total + nFeeRequired) > nBalance) // FIXME: could cause collisions in the future { return SendCoinsReturn(AmountWithFeeExceedsBalance, nFeeRequired); } return TransactionCreationFailed; } - if(!ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString())) + if(!uiInterface.ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString())) { return Aborted; } @@ -159,16 +224,17 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QListcs_wallet); - std::map::iterator mi = wallet->mapAddressBook.find(strAddress); + std::map::iterator mi = wallet->mapAddressBook.find(dest); // Check if we have a new address or an updated label if (mi == wallet->mapAddressBook.end() || mi->second != strLabel) { - wallet->SetAddressBookName(strAddress, strLabel); + wallet->SetAddressBookName(dest, strLabel); } } } @@ -246,15 +312,83 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri return retval; } +void WalletModel::getStakeWeight(uint64& nMinWeight, uint64& nMaxWeight, uint64& nWeight) +{ + wallet->GetStakeWeight(*wallet, nMinWeight, nMaxWeight, nWeight); +} + +void WalletModel::getStakeWeightFromValue(const int64& nTime, const int64& nValue, uint64& nWeight) +{ + wallet->GetStakeWeightFromValue(nTime, nValue, nWeight); +} + +bool WalletModel::dumpWallet(const QString &filename) +{ + return DumpWallet(wallet, filename.toLocal8Bit().data()); +} + +bool WalletModel::importWallet(const QString &filename) +{ + return ImportWallet(wallet, filename.toLocal8Bit().data()); +} + bool WalletModel::backupWallet(const QString &filename) { return BackupWallet(*wallet, filename.toLocal8Bit().data()); } +// Handlers for core signals +static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel, CCryptoKeyStore *wallet) +{ + OutputDebugStringF("NotifyKeyStoreStatusChanged\n"); + QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection); +} + +static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, ChangeType status) +{ + OutputDebugStringF("NotifyAddressBookChanged %s %s isMine=%i status=%i\n", CBitcoinAddress(address).ToString().c_str(), label.c_str(), isMine, status); + QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(CBitcoinAddress(address).ToString())), + Q_ARG(QString, QString::fromStdString(label)), + Q_ARG(bool, isMine), + Q_ARG(int, status)); +} + +static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status) +{ + OutputDebugStringF("NotifyTransactionChanged %s status=%i\n", hash.GetHex().c_str(), status); + QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(hash.GetHex())), + Q_ARG(int, status)); +} + +void WalletModel::subscribeToCoreSignals() +{ + // Connect signals to wallet + wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1)); + wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5)); + wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); +} + +void WalletModel::unsubscribeFromCoreSignals() +{ + // Disconnect signals from wallet + wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1)); + wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5)); + wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); +} + // WalletModel::UnlockContext implementation WalletModel::UnlockContext WalletModel::requestUnlock() { bool was_locked = getEncryptionStatus() == Locked; + + if ((!was_locked) && fWalletUnlockMintOnly) + { + setWalletLocked(true); + was_locked = getEncryptionStatus() == Locked; + + } if(was_locked) { // Request UI to unlock wallet @@ -263,7 +397,7 @@ WalletModel::UnlockContext WalletModel::requestUnlock() // If wallet is still locked, unlock was failed or cancelled, mark context as invalid bool valid = getEncryptionStatus() != Locked; - return UnlockContext(this, valid, was_locked); + return UnlockContext(this, valid, was_locked && !fWalletUnlockMintOnly); } WalletModel::UnlockContext::UnlockContext(WalletModel *wallet, bool valid, bool relock): @@ -287,3 +421,71 @@ void WalletModel::UnlockContext::CopyFrom(const UnlockContext& rhs) *this = rhs; rhs.relock = false; } + +bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const +{ + return wallet->GetPubKey(address, vchPubKeyOut); +} + +// returns a list of COutputs from COutPoints +void WalletModel::getOutputs(const std::vector& vOutpoints, std::vector& vOutputs) +{ + BOOST_FOREACH(const COutPoint& outpoint, vOutpoints) + { + if (!wallet->mapWallet.count(outpoint.hash)) continue; + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, wallet->mapWallet[outpoint.hash].GetDepthInMainChain(), true); + vOutputs.push_back(out); + } +} + +// AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address) +void WalletModel::listCoins(std::map >& mapCoins) const +{ + std::vector vCoins; + wallet->AvailableCoins(vCoins); + std::vector vLockedCoins; + + // add locked coins + BOOST_FOREACH(const COutPoint& outpoint, vLockedCoins) + { + if (!wallet->mapWallet.count(outpoint.hash)) continue; + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, wallet->mapWallet[outpoint.hash].GetDepthInMainChain(), true); + vCoins.push_back(out); + } + + BOOST_FOREACH(const COutput& out, vCoins) + { + COutput cout = out; + + while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0])) + { + if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break; + cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true); + } + + CTxDestination address; + if(!out.fSpendable || !ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address)) + continue; + mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back(out); + } +} + +bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const +{ + return false; +} + +void WalletModel::lockCoin(COutPoint& output) +{ + return; +} + +void WalletModel::unlockCoin(COutPoint& output) +{ + return; +} + +void WalletModel::listLockedCoins(std::vector& vOutpts) +{ + return; +}