Browse Source

SilentDragonX

Add support to SD for DragonX. Currently there is no UI for switching
between coins and SD does not render data for multiple coins at one time.
Everything works based on the name of the binary that is used to start
the wallet. If the binary is named "silentdragonx" then the code will
connect to the DragonX full node instead of the Hush full node.

SDX has it's own log file and stores data in it's own files, so it is
possible to run SD and SDX at the same time.

Currently the images, icons and translations still need to be customized
for DragonX.

To compile run ./build-sdx.sh and then run ./silentdragonx
pull/112/head
Duke 1 year ago
parent
commit
443a07e676
  1. 4
      .gitignore
  2. 11
      README.md
  3. 20
      build-sdx.sh
  4. 2
      build.sh
  5. 168
      silentdragonx.pro
  6. 4
      src/addressbook.cpp
  7. 78
      src/connection.cpp
  8. 2
      src/createhushconfdialog.ui
  9. 24
      src/main.cpp
  10. 75
      src/mainwindow.cpp
  11. 26
      src/mainwindow.ui
  12. 13
      src/requestdialog.cpp
  13. 2
      src/requestdialog.ui
  14. 41
      src/rpc.cpp
  15. 5
      src/senttxstore.cpp
  16. 29
      src/settings.cpp
  17. 4
      src/settings.ui
  18. 19
      src/txtablemodel.cpp

4
.gitignore

@ -7,7 +7,7 @@ docs/website/public
hushd hushd
IDEWorkspaceChecks.plist IDEWorkspaceChecks.plist
hush-cli hush-cli
hushd dragonxd
*.mak *.mak
Makefile Makefile
Makefile.* Makefile.*
@ -18,7 +18,7 @@ res/libsodium.a
res/libsodium.a res/libsodium.a
res/libsodium/libsodium* res/libsodium/libsodium*
silentdragon silentdragon
silentdragon silentdragonx
silentdragon.pro.user silentdragon.pro.user
*.sln *.sln
src/precompiled.h.cpp src/precompiled.h.cpp

11
README.md

@ -142,6 +142,17 @@ make
./SilentDragon.app/Contents/MacOS/SilentDragon ./SilentDragon.app/Contents/MacOS/SilentDragon
``` ```
### Building SilentDragonX
```
git clone https://git.hush.is/hush/SilentDragon
cd SilentDragon
./build-sdx.sh
```
The binary will be called `silentdragonx`
### Emulating the embedded node ### Emulating the embedded node
In binary releases, SilentDragon will use node binaries in the current directory to sync a node from scratch. In binary releases, SilentDragon will use node binaries in the current directory to sync a node from scratch.

20
build-sdx.sh

@ -0,0 +1,20 @@
#!/bin/bash
# Copyright 2018-2023 The Hush Developers
# Released under the GPLv3
# This builds a binary called "silentdragonx"
set -e
if [ -e dragonxd ]; then
echo "Found dragonxd binary"
else
echo "dragonxd could not be found!"
echo "Either copy the binary to this dir or make a symlink."
echo "This command will create a symlink to it if this repo is in the same directory as your hush3.git: "
echo "ln -s ../hush3/src/dragonxd"
exit 1
fi
# Use a modified QT project file with same build.sh
SDCONF=silentdragonx.pro ./build.sh

2
build.sh

@ -17,7 +17,7 @@ fi
VERSION=$(cat src/version.h |cut -d\" -f2) VERSION=$(cat src/version.h |cut -d\" -f2)
echo "Compiling SilentDragon $VERSION with $JOBS threads..." echo "Compiling SilentDragon $VERSION with $JOBS threads..."
CONF=silentdragon.pro CONF=${SDCONF:-silentdragon.pro}
if ! command -v qmake &> /dev/null if ! command -v qmake &> /dev/null
then then

168
silentdragonx.pro

@ -0,0 +1,168 @@
# Copyright 2018-2023 The Hush Developers
# Released under the GPLv3
QT += core gui network
CONFIG += precompile_header
PRECOMPILED_HEADER = src/precompiled.h
QT += widgets
QT += websockets
TARGET = silentdragonx
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += \
QT_DEPRECATED_WARNINGS
INCLUDEPATH += src/3rdparty/
INCLUDEPATH += src/
mac: LIBS+= -Wl,-dead_strip
mac: LIBS+= -Wl,-dead_strip_dylibs
mac: LIBS+= -Wl,-bind_at_load
RESOURCES = application.qrc
MOC_DIR = bin
OBJECTS_DIR = bin
UI_DIR = src
CONFIG += c++14
SOURCES += \
src/main.cpp \
src/mainwindow.cpp \
src/rpc.cpp \
src/balancestablemodel.cpp \
src/3rdparty/qrcode/BitBuffer.cpp \
src/3rdparty/qrcode/QrCode.cpp \
src/3rdparty/qrcode/QrSegment.cpp \
src/settings.cpp \
src/sendtab.cpp \
src/senttxstore.cpp \
src/txtablemodel.cpp \
src/peerstablemodel.cpp \
src/bannedpeerstablemodel.cpp \
src/qrcodelabel.cpp \
src/connection.cpp \
src/fillediconlabel.cpp \
src/addressbook.cpp \
src/logger.cpp \
src/addresscombo.cpp \
src/validateaddress.cpp \
src/websockets.cpp \
src/mobileappconnector.cpp \
src/recurring.cpp \
src/requestdialog.cpp \
src/memoedit.cpp \
src/viewalladdresses.cpp
HEADERS += \
src/guiconstants.h \
src/mainwindow.h \
src/precompiled.h \
src/rpc.h \
src/balancestablemodel.h \
src/3rdparty/qrcode/BitBuffer.hpp \
src/3rdparty/qrcode/QrCode.hpp \
src/3rdparty/qrcode/QrSegment.hpp \
src/settings.h \
src/txtablemodel.h \
src/peerstablemodel.h \
src/bannedpeerstablemodel.h \
src/senttxstore.h \
src/qrcodelabel.h \
src/connection.h \
src/fillediconlabel.h \
src/addressbook.h \
src/logger.h \
src/addresscombo.h \
src/validateaddress.h \
src/websockets.h \
src/mobileappconnector.h \
src/recurring.h \
src/requestdialog.h \
src/memoedit.h \
src/viewalladdresses.h
FORMS += \
src/mainwindow.ui \
src/qrcode.ui \
src/rescandialog.ui \
src/settings.ui \
src/about.ui \
src/confirm.ui \
src/privkey.ui \
src/viewkey.ui \
src/memodialog.ui \
src/viewalladdresses.ui \
src/validateaddress.ui \
src/viewalladdresses.ui \
src/connection.ui \
src/addressbook.ui \
src/viewalladdresses.ui \
src/mobileappconnector.ui \
src/createhushconfdialog.ui \
src/recurringdialog.ui \
src/newrecurring.ui \
src/requestdialog.ui
TRANSLATIONS = res-drgx/silentdragon_be.ts \
res-drgx/silentdragon_bg.ts \
res-drgx/silentdragon_de.ts \
res-drgx/silentdragon_es.ts \
res-drgx/silentdragon_fi.ts \
res-drgx/silentdragon_fil.ts \
res-drgx/silentdragon_fr.ts \
res-drgx/silentdragon_hr.ts \
res-drgx/silentdragon_id.ts \
res-drgx/silentdragon_it.ts \
res-drgx/silentdragon_nl.ts \
res-drgx/silentdragon_pl.ts \
res-drgx/silentdragon_pt.ts \
res-drgx/silentdragon_ro.ts \
res-drgx/silentdragon_ru.ts \
res-drgx/silentdragon_sr.ts \
res-drgx/silentdragon_tr.ts \
res-drgx/silentdragon_uk.ts \
res-drgx/silentdragon_zh.ts
include(singleapplication/singleapplication.pri)
DEFINES += QAPPLICATION_CLASS=QApplication _FORTIFY_SOURCE=2
QMAKE_INFO_PLIST = res/Info.plist
win32: RC_ICONS = res/icon.ico
ICON = res/logo.icns
libsodium.target = $$PWD/res/libsodium.a
libsodium.commands = res/libsodium/buildlibsodium.sh
QMAKE_EXTRA_TARGETS += libsodium
QMAKE_CLEAN += res/libsodium.a
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/res/ -llibsodium
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/res/ -llibsodiumd
else:unix: LIBS += -L$$PWD/res/ -lsodium
INCLUDEPATH += $$PWD/res
DEPENDPATH += $$PWD/res
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/res/liblibsodium.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/res/liblibsodium.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/res/libsodium.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/res/libsodiumd.lib
else:unix: PRE_TARGETDEPS += $$PWD/res/libsodium.a

4
src/addressbook.cpp

@ -7,6 +7,7 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "rpc.h" #include "rpc.h"
extern bool isdragonx;
AddressBookModel::AddressBookModel(QTableView *parent) AddressBookModel::AddressBookModel(QTableView *parent)
: QAbstractTableModel(parent) { : QAbstractTableModel(parent) {
@ -293,6 +294,9 @@ void AddressBook::writeToStorage() {
QString AddressBook::writeableFile() { QString AddressBook::writeableFile() {
auto filename = QStringLiteral("addresslabels.dat"); auto filename = QStringLiteral("addresslabels.dat");
if (isdragonx) {
filename = QStringLiteral("addresslabels-drgx.dat");
}
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
if (!dir.exists()) if (!dir.exists())

78
src/connection.cpp

@ -1,4 +1,4 @@
// Copyright 2019-2022 The Hush developers // Copyright 2019-2023 The Hush developers
// Released under the GPLv3 // Released under the GPLv3
#include "connection.h" #include "connection.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -9,6 +9,8 @@
#include "precompiled.h" #include "precompiled.h"
#include "version.h" #include "version.h"
extern bool isdragonx;
ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) { ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) {
qDebug() << __func__; qDebug() << __func__;
this->main = main; this->main = main;
@ -92,11 +94,23 @@ void ConnectionLoader::doAutoConnect(bool tryEhushdStart) {
"with SilentDragon\n\n." "with SilentDragon\n\n."
"Please remove the following line from your HUSH3.conf and restart SilentDragon\n" "Please remove the following line from your HUSH3.conf and restart SilentDragon\n"
"daemon=1"); "daemon=1");
if (isdragonx) {
explanation = QString() % QObject::tr("You have dragonxd set to start as a daemon, which can cause problems "
"with SilentDragonX\n\n."
"Please remove the following line from your DRAGONX.conf and restart SilentDragonX\n"
"daemon=1");
}
} else { } else {
explanation = QString() % QObject::tr("Couldn't start the embedded hushd.\n\n" explanation = QString() % QObject::tr("Couldn't start the embedded hushd.\n\n"
"Please try restarting.\n\nIf you previously started hushd with custom arguments, you might need to reset HUSH3.conf.\n\n" "Please try restarting.\n\nIf you previously started hushd with custom arguments, you might need to reset HUSH3.conf.\n\n"
"If all else fails, please run hushd manually.") % "If all else fails, please run hushd manually.") %
(ehushd ? QObject::tr("The process returned") + ":\n\n" % ehushd->errorString() : QString("")); (ehushd ? QObject::tr("The process returned") + ":\n\n" % ehushd->errorString() : QString(""));
if(isdragonx) {
explanation = QString() % QObject::tr("Couldn't start the embedded dragonxd.\n\n"
"Please try restarting.\n\nIf you previously started hushd with custom arguments, you might need to reset DRAGONX.conf.\n\n"
"If all else fails, please run dragonxd manually.") %
(ehushd ? QObject::tr("The process returned") + ":\n\n" % ehushd->errorString() : QString(""));
}
} }
this->showError(explanation); this->showError(explanation);
@ -106,6 +120,11 @@ void ConnectionLoader::doAutoConnect(bool tryEhushdStart) {
main->logger->write("Not using embedded and couldn't connect to hushd"); main->logger->write("Not using embedded and couldn't connect to hushd");
QString explanation = QString() % QObject::tr("Couldn't connect to hushd configured in HUSH3.conf.\n\n" QString explanation = QString() % QObject::tr("Couldn't connect to hushd configured in HUSH3.conf.\n\n"
"Not starting embedded hushd because --no-embedded was passed"); "Not starting embedded hushd because --no-embedded was passed");
if(isdragonx) {
main->logger->write("Not using embedded and couldn't connect to dragonxd");
QString explanation = QString() % QObject::tr("Couldn't connect to dragonxd configured in DRAGONX.conf.\n\n"
"Not starting embedded dragonxd because --no-embedded was passed");
}
this->showError(explanation); this->showError(explanation);
} }
}); });
@ -189,9 +208,9 @@ void ConnectionLoader::createHushConf() {
QFile file(confLocation); QFile file(confLocation);
if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) { if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
main->logger->write("Could not create HUSH3.conf, returning"); QString explanation = QString() % (isdragonx ? QObject::tr("Could not create DRAGONX.conf.") : QObject::tr("Could not create HUSH3.conf.") );
main->logger->write(explanation);
QString explanation = QString() % QObject::tr("Could not create HUSH3.conf.");
this->showError(explanation); this->showError(explanation);
return; return;
} }
@ -346,23 +365,27 @@ bool ConnectionLoader::startEmbeddedHushd() {
#ifdef Q_OS_WIN64 #ifdef Q_OS_WIN64
auto hushdProgram = appPath.absoluteFilePath("hushd.exe"); auto hushdProgram = appPath.absoluteFilePath("hushd.exe");
// params for DRGX are handled below
#else #else
auto hushdProgram = appPath.absoluteFilePath("hushd"); auto hushdProgram = appPath.absoluteFilePath("hushd");
if (isdragonx) {
hushdProgram = appPath.absoluteFilePath("dragonxd");
}
#endif #endif
//if (!QFile(hushdProgram).exists()) { //if (!QFile(hushdProgram).exists()) {
if (!QFile::exists(hushdProgram)) { if (!QFile::exists(hushdProgram)) {
qDebug() << "Can't find hushd at " << hushdProgram; qDebug() << "Can't find binary at " << hushdProgram;
main->logger->write("Can't find hushd at " + hushdProgram); main->logger->write("Can't find binary at " + hushdProgram);
return false; return false;
} else { } else {
qDebug() << "Found hushd at " << hushdProgram; qDebug() << "Found binary at " << hushdProgram;
main->logger->write("Found hushd at " + hushdProgram); main->logger->write("Found binary at " + hushdProgram);
} }
ehushd = std::shared_ptr<QProcess>(new QProcess(main)); ehushd = std::shared_ptr<QProcess>(new QProcess(main));
QObject::connect(ehushd.get(), &QProcess::started, [=] () { QObject::connect(ehushd.get(), &QProcess::started, [=] () {
qDebug() << "Embedded hushd started via " << hushdProgram; qDebug() << "Embedded binary started via " << hushdProgram;
}); });
QObject::connect(ehushd.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), QObject::connect(ehushd.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
@ -396,6 +419,10 @@ bool ConnectionLoader::startEmbeddedHushd() {
qDebug() << "No ASN map file found"; qDebug() << "No ASN map file found";
} }
*/ */
if(isdragonx) {
// dragonxd bash script cannot be used on windows, so specify exact chain params
params += " -ac_name=DRAGONX -ac_algo=randomx -ac_halving=3500000 -ac_reward=300000000 -ac_blocktime=36 -ac_private=1 -addnode=176.126.87.241 ";
}
QStringList arguments = params.split(" "); QStringList arguments = params.split(" ");
@ -557,6 +584,21 @@ void ConnectionLoader::showError(QString explanation) {
} }
QString ConnectionLoader::locateHushConfFile() { QString ConnectionLoader::locateHushConfFile() {
// HSC's have no legacy locations
if (isdragonx) {
auto ticker = "DRAGONX";
#ifdef Q_OS_LINUX
auto confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, QString(".hush/") + ticker + "/" + ticker + ".conf");
#elif defined(Q_OS_DARWIN)
auto confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, "Library/Application Support/Hush/HUSH3/HUSH3.conf");
#else
auto confLocation = QStandardPaths::locate(QStandardPaths::AppDataLocation, "../../Hush/HUSH3/HUSH3.conf");
#endif
qDebug() << "found conf at " << confLocation;
return QDir::cleanPath(confLocation);
}
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
auto confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, ".hush/HUSH3/HUSH3.conf"); auto confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, ".hush/HUSH3/HUSH3.conf");
if(!QFile(confLocation).exists()) { if(!QFile(confLocation).exists()) {
@ -585,10 +627,19 @@ QString ConnectionLoader::locateHushConfFile() {
QString ConnectionLoader::hushConfWritableLocation() { QString ConnectionLoader::hushConfWritableLocation() {
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(".hush/HUSH3/HUSH3.conf"); auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(".hush/HUSH3/HUSH3.conf");
if(isdragonx) {
confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(".hush/DRAGONX/DRAGONX.conf");
}
#elif defined(Q_OS_DARWIN) #elif defined(Q_OS_DARWIN)
auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath("Library/Application Support/Hush/HUSH3/HUSH3.conf"); auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath("Library/Application Support/Hush/HUSH3/HUSH3.conf");
if(isdragonx) {
confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath("Library/Application Support/Hush/DRAGONX/DRAGONX.conf");
}
#else #else
auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("../../Hush/HUSH3/HUSH3.conf"); auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("../../Hush/HUSH3/HUSH3.conf");
if(isdragonx) {
confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("../../Hush/DRAGONX/DRAGONX.conf");
}
#endif #endif
main->logger->write("HUSH3.conf writeable location at " + QDir::cleanPath(confLocation)); main->logger->write("HUSH3.conf writeable location at " + QDir::cleanPath(confLocation));
@ -663,7 +714,8 @@ bool ConnectionLoader::verifyParams() {
} }
/** /**
* Try to automatically detect a HUSH3/HUSH3.conf file in the correct location and load parameters * Try to automatically detect a HUSH3/HUSH3.conf file
or DRAGONX/DRAGONX.conf in the correct location and load parameters
*/ */
std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectHushConf() { std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectHushConf() {
auto confLocation = locateHushConfFile(); auto confLocation = locateHushConfFile();
@ -728,7 +780,13 @@ std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectHushConf() {
} }
// If rpcport is not in the file, and it was not set by the testnet=1 flag, then go to default // If rpcport is not in the file, and it was not set by the testnet=1 flag, then go to default
if (hushconf->port.isEmpty()) hushconf->port = "18031"; if (hushconf->port.isEmpty()) {
if(isdragonx) {
hushconf->port = "21769";
} else {
hushconf->port = "18031";
}
}
file.close(); file.close();
// Save to Qsettings // Save to Qsettings

2
src/createhushconfdialog.ui

@ -11,7 +11,7 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Configure HUSH3.conf</string> <string>Configuration</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="1"> <item row="0" column="1">

24
src/main.cpp

@ -7,6 +7,8 @@
#include "settings.h" #include "settings.h"
#include "version.h" #include "version.h"
bool isdragonx = 0;
class SignalHandler class SignalHandler
{ {
public: public:
@ -140,6 +142,14 @@ public:
~Application() {} ~Application() {}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
fprintf(stderr,"%s: argv0 = %s\n", __func__, argv[0]);
QString binaryName(argv[0]);
QStringList pathParts = binaryName.split(QLatin1Char('/'));
qDebug() << pathParts;
isdragonx = binaryName.endsWith("dragonx") || binaryName.endsWith("dragonx.exe");
qDebug() << "isdragonx=" << isdragonx;
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
@ -173,14 +183,18 @@ public:
} }
QCoreApplication::setOrganizationName("Hush"); QCoreApplication::setOrganizationName("Hush");
QCoreApplication::setApplicationName("SilentDragon"); QCoreApplication::setApplicationName(isdragonx ? "SilentDragonX" : "SilentDragon");
QString locale = QLocale::system().name(); QString locale = QLocale::system().name();
locale.truncate(locale.lastIndexOf('_')); // Get the language code locale.truncate(locale.lastIndexOf('_')); // Get the language code
qDebug() << "Loading locale " << locale; qDebug() << "Loading locale " << locale;
QTranslator translator; QTranslator translator;
translator.load(QString(":/translations/res/silentdragon_") + locale); if(isdragonx) {
translator.load(QString(":/translations/res-drgx/silentdragon_") + locale);
} else {
translator.load(QString(":/translations/res/silentdragon_") + locale);
}
a.installTranslator(&translator); a.installTranslator(&translator);
QIcon icon(":/icons/res/icon.ico"); QIcon icon(":/icons/res/icon.ico");
@ -218,7 +232,11 @@ public:
} }
w = new MainWindow(); w = new MainWindow();
w->setWindowTitle("SilentDragon v" + QString(APP_VERSION)); if(isdragonx) {
w->setWindowTitle("SilentDragonX v" + QString(APP_VERSION));
} else {
w->setWindowTitle("SilentDragon v" + QString(APP_VERSION));
}
// If there was a payment URI on the command line, pay it // If there was a payment URI on the command line, pay it
if (parser.positionalArguments().length() > 0) { if (parser.positionalArguments().length() > 0) {

75
src/mainwindow.cpp

@ -24,6 +24,8 @@
#include "requestdialog.h" #include "requestdialog.h"
#include "websockets.h" #include "websockets.h"
extern bool isdragonx;
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
ui(new Ui::MainWindow) ui(new Ui::MainWindow)
@ -42,7 +44,7 @@ MainWindow::MainWindow(QWidget *parent) :
this->slot_change_theme(theme_name); this->slot_change_theme(theme_name);
ui->setupUi(this); ui->setupUi(this);
logger = new Logger(this, QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("SilentDragon.log")); logger = new Logger(this, QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath(isdragonx ? "SilentDragonX.log" : "SilentDragon.log"));
// Status Bar // Status Bar
setupStatusBar(); setupStatusBar();
@ -52,7 +54,6 @@ MainWindow::MainWindow(QWidget *parent) :
// Set up actions // Set up actions
QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close); QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close);
QObject::connect(ui->actionDonate, &QAction::triggered, this, &MainWindow::donate);
QObject::connect(ui->actionTelegram, &QAction::triggered, this, &MainWindow::telegram); QObject::connect(ui->actionTelegram, &QAction::triggered, this, &MainWindow::telegram);
QObject::connect(ui->actionReportBug, &QAction::triggered, this, &MainWindow::reportbug); QObject::connect(ui->actionReportBug, &QAction::triggered, this, &MainWindow::reportbug);
QObject::connect(ui->actionWebsite, &QAction::triggered, this, &MainWindow::website); QObject::connect(ui->actionWebsite, &QAction::triggered, this, &MainWindow::website);
@ -527,7 +528,7 @@ void MainWindow::setupSettingsModal() {
settings.rpcuser->setReadOnly(true); settings.rpcuser->setReadOnly(true);
settings.rpcpassword->setReadOnly(true); settings.rpcpassword->setReadOnly(true);
} else { } else {
settings.confMsg->setText("No local HUSH3.conf found. Please configure connection manually."); settings.confMsg->setText("No " % hushConfLocation % " found. Please configure connection manually.");
settings.hostname->setEnabled(true); settings.hostname->setEnabled(true);
settings.port->setEnabled(true); settings.port->setEnabled(true);
settings.rpcuser->setEnabled(true); settings.rpcuser->setEnabled(true);
@ -789,33 +790,26 @@ void MainWindow::addressBook() {
void MainWindow::telegram() { void MainWindow::telegram() {
QString url = "https://hush.is/tg"; QString url = "https://hush.is/tg";
if (isdragonx) {
url = "https://dragonx.is/tg";
}
QDesktopServices::openUrl(QUrl(url)); QDesktopServices::openUrl(QUrl(url));
} }
void MainWindow::reportbug() { void MainWindow::reportbug() {
// dragonx doesn't have it's own support, for now
QString url = "https://hush.is/tg_support"; QString url = "https://hush.is/tg_support";
QDesktopServices::openUrl(QUrl(url)); QDesktopServices::openUrl(QUrl(url));
} }
void MainWindow::website() { void MainWindow::website() {
QString url = "https://hush.is"; QString url = "https://hush.is";
if (isdragonx) {
url = "https://dragonx.is";
}
QDesktopServices::openUrl(QUrl(url)); QDesktopServices::openUrl(QUrl(url));
} }
void MainWindow::donate() {
removeExtraAddresses();
ui->Address1->setText(Settings::getDonationAddr());
ui->Address1->setCursorPosition(0);
ui->Amount1->setText("0.00");
ui->MemoTxt1->setText(tr("Some feedback about SilentDragon or Hush..."));
ui->statusBar->showMessage(tr("Send Duke some private and shielded feedback about ") % Settings::getTokenName() % tr(" or SilentDragon"));
// And switch to the send tab.
ui->tabWidget->setCurrentIndex(1);
}
// Validate an address // Validate an address
void MainWindow::validateAddress() { void MainWindow::validateAddress() {
// Make sure everything is up and running // Make sure everything is up and running
@ -940,6 +934,10 @@ void MainWindow::payHushURI(QString uri, QString myAddr) {
if (uri.isEmpty()) { if (uri.isEmpty()) {
uri = QInputDialog::getText(this, tr("Paste HUSH URI"), uri = QInputDialog::getText(this, tr("Paste HUSH URI"),
"HUSH URI" + QString(" ").repeated(180)); "HUSH URI" + QString(" ").repeated(180));
if(isdragonx) {
uri = QInputDialog::getText(this, tr("Paste DRGX URI"),
"DRGX URI" + QString(" ").repeated(180));
}
} }
// If there's no URI, just exit // If there's no URI, just exit
@ -950,8 +948,13 @@ void MainWindow::payHushURI(QString uri, QString myAddr) {
qDebug() << "Received URI " << uri; qDebug() << "Received URI " << uri;
PaymentURI paymentInfo = Settings::parseURI(uri); PaymentURI paymentInfo = Settings::parseURI(uri);
if (!paymentInfo.error.isEmpty()) { if (!paymentInfo.error.isEmpty()) {
QMessageBox::critical(this, tr("Error paying Hush URI"), if(isdragonx) {
QMessageBox::critical(this, tr("Error paying DragonX URI"),
tr("URI should be of the form 'drgx:<addr>?amt=x&memo=y") + "\n" + paymentInfo.error);
} else {
QMessageBox::critical(this, tr("Error paying Hush URI"),
tr("URI should be of the form 'hush:<addr>?amt=x&memo=y") + "\n" + paymentInfo.error); tr("URI should be of the form 'hush:<addr>?amt=x&memo=y") + "\n" + paymentInfo.error);
}
return; return;
} }
@ -1404,6 +1407,29 @@ void MainWindow::setupBalancesTab() {
}); });
} }
menu.addAction(tr("Shield mining funds to default zaddr"), [=] () {
auto defaultZaddr = rpc->getDefaultSaplingAddress();
QJsonArray params = QJsonArray {addr, defaultZaddr };
qDebug() << "Calling shieldCoinbase with params=" << params;
rpc->shieldCoinbase(params, [=](const QJsonValue& reply) {
QString shieldingValue = reply.toObject()["shieldingValue"].toString();
QString opid = reply.toObject()["opid"].toString();
auto remainingUTXOs = reply.toObject()["remainingUTXOs"].toInt();
qDebug() << "ShieldCoinbase reply=" << reply;
// By default we shield 50 blocks at a time
if(remainingUTXOs > 0) {
//TODO: more utxos to shield
}
ui->statusBar->showMessage(tr("Shielded") + shieldingValue + " HUSH in Mining funds to " + addr + " in opid " + opid, 3 * 1000);
}, [=](QString errStr) {
//error("", errStr);
qDebug() << "z_shieldcoinbase pooped:" << errStr;
if(errStr == "Could not find any coinbase funds to shield.") {
ui->statusBar->showMessage("No mining funds found to shield!");
}
});
});
menu.addAction(tr("View on block explorer"), [=] () { menu.addAction(tr("View on block explorer"), [=] () {
QString url; QString url;
auto explorer = Settings::getInstance()->getExplorer(); auto explorer = Settings::getInstance()->getExplorer();
@ -1435,6 +1461,7 @@ void MainWindow::setupBalancesTab() {
//TODO: should this be kept? //TODO: should this be kept?
menu.addAction(tr("Convert Address"), [=] () { menu.addAction(tr("Convert Address"), [=] () {
QString url; QString url;
// HUSH3 can be used for all HSC's since they all have the same address format
url = "https://dexstats.info/addressconverter.php?fromcoin=HUSH3&address=" + addr; url = "https://dexstats.info/addressconverter.php?fromcoin=HUSH3&address=" + addr;
QDesktopServices::openUrl(QUrl(url)); QDesktopServices::openUrl(QUrl(url));
}); });
@ -1609,23 +1636,23 @@ void MainWindow::setupPeersTab() {
}); });
/* /*
//grep 'BAN THRESHOLD EXCEEDED' ~/.komodo/HUSH3/debug.log //grep 'BAN THRESHOLD EXCEEDED' ~/.hush/HUSH3/debug.log
//grep Disconnected ... //grep Disconnected ...
QFile debuglog = ""; QFile debuglog = "";
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
debuglog = "~/.komodo/HUSH3/debug.log"; debuglog = "~/.hush/HUSH3/debug.log";
#elif defined(Q_OS_DARWIN) #elif defined(Q_OS_DARWIN)
debuglog = "~/Library/Application Support/Komodo/HUSH3/debug.log"; debuglog = "~/Library/Application Support/Hush/HUSH3/debug.log";
#elif defined(Q_OS_WIN64) #elif defined(Q_OS_WIN64)
// "C:/Users/<USER>/AppData/Roaming/<APPNAME>", // "C:/Users/<USER>/AppData/Roaming/<APPNAME>",
// TODO: get current username // TODO: get current username
debuglog = "C:/Users/<USER>/AppData/Roaming/Komodo/HUSH3/debug.log"; debuglog = "C:/Users/<USER>/AppData/Roaming/Hush/HUSH3/debug.log";
#else #else
// Bless Your Heart, You Like Danger! // Bless Your Heart, You Like Danger!
// There are open bounties to port HUSH softtware to OpenBSD and friends: // There are open bounties to port HUSH softtware to OpenBSD and friends:
// git.hush.is/hush/tasks // git.hush.is/hush/tasks
debuglog = "~/.komodo/HUSH3/debug.log"; debuglog = "~/.hush/HUSH3/debug.log";
#endif // Q_OS_LINUX #endif // Q_OS_LINUX
if(debuglog.exists()) { if(debuglog.exists()) {
@ -1801,7 +1828,7 @@ void MainWindow::setupTransactionsTab() {
*/ */
// Payment Request // Payment Request
if (!memo.isEmpty() && memo.startsWith("hush:")) { if (!memo.isEmpty() && memo.startsWith(isdragonx ? "drgx:" : "hush:")) {
menu.addAction(tr("View Payment Request"), [=] () { menu.addAction(tr("View Payment Request"), [=] () {
RequestDialog::showPaymentConfirmation(this, memo); RequestDialog::showPaymentConfirmation(this, memo);
}); });

26
src/mainwindow.ui

@ -1061,7 +1061,7 @@
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Hush Market Information&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Market Information&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -1132,7 +1132,7 @@
</widget> </widget>
<widget class="QWidget" name="tab_5"> <widget class="QWidget" name="tab_5">
<attribute name="title"> <attribute name="title">
<string>hushd</string> <string>Node info</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_7"> <layout class="QVBoxLayout" name="verticalLayout_7">
<item> <item>
@ -1609,7 +1609,6 @@
<property name="title"> <property name="title">
<string>&amp;Help</string> <string>&amp;Help</string>
</property> </property>
<addaction name="actionDonate"/>
<addaction name="actionTelegram"/> <addaction name="actionTelegram"/>
<addaction name="actionWebsite"/> <addaction name="actionWebsite"/>
<addaction name="actionCheck_for_Updates"/> <addaction name="actionCheck_for_Updates"/>
@ -1660,19 +1659,14 @@
<string>Ctrl+P</string> <string>Ctrl+P</string>
</property> </property>
</action> </action>
<action name="actionDonate">
<property name="text">
<string>&amp;Send Duke Feedback</string>
</property>
</action>
<action name="actionTelegram"> <action name="actionTelegram">
<property name="text"> <property name="text">
<string>&amp;Hush Telegram</string> <string>&amp;Telegram</string>
</property> </property>
</action> </action>
<action name="actionWebsite"> <action name="actionWebsite">
<property name="text"> <property name="text">
<string>&amp;Hush Website</string> <string>&amp;Website</string>
</property> </property>
</action> </action>
<action name="actionCheck_for_Updates"> <action name="actionCheck_for_Updates">
@ -1690,14 +1684,6 @@
<string>&amp;Export all private keys</string> <string>&amp;Export all private keys</string>
</property> </property>
</action> </action>
<action name="actionz_board_net">
<property name="text">
<string>&amp;z-board.net</string>
</property>
<property name="shortcut">
<string>Ctrl+A, Ctrl+Z</string>
</property>
</action>
<action name="action_Address_Book"> <action name="action_Address_Book">
<property name="text"> <property name="text">
<string>Address &amp;book</string> <string>Address &amp;book</string>
@ -1718,7 +1704,7 @@
</action> </action>
<action name="actionPay_URI"> <action name="actionPay_URI">
<property name="text"> <property name="text">
<string>Pay HUSH &amp;URI...</string> <string>Pay URI...</string>
</property> </property>
</action> </action>
<action name="actionConnect_Mobile_App"> <action name="actionConnect_Mobile_App">
@ -1731,7 +1717,7 @@
</action> </action>
<action name="actionRequest_hush"> <action name="actionRequest_hush">
<property name="text"> <property name="text">
<string>Request HUSH...</string> <string>Request funds...</string>
</property> </property>
</action> </action>
<action name="actionValidate_Address"> <action name="actionValidate_Address">

13
src/requestdialog.cpp

@ -7,8 +7,8 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "rpc.h" #include "rpc.h"
#include "settings.h" #include "settings.h"
#include "precompiled.h" #include "precompiled.h"
extern bool isdragonx;
RequestDialog::RequestDialog(QWidget *parent) : RequestDialog::RequestDialog(QWidget *parent) :
QDialog(parent), QDialog(parent),
@ -49,8 +49,13 @@ void RequestDialog::setupDialog(MainWindow* main, QDialog* d, Ui_RequestDialog*
void RequestDialog::showPaymentConfirmation(MainWindow* main, QString paymentURI) { void RequestDialog::showPaymentConfirmation(MainWindow* main, QString paymentURI) {
PaymentURI payInfo = Settings::parseURI(paymentURI); PaymentURI payInfo = Settings::parseURI(paymentURI);
if (!payInfo.error.isEmpty()) { if (!payInfo.error.isEmpty()) {
QMessageBox::critical(main, tr("Error paying HUSH URI"), if(isdragonx) {
QMessageBox::critical(main, tr("Error paying DRAGONX URI"),
tr("URI should be of the form 'drgx:<addr>?amt=x&memo=y") + "\n" + payInfo.error);
} else {
QMessageBox::critical(main, tr("Error paying HUSH URI"),
tr("URI should be of the form 'hush:<addr>?amt=x&memo=y") + "\n" + payInfo.error); tr("URI should be of the form 'hush:<addr>?amt=x&memo=y") + "\n" + payInfo.error);
}
return; return;
} }
@ -126,11 +131,11 @@ void RequestDialog::showRequestZcash(MainWindow* main) {
if (d.exec() == QDialog::Accepted) { if (d.exec() == QDialog::Accepted) {
// Construct a Hush Payment URI with the data and pay it immediately. // Construct a Hush Payment URI with the data and pay it immediately.
QString memoURI = "hush:" + req.cmbMyAddress->currentText() QString memoURI = (isdragonx ? "drgx:" : "hush:" ) + req.cmbMyAddress->currentText()
+ "?amt=" + Settings::getDecimalString(req.txtAmount->text().toDouble()) + "?amt=" + Settings::getDecimalString(req.txtAmount->text().toDouble())
+ "&memo=" + QUrl::toPercentEncoding(req.txtMemo->toPlainText()); + "&memo=" + QUrl::toPercentEncoding(req.txtMemo->toPlainText());
QString sendURI = "hush:" + AddressBook::addressFromAddressLabel(req.txtFrom->text()) QString sendURI = (isdragonx ? "drgx:" : "hush:" ) + AddressBook::addressFromAddressLabel(req.txtFrom->text())
+ "?amt=0.0001" + "?amt=0.0001"
+ "&memo=" + QUrl::toPercentEncoding(memoURI); + "&memo=" + QUrl::toPercentEncoding(memoURI);

2
src/requestdialog.ui

@ -216,7 +216,7 @@
<item row="0" column="2" colspan="2"> <item row="0" column="2" colspan="2">
<widget class="QLabel" name="lblHeader"> <widget class="QLabel" name="lblHeader">
<property name="text"> <property name="text">
<string>Request payment from a Sapling address. You'll send a HUSH 0.0001 transaction to the address with a HUSH payment URI. The memo will be included in the transaction when the address pays you.</string> <string>Request payment from a zaddr. You'll send a 0.0001 transaction to the address with a payment URI. The memo will be included in the transaction when the address pays you.</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>

41
src/rpc.cpp

@ -7,6 +7,8 @@
#include "version.h" #include "version.h"
#include "websockets.h" #include "websockets.h"
extern bool isdragonx;
RPC::RPC(MainWindow* main) { RPC::RPC(MainWindow* main) {
auto cl = new ConnectionLoader(main, this); auto cl = new ConnectionLoader(main, this);
@ -729,6 +731,10 @@ void RPC::getInfoThenRefresh(bool force) {
int blocks_until_halving= 2020000 - curBlock; int blocks_until_halving= 2020000 - curBlock;
char halving_days[8]; char halving_days[8];
int blocktime = 75; // seconds int blocktime = 75; // seconds
if(isdragonx) {
blocks_until_halving= 3500000 - curBlock;
blocktime = 60;
}
sprintf(halving_days, "%.2f", (double) (blocks_until_halving * blocktime) / (60*60*24) ); sprintf(halving_days, "%.2f", (double) (blocks_until_halving * blocktime) / (60*60*24) );
QString ntzhash = reply["notarizedhash"].toString(); QString ntzhash = reply["notarizedhash"].toString();
QString ntztxid = reply["notarizedtxid"].toString(); QString ntztxid = reply["notarizedtxid"].toString();
@ -776,7 +782,11 @@ void RPC::getInfoThenRefresh(bool force) {
qint64 solrate = reply.toInt(); qint64 solrate = reply.toInt();
//TODO: format decimal //TODO: format decimal
ui->solrate->setText(QString::number((double)solrate / 1000000) % " MegaSol/s"); if(isdragonx) {
ui->solrate->setText(QString::number((double)solrate) % " Hash/s");
} else {
ui->solrate->setText(QString::number((double)solrate / 1000000) % " MegaSol/s");
}
}); });
// Get network info // Get network info
@ -833,14 +843,18 @@ void RPC::getInfoThenRefresh(bool force) {
ui->heightLabel->setText(QObject::tr("Block height")); ui->heightLabel->setText(QObject::tr("Block height"));
} }
auto ticker_price = s->get_price(ticker);
QString extra = ""; QString extra = "";
if(ticker_price > 0 && ticker != "BTC") {
extra = QString::number( s->getBTCPrice() ) % "sat";
}
QString price = ""; QString price = "";
if (ticker_price > 0) {
price = QString(", ") % "HUSH" % "=" % QString::number( (double)ticker_price,'f',8) % " " % ticker % " " % extra; // No price data for dragonx for now
if (!isdragonx) {
auto ticker_price = s->get_price(ticker);
if(ticker_price > 0 && ticker != "BTC") {
extra = QString::number( s->getBTCPrice() ) % "sat";
}
if (ticker_price > 0) {
price = QString(", ") % "HUSH" % "=" % QString::number( (double)ticker_price,'f',8) % " " % ticker % " " % extra;
}
} }
// Update the status bar // Update the status bar
@ -857,14 +871,13 @@ void RPC::getInfoThenRefresh(bool force) {
auto hushPrice = Settings::getUSDFormat(1); auto hushPrice = Settings::getUSDFormat(1);
QString tooltip; QString tooltip;
if (connections > 0) { if (connections > 0) {
tooltip = QObject::tr("Connected to hushd"); tooltip = QObject::tr("Connected");
} } else {
else { tooltip = QObject::tr("No peer connections! Network issues?");
tooltip = QObject::tr("hushd has no peer connections! Network issues?");
} }
tooltip = tooltip % "(v" % QString::number(Settings::getInstance()->getHushdVersion()) % ")"; tooltip = tooltip % "(v" % QString::number(Settings::getInstance()->getHushdVersion()) % ")";
if (!hushPrice.isEmpty()) { if (!isdragonx && !hushPrice.isEmpty()) {
tooltip = "1 HUSH = " % hushPrice % "\n" % tooltip; tooltip = "1 HUSH = " % hushPrice % "\n" % tooltip;
} }
main->statusLabel->setToolTip(tooltip); main->statusLabel->setToolTip(tooltip);
@ -1363,6 +1376,10 @@ void RPC::refreshPrice() {
if (conn == nullptr) if (conn == nullptr)
return noConnection(); return noConnection();
if (isdragonx) {
return;
}
auto s = Settings::getInstance(); auto s = Settings::getInstance();
if (s->getAllowFetchPrices() == false) { if (s->getAllowFetchPrices() == false) {

5
src/senttxstore.cpp

@ -3,9 +3,14 @@
#include "senttxstore.h" #include "senttxstore.h"
#include "settings.h" #include "settings.h"
extern bool isdragonx;
/// Get the location of the app data file to be written. /// Get the location of the app data file to be written.
QString SentTxStore::writeableFile() { QString SentTxStore::writeableFile() {
auto filename = QStringLiteral("senttxstore.dat"); auto filename = QStringLiteral("senttxstore.dat");
if (isdragonx) {
filename = QStringLiteral("senttxstore-drgx.dat");
}
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
if (!dir.exists()) if (!dir.exists())

29
src/settings.cpp

@ -3,6 +3,8 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "settings.h" #include "settings.h"
extern bool isdragonx;
Settings* Settings::instance = nullptr; Settings* Settings::instance = nullptr;
Settings* Settings::init() { Settings* Settings::init() {
@ -39,6 +41,10 @@ Explorer Settings::getExplorer() {
//TODO: make it easy for people to use other explorers //TODO: make it easy for people to use other explorers
QString explorer = "https://explorer.hush.is"; QString explorer = "https://explorer.hush.is";
if(isdragonx) {
explorer = "https://explorer.dragonx.is";
}
auto txExplorerUrl = s.value("explorer/txExplorerUrl", explorer + "/tx/").toString(); auto txExplorerUrl = s.value("explorer/txExplorerUrl", explorer + "/tx/").toString();
auto addressExplorerUrl = s.value("explorer/addressExplorerUrl", explorer + "/address/").toString(); auto addressExplorerUrl = s.value("explorer/addressExplorerUrl", explorer + "/address/").toString();
@ -328,6 +334,9 @@ QString Settings::getHUSHUSDDisplayFormat(double bal) {
const QString Settings::txidStatusMessage = QString(QObject::tr("Transaction submitted (right click to copy) txid:")); const QString Settings::txidStatusMessage = QString(QObject::tr("Transaction submitted (right click to copy) txid:"));
QString Settings::getTokenName() { QString Settings::getTokenName() {
if (isdragonx) {
return "DRGX";
}
if (Settings::getInstance()->isTestnet()) { if (Settings::getInstance()->isTestnet()) {
return "TUSH"; return "TUSH";
} else { } else {
@ -449,12 +458,26 @@ QString Settings::paymentURIPretty(PaymentURI uri) {
PaymentURI Settings::parseURI(QString uri) { PaymentURI Settings::parseURI(QString uri) {
PaymentURI ans; PaymentURI ans;
if (!uri.startsWith("hush:")) { auto proto="";
ans.error = "Not a HUSH payment URI"; if (isdragonx) {
return ans; proto ="drgx:";
if (!uri.startsWith(proto % QString(":"))) {
ans.error = "Not a DRGX payment URI";
return ans;
}
} else {
proto = "hush:";
if (!uri.startsWith(proto % QString(":"))) {
ans.error = "Not a HUSH payment URI";
return ans;
}
} }
uri = uri.right(uri.length() - QString("hush:").length()); uri = uri.right(uri.length() - QString("hush:").length());
if(isdragonx) {
uri = uri.right(uri.length() - QString("drgx:").length());
}
QRegExp re("([a-zA-Z0-9]+)"); QRegExp re("([a-zA-Z0-9]+)");
int pos; int pos;

4
src/settings.ui

@ -588,14 +588,14 @@
<item row="12" column="0" colspan="2"> <item row="12" column="0" colspan="2">
<widget class="QLabel" name="label_10"> <widget class="QLabel" name="label_10">
<property name="text"> <property name="text">
<string>Connect to the internet to fetch HUSH prices</string> <string>Connect to the internet to fetch prices</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="0" colspan="2"> <item row="11" column="0" colspan="2">
<widget class="QCheckBox" name="chkFetchPrices"> <widget class="QCheckBox" name="chkFetchPrices">
<property name="text"> <property name="text">
<string>Fetch HUSH prices</string> <string>Fetch prices</string>
</property> </property>
</widget> </widget>
</item> </item>

19
src/txtablemodel.cpp

@ -5,6 +5,8 @@
#include "rpc.h" #include "rpc.h"
#include "guiconstants.h" #include "guiconstants.h"
extern bool isdragonx;
TxTableModel::TxTableModel(QObject *parent) TxTableModel::TxTableModel(QObject *parent)
: QAbstractTableModel(parent) { : QAbstractTableModel(parent) {
headers << QObject::tr("Type") << QObject::tr("Address") << QObject::tr("Date/Time") << QObject::tr("Amount"); headers << QObject::tr("Type") << QObject::tr("Address") << QObject::tr("Date/Time") << QObject::tr("Amount");
@ -195,14 +197,19 @@ int TxTableModel::columnCount(const QModelIndex&) const
if (!dat.memo.isEmpty()) { if (!dat.memo.isEmpty()) {
// If the memo is a Payment URI, then show a payment request icon // If the memo is a Payment URI, then show a payment request icon
if (dat.memo.startsWith("hush:")) { if(isdragonx) {
if (dat.memo.startsWith("drgx:")) {
QIcon icon(":/icons/res-drgx/paymentreq.gif");
return QVariant(icon.pixmap(16, 16));
}
} else if (dat.memo.startsWith("hush:")) {
QIcon icon(":/icons/res/paymentreq.gif"); QIcon icon(":/icons/res/paymentreq.gif");
return QVariant(icon.pixmap(16, 16)); return QVariant(icon.pixmap(16, 16));
} else { }
// Return the info pixmap to indicate memo
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); // Return the info pixmap to indicate memo
return QVariant(icon.pixmap(16, 16)); QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
} return QVariant(icon.pixmap(16, 16));
} else { } else {
// TODO: Add appropriate icons for types of txs instead of empty pixmap // TODO: Add appropriate icons for types of txs instead of empty pixmap
//qDebug() << "Type = " +getType(index.row()) + "Address = " +getAddr(index.row()) + "From Address = " +getFromAddr(index.row()); //qDebug() << "Type = " +getType(index.row()) + "Address = " +getAddr(index.row()) + "From Address = " +getFromAddr(index.row());

Loading…
Cancel
Save