Add CashAddr Address Format
Ported from Bitcoin Unlimited, Bitcoin ABC
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
#include "guiutil.h"
|
||||
#include "walletmodel.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "dstencode.h"
|
||||
#include "wallet/wallet.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
@@ -81,16 +81,16 @@ public:
|
||||
cachedAddressTable.clear();
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook)
|
||||
for (const std::pair<CTxDestination, CAddressBookData>& item : wallet->mapAddressBook)
|
||||
{
|
||||
const CBitcoinAddress& address = item.first;
|
||||
bool fMine = IsMine(*wallet, address.Get());
|
||||
const CTxDestination& address = item.first;
|
||||
bool fMine = IsMine(*wallet, address);
|
||||
AddressTableEntry::Type addressType = translateTransactionType(
|
||||
QString::fromStdString(item.second.purpose), fMine);
|
||||
const std::string& strName = item.second.name;
|
||||
cachedAddressTable.append(AddressTableEntry(addressType,
|
||||
QString::fromStdString(strName),
|
||||
QString::fromStdString(address.ToString())));
|
||||
QString::fromStdString(EncodeDestination(address))));
|
||||
}
|
||||
}
|
||||
// qLowerBound() and qUpperBound() require our cachedAddressTable list to be sorted in asc order
|
||||
@@ -247,7 +247,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
|
||||
if(role == Qt::EditRole)
|
||||
{
|
||||
LOCK(wallet->cs_wallet); /* For SetAddressBook / DelAddressBook */
|
||||
CTxDestination curAddress = CBitcoinAddress(rec->address.toStdString()).Get();
|
||||
CTxDestination curAddress = DecodeDestination(rec->address.toStdString());
|
||||
if(index.column() == Label)
|
||||
{
|
||||
// Do nothing, if old label == new label
|
||||
@@ -258,7 +258,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value,
|
||||
}
|
||||
wallet->SetAddressBook(curAddress, value.toString().toStdString(), strPurpose);
|
||||
} else if(index.column() == Address) {
|
||||
CTxDestination newAddress = CBitcoinAddress(value.toString().toStdString()).Get();
|
||||
CTxDestination newAddress = DecodeDestination(value.toString().toStdString());
|
||||
// Refuse to set invalid address, set error status and return false
|
||||
if(boost::get<CNoDestination>(&newAddress))
|
||||
{
|
||||
@@ -359,7 +359,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
|
||||
// Check for duplicate addresses
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
if(wallet->mapAddressBook.count(CBitcoinAddress(strAddress).Get()))
|
||||
if(wallet->mapAddressBook.count(DecodeDestination(strAddress)))
|
||||
{
|
||||
editStatus = DUPLICATE_ADDRESS;
|
||||
return QString();
|
||||
@@ -385,7 +385,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
strAddress = CBitcoinAddress(newKey.GetID()).ToString();
|
||||
strAddress = EncodeDestination(newKey.GetID());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -395,7 +395,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
|
||||
// Add entry
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
wallet->SetAddressBook(CBitcoinAddress(strAddress).Get(), strLabel,
|
||||
wallet->SetAddressBook(DecodeDestination(strAddress), strLabel,
|
||||
(type == Send ? "send" : "receive"));
|
||||
}
|
||||
return QString::fromStdString(strAddress);
|
||||
@@ -413,7 +413,7 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex &parent
|
||||
}
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
wallet->DelAddressBook(CBitcoinAddress(rec->address.toStdString()).Get());
|
||||
wallet->DelAddressBook(DecodeDestination(rec->address.toStdString()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -424,8 +424,8 @@ QString AddressTableModel::labelForAddress(const QString &address) const
|
||||
{
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
CBitcoinAddress address_parsed(address.toStdString());
|
||||
std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(address_parsed.Get());
|
||||
CTxDestination destination = DecodeDestination(address.toStdString());
|
||||
std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(destination);
|
||||
if (mi != wallet->mapAddressBook.end())
|
||||
{
|
||||
return QString::fromStdString(mi->second.name);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "clientmodel.h"
|
||||
#include "config.h"
|
||||
#include "guiconstants.h"
|
||||
#include "guiutil.h"
|
||||
#include "intro.h"
|
||||
@@ -81,10 +82,10 @@ Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
|
||||
Q_DECLARE_METATYPE(bool*)
|
||||
Q_DECLARE_METATYPE(CAmount)
|
||||
|
||||
static void InitMessage(const std::string &message)
|
||||
{
|
||||
LogPrintf("init message: %s\n", message);
|
||||
}
|
||||
// Config is non-copyable so we can only register pointers to it
|
||||
Q_DECLARE_METATYPE(Config *)
|
||||
|
||||
static void InitMessage(const std::string &message) { LogPrintf("init message: %s\n", message); }
|
||||
|
||||
/*
|
||||
Translate string to current locale using Qt.
|
||||
@@ -173,7 +174,7 @@ public:
|
||||
explicit BitcoinCore();
|
||||
|
||||
public Q_SLOTS:
|
||||
void initialize();
|
||||
void initialize(Config *config);
|
||||
void shutdown();
|
||||
|
||||
Q_SIGNALS:
|
||||
@@ -206,12 +207,12 @@ public:
|
||||
/// Create options model
|
||||
void createOptionsModel(bool resetSettings);
|
||||
/// Create main window
|
||||
void createWindow(const NetworkStyle *networkStyle);
|
||||
void createWindow(const Config *, const NetworkStyle *networkStyle);
|
||||
/// Create splash screen
|
||||
void createSplashScreen(const NetworkStyle *networkStyle);
|
||||
|
||||
/// Request core initialization
|
||||
void requestInitialize();
|
||||
void requestInitialize(Config &config);
|
||||
/// Request core shutdown
|
||||
void requestShutdown();
|
||||
|
||||
@@ -228,7 +229,7 @@ public Q_SLOTS:
|
||||
void handleRunawayException(const QString &message);
|
||||
|
||||
Q_SIGNALS:
|
||||
void requestedInitialize();
|
||||
void requestedInitialize(Config *config);
|
||||
void requestedShutdown();
|
||||
void stopThread();
|
||||
void splashFinished(QWidget *window);
|
||||
@@ -262,12 +263,13 @@ void BitcoinCore::handleRunawayException(const std::exception *e)
|
||||
Q_EMIT runawayException(QString::fromStdString(strMiscWarning));
|
||||
}
|
||||
|
||||
void BitcoinCore::initialize()
|
||||
void BitcoinCore::initialize(Config *cfg)
|
||||
{
|
||||
Config &config(*cfg);
|
||||
try
|
||||
{
|
||||
qDebug() << __func__ << ": Running AppInit2 in thread";
|
||||
int rv = AppInit2(threadGroup, scheduler);
|
||||
int rv = AppInit2(config, threadGroup, scheduler);
|
||||
Q_EMIT initializeResult(rv);
|
||||
} catch (const std::exception& e) {
|
||||
handleRunawayException(&e);
|
||||
@@ -353,9 +355,9 @@ void BitcoinApplication::createOptionsModel(bool resetSettings)
|
||||
optionsModel = new OptionsModel(NULL, resetSettings);
|
||||
}
|
||||
|
||||
void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
|
||||
void BitcoinApplication::createWindow(const Config *config, const NetworkStyle *networkStyle)
|
||||
{
|
||||
window = new BitcoinGUI(platformStyle, networkStyle, 0);
|
||||
window = new BitcoinGUI(config, platformStyle, networkStyle, 0);
|
||||
|
||||
pollShutdownTimer = new QTimer(window);
|
||||
connect(pollShutdownTimer, SIGNAL(timeout()), window, SLOT(detectShutdown()));
|
||||
@@ -384,7 +386,7 @@ void BitcoinApplication::startThread()
|
||||
connect(executor, SIGNAL(initializeResult(int)), this, SLOT(initializeResult(int)));
|
||||
connect(executor, SIGNAL(shutdownResult(int)), this, SLOT(shutdownResult(int)));
|
||||
connect(executor, SIGNAL(runawayException(QString)), this, SLOT(handleRunawayException(QString)));
|
||||
connect(this, SIGNAL(requestedInitialize()), executor, SLOT(initialize()));
|
||||
connect(this, SIGNAL(requestedInitialize(Config *)), executor, SLOT(initialize(Config *)));
|
||||
connect(this, SIGNAL(requestedShutdown()), executor, SLOT(shutdown()));
|
||||
/* make sure executor object is deleted in its own thread */
|
||||
connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater()));
|
||||
@@ -399,11 +401,11 @@ void BitcoinApplication::parameterSetup()
|
||||
InitParameterInteraction();
|
||||
}
|
||||
|
||||
void BitcoinApplication::requestInitialize()
|
||||
void BitcoinApplication::requestInitialize(Config &config)
|
||||
{
|
||||
qDebug() << __func__ << ": Requesting initialize";
|
||||
startThread();
|
||||
Q_EMIT requestedInitialize();
|
||||
Q_EMIT requestedInitialize(&config);
|
||||
}
|
||||
|
||||
void BitcoinApplication::requestShutdown()
|
||||
@@ -472,7 +474,7 @@ void BitcoinApplication::initializeResult(int retval)
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
// Now that initialization/startup is done, process any command-line
|
||||
// bitcoin: URIs or payment requests:
|
||||
// blackcoin: URIs or payment requests:
|
||||
connect(paymentServer, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
|
||||
window, SLOT(handlePaymentRequest(SendCoinsRecipient)));
|
||||
connect(window, SIGNAL(receivedURI(QString)),
|
||||
@@ -547,7 +549,9 @@ int main(int argc, char *argv[])
|
||||
qRegisterMetaType< bool* >();
|
||||
// Need to pass name here as CAmount is a typedef (see http://qt-project.org/doc/qt-5/qmetatype.html#qRegisterMetaType)
|
||||
// IMPORTANT if it is no longer a typedef use the normal variant above
|
||||
qRegisterMetaType< CAmount >("CAmount");
|
||||
qRegisterMetaType<CAmount>("CAmount");
|
||||
// Config is non-copyable so we can't register as a non pointer type
|
||||
qRegisterMetaType<Config *>();
|
||||
|
||||
/// 3. Application identification
|
||||
// must be set before OptionsModel is initialized or translations are loaded,
|
||||
@@ -629,7 +633,8 @@ int main(int argc, char *argv[])
|
||||
exit(0);
|
||||
|
||||
// Start up the payment server early, too, so impatient users that click on
|
||||
// bitcoin: links repeatedly have their payment requests routed to this process:
|
||||
// blackcoin: links repeatedly have their payment requests routed to this
|
||||
// process:
|
||||
app.createPaymentServer();
|
||||
#endif
|
||||
|
||||
@@ -658,10 +663,13 @@ int main(int argc, char *argv[])
|
||||
if (GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !GetBoolArg("-min", false))
|
||||
app.createSplashScreen(networkStyle.data());
|
||||
|
||||
// Get global config
|
||||
Config &config = const_cast<Config &>(GetConfig());
|
||||
|
||||
try
|
||||
{
|
||||
app.createWindow(networkStyle.data());
|
||||
app.requestInitialize();
|
||||
app.createWindow(&config, networkStyle.data());
|
||||
app.requestInitialize(config);
|
||||
#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
|
||||
WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("Bitcoin Core didn't yet exit safely..."), (HWND)app.getMainWinId());
|
||||
#endif
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
// Copyright (c) 2011-2014 The Bitcoin Core developers
|
||||
// Copyright (c) 2015-2017 The Bitcoin Unlimited developers
|
||||
// Copyright (c) 2017 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "bitcoinaddressvalidator.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "cashaddr.h"
|
||||
#include "dstencode.h"
|
||||
|
||||
/* Base58 characters are:
|
||||
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||
@@ -14,9 +17,49 @@
|
||||
- All upper-case letters except for 'I' and 'O'
|
||||
- All lower-case letters except for 'l'
|
||||
*/
|
||||
static bool ValidLegacyInput(const QString &input)
|
||||
{
|
||||
// Alphanumeric and not a 'forbidden' character
|
||||
for (QChar ch : input)
|
||||
{
|
||||
if (!(((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) && ch != 'l' &&
|
||||
ch != 'I' && ch != '0' && ch != 'O'))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BitcoinAddressEntryValidator::BitcoinAddressEntryValidator(QObject *parent) :
|
||||
QValidator(parent)
|
||||
static bool ValidCashaddrInput(const QString &prefix, const QString &input)
|
||||
{
|
||||
std::vector<uint8_t> charset = cashaddr::EncodingCharset();
|
||||
|
||||
// Input may be incomplete. We're checking if it so far looks good.
|
||||
|
||||
for (int i = 0; i < input.size(); ++i)
|
||||
{
|
||||
char ch = std::tolower(input[i].toLatin1());
|
||||
|
||||
// Does the input have the right prefix?
|
||||
if (i < prefix.size())
|
||||
{
|
||||
if (ch != prefix[i].toLatin1())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Payload, must use cashaddr charset.
|
||||
if (std::find(begin(charset), end(charset), ch) == end(charset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BitcoinAddressEntryValidator::BitcoinAddressEntryValidator(const std::string &cashaddrprefix, QObject *parent)
|
||||
: QValidator(parent), cashaddrprefix(cashaddrprefix)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -59,25 +102,9 @@ QValidator::State BitcoinAddressEntryValidator::validate(QString &input, int &po
|
||||
}
|
||||
|
||||
// Validation
|
||||
QValidator::State state = QValidator::Acceptable;
|
||||
for (int idx = 0; idx < input.size(); ++idx)
|
||||
{
|
||||
int ch = input.at(idx).unicode();
|
||||
|
||||
if (((ch >= '0' && ch<='9') ||
|
||||
(ch >= 'a' && ch<='z') ||
|
||||
(ch >= 'A' && ch<='Z')) &&
|
||||
ch != 'l' && ch != 'I' && ch != '0' && ch != 'O')
|
||||
{
|
||||
// Alphanumeric and not a 'forbidden' character
|
||||
}
|
||||
else
|
||||
{
|
||||
state = QValidator::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
const QString cashPrefix = QString::fromStdString(cashaddrprefix) + ":";
|
||||
return (ValidLegacyInput(input) || ValidCashaddrInput(cashPrefix, input)) ? QValidator::Acceptable :
|
||||
QValidator::Invalid;
|
||||
}
|
||||
|
||||
BitcoinAddressCheckValidator::BitcoinAddressCheckValidator(QObject *parent) :
|
||||
@@ -89,9 +116,10 @@ QValidator::State BitcoinAddressCheckValidator::validate(QString &input, int &po
|
||||
{
|
||||
Q_UNUSED(pos);
|
||||
// Validate the passed Bitcoin address
|
||||
CBitcoinAddress addr(input.toStdString());
|
||||
if (addr.IsValid())
|
||||
if (IsValidDestinationString(input.toStdString()))
|
||||
{
|
||||
return QValidator::Acceptable;
|
||||
}
|
||||
|
||||
return QValidator::Invalid;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// Copyright (c) 2011-2014 The Bitcoin Core developers
|
||||
// Copyright (c) 2015-2017 The Bitcoin Unlimited developers
|
||||
// Copyright (c) 2017 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -7,7 +9,8 @@
|
||||
|
||||
#include <QValidator>
|
||||
|
||||
/** Base58 entry widget validator, checks for valid characters and
|
||||
/**
|
||||
* Bitcoin address entry widget validator, checks for valid characters and
|
||||
* removes some whitespace.
|
||||
*/
|
||||
class BitcoinAddressEntryValidator : public QValidator
|
||||
@@ -15,9 +18,12 @@ class BitcoinAddressEntryValidator : public QValidator
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BitcoinAddressEntryValidator(QObject *parent);
|
||||
explicit BitcoinAddressEntryValidator(const std::string &cashaddrprefix, QObject *parent);
|
||||
|
||||
State validate(QString &input, int &pos) const;
|
||||
|
||||
private:
|
||||
std::string cashaddrprefix;
|
||||
};
|
||||
|
||||
/** Bitcoin address widget validator, checks for a valid bitcoin address.
|
||||
|
||||
@@ -75,7 +75,7 @@ const QString BitcoinGUI::DEFAULT_WALLET = "~Default";
|
||||
extern int64_t nLastCoinStakeSearchInterval;
|
||||
double GetPoSKernelPS();
|
||||
|
||||
BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
|
||||
BitcoinGUI::BitcoinGUI(const Config *cfg, const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
clientModel(0),
|
||||
walletFrame(0),
|
||||
@@ -118,7 +118,8 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n
|
||||
helpMessageDialog(0),
|
||||
prevBlocks(0),
|
||||
spinnerFrame(0),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(platformStyle),
|
||||
cfg(cfg)
|
||||
{
|
||||
GUIUtil::restoreWindowGeometry("nWindow", QSize(850, 550), this);
|
||||
|
||||
@@ -156,7 +157,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *n
|
||||
if(enableWallet)
|
||||
{
|
||||
/** Create wallet frame and make it the central widget */
|
||||
walletFrame = new WalletFrame(platformStyle, this);
|
||||
walletFrame = new WalletFrame(platformStyle, cfg, this);
|
||||
setCentralWidget(walletFrame);
|
||||
} else
|
||||
#endif // ENABLE_WALLET
|
||||
@@ -297,7 +298,7 @@ void BitcoinGUI::createActions()
|
||||
sendCoinsMenuAction->setToolTip(sendCoinsMenuAction->statusTip());
|
||||
|
||||
receiveCoinsAction = new QAction(platformStyle->SingleColorIcon(":/icons/receiving_addresses"), tr("&Receive"), this);
|
||||
receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)"));
|
||||
receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and %1: URIs)").arg(GUIUtil::bitcoinURIScheme(*cfg)));
|
||||
receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
|
||||
receiveCoinsAction->setCheckable(true);
|
||||
receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
|
||||
@@ -376,7 +377,7 @@ void BitcoinGUI::createActions()
|
||||
usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels"));
|
||||
|
||||
openAction = new QAction(platformStyle->TextColorIcon(":/icons/open"), tr("Open &URI..."), this);
|
||||
openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
|
||||
openAction->setStatusTip(tr("Open a %1: URI or payment request").arg(GUIUtil::bitcoinURIScheme(*cfg)));
|
||||
|
||||
showHelpMessageAction = new QAction(platformStyle->TextColorIcon(":/icons/info"), tr("&Command-line options"), this);
|
||||
showHelpMessageAction->setMenuRole(QAction::NoRole);
|
||||
@@ -670,8 +671,8 @@ void BitcoinGUI::showHelpMessageClicked()
|
||||
#ifdef ENABLE_WALLET
|
||||
void BitcoinGUI::openClicked()
|
||||
{
|
||||
OpenURIDialog dlg(this);
|
||||
if(dlg.exec())
|
||||
OpenURIDialog dlg(cfg, this);
|
||||
if (dlg.exec())
|
||||
{
|
||||
Q_EMIT receivedURI(dlg.getURI());
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ class WalletFrame;
|
||||
class WalletModel;
|
||||
class HelpMessageDialog;
|
||||
|
||||
class Config;
|
||||
class CWallet;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@@ -50,7 +51,10 @@ public:
|
||||
static const QString DEFAULT_WALLET;
|
||||
static const std::string DEFAULT_UIPLATFORM;
|
||||
|
||||
explicit BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = 0);
|
||||
explicit BitcoinGUI(const Config *,
|
||||
const PlatformStyle *platformStyle,
|
||||
const NetworkStyle *networkStyle,
|
||||
QWidget *parent = 0);
|
||||
~BitcoinGUI();
|
||||
|
||||
/** Set the client model.
|
||||
@@ -129,6 +133,7 @@ private:
|
||||
uint64_t nWeight;
|
||||
|
||||
const PlatformStyle *platformStyle;
|
||||
const Config *cfg;
|
||||
|
||||
/** Create the main UI actions. */
|
||||
void createActions();
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "walletmodel.h"
|
||||
|
||||
#include "coincontrol.h"
|
||||
#include "dstencode.h"
|
||||
#include "init.h"
|
||||
#include "main.h" // For minRelayTxFee
|
||||
#include "wallet/wallet.h"
|
||||
@@ -734,9 +735,10 @@ void CoinControlDialog::updateView()
|
||||
QString sAddress = "";
|
||||
if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, outputAddress))
|
||||
{
|
||||
sAddress = QString::fromStdString(CBitcoinAddress(outputAddress).ToString());
|
||||
sAddress = QString::fromStdString(EncodeDestination(outputAddress));
|
||||
|
||||
// if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs
|
||||
// if listMode or change => show bitcoin address. In tree mode,
|
||||
// address is not shown again for direct wallet address outputs
|
||||
if (!treeMode || (!(sAddress == sWalletAddress)))
|
||||
itemOutput->setText(COLUMN_ADDRESS, sAddress);
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ static const int TOOLTIP_WRAP_THRESHOLD = 80;
|
||||
static const int MAX_URI_LENGTH = 255;
|
||||
|
||||
/* QRCodeDialog -- size of exported QR Code image */
|
||||
#define QR_IMAGE_SIZE 300
|
||||
#define QR_IMAGE_SIZE 350
|
||||
|
||||
/* Number of frames in spinner animation */
|
||||
#define SPINNER_FRAMES 36
|
||||
|
||||
@@ -10,12 +10,16 @@
|
||||
#include "walletmodel.h"
|
||||
|
||||
#include "primitives/transaction.h"
|
||||
#include "cashaddr.h"
|
||||
#include "config.h"
|
||||
#include "dstencode.h"
|
||||
#include "init.h"
|
||||
#include "main.h" // For minRelayTxFee
|
||||
#include "protocol.h"
|
||||
#include "script/script.h"
|
||||
#include "script/standard.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32_WINNT
|
||||
@@ -107,35 +111,46 @@ QFont fixedPitchFont()
|
||||
#endif
|
||||
}
|
||||
|
||||
// Just some dummy data to generate an convincing random-looking (but consistent) address
|
||||
static const uint8_t dummydata[] = {0xeb,0x15,0x23,0x1d,0xfc,0xeb,0x60,0x92,0x58,0x86,0xb6,0x7d,0x06,0x52,0x99,0x92,0x59,0x15,0xae,0xb1,0x72,0xc0,0x66,0x47};
|
||||
|
||||
// Generate a dummy address with invalid CRC, starting with the network prefix.
|
||||
static std::string DummyAddress(const CChainParams ¶ms)
|
||||
static std::string MakeAddrInvalid(std::string addr)
|
||||
{
|
||||
std::vector<unsigned char> sourcedata = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
|
||||
sourcedata.insert(sourcedata.end(), dummydata, dummydata + sizeof(dummydata));
|
||||
for(int i=0; i<256; ++i) { // Try every trailing byte
|
||||
std::string s = EncodeBase58(begin_ptr(sourcedata), end_ptr(sourcedata));
|
||||
if (!CBitcoinAddress(s).IsValid())
|
||||
return s;
|
||||
sourcedata[sourcedata.size()-1] += 1;
|
||||
if (addr.size() < 2)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
// Checksum is at the end of the address. Swapping chars to make it invalid.
|
||||
std::swap(addr[addr.size() - 1], addr[addr.size() - 2]);
|
||||
if (!IsValidDestinationString(addr))
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string DummyAddress(const CChainParams ¶ms, const Config &cfg)
|
||||
{
|
||||
// Just some dummy data to generate an convincing random-looking (but
|
||||
// consistent) address
|
||||
static const std::vector<uint8_t> dummydata = {0xeb, 0x15, 0x23, 0x1d, 0xfc, 0xeb, 0x60, 0x92, 0x58, 0x86, 0xb6,
|
||||
0x7d, 0x06, 0x52, 0x99, 0x92, 0x59, 0x15, 0xae, 0xb1};
|
||||
|
||||
const CTxDestination dstKey = CKeyID(uint160(dummydata));
|
||||
return MakeAddrInvalid(EncodeDestination(dstKey, params, cfg));
|
||||
}
|
||||
|
||||
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
|
||||
{
|
||||
parent->setFocusProxy(widget);
|
||||
|
||||
widget->setFont(fixedPitchFont());
|
||||
const CChainParams ¶ms = Params();
|
||||
#if QT_VERSION >= 0x040700
|
||||
// We don't want translators to use own addresses in translations
|
||||
// and this is the only place, where this address is supplied.
|
||||
widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. %1)").arg(
|
||||
QString::fromStdString(DummyAddress(Params()))));
|
||||
widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. %1)")
|
||||
.arg(QString::fromStdString(DummyAddress(params, GetConfig()))));
|
||||
#endif
|
||||
widget->setValidator(new BitcoinAddressEntryValidator(parent));
|
||||
widget->setValidator(new BitcoinAddressEntryValidator(params.CashAddrPrefix(), parent));
|
||||
widget->setCheckValidator(new BitcoinAddressCheckValidator(parent));
|
||||
}
|
||||
|
||||
@@ -148,16 +163,48 @@ void setupAmountWidget(QLineEdit *widget, QWidget *parent)
|
||||
widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
|
||||
}
|
||||
|
||||
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
|
||||
QString bitcoinURIScheme(const CChainParams ¶ms, bool useCashAddr)
|
||||
{
|
||||
// return if URI is not valid or is no bitcoin: URI
|
||||
if(!uri.isValid() || uri.scheme() != QString("bitcoin"))
|
||||
if (!useCashAddr)
|
||||
{
|
||||
return "blackcoin";
|
||||
}
|
||||
return QString::fromStdString(params.CashAddrPrefix());
|
||||
}
|
||||
|
||||
QString bitcoinURIScheme(const Config &cfg)
|
||||
{
|
||||
return bitcoinURIScheme(cfg.GetChainParams(), cfg.UseCashAddrEncoding());
|
||||
}
|
||||
|
||||
static bool IsCashAddrEncoded(const QUrl &uri)
|
||||
{
|
||||
const std::string addr = (uri.scheme() + ":" + uri.path()).toStdString();
|
||||
auto decoded = cashaddr::Decode(addr, "");
|
||||
return !decoded.first.empty();
|
||||
}
|
||||
|
||||
bool parseBitcoinURI(const QString &scheme, const QUrl &uri, SendCoinsRecipient *out)
|
||||
{
|
||||
// return if URI has wrong scheme.
|
||||
if (!uri.isValid() || uri.scheme() != scheme)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SendCoinsRecipient rv;
|
||||
rv.address = uri.path();
|
||||
if (IsCashAddrEncoded(uri))
|
||||
{
|
||||
rv.address = uri.scheme() + ":" + uri.path();
|
||||
}
|
||||
else
|
||||
{
|
||||
// strip out uri scheme for base58 encoded addresses
|
||||
rv.address = uri.path();
|
||||
}
|
||||
// Trim any following forward slash which may have been added by the OS
|
||||
if (rv.address.endsWith("/")) {
|
||||
if (rv.address.endsWith("/"))
|
||||
{
|
||||
rv.address.truncate(rv.address.length() - 1);
|
||||
}
|
||||
rv.amount = 0;
|
||||
@@ -189,9 +236,9 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
|
||||
}
|
||||
else if (i->first == "amount")
|
||||
{
|
||||
if(!i->second.isEmpty())
|
||||
if (!i->second.isEmpty())
|
||||
{
|
||||
if(!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, &rv.amount))
|
||||
if (!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, &rv.amount))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -202,30 +249,35 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
|
||||
if (fShouldReturnFalse)
|
||||
return false;
|
||||
}
|
||||
if(out)
|
||||
if (out)
|
||||
{
|
||||
*out = rv;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseBitcoinURI(QString uri, SendCoinsRecipient *out)
|
||||
bool parseBitcoinURI(const QString &scheme, QString uri, SendCoinsRecipient *out)
|
||||
{
|
||||
// Convert bitcoin:// to bitcoin:
|
||||
//
|
||||
// Cannot handle this later, because bitcoin:// will cause Qt to see the part after // as host,
|
||||
// Cannot handle this later, because blackcoin://
|
||||
// will cause Qt to see the part after // as host,
|
||||
// which will lower-case it (and thus invalidate the address).
|
||||
if(uri.startsWith("bitcoin://", Qt::CaseInsensitive))
|
||||
if (uri.startsWith(scheme + "://", Qt::CaseInsensitive))
|
||||
{
|
||||
uri.replace(0, 10, "bitcoin:");
|
||||
uri.replace(0, scheme.length() + 3, scheme + ":");
|
||||
}
|
||||
QUrl uriInstance(uri);
|
||||
return parseBitcoinURI(uriInstance, out);
|
||||
return parseBitcoinURI(scheme, uriInstance, out);
|
||||
}
|
||||
|
||||
QString formatBitcoinURI(const SendCoinsRecipient &info)
|
||||
QString formatBitcoinURI(const Config &cfg, const SendCoinsRecipient &info)
|
||||
{
|
||||
QString ret = QString("blackcoin:%1").arg(info.address);
|
||||
QString ret = info.address;
|
||||
if (!cfg.UseCashAddrEncoding())
|
||||
{
|
||||
// prefix address with uri scheme for base58 encoded addresses.
|
||||
ret = (bitcoinURIScheme(cfg) + ":%1").arg(ret);
|
||||
}
|
||||
int paramCount = 0;
|
||||
|
||||
if (info.amount)
|
||||
@@ -253,7 +305,7 @@ QString formatBitcoinURI(const SendCoinsRecipient &info)
|
||||
|
||||
bool isDust(const QString& address, const CAmount& amount)
|
||||
{
|
||||
CTxDestination dest = CBitcoinAddress(address.toStdString()).Get();
|
||||
CTxDestination dest = DecodeDestination(address.toStdString());
|
||||
CScript script = GetScriptForDestination(dest);
|
||||
CTxOut txOut(amount, script);
|
||||
return txOut.IsDust(::minRelayTxFee);
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
class QValidatedLineEdit;
|
||||
class SendCoinsRecipient;
|
||||
class CChainParams;
|
||||
class Config;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAbstractItemView;
|
||||
@@ -40,14 +42,20 @@ namespace GUIUtil
|
||||
// Return a monospace font
|
||||
QFont fixedPitchFont();
|
||||
|
||||
// Generate an invalid, but convincing address.
|
||||
std::string DummyAddress(const CChainParams ¶ms, const Config &cfg);
|
||||
|
||||
// Set up widgets for address and amounts
|
||||
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent);
|
||||
void setupAmountWidget(QLineEdit *widget, QWidget *parent);
|
||||
|
||||
// Parse "bitcoin:" URI into recipient object, return true on successful parsing
|
||||
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out);
|
||||
bool parseBitcoinURI(QString uri, SendCoinsRecipient *out);
|
||||
QString formatBitcoinURI(const SendCoinsRecipient &info);
|
||||
QString bitcoinURIScheme(const CChainParams &, bool useCashAddr);
|
||||
QString bitcoinURIScheme(const Config &);
|
||||
// Parse "blackcoin:" URI into recipient object, return true on successful
|
||||
// parsing
|
||||
bool parseBitcoinURI(const QString &scheme, const QUrl &uri, SendCoinsRecipient *out);
|
||||
bool parseBitcoinURI(const QString &scheme, QString uri, SendCoinsRecipient *out);
|
||||
QString formatBitcoinURI(const Config &cfg, const SendCoinsRecipient &info);
|
||||
|
||||
// Returns true if given address+amount meets "dust" definition
|
||||
bool isDust(const QString& address, const CAmount& amount);
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
OpenURIDialog::OpenURIDialog(QWidget *parent) :
|
||||
OpenURIDialog::OpenURIDialog(const Config *cfg, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::OpenURIDialog)
|
||||
ui(new Ui::OpenURIDialog),
|
||||
cfg(cfg)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
#if QT_VERSION >= 0x040700
|
||||
@@ -33,7 +34,8 @@ QString OpenURIDialog::getURI()
|
||||
void OpenURIDialog::accept()
|
||||
{
|
||||
SendCoinsRecipient rcp;
|
||||
if(GUIUtil::parseBitcoinURI(getURI(), &rcp))
|
||||
QString uriScheme = GUIUtil::bitcoinURIScheme(*cfg);
|
||||
if (GUIUtil::parseBitcoinURI(uriScheme, getURI(), &rcp))
|
||||
{
|
||||
/* Only accept value URIs */
|
||||
QDialog::accept();
|
||||
@@ -48,5 +50,5 @@ void OpenURIDialog::on_selectFileButton_clicked()
|
||||
if(filename.isEmpty())
|
||||
return;
|
||||
QUrl fileUri = QUrl::fromLocalFile(filename);
|
||||
ui->uriEdit->setText("blackcoin:?r=" + QUrl::toPercentEncoding(fileUri.toString()));
|
||||
ui->uriEdit->setText(GUIUtil::bitcoinURIScheme(*cfg) + ":?r=" + QUrl::toPercentEncoding(fileUri.toString()));
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class Config;
|
||||
|
||||
namespace Ui {
|
||||
class OpenURIDialog;
|
||||
}
|
||||
@@ -16,7 +18,7 @@ class OpenURIDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OpenURIDialog(QWidget *parent);
|
||||
explicit OpenURIDialog(const Config *cfg, QWidget *parent);
|
||||
~OpenURIDialog();
|
||||
|
||||
QString getURI();
|
||||
@@ -29,6 +31,7 @@ private Q_SLOTS:
|
||||
|
||||
private:
|
||||
Ui::OpenURIDialog *ui;
|
||||
const Config *cfg;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_QT_OPENURIDIALOG_H
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
#include "guiutil.h"
|
||||
#include "optionsmodel.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "chainparams.h"
|
||||
#include "config.h"
|
||||
#include "dstencode.h"
|
||||
#include "main.h" // For minRelayTxFee
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
@@ -52,9 +53,9 @@ const QString BITCOIN_IPC_PREFIX("blackcoin:");
|
||||
const char* BIP70_MESSAGE_PAYMENTACK = "PaymentACK";
|
||||
const char* BIP70_MESSAGE_PAYMENTREQUEST = "PaymentRequest";
|
||||
// BIP71 payment protocol media types
|
||||
const char* BIP71_MIMETYPE_PAYMENT = "application/bitcoin-payment";
|
||||
const char* BIP71_MIMETYPE_PAYMENTACK = "application/bitcoin-paymentack";
|
||||
const char* BIP71_MIMETYPE_PAYMENTREQUEST = "application/bitcoin-paymentrequest";
|
||||
const char* BIP71_MIMETYPE_PAYMENT = "application/blackcoin-payment";
|
||||
const char* BIP71_MIMETYPE_PAYMENTACK = "application/blackcoin-paymentack";
|
||||
const char* BIP71_MIMETYPE_PAYMENTREQUEST = "application/blackcoin-paymentrequest";
|
||||
// BIP70 max payment request size in bytes (DoS protection)
|
||||
const qint64 BIP70_MAX_PAYMENTREQUEST_SIZE = 50000;
|
||||
|
||||
@@ -192,6 +193,37 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
|
||||
// "certificate stapling" with server-side caching is more efficient
|
||||
}
|
||||
|
||||
static std::string ipcParseURI(const QString &arg, const CChainParams ¶ms, bool useCashAddr)
|
||||
{
|
||||
const QString scheme = GUIUtil::bitcoinURIScheme(params, useCashAddr);
|
||||
if (!arg.startsWith(scheme + ":", Qt::CaseInsensitive))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
SendCoinsRecipient r;
|
||||
if (!GUIUtil::parseBitcoinURI(scheme, arg, &r))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return r.address.toStdString();
|
||||
}
|
||||
|
||||
static bool ipcCanParseCashAddrURI(const QString &arg, const std::string &network)
|
||||
{
|
||||
const CChainParams ¶ms(Params(network));
|
||||
std::string addr = ipcParseURI(arg, params, true);
|
||||
return IsValidDestinationString(addr, params);
|
||||
}
|
||||
|
||||
static bool ipcCanParseLegacyURI(const QString &arg, const std::string &network)
|
||||
{
|
||||
const CChainParams ¶ms(Params(network));
|
||||
std::string addr = ipcParseURI(arg, params, false);
|
||||
return IsValidDestinationString(addr, params);
|
||||
}
|
||||
|
||||
//
|
||||
// Sending to the server is done synchronously, at startup.
|
||||
// If the server isn't already running, startup continues,
|
||||
@@ -203,58 +235,77 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
|
||||
//
|
||||
void PaymentServer::ipcParseCommandLine(int argc, char* argv[])
|
||||
{
|
||||
std::array<const std::string *, 3> networks = {
|
||||
&CBaseChainParams::MAIN, &CBaseChainParams::TESTNET, &CBaseChainParams::REGTEST};
|
||||
|
||||
const std::string *chosenNetwork = nullptr;
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
QString arg(argv[i]);
|
||||
if (arg.startsWith("-"))
|
||||
continue;
|
||||
|
||||
// If the bitcoin: URI contains a payment request, we are not able to detect the
|
||||
// network as that would require fetching and parsing the payment request.
|
||||
// That means clicking such an URI which contains a testnet payment request
|
||||
// will start a mainnet instance and throw a "wrong network" error.
|
||||
if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
|
||||
const std::string *itemNetwork = nullptr;
|
||||
|
||||
// Try to parse as a URI
|
||||
for (auto net : networks)
|
||||
{
|
||||
savedPaymentRequests.append(arg);
|
||||
|
||||
SendCoinsRecipient r;
|
||||
if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty())
|
||||
if (ipcCanParseCashAddrURI(arg, *net))
|
||||
{
|
||||
CBitcoinAddress address(r.address.toStdString());
|
||||
itemNetwork = net;
|
||||
break;
|
||||
}
|
||||
|
||||
if (address.IsValid(Params(CBaseChainParams::MAIN)))
|
||||
{
|
||||
SelectParams(CBaseChainParams::MAIN);
|
||||
}
|
||||
else if (address.IsValid(Params(CBaseChainParams::TESTNET)))
|
||||
{
|
||||
SelectParams(CBaseChainParams::TESTNET);
|
||||
}
|
||||
if (ipcCanParseLegacyURI(arg, *net))
|
||||
{
|
||||
itemNetwork = net;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (QFile::exists(arg)) // Filename
|
||||
{
|
||||
savedPaymentRequests.append(arg);
|
||||
|
||||
if (!itemNetwork && QFile::exists(arg))
|
||||
{
|
||||
// Filename
|
||||
PaymentRequestPlus request;
|
||||
if (readPaymentRequestFromFile(arg, request))
|
||||
{
|
||||
if (request.getDetails().network() == "main")
|
||||
for (auto net : networks)
|
||||
{
|
||||
SelectParams(CBaseChainParams::MAIN);
|
||||
}
|
||||
else if (request.getDetails().network() == "test")
|
||||
{
|
||||
SelectParams(CBaseChainParams::TESTNET);
|
||||
if (*net == request.getDetails().network())
|
||||
{
|
||||
itemNetwork = net;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (itemNetwork == nullptr)
|
||||
{
|
||||
// Printing to debug.log is about the best we can do here, the
|
||||
// GUI hasn't started yet so we can't pop up a message box.
|
||||
qWarning() << "PaymentServer::ipcSendCommandLine: Payment request file does not exist: " << arg;
|
||||
// Printing to debug.log is about the best we can do here, the GUI
|
||||
// hasn't started yet so we can't pop up a message box.
|
||||
qWarning() << "PaymentServer::ipcSendCommandLine: Payment request "
|
||||
"file or URI does not exist or is invalid: "
|
||||
<< arg;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chosenNetwork && chosenNetwork != itemNetwork)
|
||||
{
|
||||
qWarning() << "PaymentServer::ipcSendCommandLine: Payment request "
|
||||
"from network "
|
||||
<< QString(itemNetwork->c_str()) << " does not match already chosen network "
|
||||
<< QString(chosenNetwork->c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
savedPaymentRequests.append(arg);
|
||||
chosenNetwork = itemNetwork;
|
||||
}
|
||||
|
||||
if (chosenNetwork)
|
||||
{
|
||||
SelectParams(*chosenNetwork);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +360,7 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
// Install global event filter to catch QFileOpenEvents
|
||||
// on Mac: sent when you click bitcoin: links
|
||||
// on Mac: sent when you click blackcoin: links
|
||||
// other OSes: helpful when dealing with payment request files
|
||||
if (parent)
|
||||
parent->installEventFilter(this);
|
||||
@@ -323,10 +374,11 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
|
||||
{
|
||||
uriServer = new QLocalServer(this);
|
||||
|
||||
if (!uriServer->listen(name)) {
|
||||
// constructor is called early in init, so don't use "Q_EMIT message()" here
|
||||
QMessageBox::critical(0, tr("Payment request error"),
|
||||
tr("Cannot start blackcoin: click-to-pay handler"));
|
||||
if (!uriServer->listen(name))
|
||||
{
|
||||
// constructor is called early in init, so don't use "Q_EMIT
|
||||
// message()" here
|
||||
QMessageBox::critical(0, tr("Payment request error"), tr("Cannot start click-to-pay handler"));
|
||||
}
|
||||
else {
|
||||
connect(uriServer, SIGNAL(newConnection()), this, SLOT(handleURIConnection()));
|
||||
@@ -341,7 +393,7 @@ PaymentServer::~PaymentServer()
|
||||
}
|
||||
|
||||
//
|
||||
// OSX-specific way of handling bitcoin: URIs and PaymentRequest mime types.
|
||||
// OSX-specific way of handling blackcoin: URIs and PaymentRequest mime types.
|
||||
// Also used by paymentservertests.cpp and when opening a payment request file
|
||||
// via "Open URI..." menu entry.
|
||||
//
|
||||
@@ -367,7 +419,7 @@ void PaymentServer::initNetManager()
|
||||
if (netManager != NULL)
|
||||
delete netManager;
|
||||
|
||||
// netManager is used to fetch paymentrequests given in bitcoin: URIs
|
||||
// netManager is used to fetch paymentrequests given in blackcoin: URIs
|
||||
netManager = new QNetworkAccessManager(this);
|
||||
|
||||
QNetworkProxy proxy;
|
||||
@@ -399,7 +451,65 @@ void PaymentServer::uiReady()
|
||||
savedPaymentRequests.clear();
|
||||
}
|
||||
|
||||
void PaymentServer::handleURIOrFile(const QString& s)
|
||||
bool PaymentServer::handleURI(const QString &scheme, const QString &s)
|
||||
{
|
||||
if (!s.startsWith(scheme + ":", Qt::CaseInsensitive))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#if QT_VERSION < 0x050000
|
||||
QUrl uri(s);
|
||||
#else
|
||||
QUrlQuery uri((QUrl(s)));
|
||||
#endif
|
||||
if (uri.hasQueryItem("r"))
|
||||
{
|
||||
// payment request URI
|
||||
QByteArray temp;
|
||||
temp.append(uri.queryItemValue("r"));
|
||||
QString decoded = QUrl::fromPercentEncoding(temp);
|
||||
QUrl fetchUrl(decoded, QUrl::StrictMode);
|
||||
|
||||
if (fetchUrl.isValid())
|
||||
{
|
||||
qDebug() << "PaymentServer::handleURIOrFile: fetchRequest(" << fetchUrl << ")";
|
||||
fetchRequest(fetchUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "PaymentServer::handleURIOrFile: Invalid URL: " << fetchUrl;
|
||||
Q_EMIT message(tr("URI handling"), tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()),
|
||||
CClientUIInterface::ICON_WARNING);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// normal URI
|
||||
SendCoinsRecipient recipient;
|
||||
if (GUIUtil::parseBitcoinURI(scheme, s, &recipient))
|
||||
{
|
||||
if (!IsValidDestinationString(recipient.address.toStdString()))
|
||||
{
|
||||
Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_EMIT receivedPaymentRequest(recipient);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_EMIT message(tr("URI handling"), tr("URI cannot be parsed! This can be caused by an invalid "
|
||||
"Bitcoin address or malformed URI parameters."),
|
||||
CClientUIInterface::ICON_WARNING);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaymentServer::handleURIOrFile(const QString &s)
|
||||
{
|
||||
if (saveURIs)
|
||||
{
|
||||
@@ -407,55 +517,18 @@ void PaymentServer::handleURIOrFile(const QString& s)
|
||||
return;
|
||||
}
|
||||
|
||||
if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
|
||||
// blackcoin: CashAddr URI
|
||||
QString schemeCash = GUIUtil::bitcoinURIScheme(Params(), true);
|
||||
if (handleURI(schemeCash, s))
|
||||
{
|
||||
#if QT_VERSION < 0x050000
|
||||
QUrl uri(s);
|
||||
#else
|
||||
QUrlQuery uri((QUrl(s)));
|
||||
#endif
|
||||
if (uri.hasQueryItem("r")) // payment request URI
|
||||
{
|
||||
QByteArray temp;
|
||||
temp.append(uri.queryItemValue("r"));
|
||||
QString decoded = QUrl::fromPercentEncoding(temp);
|
||||
QUrl fetchUrl(decoded, QUrl::StrictMode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fetchUrl.isValid())
|
||||
{
|
||||
qDebug() << "PaymentServer::handleURIOrFile: fetchRequest(" << fetchUrl << ")";
|
||||
fetchRequest(fetchUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "PaymentServer::handleURIOrFile: Invalid URL: " << fetchUrl;
|
||||
Q_EMIT message(tr("URI handling"),
|
||||
tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()),
|
||||
CClientUIInterface::ICON_WARNING);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else // normal URI
|
||||
{
|
||||
SendCoinsRecipient recipient;
|
||||
if (GUIUtil::parseBitcoinURI(s, &recipient))
|
||||
{
|
||||
CBitcoinAddress address(recipient.address.toStdString());
|
||||
if (!address.IsValid()) {
|
||||
Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
}
|
||||
else
|
||||
Q_EMIT receivedPaymentRequest(recipient);
|
||||
}
|
||||
else
|
||||
Q_EMIT message(tr("URI handling"),
|
||||
tr("URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."),
|
||||
CClientUIInterface::ICON_WARNING);
|
||||
|
||||
return;
|
||||
}
|
||||
// blackcoin: Legacy URI
|
||||
QString schemeLegacy = GUIUtil::bitcoinURIScheme(Params(), false);
|
||||
if (handleURI(schemeLegacy, s))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (QFile::exists(s)) // payment request file
|
||||
@@ -560,12 +633,13 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen
|
||||
CTxDestination dest;
|
||||
if (ExtractDestination(sendingTo.first, dest)) {
|
||||
// Append destination address
|
||||
addresses.append(QString::fromStdString(CBitcoinAddress(dest).ToString()));
|
||||
addresses.append(QString::fromStdString(EncodeDestination(dest)));
|
||||
}
|
||||
else if (!recipient.authenticatedMerchant.isEmpty()) {
|
||||
// Unauthenticated payment requests to custom bitcoin addresses are not supported
|
||||
// (there is no good way to tell the user where they are paying in a way they'd
|
||||
// have a chance of understanding).
|
||||
else if (!recipient.authenticatedMerchant.isEmpty())
|
||||
{
|
||||
// Unauthenticated payment requests to custom bitcoin addresses are
|
||||
// not supported (there is no good way to tell the user where they
|
||||
// are paying in a way they'd have a chance of understanding).
|
||||
Q_EMIT message(tr("Payment request rejected"),
|
||||
tr("Unverified payment requests to custom payment scripts are unsupported."),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define BITCOIN_QT_PAYMENTSERVER_H
|
||||
|
||||
// This class handles payment requests from clicking on
|
||||
// bitcoin: URIs
|
||||
// blackcoin: URIs
|
||||
//
|
||||
// This is somewhat tricky, because we have to deal with
|
||||
// the situation where the user clicks on a link during
|
||||
@@ -131,6 +131,7 @@ protected:
|
||||
|
||||
private:
|
||||
static bool readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request);
|
||||
bool handleURI(const QString &scheme, const QString &s);
|
||||
bool processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient);
|
||||
void fetchRequest(const QUrl& url);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "addressbookpage.h"
|
||||
#include "addresstablemodel.h"
|
||||
#include "bitcoinunits.h"
|
||||
#include "config.h"
|
||||
#include "guiutil.h"
|
||||
#include "optionsmodel.h"
|
||||
#include "platformstyle.h"
|
||||
@@ -22,12 +23,13 @@
|
||||
#include <QScrollBar>
|
||||
#include <QTextDocument>
|
||||
|
||||
ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent) :
|
||||
ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *platformStyle, const Config *cfg, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ReceiveCoinsDialog),
|
||||
columnResizingFixer(0),
|
||||
model(0),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(platformStyle),
|
||||
cfg(cfg)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
@@ -44,18 +46,21 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidg
|
||||
}
|
||||
|
||||
// context menu actions
|
||||
QAction *copyURIAction = new QAction(tr("Copy URI"), this);
|
||||
QAction *copyLabelAction = new QAction(tr("Copy label"), this);
|
||||
QAction *copyMessageAction = new QAction(tr("Copy message"), this);
|
||||
QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
|
||||
|
||||
// context menu
|
||||
contextMenu = new QMenu(this);
|
||||
contextMenu->addAction(copyURIAction);
|
||||
contextMenu->addAction(copyLabelAction);
|
||||
contextMenu->addAction(copyMessageAction);
|
||||
contextMenu->addAction(copyAmountAction);
|
||||
|
||||
// context menu signals
|
||||
connect(ui->recentRequestsView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint)));
|
||||
connect(copyURIAction, SIGNAL(triggered()), this, SLOT(copyURI()));
|
||||
connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
|
||||
connect(copyMessageAction, SIGNAL(triggered()), this, SLOT(copyMessage()));
|
||||
connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
|
||||
@@ -153,7 +158,7 @@ void ReceiveCoinsDialog::on_receiveButton_clicked()
|
||||
}
|
||||
SendCoinsRecipient info(address, label,
|
||||
ui->reqAmount->value(), ui->reqMessage->text());
|
||||
ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
|
||||
ReceiveRequestDialog *dialog = new ReceiveRequestDialog(cfg, this);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dialog->setModel(model->getOptionsModel());
|
||||
dialog->setInfo(info);
|
||||
@@ -167,7 +172,7 @@ void ReceiveCoinsDialog::on_receiveButton_clicked()
|
||||
void ReceiveCoinsDialog::on_recentRequestsView_doubleClicked(const QModelIndex &index)
|
||||
{
|
||||
const RecentRequestsTableModel *submodel = model->getRecentRequestsTableModel();
|
||||
ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
|
||||
ReceiveRequestDialog *dialog = new ReceiveRequestDialog(cfg, this);
|
||||
dialog->setModel(model->getOptionsModel());
|
||||
dialog->setInfo(submodel->entry(index.row()).recipient);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
@@ -229,30 +234,55 @@ void ReceiveCoinsDialog::keyPressEvent(QKeyEvent *event)
|
||||
this->QDialog::keyPressEvent(event);
|
||||
}
|
||||
|
||||
QModelIndex ReceiveCoinsDialog::selectedRow()
|
||||
{
|
||||
if (!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
|
||||
return QModelIndex();
|
||||
QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
|
||||
if (selection.empty())
|
||||
return QModelIndex();
|
||||
// correct for selection mode ContiguousSelection
|
||||
QModelIndex firstIndex = selection.at(0);
|
||||
return firstIndex;
|
||||
}
|
||||
|
||||
// copy column of selected row to clipboard
|
||||
void ReceiveCoinsDialog::copyColumnToClipboard(int column)
|
||||
{
|
||||
if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
|
||||
QModelIndex firstIndex = selectedRow();
|
||||
if (!firstIndex.isValid())
|
||||
{
|
||||
return;
|
||||
QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
|
||||
if(selection.empty())
|
||||
return;
|
||||
// correct for selection mode ContiguousSelection
|
||||
QModelIndex firstIndex = selection.at(0);
|
||||
GUIUtil::setClipboard(model->getRecentRequestsTableModel()->data(firstIndex.child(firstIndex.row(), column), Qt::EditRole).toString());
|
||||
}
|
||||
GUIUtil::setClipboard(model->getRecentRequestsTableModel()
|
||||
->data(firstIndex.child(firstIndex.row(), column), Qt::EditRole)
|
||||
.toString());
|
||||
}
|
||||
|
||||
// context menu
|
||||
void ReceiveCoinsDialog::showMenu(const QPoint &point)
|
||||
{
|
||||
if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
|
||||
return;
|
||||
QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
|
||||
if(selection.empty())
|
||||
if (!selectedRow().isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
contextMenu->exec(QCursor::pos());
|
||||
}
|
||||
|
||||
// context menu action: copy URI
|
||||
void ReceiveCoinsDialog::copyURI()
|
||||
{
|
||||
QModelIndex sel = selectedRow();
|
||||
if (!sel.isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const RecentRequestsTableModel *const submodel = model->getRecentRequestsTableModel();
|
||||
const QString uri = GUIUtil::formatBitcoinURI(*cfg, submodel->entry(sel.row()).recipient);
|
||||
GUIUtil::setClipboard(uri);
|
||||
}
|
||||
|
||||
// context menu action: copy label
|
||||
void ReceiveCoinsDialog::copyLabel()
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <QPoint>
|
||||
#include <QVariant>
|
||||
|
||||
class Config;
|
||||
class OptionsModel;
|
||||
class PlatformStyle;
|
||||
class WalletModel;
|
||||
@@ -40,7 +41,7 @@ public:
|
||||
MINIMUM_COLUMN_WIDTH = 130
|
||||
};
|
||||
|
||||
explicit ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = 0);
|
||||
explicit ReceiveCoinsDialog(const PlatformStyle *platformStyle, const Config *cfg, QWidget *parent = 0);
|
||||
~ReceiveCoinsDialog();
|
||||
|
||||
void setModel(WalletModel *model);
|
||||
@@ -59,7 +60,9 @@ private:
|
||||
WalletModel *model;
|
||||
QMenu *contextMenu;
|
||||
const PlatformStyle *platformStyle;
|
||||
const Config *cfg;
|
||||
|
||||
QModelIndex selectedRow();
|
||||
void copyColumnToClipboard(int column);
|
||||
virtual void resizeEvent(QResizeEvent *event);
|
||||
|
||||
@@ -71,6 +74,7 @@ private Q_SLOTS:
|
||||
void recentRequestsView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
||||
void updateDisplayUnit();
|
||||
void showMenu(const QPoint &point);
|
||||
void copyURI();
|
||||
void copyLabel();
|
||||
void copyMessage();
|
||||
void copyAmount();
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// Copyright (c) 2011-2013 The Bitcoin Core developers
|
||||
// Copyright (c) 2015-2017 The Bitcoin Unlimited developers
|
||||
// Copyright (c) 2017 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -6,6 +8,8 @@
|
||||
#include "ui_receiverequestdialog.h"
|
||||
|
||||
#include "bitcoinunits.h"
|
||||
#include "config.h"
|
||||
#include "dstencode.h"
|
||||
#include "guiconstants.h"
|
||||
#include "guiutil.h"
|
||||
#include "optionsmodel.h"
|
||||
@@ -45,7 +49,7 @@ QImage QRImageWidget::exportImage()
|
||||
{
|
||||
if(!pixmap())
|
||||
return QImage();
|
||||
return pixmap()->toImage();
|
||||
return pixmap()->toImage().scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE);
|
||||
}
|
||||
|
||||
void QRImageWidget::mousePressEvent(QMouseEvent *event)
|
||||
@@ -89,10 +93,11 @@ void QRImageWidget::contextMenuEvent(QContextMenuEvent *event)
|
||||
contextMenu->exec(event->globalPos());
|
||||
}
|
||||
|
||||
ReceiveRequestDialog::ReceiveRequestDialog(QWidget *parent) :
|
||||
ReceiveRequestDialog::ReceiveRequestDialog(const Config *cfg, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ReceiveRequestDialog),
|
||||
model(0)
|
||||
model(0),
|
||||
cfg(cfg)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
@@ -120,9 +125,26 @@ void ReceiveRequestDialog::setModel(OptionsModel *model)
|
||||
update();
|
||||
}
|
||||
|
||||
void ReceiveRequestDialog::setInfo(const SendCoinsRecipient &info)
|
||||
// Addresses are stored in the database with the encoding that the client was
|
||||
// configured with at the time of creation.
|
||||
//
|
||||
// This converts to clients current configuration.
|
||||
QString ToCurrentEncoding(const QString &addr, const Config &cfg)
|
||||
{
|
||||
this->info = info;
|
||||
if (!IsValidDestinationString(addr.toStdString(), cfg.GetChainParams()))
|
||||
{
|
||||
// We have something sketchy as input. Do not try to convert.
|
||||
return addr;
|
||||
}
|
||||
CTxDestination dst = DecodeDestination(addr.toStdString(), cfg.GetChainParams());
|
||||
return QString::fromStdString(EncodeDestination(dst, cfg.GetChainParams(), cfg));
|
||||
}
|
||||
|
||||
void ReceiveRequestDialog::setInfo(const SendCoinsRecipient &_info)
|
||||
{
|
||||
this->info = _info;
|
||||
// Display addresses with currently configured encoding.
|
||||
this->info.address = ToCurrentEncoding(this->info.address, *cfg);
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -135,7 +157,7 @@ void ReceiveRequestDialog::update()
|
||||
target = info.address;
|
||||
setWindowTitle(tr("Request payment to %1").arg(target));
|
||||
|
||||
QString uri = GUIUtil::formatBitcoinURI(info);
|
||||
QString uri = GUIUtil::formatBitcoinURI(*cfg, info);
|
||||
ui->btnSaveAs->setEnabled(false);
|
||||
QString html;
|
||||
html += "<html><font face='verdana, arial, helvetica, sans-serif'>";
|
||||
@@ -152,6 +174,8 @@ void ReceiveRequestDialog::update()
|
||||
ui->outUri->setText(html);
|
||||
|
||||
#ifdef USE_QRCODE
|
||||
int fontSize = cfg->UseCashAddrEncoding() ? 10 : 12;
|
||||
|
||||
ui->lblQRCode->setText("");
|
||||
if(!uri.isEmpty())
|
||||
{
|
||||
@@ -179,16 +203,16 @@ void ReceiveRequestDialog::update()
|
||||
}
|
||||
QRcode_free(code);
|
||||
|
||||
QImage qrAddrImage = QImage(QR_IMAGE_SIZE, QR_IMAGE_SIZE+20, QImage::Format_RGB32);
|
||||
QImage qrAddrImage = QImage(QR_IMAGE_SIZE, QR_IMAGE_SIZE + 20, QImage::Format_RGB32);
|
||||
qrAddrImage.fill(0xffffff);
|
||||
QPainter painter(&qrAddrImage);
|
||||
painter.drawImage(0, 0, qrImage.scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE));
|
||||
QFont font = GUIUtil::fixedPitchFont();
|
||||
font.setPixelSize(12);
|
||||
font.setPixelSize(fontSize);
|
||||
painter.setFont(font);
|
||||
QRect paddedRect = qrAddrImage.rect();
|
||||
paddedRect.setHeight(QR_IMAGE_SIZE+12);
|
||||
painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, info.address);
|
||||
paddedRect.setHeight(QR_IMAGE_SIZE + 12);
|
||||
painter.drawText(paddedRect, Qt::AlignBottom | Qt::AlignCenter, info.address);
|
||||
painter.end();
|
||||
|
||||
ui->lblQRCode->setPixmap(QPixmap::fromImage(qrAddrImage));
|
||||
@@ -200,7 +224,7 @@ void ReceiveRequestDialog::update()
|
||||
|
||||
void ReceiveRequestDialog::on_btnCopyURI_clicked()
|
||||
{
|
||||
GUIUtil::setClipboard(GUIUtil::formatBitcoinURI(info));
|
||||
GUIUtil::setClipboard(GUIUtil::formatBitcoinURI(*cfg, info));
|
||||
}
|
||||
|
||||
void ReceiveRequestDialog::on_btnCopyAddress_clicked()
|
||||
|
||||
@@ -11,8 +11,10 @@
|
||||
#include <QImage>
|
||||
#include <QLabel>
|
||||
#include <QPainter>
|
||||
#include <QString>
|
||||
|
||||
class OptionsModel;
|
||||
class Config;
|
||||
|
||||
namespace Ui {
|
||||
class ReceiveRequestDialog;
|
||||
@@ -50,7 +52,7 @@ class ReceiveRequestDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ReceiveRequestDialog(QWidget *parent = 0);
|
||||
explicit ReceiveRequestDialog(const Config *cfg, QWidget *parent = 0);
|
||||
~ReceiveRequestDialog();
|
||||
|
||||
void setModel(OptionsModel *model);
|
||||
@@ -66,6 +68,10 @@ private:
|
||||
Ui::ReceiveRequestDialog *ui;
|
||||
OptionsModel *model;
|
||||
SendCoinsRecipient info;
|
||||
const Config *cfg;
|
||||
};
|
||||
|
||||
// exported for unittesting
|
||||
QString ToCurrentEncoding(const QString &addr, const Config &);
|
||||
|
||||
#endif // BITCOIN_QT_RECEIVEREQUESTDIALOG_H
|
||||
|
||||
@@ -53,7 +53,8 @@ private:
|
||||
Qt::SortOrder order;
|
||||
};
|
||||
|
||||
/** Model for list of recently generated payment requests / bitcoin: URIs.
|
||||
/**
|
||||
* Model for list of recently generated payment requests / blackcoin: URIs.
|
||||
* Part of wallet model.
|
||||
*/
|
||||
class RecentRequestsTableModel: public QAbstractTableModel
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
#include "sendcoinsentry.h"
|
||||
#include "walletmodel.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "coincontrol.h"
|
||||
#include "dstencode.h"
|
||||
#include "main.h" // mempool and minRelayTxFee
|
||||
#include "ui_interface.h"
|
||||
#include "txmempool.h"
|
||||
@@ -746,26 +746,43 @@ void SendCoinsDialog::coinControlChangeEdited(const QString& text)
|
||||
CoinControlDialog::coinControl->destChange = CNoDestination();
|
||||
ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}");
|
||||
|
||||
CBitcoinAddress addr = CBitcoinAddress(text.toStdString());
|
||||
const CTxDestination dest = DecodeDestination(text.toStdString());
|
||||
|
||||
if (text.isEmpty()) // Nothing entered
|
||||
{
|
||||
ui->labelCoinControlChangeLabel->setText("");
|
||||
}
|
||||
else if (!addr.IsValid()) // Invalid address
|
||||
else if (!IsValidDestination(dest))
|
||||
{
|
||||
// Invalid address
|
||||
ui->labelCoinControlChangeLabel->setText(tr("Warning: Invalid Bitcoin address"));
|
||||
}
|
||||
else // Valid address
|
||||
else
|
||||
{
|
||||
CKeyID keyid;
|
||||
addr.GetKeyID(keyid);
|
||||
if (!model->havePrivKey(keyid)) // Unknown change address
|
||||
// Valid address
|
||||
if (!model->IsSpendable(dest))
|
||||
{
|
||||
ui->labelCoinControlChangeLabel->setText(tr("Warning: Unknown change address"));
|
||||
|
||||
// confirmation dialog
|
||||
QMessageBox::StandardButton btnRetVal = QMessageBox::question(this, tr("Confirm custom change address"),
|
||||
tr("The address you selected for change is not part of "
|
||||
"this wallet. Any or all funds in your wallet may be "
|
||||
"sent to this address. Are you sure?"),
|
||||
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
|
||||
|
||||
if (btnRetVal == QMessageBox::Yes)
|
||||
CoinControlDialog::coinControl->destChange = dest;
|
||||
else
|
||||
{
|
||||
ui->lineEditCoinControlChange->setText("");
|
||||
ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:black;}");
|
||||
ui->labelCoinControlChangeLabel->setText("");
|
||||
}
|
||||
}
|
||||
else // Known change address
|
||||
else
|
||||
{
|
||||
// Known change address
|
||||
ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:black;}");
|
||||
|
||||
// Query label
|
||||
@@ -775,7 +792,7 @@ void SendCoinsDialog::coinControlChangeEdited(const QString& text)
|
||||
else
|
||||
ui->labelCoinControlChangeLabel->setText(tr("(no label)"));
|
||||
|
||||
CoinControlDialog::coinControl->destChange = addr.Get();
|
||||
CoinControlDialog::coinControl->destChange = dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "addressbookpage.h"
|
||||
#include "addresstablemodel.h"
|
||||
#include "config.h"
|
||||
#include "guiutil.h"
|
||||
#include "optionsmodel.h"
|
||||
#include "platformstyle.h"
|
||||
@@ -29,6 +30,11 @@ SendCoinsEntry::SendCoinsEntry(const PlatformStyle *platformStyle, QWidget *pare
|
||||
ui->deleteButton_is->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
|
||||
ui->deleteButton_s->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
|
||||
|
||||
ui->messageTextLabel->setToolTip(tr("A message that was attached to the %1 URI which will be"
|
||||
" stored with the transaction for your reference. Note: "
|
||||
"This message will not be sent over the Bitcoin network.")
|
||||
.arg(GUIUtil::bitcoinURIScheme(GetConfig())));
|
||||
|
||||
setCurrentWidget(ui->SendCoins);
|
||||
|
||||
if (platformStyle->getUseExtraSpacing())
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "platformstyle.h"
|
||||
#include "walletmodel.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "dstencode.h"
|
||||
#include "init.h"
|
||||
#include "main.h" // For strMessageMagic
|
||||
#include "wallet/wallet.h"
|
||||
@@ -117,15 +117,15 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
|
||||
/* Clear old signature to ensure users don't get confused on error with an old signature displayed */
|
||||
ui->signatureOut_SM->clear();
|
||||
|
||||
CBitcoinAddress addr(ui->addressIn_SM->text().toStdString());
|
||||
if (!addr.IsValid())
|
||||
CTxDestination destination = DecodeDestination(ui->addressIn_SM->text().toStdString());
|
||||
if (!IsValidDestination(destination))
|
||||
{
|
||||
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
|
||||
ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
|
||||
return;
|
||||
}
|
||||
CKeyID keyID;
|
||||
if (!addr.GetKeyID(keyID))
|
||||
const CKeyID *keyID = boost::get<CKeyID>(&destination);
|
||||
if (!keyID)
|
||||
{
|
||||
ui->addressIn_SM->setValid(false);
|
||||
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
|
||||
@@ -142,7 +142,7 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
|
||||
}
|
||||
|
||||
CKey key;
|
||||
if (!pwalletMain->GetKey(keyID, key))
|
||||
if (!pwalletMain->GetKey(*keyID, key))
|
||||
{
|
||||
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
|
||||
ui->statusLabel_SM->setText(tr("Private key for the entered address is not available."));
|
||||
@@ -197,15 +197,14 @@ void SignVerifyMessageDialog::on_addressBookButton_VM_clicked()
|
||||
|
||||
void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
|
||||
{
|
||||
CBitcoinAddress addr(ui->addressIn_VM->text().toStdString());
|
||||
if (!addr.IsValid())
|
||||
CTxDestination destination = DecodeDestination(ui->addressIn_VM->text().toStdString());
|
||||
if (!IsValidDestination(destination))
|
||||
{
|
||||
ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
|
||||
ui->statusLabel_VM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
|
||||
return;
|
||||
}
|
||||
CKeyID keyID;
|
||||
if (!addr.GetKeyID(keyID))
|
||||
if (!boost::get<CKeyID>(&destination))
|
||||
{
|
||||
ui->addressIn_VM->setValid(false);
|
||||
ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
|
||||
@@ -237,7 +236,7 @@ void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(CBitcoinAddress(pubkey.GetID()) == addr))
|
||||
if (!(CTxDestination(pubkey.GetID()) == destination))
|
||||
{
|
||||
ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
|
||||
ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>"));
|
||||
|
||||
36
src/qt/test/bitcoinaddressvalidatortests.cpp
Normal file
36
src/qt/test/bitcoinaddressvalidatortests.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2017 The Bitcoin Developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "qt/test/bitcoinaddressvalidatortests.h"
|
||||
#include "chainparams.h"
|
||||
#include "qt/bitcoinaddressvalidator.h"
|
||||
#include <QValidator>
|
||||
|
||||
void BitcoinAddressValidatorTests::inputTests() {
|
||||
const std::string prefix = Params(CBaseChainParams::MAIN).CashAddrPrefix();
|
||||
BitcoinAddressEntryValidator v(prefix, nullptr);
|
||||
|
||||
int unused = 0;
|
||||
QString in;
|
||||
|
||||
// invalid base58 because of I, invalid cashaddr
|
||||
in = "BIIC";
|
||||
QVERIFY(QValidator::Invalid == v.validate(in, unused));
|
||||
|
||||
// invalid base58, invalid cashaddr
|
||||
in = "BITCOINCASHH";
|
||||
QVERIFY(QValidator::Invalid == v.validate(in, unused));
|
||||
|
||||
// invalid base58 because of I, but could be a cashaddr prefix
|
||||
in = "BITC";
|
||||
QVERIFY(QValidator::Acceptable == v.validate(in, unused));
|
||||
|
||||
// invalid base58, valid cashaddr
|
||||
in = "BITCOINCASH:QP";
|
||||
QVERIFY(QValidator::Acceptable == v.validate(in, unused));
|
||||
|
||||
// valid base58, invalid cash
|
||||
in = "BBBBBBBBBBBBBB";
|
||||
QVERIFY(QValidator::Acceptable == v.validate(in, unused));
|
||||
}
|
||||
18
src/qt/test/bitcoinaddressvalidatortests.h
Normal file
18
src/qt/test/bitcoinaddressvalidatortests.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2017 The Bitcoin Developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_QT_TEST_BITCOINADDRESSVALIDATORTESTS_H
|
||||
#define BITCOIN_QT_TEST_BITCOINADDRESSVALIDATORTESTS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTest>
|
||||
|
||||
class BitcoinAddressValidatorTests : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void inputTests();
|
||||
};
|
||||
|
||||
#endif
|
||||
62
src/qt/test/guiutiltests.cpp
Normal file
62
src/qt/test/guiutiltests.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2017 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "guiutiltests.h"
|
||||
#include "chainparams.h"
|
||||
#include "config.h"
|
||||
#include "dstencode.h"
|
||||
#include "guiutil.h"
|
||||
#include "receiverequestdialog.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class UtilCfgDummy : public DummyConfig {
|
||||
public:
|
||||
UtilCfgDummy() : useCashAddr(false) {}
|
||||
void SetCashAddrEncoding(bool b) override { useCashAddr = b; }
|
||||
bool UseCashAddrEncoding() const override { return useCashAddr; }
|
||||
const CChainParams &GetChainParams() const override {
|
||||
return Params(CBaseChainParams::MAIN);
|
||||
}
|
||||
|
||||
private:
|
||||
bool useCashAddr;
|
||||
};
|
||||
|
||||
} // anon ns
|
||||
|
||||
void GUIUtilTests::dummyAddressTest() {
|
||||
CChainParams ¶ms = Params(CBaseChainParams::MAIN);
|
||||
UtilCfgDummy cfg;
|
||||
std::string dummyaddr;
|
||||
|
||||
cfg.SetCashAddrEncoding(false);
|
||||
dummyaddr = GUIUtil::DummyAddress(params, cfg);
|
||||
QVERIFY(!IsValidDestinationString(dummyaddr, params));
|
||||
QVERIFY(!dummyaddr.empty());
|
||||
|
||||
cfg.SetCashAddrEncoding(true);
|
||||
dummyaddr = GUIUtil::DummyAddress(params, cfg);
|
||||
QVERIFY(!IsValidDestinationString(dummyaddr, params));
|
||||
QVERIFY(!dummyaddr.empty());
|
||||
}
|
||||
|
||||
void GUIUtilTests::toCurrentEncodingTest() {
|
||||
UtilCfgDummy config;
|
||||
|
||||
// garbage in, garbage out
|
||||
QVERIFY(ToCurrentEncoding("garbage", config) == "garbage");
|
||||
|
||||
QString cashaddr_pubkey =
|
||||
"blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a";
|
||||
QString base58_pubkey = "1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu";
|
||||
|
||||
config.SetCashAddrEncoding(true);
|
||||
QVERIFY(ToCurrentEncoding(cashaddr_pubkey, config) == cashaddr_pubkey);
|
||||
QVERIFY(ToCurrentEncoding(base58_pubkey, config) == cashaddr_pubkey);
|
||||
|
||||
config.SetCashAddrEncoding(false);
|
||||
QVERIFY(ToCurrentEncoding(cashaddr_pubkey, config) == base58_pubkey);
|
||||
QVERIFY(ToCurrentEncoding(base58_pubkey, config) == base58_pubkey);
|
||||
}
|
||||
19
src/qt/test/guiutiltests.h
Normal file
19
src/qt/test/guiutiltests.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2017 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_QT_TEST_GUIUTILTESTS_H
|
||||
#define BITCOIN_QT_TEST_GUIUTILTESTS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTest>
|
||||
|
||||
class GUIUtilTests : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void dummyAddressTest();
|
||||
void toCurrentEncodingTest();
|
||||
};
|
||||
|
||||
#endif // BITCOIN_QT_TEST_GUIUTILTESTS_H
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "config/bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include "bitcoinaddressvalidatortests.h"
|
||||
#include "guiutiltests.h"
|
||||
#include "util.h"
|
||||
#include "uritests.h"
|
||||
|
||||
@@ -48,6 +50,10 @@ int main(int argc, char *argv[])
|
||||
if (QTest::qExec(&test2) != 0)
|
||||
fInvalid = true;
|
||||
#endif
|
||||
GUIUtilTests test5;
|
||||
if (QTest::qExec(&test5) != 0) fInvalid = true;
|
||||
BitcoinAddressValidatorTests test6;
|
||||
if (QTest::qExec(&test6) != 0) fInvalid = true;
|
||||
|
||||
return fInvalid;
|
||||
}
|
||||
|
||||
@@ -1,66 +1,219 @@
|
||||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
||||
// Copyright (c) 2015-2017 The Bitcoin Unlimited developers
|
||||
// Copyright (c) 2017 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "uritests.h"
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "config.h"
|
||||
#include "guiutil.h"
|
||||
#include "walletmodel.h"
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
void URITests::uriTests()
|
||||
void URITests::uriTestsBase58()
|
||||
{
|
||||
SendCoinsRecipient rv;
|
||||
QString scheme =
|
||||
QString::fromStdString(Params(CBaseChainParams::MAIN).CashAddrPrefix());
|
||||
QUrl uri;
|
||||
uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist="));
|
||||
QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
|
||||
uri.setUrl(QString("blackcoin175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist="));
|
||||
QVERIFY(!GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
|
||||
uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist="));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
|
||||
uri.setUrl(QString("blackcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist="));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
|
||||
QVERIFY(rv.label == QString());
|
||||
QVERIFY(rv.amount == 0);
|
||||
|
||||
uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
|
||||
uri.setUrl(QString("blackcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
|
||||
QVERIFY(rv.label == QString("Wikipedia Example Address"));
|
||||
QVERIFY(rv.amount == 0);
|
||||
|
||||
uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
|
||||
uri.setUrl(QString("blackcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
|
||||
QVERIFY(rv.label == QString());
|
||||
QVERIFY(rv.amount == 100000);
|
||||
|
||||
uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
|
||||
uri.setUrl(QString("blackcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
|
||||
QVERIFY(rv.label == QString());
|
||||
QVERIFY(rv.amount == 100100000);
|
||||
|
||||
uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
|
||||
uri.setUrl(QString("blackcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
|
||||
QVERIFY(rv.amount == 10000000000LL);
|
||||
QVERIFY(rv.label == QString("Wikipedia Example"));
|
||||
|
||||
uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
|
||||
uri.setUrl(QString("blackcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
|
||||
QVERIFY(rv.label == QString());
|
||||
|
||||
QVERIFY(GUIUtil::parseBitcoinURI("bitcoin://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, "blackcoin://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?"
|
||||
"message=Wikipedia Example Address",
|
||||
&rv));
|
||||
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
|
||||
QVERIFY(rv.label == QString());
|
||||
|
||||
uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
|
||||
uri.setUrl(QString("blackcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
|
||||
uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example"));
|
||||
QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
|
||||
uri.setUrl(QString("blackcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example"));
|
||||
QVERIFY(!GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
|
||||
uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example"));
|
||||
QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
|
||||
uri.setUrl(QString("blackcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example"));
|
||||
QVERIFY(!GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
}
|
||||
|
||||
void URITests::uriTestsCashAddr() {
|
||||
SendCoinsRecipient rv;
|
||||
QUrl uri;
|
||||
QString scheme =
|
||||
QString::fromStdString(Params(CBaseChainParams::MAIN).CashAddrPrefix());
|
||||
uri.setUrl(QString("blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?"
|
||||
"req-dontexist="));
|
||||
QVERIFY(!GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
|
||||
uri.setUrl(QString(
|
||||
"blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?dontexist="));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
QVERIFY(rv.address ==
|
||||
QString("blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"));
|
||||
QVERIFY(rv.label == QString());
|
||||
QVERIFY(rv.amount == 0);
|
||||
|
||||
uri.setUrl(
|
||||
QString("blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?label="
|
||||
"Wikipedia Example Address"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
QVERIFY(rv.address ==
|
||||
QString("blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"));
|
||||
QVERIFY(rv.label == QString("Wikipedia Example Address"));
|
||||
QVERIFY(rv.amount == 0);
|
||||
|
||||
uri.setUrl(QString(
|
||||
"blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?amount=0.001"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
QVERIFY(rv.address ==
|
||||
QString("blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"));
|
||||
QVERIFY(rv.label == QString());
|
||||
QVERIFY(rv.amount == 100000);
|
||||
|
||||
uri.setUrl(QString(
|
||||
"blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?amount=1.001"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
QVERIFY(rv.address ==
|
||||
QString("blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"));
|
||||
QVERIFY(rv.label == QString());
|
||||
QVERIFY(rv.amount == 100100000);
|
||||
|
||||
uri.setUrl(QString(
|
||||
"blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?amount=100&"
|
||||
"label=Wikipedia Example"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
QVERIFY(rv.address ==
|
||||
QString("blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"));
|
||||
QVERIFY(rv.amount == 10000000000LL);
|
||||
QVERIFY(rv.label == QString("Wikipedia Example"));
|
||||
|
||||
uri.setUrl(QString(
|
||||
"blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?message="
|
||||
"Wikipedia Example Address"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
QVERIFY(rv.address ==
|
||||
QString("blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"));
|
||||
QVERIFY(rv.label == QString());
|
||||
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(
|
||||
scheme, "blackcoin://"
|
||||
"qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?"
|
||||
"message=Wikipedia Example Address",
|
||||
&rv));
|
||||
QVERIFY(rv.address ==
|
||||
QString("blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"));
|
||||
QVERIFY(rv.label == QString());
|
||||
|
||||
uri.setUrl(QString(
|
||||
"blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?req-message="
|
||||
"Wikipedia Example Address"));
|
||||
QVERIFY(GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
|
||||
uri.setUrl(QString(
|
||||
"blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?amount=1,"
|
||||
"000&label=Wikipedia Example"));
|
||||
QVERIFY(!GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
|
||||
uri.setUrl(QString(
|
||||
"blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?amount=1,"
|
||||
"000.0&label=Wikipedia Example"));
|
||||
QVERIFY(!GUIUtil::parseBitcoinURI(scheme, uri, &rv));
|
||||
}
|
||||
|
||||
namespace {
|
||||
class UriTestConfig : public DummyConfig {
|
||||
public:
|
||||
UriTestConfig(bool useCashAddr)
|
||||
: useCashAddr(useCashAddr), net(CBaseChainParams::MAIN) {}
|
||||
bool UseCashAddrEncoding() const override { return useCashAddr; }
|
||||
const CChainParams &GetChainParams() const override { return Params(net); }
|
||||
void SetChainParams(const std::string &n) { net = n; }
|
||||
|
||||
private:
|
||||
bool useCashAddr;
|
||||
std::string net;
|
||||
};
|
||||
|
||||
} // anon ns
|
||||
|
||||
void URITests::uriTestFormatURI() {
|
||||
{
|
||||
UriTestConfig cfg(true);
|
||||
SendCoinsRecipient r;
|
||||
r.address = "blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a";
|
||||
r.message = "test";
|
||||
QString uri = GUIUtil::formatBitcoinURI(cfg, r);
|
||||
QVERIFY(uri == "blackcoin:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a?"
|
||||
"message=test");
|
||||
}
|
||||
|
||||
{
|
||||
UriTestConfig cfg(false);
|
||||
SendCoinsRecipient r;
|
||||
r.address = "175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W";
|
||||
r.message = "test";
|
||||
QString uri = GUIUtil::formatBitcoinURI(cfg, r);
|
||||
QVERIFY(uri ==
|
||||
"blackcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=test");
|
||||
}
|
||||
}
|
||||
|
||||
void URITests::uriTestScheme() {
|
||||
{
|
||||
// cashaddr - scheme depends on selected chain params
|
||||
UriTestConfig config(true);
|
||||
config.SetChainParams(CBaseChainParams::MAIN);
|
||||
QVERIFY("blackcoin" == GUIUtil::bitcoinURIScheme(config));
|
||||
config.SetChainParams(CBaseChainParams::TESTNET);
|
||||
QVERIFY("blktest" == GUIUtil::bitcoinURIScheme(config));
|
||||
config.SetChainParams(CBaseChainParams::REGTEST);
|
||||
QVERIFY("blkreg" == GUIUtil::bitcoinURIScheme(config));
|
||||
}
|
||||
{
|
||||
// legacy - scheme is "blackcoin" regardless of chain params
|
||||
UriTestConfig config(false);
|
||||
config.SetChainParams(CBaseChainParams::MAIN);
|
||||
QVERIFY("blackcoin" == GUIUtil::bitcoinURIScheme(config));
|
||||
config.SetChainParams(CBaseChainParams::TESTNET);
|
||||
QVERIFY("blackcoin" == GUIUtil::bitcoinURIScheme(config));
|
||||
config.SetChainParams(CBaseChainParams::REGTEST);
|
||||
QVERIFY("blackcoin" == GUIUtil::bitcoinURIScheme(config));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,10 @@ class URITests : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void uriTests();
|
||||
void uriTestsBase58();
|
||||
void uriTestsCashAddr();
|
||||
void uriTestFormatURI();
|
||||
void uriTestScheme();
|
||||
};
|
||||
|
||||
#endif // BITCOIN_QT_TEST_URITESTS_H
|
||||
|
||||
@@ -8,9 +8,8 @@
|
||||
#include "guiutil.h"
|
||||
#include "paymentserver.h"
|
||||
#include "transactionrecord.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "consensus/consensus.h"
|
||||
#include "dstencode.h"
|
||||
#include "main.h"
|
||||
#include "script/script.h"
|
||||
#include "timedata.h"
|
||||
@@ -91,9 +90,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
if (nNet > 0)
|
||||
{
|
||||
// Credit
|
||||
if (CBitcoinAddress(rec->address).IsValid())
|
||||
CTxDestination address = DecodeDestination(rec->address);
|
||||
if (IsValidDestination(address))
|
||||
{
|
||||
CTxDestination address = CBitcoinAddress(rec->address).Get();
|
||||
if (wallet->mapAddressBook.count(address))
|
||||
{
|
||||
strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
|
||||
@@ -118,7 +117,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
// Online transaction
|
||||
std::string strAddress = wtx.mapValue["to"];
|
||||
strHTML += "<b>" + tr("To") + ":</b> ";
|
||||
CTxDestination dest = CBitcoinAddress(strAddress).Get();
|
||||
CTxDestination dest = DecodeDestination(strAddress);
|
||||
if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].name.empty())
|
||||
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest].name) + " ";
|
||||
strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
|
||||
@@ -189,7 +188,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
strHTML += "<b>" + tr("To") + ":</b> ";
|
||||
if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
|
||||
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
|
||||
strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
|
||||
strHTML += GUIUtil::HtmlEscape(EncodeDestination(address));
|
||||
if(toSelf == ISMINE_SPENDABLE)
|
||||
strHTML += " (own address)";
|
||||
else if(toSelf & ISMINE_WATCH_ONLY)
|
||||
@@ -243,10 +242,12 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
strHTML += "<b>" + tr("Transaction ID") + ":</b> " + rec->getTxID() + "<br>";
|
||||
strHTML += "<b>" + tr("Output index") + ":</b> " + QString::number(rec->getOutputIndex()) + "<br>";
|
||||
|
||||
// Message from normal bitcoin:URI (bitcoin:123...?message=example)
|
||||
Q_FOREACH (const PAIRTYPE(std::string, std::string)& r, wtx.vOrderForm)
|
||||
// Message from normal blackcoin:URI (blackcoin:123...?message=example)
|
||||
for (const std::pair<std::string, std::string> &r : wtx.vOrderForm)
|
||||
{
|
||||
if (r.first == "Message")
|
||||
strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>";
|
||||
}
|
||||
|
||||
//
|
||||
// PaymentRequest info:
|
||||
@@ -304,7 +305,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
{
|
||||
if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
|
||||
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
|
||||
strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
|
||||
strHTML += QString::fromStdString(EncodeDestination(address));
|
||||
}
|
||||
strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatHtmlWithUnit(unit, vout.nValue);
|
||||
strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + "</li>";
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "transactionrecord.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "dstencode.h"
|
||||
#include "consensus/consensus.h"
|
||||
#include "main.h"
|
||||
#include "timedata.h"
|
||||
@@ -61,7 +62,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
|
||||
{
|
||||
// Received by Bitcoin Address
|
||||
sub.type = TransactionRecord::RecvWithAddress;
|
||||
sub.address = CBitcoinAddress(address).ToString();
|
||||
sub.address = EncodeDestination(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -140,7 +141,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
|
||||
{
|
||||
// Sent to Bitcoin Address
|
||||
sub.type = TransactionRecord::SendToAddress;
|
||||
sub.address = CBitcoinAddress(address).ToString();
|
||||
sub.address = EncodeDestination(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
|
||||
WalletFrame::WalletFrame(const PlatformStyle *platformStyle, BitcoinGUI *_gui) :
|
||||
WalletFrame::WalletFrame(const PlatformStyle *platformStyle, const Config *cfg, BitcoinGUI *_gui) :
|
||||
QFrame(_gui),
|
||||
gui(_gui),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(platformStyle),
|
||||
cfg(cfg)
|
||||
{
|
||||
// Leave HBox hook for adding a list view later
|
||||
QHBoxLayout *walletFrameLayout = new QHBoxLayout(this);
|
||||
@@ -43,7 +44,7 @@ bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel)
|
||||
if (!gui || !clientModel || !walletModel || mapWalletViews.count(name) > 0)
|
||||
return false;
|
||||
|
||||
WalletView *walletView = new WalletView(platformStyle, this);
|
||||
WalletView *walletView = new WalletView(platformStyle, cfg, this);
|
||||
walletView->setBitcoinGUI(gui);
|
||||
walletView->setClientModel(clientModel);
|
||||
walletView->setWalletModel(walletModel);
|
||||
|
||||
@@ -14,6 +14,7 @@ class PlatformStyle;
|
||||
class SendCoinsRecipient;
|
||||
class WalletModel;
|
||||
class WalletView;
|
||||
class Config;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QStackedWidget;
|
||||
@@ -24,7 +25,7 @@ class WalletFrame : public QFrame
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WalletFrame(const PlatformStyle *platformStyle, BitcoinGUI *_gui = 0);
|
||||
explicit WalletFrame(const PlatformStyle *platformStyle, const Config *cfg, BitcoinGUI *_gui = 0);
|
||||
~WalletFrame();
|
||||
|
||||
void setClientModel(ClientModel *clientModel);
|
||||
@@ -47,6 +48,7 @@ private:
|
||||
bool bOutOfSync;
|
||||
|
||||
const PlatformStyle *platformStyle;
|
||||
const Config *cfg;
|
||||
|
||||
WalletView *currentWalletView();
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
#include "paymentserver.h"
|
||||
#include "recentrequeststablemodel.h"
|
||||
#include "transactiontablemodel.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "dstencode.h"
|
||||
#include "keystore.h"
|
||||
#include "main.h"
|
||||
#include "sync.h"
|
||||
@@ -183,11 +182,7 @@ void WalletModel::updateWatchOnlyFlag(bool fHaveWatchonly)
|
||||
Q_EMIT notifyWatchonlyChanged(fHaveWatchonly);
|
||||
}
|
||||
|
||||
bool WalletModel::validateAddress(const QString &address)
|
||||
{
|
||||
CBitcoinAddress addressParsed(address.toStdString());
|
||||
return addressParsed.IsValid();
|
||||
}
|
||||
bool WalletModel::validateAddress(const QString &address) { return IsValidDestinationString(address.toStdString()); }
|
||||
|
||||
WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl)
|
||||
{
|
||||
@@ -244,14 +239,14 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
|
||||
setAddress.insert(rcp.address);
|
||||
++nAddresses;
|
||||
|
||||
CScript scriptPubKey = GetScriptForDestination(CBitcoinAddress(rcp.address.toStdString()).Get());
|
||||
CScript scriptPubKey = GetScriptForDestination(DecodeDestination(rcp.address.toStdString()));
|
||||
CRecipient recipient = {scriptPubKey, rcp.amount, rcp.fSubtractFeeFromAmount};
|
||||
vecSend.push_back(recipient);
|
||||
|
||||
total += rcp.amount;
|
||||
}
|
||||
}
|
||||
if(setAddress.size() != nAddresses)
|
||||
if (setAddress.size() != nAddresses)
|
||||
{
|
||||
return DuplicateAddress;
|
||||
}
|
||||
@@ -323,7 +318,13 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
|
||||
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)
|
||||
else if (!rcp.message.isEmpty())
|
||||
{
|
||||
// Message from normal blackcoin:URI
|
||||
// (blackcoin:123...?message=example)
|
||||
newTx->vOrderForm.push_back(make_pair("Message", rcp.message.toStdString()));
|
||||
}
|
||||
else if (!rcp.message.isEmpty()) // Message from normal blackcoin:URI (blackcoin:123...?message=example)
|
||||
newTx->vOrderForm.push_back(make_pair("Message", rcp.message.toStdString()));
|
||||
}
|
||||
|
||||
@@ -345,7 +346,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
|
||||
if (!rcp.paymentRequest.IsInitialized())
|
||||
{
|
||||
std::string strAddress = rcp.address.toStdString();
|
||||
CTxDestination dest = CBitcoinAddress(strAddress).Get();
|
||||
CTxDestination dest = DecodeDestination(strAddress);
|
||||
std::string strLabel = rcp.label.toStdString();
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
@@ -461,7 +462,7 @@ static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
|
||||
const CTxDestination &address, const std::string &label, bool isMine,
|
||||
const std::string &purpose, ChangeType status)
|
||||
{
|
||||
QString strAddress = QString::fromStdString(CBitcoinAddress(address).ToString());
|
||||
QString strAddress = QString::fromStdString(EncodeDestination(address));
|
||||
QString strLabel = QString::fromStdString(label);
|
||||
QString strPurpose = QString::fromStdString(purpose);
|
||||
|
||||
@@ -566,11 +567,7 @@ bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
|
||||
return wallet->GetPubKey(address, vchPubKeyOut);
|
||||
}
|
||||
|
||||
bool WalletModel::havePrivKey(const CKeyID &address) const
|
||||
{
|
||||
return wallet->HaveKey(address);
|
||||
}
|
||||
|
||||
bool WalletModel::IsSpendable(const CTxDestination &dest) const { return wallet->IsMine(dest) & ISMINE_SPENDABLE; }
|
||||
// returns a list of COutputs from COutPoints
|
||||
void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs)
|
||||
{
|
||||
@@ -625,7 +622,7 @@ void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins)
|
||||
CTxDestination address;
|
||||
if(!out.fSpendable || !ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address))
|
||||
continue;
|
||||
mapCoins[QString::fromStdString(CBitcoinAddress(address).ToString())].push_back(out);
|
||||
mapCoins[QString::fromStdString(EncodeDestination(address))].push_back(out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -664,7 +661,7 @@ void WalletModel::loadReceiveRequests(std::vector<std::string>& vReceiveRequests
|
||||
|
||||
bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest)
|
||||
{
|
||||
CTxDestination dest = CBitcoinAddress(sAddress).Get();
|
||||
CTxDestination dest = DecodeDestination(sAddress);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << nId;
|
||||
|
||||
@@ -187,7 +187,7 @@ public:
|
||||
UnlockContext requestUnlock();
|
||||
|
||||
bool getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
|
||||
bool havePrivKey(const CKeyID &address) const;
|
||||
bool IsSpendable(const CTxDestination &dest) const;
|
||||
void getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs);
|
||||
bool isSpent(const COutPoint& outpoint) const;
|
||||
void listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const;
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
WalletView::WalletView(const PlatformStyle *platformStyle, QWidget *parent):
|
||||
WalletView::WalletView(const PlatformStyle *_platformStyle, const Config *cfg, QWidget *parent):
|
||||
QStackedWidget(parent),
|
||||
clientModel(0),
|
||||
walletModel(0),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(_platformStyle)
|
||||
{
|
||||
// Create tabs
|
||||
overviewPage = new OverviewPage(platformStyle);
|
||||
@@ -53,7 +53,7 @@ WalletView::WalletView(const PlatformStyle *platformStyle, QWidget *parent):
|
||||
vbox->addLayout(hbox_buttons);
|
||||
transactionsPage->setLayout(vbox);
|
||||
|
||||
receiveCoinsPage = new ReceiveCoinsDialog(platformStyle);
|
||||
receiveCoinsPage = new ReceiveCoinsDialog(platformStyle, cfg);
|
||||
sendCoinsPage = new SendCoinsDialog(platformStyle);
|
||||
|
||||
usedSendingAddressesPage = new AddressBookPage(platformStyle, AddressBookPage::ForEditing, AddressBookPage::SendingTab, this);
|
||||
|
||||
@@ -19,6 +19,7 @@ class SendCoinsRecipient;
|
||||
class TransactionView;
|
||||
class WalletModel;
|
||||
class AddressBookPage;
|
||||
class Config;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QModelIndex;
|
||||
@@ -36,7 +37,7 @@ class WalletView : public QStackedWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WalletView(const PlatformStyle *platformStyle, QWidget *parent);
|
||||
explicit WalletView(const PlatformStyle *platformStyle, const Config *cfg, QWidget *parent);
|
||||
~WalletView();
|
||||
|
||||
void setBitcoinGUI(BitcoinGUI *gui);
|
||||
|
||||
Reference in New Issue
Block a user