void WalletModel::pollBalanceChanged() { // Get required locks upfront. This avoids the GUI from getting stuck on // periodical polls if the core is holding the locks for a longer time - // for example, during a wallet rescan. TRY_LOCK(cs_main, lockMain); if(!lockMain) return; TRY_LOCK(wallet->cs_wallet, lockWallet); if(!lockWallet) return; if(fForceCheckBalanceChanged || chainActive.Height() != cachedNumBlocks || privateSendClient.nPrivateSendRounds != cachedPrivateSendRounds || cachedTxLocks != nCompleteTXLocks) { fForceCheckBalanceChanged = false; // Balance and number of transactions might have changed cachedNumBlocks = chainActive.Height(); cachedPrivateSendRounds = privateSendClient.nPrivateSendRounds; checkBalanceChanged(); if(transactionTableModel) transactionTableModel->updateConfirmations(); } }
void WalletModel::pollBalanceChanged() { // Try to get balances and return early if locks can't be acquired. This // avoids the GUI from getting stuck on periodical polls if the core is // holding the locks for a longer time - for example, during a wallet // rescan. interfaces::WalletBalances new_balances; interfaces::CoinJoinStatus new_status; int numBlocks = -1; if (!m_wallet->tryGetBalances(new_balances, new_status, numBlocks)) { return; } if(fForceCheckBalanceChanged || m_node.getNumBlocks() != cachedNumBlocks) { fForceCheckBalanceChanged = false; // Balance and number of transactions might have changed cachedNumBlocks = m_node.getNumBlocks(); checkBalanceChanged(new_balances); checkCoinJoinChanged(new_status); if(transactionTableModel) transactionTableModel->updateConfirmations(); } }
void WalletModel::pollBalanceChanged() { if(nBestHeight != cachedNumBlocks) { // Balance and number of transactions might have changed cachedNumBlocks = nBestHeight; checkBalanceChanged(); if (!IsInitialBlockDownload()) { if (!fSyncedAtLeastOnce) { // On client start it fails to broadcast (too few connections?), so we wait for full synchronization QDateTime lastBlockDate = QDateTime::fromTime_t(pindexBest->GetBlockTime()); QDateTime currentDate = QDateTime::currentDateTime(); int secs = lastBlockDate.secsTo(currentDate); if (secs < 90*60 && nBestHeight >= GetNumBlocksOfPeers()) fSyncedAtLeastOnce = true; } if (fSyncedAtLeastOnce) sendPendingNameFirstUpdates(); } } }
void WalletModel::updateTransaction(const QString &hash, int status) { if(transactionTableModel) transactionTableModel->updateTransaction(hash, status); // Balance and number of transactions might have changed checkBalanceChanged(); }
void WalletModel::pollBalanceChanged() { if(nBestHeight != cachedNumBlocks) { // Balance and number of transactions might have changed cachedNumBlocks = nBestHeight; checkBalanceChanged(); } }
void WalletModel::pollBalanceChanged() { if(chainActive.Height() != cachedNumBlocks) { // Balance and number of transactions might have changed cachedNumBlocks = chainActive.Height(); checkBalanceChanged(); } }
void WalletModel::pollBalanceChanged() { if(nBestHeight != cachedNumBlocks) { cachedNumBlocks = nBestHeight; checkBalanceChanged(); } if(cachedUnconfirmedBalance || cachedImmatureBalance) pollTimer->start(); }
void WalletModel::updateTransaction() { // Balance and number of transactions might have changed checkBalanceChanged(); int newNumTransactions = getNumTransactions(); if(cachedNumTransactions != newNumTransactions) { cachedNumTransactions = newNumTransactions; emit numTransactionsChanged(newNumTransactions); } }
void WalletModel::updateTransaction(const QString &hash, int status) { 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::pollBalanceChanged() { if(nBestHeight != cachedNumBlocks) { // Balance and number of transactions might have changed cachedNumBlocks = nBestHeight; checkBalanceChanged(); } if (bForceUpdate) { emit balanceChanged(cachedBalance, cachedUnconfirmedBalance, cachedImmatureBalance); bForceUpdate=false; } }
void WalletModel::updateTransaction(const QString &hash, int status) { if(transactionTableModel) transactionTableModel->updateTransaction(hash, status); // Balance and number of transactions might have changed checkBalanceChanged(); if(cachedUnconfirmedBalance || cachedImmatureBalance) pollTimer->start(); int newNumTransactions = getNumTransactions(); if(cachedNumTransactions != newNumTransactions) { emit numTransactionsChanged(newNumTransactions); cachedNumTransactions = newNumTransactions; } }
void WalletModel::pollBalanceChanged() { bool heightChanged = false; { LOCK(cs_main); if(chainActive.Height() != cachedNumBlocks) { // Balance and number of transactions might have changed cachedNumBlocks = chainActive.Height(); heightChanged = true; } } if(heightChanged) { checkBalanceChanged(); if(transactionTableModel) transactionTableModel->updateConfirmations(); } }
void WalletModel::pollBalanceChanged() { // Get required locks upfront. This avoids the GUI from getting stuck on // periodical polls if the core is holding the locks for a longer time - // for example, during a wallet rescan. TRY_LOCK(cs_main, lockMain); if(!lockMain) return; TRY_LOCK(wallet->cs_wallet, lockWallet); if(!lockWallet) return; if(nBestHeight != cachedNumBlocks) { // Balance and number of transactions might have changed cachedNumBlocks = nBestHeight; checkBalanceChanged(); if(transactionTableModel) transactionTableModel->updateConfirmations(); } }
WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &transaction) { QByteArray transaction_array; /* store serialized transaction */ { std::vector<std::pair<std::string, std::string>> vOrderForm; for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { #ifdef ENABLE_BIP70 if (rcp.paymentRequest.IsInitialized()) { // Make sure any payment requests involved are still valid. if (PaymentServer::verifyExpired(rcp.paymentRequest.getDetails())) { return PaymentRequestExpired; } // Store PaymentRequests in wtx.vOrderForm in wallet. std::string value; rcp.paymentRequest.SerializeToString(&value); vOrderForm.emplace_back("PaymentRequest", std::move(value)); } else #endif if (!rcp.message.isEmpty()) // Message from normal bitcoin:URI (bitcoin:123...?message=example) vOrderForm.emplace_back("Message", rcp.message.toStdString()); } auto& newTx = transaction.getWtx(); bool fCoinJoin = true; // CoinJoin is executed per-tx for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { if (!rcp.fCoinJoin) { fCoinJoin = false; continue; } } std::string rejectReason; if (!newTx->commit({} /* mapValue */, std::move(vOrderForm), rejectReason, fCoinJoin)) return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(rejectReason)); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << newTx->get(); transaction_array.append(&(ssTx[0]), ssTx.size()); } // Add addresses / update labels that we've sent to the address book, // and emit coinsSent signal for each recipient for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { // Don't touch the address book when we have a payment request #ifdef ENABLE_BIP70 if (!rcp.paymentRequest.IsInitialized()) #endif { std::string strAddress = rcp.address.toStdString(); CTxDestination dest = DecodeDestination(strAddress); std::string strLabel = rcp.label.toStdString(); { // Check if we have a new address or an updated label std::string name; if (!m_wallet->getAddress( dest, &name, /* is_mine= */ nullptr, /* purpose= */ nullptr)) { m_wallet->setAddressBook(dest, strLabel, "send"); } else if (name != strLabel) { m_wallet->setAddressBook(dest, strLabel, ""); // "" means don't change purpose } } } Q_EMIT coinsSent(this, rcp, transaction_array); } checkBalanceChanged(m_wallet->getBalances()); // update balance immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits checkCoinJoinChanged(m_wallet->getCoinJoinStatus()); // update status immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits return SendCoinsReturn(OK); }
WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &transaction) { QByteArray transaction_array; /* store serialized transaction */ { LOCK2(cs_main, wallet->cs_wallet); CWalletTx *newTx = transaction.getTransaction(); Q_FOREACH(const SendCoinsRecipient &rcp, transaction.getRecipients()) { if (rcp.paymentRequest.IsInitialized()) { // Make sure any payment requests involved are still valid. if (PaymentServer::verifyExpired(rcp.paymentRequest.getDetails())) { return PaymentRequestExpired; } // Store PaymentRequests in wtx.vOrderForm in wallet. std::string key("PaymentRequest"); std::string value; rcp.paymentRequest.SerializeToString(&value); newTx->vOrderForm.push_back(make_pair(key, value)); } else if (!rcp.message.isEmpty()) // Message from normal bitcoin:URI (bitcoin:123...?message=example) newTx->vOrderForm.push_back(make_pair("Message", rcp.message.toStdString())); } CReserveKey *keyChange = transaction.getPossibleKeyChange(); if(!wallet->CommitTransaction(*newTx, *keyChange)) return TransactionCommitFailed; CTransaction* t = (CTransaction*)newTx; CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << *t; transaction_array.append(&(ssTx[0]), ssTx.size()); } // Add addresses / update labels that we've sent to to the address book, // and emit coinsSent signal for each recipient Q_FOREACH(const SendCoinsRecipient &rcp, transaction.getRecipients()) { // Don't touch the address book when we have a payment request if (!rcp.paymentRequest.IsInitialized()) { std::string strAddress = rcp.address.toStdString(); CTxDestination dest = CBitcoinAddress(strAddress).Get(); std::string strLabel = rcp.label.toStdString(); { LOCK(wallet->cs_wallet); std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest); // Check if we have a new address or an updated label if (mi == wallet->mapAddressBook.end()) { wallet->SetAddressBook(dest, strLabel, "send"); } else if (mi->second.name != strLabel) { wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose } } } Q_EMIT coinsSent(wallet, rcp, transaction_array); } checkBalanceChanged(); // update balance immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits return SendCoinsReturn(OK); }