Changeset View
Changeset View
Standalone View
Standalone View
src/qt/walletmodel.cpp
// Copyright (c) 2011-2019 The Bitcoin Core developers | // Copyright (c) 2011-2019 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#if defined(HAVE_CONFIG_H) | |||||
#include <config/bitcoin-config.h> | |||||
#endif | |||||
#include <qt/walletmodel.h> | #include <qt/walletmodel.h> | ||||
#include <cashaddrenc.h> | #include <cashaddrenc.h> | ||||
#include <interfaces/handler.h> | #include <interfaces/handler.h> | ||||
#include <interfaces/node.h> | #include <interfaces/node.h> | ||||
#include <key_io.h> | #include <key_io.h> | ||||
#include <qt/addresstablemodel.h> | #include <qt/addresstablemodel.h> | ||||
#include <qt/guiconstants.h> | #include <qt/guiconstants.h> | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | WalletModel::prepareTransaction(WalletModelTransaction &transaction, | ||||
// Used to detect duplicates | // Used to detect duplicates | ||||
QSet<QString> setAddress; | QSet<QString> setAddress; | ||||
int nAddresses = 0; | int nAddresses = 0; | ||||
// Pre-check input data for validity | // Pre-check input data for validity | ||||
for (const SendCoinsRecipient &rcp : recipients) { | for (const SendCoinsRecipient &rcp : recipients) { | ||||
if (rcp.fSubtractFeeFromAmount) fSubtractFeeFromAmount = true; | if (rcp.fSubtractFeeFromAmount) fSubtractFeeFromAmount = true; | ||||
#ifdef ENABLE_BIP70 | |||||
// PaymentRequest... | // PaymentRequest... | ||||
if (rcp.paymentRequest.IsInitialized()) { | if (rcp.paymentRequest.IsInitialized()) { | ||||
Amount subtotal = Amount::zero(); | Amount subtotal = Amount::zero(); | ||||
const payments::PaymentDetails &details = | const payments::PaymentDetails &details = | ||||
rcp.paymentRequest.getDetails(); | rcp.paymentRequest.getDetails(); | ||||
for (int i = 0; i < details.outputs_size(); i++) { | for (int i = 0; i < details.outputs_size(); i++) { | ||||
const payments::Output &out = details.outputs(i); | const payments::Output &out = details.outputs(i); | ||||
if (out.amount() <= 0) { | if (out.amount() <= 0) { | ||||
Show All 9 Lines | #ifdef ENABLE_BIP70 | ||||
rcp.fSubtractFeeFromAmount}; | rcp.fSubtractFeeFromAmount}; | ||||
vecSend.push_back(recipient); | vecSend.push_back(recipient); | ||||
} | } | ||||
if (subtotal <= Amount::zero()) { | if (subtotal <= Amount::zero()) { | ||||
return InvalidAmount; | return InvalidAmount; | ||||
} | } | ||||
total += subtotal; | total += subtotal; | ||||
} else { | } | ||||
// User-entered bitcoin address / amount: | // User-entered bitcoin address / amount: | ||||
else | |||||
#endif | |||||
{ | |||||
if (!validateAddress(rcp.address)) { | if (!validateAddress(rcp.address)) { | ||||
return InvalidAddress; | return InvalidAddress; | ||||
} | } | ||||
if (rcp.amount <= Amount::zero()) { | if (rcp.amount <= Amount::zero()) { | ||||
return InvalidAmount; | return InvalidAmount; | ||||
} | } | ||||
setAddress.insert(rcp.address); | setAddress.insert(rcp.address); | ||||
++nAddresses; | ++nAddresses; | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
WalletModel::SendCoinsReturn | WalletModel::SendCoinsReturn | ||||
WalletModel::sendCoins(WalletModelTransaction &transaction) { | WalletModel::sendCoins(WalletModelTransaction &transaction) { | ||||
/* store serialized transaction */ | /* store serialized transaction */ | ||||
QByteArray transaction_array; | QByteArray transaction_array; | ||||
std::vector<std::pair<std::string, std::string>> vOrderForm; | std::vector<std::pair<std::string, std::string>> vOrderForm; | ||||
for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { | for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { | ||||
#ifdef ENABLE_BIP70 | |||||
if (rcp.paymentRequest.IsInitialized()) { | if (rcp.paymentRequest.IsInitialized()) { | ||||
// Make sure any payment requests involved are still valid. | // Make sure any payment requests involved are still valid. | ||||
if (PaymentServer::verifyExpired(rcp.paymentRequest.getDetails())) { | if (PaymentServer::verifyExpired(rcp.paymentRequest.getDetails())) { | ||||
return PaymentRequestExpired; | return PaymentRequestExpired; | ||||
} | } | ||||
// Store PaymentRequests in wtx.vOrderForm in wallet. | // Store PaymentRequests in wtx.vOrderForm in wallet. | ||||
std::string value; | std::string value; | ||||
rcp.paymentRequest.SerializeToString(&value); | rcp.paymentRequest.SerializeToString(&value); | ||||
vOrderForm.emplace_back("PaymentRequest", std::move(value)); | vOrderForm.emplace_back("PaymentRequest", std::move(value)); | ||||
} else if (!rcp.message.isEmpty()) { | } else | ||||
#endif | |||||
if (!rcp.message.isEmpty()) { | |||||
// Message from normal bitcoincash:URI | // Message from normal bitcoincash:URI | ||||
// (bitcoincash:123...?message=example) | // (bitcoincash:123...?message=example) | ||||
vOrderForm.emplace_back("Message", rcp.message.toStdString()); | vOrderForm.emplace_back("Message", rcp.message.toStdString()); | ||||
} | } | ||||
} | } | ||||
auto &newTx = transaction.getWtx(); | auto &newTx = transaction.getWtx(); | ||||
std::string rejectReason; | std::string rejectReason; | ||||
if (!newTx->commit({} /* mapValue */, std::move(vOrderForm), | if (!newTx->commit({} /* mapValue */, std::move(vOrderForm), | ||||
{} /* fromAccount */, rejectReason)) { | {} /* fromAccount */, rejectReason)) { | ||||
return SendCoinsReturn(TransactionCommitFailed, | return SendCoinsReturn(TransactionCommitFailed, | ||||
QString::fromStdString(rejectReason)); | QString::fromStdString(rejectReason)); | ||||
} | } | ||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); | CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); | ||||
ssTx << newTx->get(); | ssTx << newTx->get(); | ||||
transaction_array.append(&(ssTx[0]), ssTx.size()); | transaction_array.append(&(ssTx[0]), ssTx.size()); | ||||
// Add addresses / update labels that we've sent to the address book, and | // Add addresses / update labels that we've sent to the address book, and | ||||
// emit coinsSent signal for each recipient | // emit coinsSent signal for each recipient | ||||
for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { | for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { | ||||
// Don't touch the address book when we have a payment request | // Don't touch the address book when we have a payment request | ||||
if (!rcp.paymentRequest.IsInitialized()) { | #ifdef ENABLE_BIP70 | ||||
if (!rcp.paymentRequest.IsInitialized()) | |||||
#endif | |||||
{ | |||||
std::string strAddress = rcp.address.toStdString(); | std::string strAddress = rcp.address.toStdString(); | ||||
CTxDestination dest = | CTxDestination dest = | ||||
DecodeDestination(strAddress, getChainParams()); | DecodeDestination(strAddress, getChainParams()); | ||||
std::string strLabel = rcp.label.toStdString(); | std::string strLabel = rcp.label.toStdString(); | ||||
// Check if we have a new address or an updated label | // Check if we have a new address or an updated label | ||||
std::string name; | std::string name; | ||||
if (!m_wallet->getAddress(dest, &name, /* is_mine= */ nullptr, | if (!m_wallet->getAddress(dest, &name, /* is_mine= */ nullptr, | ||||
/* purpose= */ nullptr)) { | /* purpose= */ nullptr)) { | ||||
▲ Show 20 Lines • Show All 227 Lines • Show Last 20 Lines |