1 #include "walletmodel.h"
2 #include "guiconstants.h"
3 #include "optionsmodel.h"
4 #include "addresstablemodel.h"
5 #include "transactiontablemodel.h"
8 #include "db.h" // for BackupWallet
12 WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) :
13 QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0),
14 transactionTableModel(0),
15 cachedBalance(0), cachedUnconfirmedBalance(0), cachedNumTransactions(0),
16 cachedEncryptionStatus(Unencrypted)
18 addressTableModel = new AddressTableModel(wallet, this);
19 transactionTableModel = new TransactionTableModel(wallet, this);
22 qint64 WalletModel::getBalance() const
24 return wallet->GetBalance();
27 qint64 WalletModel::getUnconfirmedBalance() const
29 return wallet->GetUnconfirmedBalance();
32 int WalletModel::getNumTransactions() const
34 int numTransactions = 0;
36 LOCK(wallet->cs_wallet);
37 numTransactions = wallet->mapWallet.size();
39 return numTransactions;
42 void WalletModel::update()
44 qint64 newBalance = getBalance();
45 qint64 newUnconfirmedBalance = getUnconfirmedBalance();
46 int newNumTransactions = getNumTransactions();
47 EncryptionStatus newEncryptionStatus = getEncryptionStatus();
49 if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance)
50 emit balanceChanged(newBalance, newUnconfirmedBalance);
52 if(cachedNumTransactions != newNumTransactions)
53 emit numTransactionsChanged(newNumTransactions);
55 if(cachedEncryptionStatus != newEncryptionStatus)
56 emit encryptionStatusChanged(newEncryptionStatus);
58 cachedBalance = newBalance;
59 cachedUnconfirmedBalance = newUnconfirmedBalance;
60 cachedNumTransactions = newNumTransactions;
62 addressTableModel->update();
65 void WalletModel::updateAddressList()
67 addressTableModel->update();
70 bool WalletModel::validateAddress(const QString &address)
72 CBitcoinAddress addressParsed(address.toStdString());
73 return addressParsed.IsValid();
76 WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipient> &recipients)
79 QSet<QString> setAddress;
82 if(recipients.empty())
87 // Pre-check input data for validity
88 foreach(const SendCoinsRecipient &rcp, recipients)
90 if(!validateAddress(rcp.address))
92 return InvalidAddress;
94 setAddress.insert(rcp.address);
103 if(recipients.size() > setAddress.size())
105 return DuplicateAddress;
108 if(total > getBalance())
110 return AmountExceedsBalance;
113 if((total + nTransactionFee) > getBalance())
115 return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee);
119 LOCK2(cs_main, wallet->cs_wallet);
122 std::vector<std::pair<CScript, int64> > vecSend;
123 foreach(const SendCoinsRecipient &rcp, recipients)
125 CScript scriptPubKey;
126 scriptPubKey.SetBitcoinAddress(rcp.address.toStdString());
127 vecSend.push_back(make_pair(scriptPubKey, rcp.amount));
131 CReserveKey keyChange(wallet);
132 int64 nFeeRequired = 0;
133 bool fCreated = wallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
137 if((total + nFeeRequired) > wallet->GetBalance())
139 return SendCoinsReturn(AmountWithFeeExceedsBalance, nFeeRequired);
141 return TransactionCreationFailed;
143 if(!ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString()))
147 if(!wallet->CommitTransaction(wtx, keyChange))
149 return TransactionCommitFailed;
151 hex = QString::fromStdString(wtx.GetHash().GetHex());
154 // Add addresses that we've sent to to the address book
155 foreach(const SendCoinsRecipient &rcp, recipients)
157 std::string strAddress = rcp.address.toStdString();
159 LOCK(wallet->cs_wallet);
160 if (!wallet->mapAddressBook.count(strAddress))
161 wallet->SetAddressBookName(strAddress, rcp.label.toStdString());
165 return SendCoinsReturn(OK, 0, hex);
168 OptionsModel *WalletModel::getOptionsModel()
173 AddressTableModel *WalletModel::getAddressTableModel()
175 return addressTableModel;
178 TransactionTableModel *WalletModel::getTransactionTableModel()
180 return transactionTableModel;
183 WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const
185 if(!wallet->IsCrypted())
189 else if(wallet->IsLocked())
199 bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString &passphrase)
204 return wallet->EncryptWallet(passphrase);
208 // Decrypt -- TODO; not supported yet
213 bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase)
218 return wallet->Lock();
223 return wallet->Unlock(passPhrase);
227 bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass)
231 LOCK(wallet->cs_wallet);
232 wallet->Lock(); // Make sure wallet is locked before attempting pass change
233 retval = wallet->ChangeWalletPassphrase(oldPass, newPass);
238 bool WalletModel::backupWallet(const QString &filename)
240 return BackupWallet(*wallet, filename.toLocal8Bit().data());
243 // WalletModel::UnlockContext implementation
244 WalletModel::UnlockContext WalletModel::requestUnlock()
246 bool was_locked = getEncryptionStatus() == Locked;
249 // Request UI to unlock wallet
250 emit requireUnlock();
252 // If wallet is still locked, unlock was failed or cancelled, mark context as invalid
253 bool valid = getEncryptionStatus() != Locked;
255 return UnlockContext(this, valid, was_locked);
258 WalletModel::UnlockContext::UnlockContext(WalletModel *wallet, bool valid, bool relock):
265 WalletModel::UnlockContext::~UnlockContext()
269 wallet->setWalletLocked(true);
273 void WalletModel::UnlockContext::CopyFrom(const UnlockContext& rhs)
275 // Transfer context; old object no longer relocks wallet