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
IDEWorkspaceChecks.plist
hush-cli
hushd
dragonxd
*.mak
Makefile
Makefile.*
@ -18,7 +18,7 @@ res/libsodium.a
res/libsodium.a
res/libsodium/libsodium*
silentdragon
silentdragon
silentdragonx
silentdragon.pro.user
*.sln
src/precompiled.h.cpp

11
README.md

@ -142,6 +142,17 @@ make
./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
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)
echo "Compiling SilentDragon $VERSION with $JOBS threads..."
CONF=silentdragon.pro
CONF=${SDCONF:-silentdragon.pro}
if ! command -v qmake &> /dev/null
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 "rpc.h"
extern bool isdragonx;
AddressBookModel::AddressBookModel(QTableView *parent)
: QAbstractTableModel(parent) {
@ -293,6 +294,9 @@ void AddressBook::writeToStorage() {
QString AddressBook::writeableFile() {
auto filename = QStringLiteral("addresslabels.dat");
if (isdragonx) {
filename = QStringLiteral("addresslabels-drgx.dat");
}
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
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
#include "connection.h"
#include "mainwindow.h"
@ -9,6 +9,8 @@
#include "precompiled.h"
#include "version.h"
extern bool isdragonx;
ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) {
qDebug() << __func__;
this->main = main;
@ -92,11 +94,23 @@ void ConnectionLoader::doAutoConnect(bool tryEhushdStart) {
"with SilentDragon\n\n."
"Please remove the following line from your HUSH3.conf and restart SilentDragon\n"
"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 {
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"
"If all else fails, please run hushd manually.") %
(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);
@ -106,6 +120,11 @@ void ConnectionLoader::doAutoConnect(bool tryEhushdStart) {
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"
"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);
}
});
@ -189,9 +208,9 @@ void ConnectionLoader::createHushConf() {
QFile file(confLocation);
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);
return;
}
@ -346,23 +365,27 @@ bool ConnectionLoader::startEmbeddedHushd() {
#ifdef Q_OS_WIN64
auto hushdProgram = appPath.absoluteFilePath("hushd.exe");
// params for DRGX are handled below
#else
auto hushdProgram = appPath.absoluteFilePath("hushd");
if (isdragonx) {
hushdProgram = appPath.absoluteFilePath("dragonxd");
}
#endif
//if (!QFile(hushdProgram).exists()) {
if (!QFile::exists(hushdProgram)) {
qDebug() << "Can't find hushd at " << hushdProgram;
main->logger->write("Can't find hushd at " + hushdProgram);
qDebug() << "Can't find binary at " << hushdProgram;
main->logger->write("Can't find binary at " + hushdProgram);
return false;
} else {
qDebug() << "Found hushd at " << hushdProgram;
main->logger->write("Found hushd at " + hushdProgram);
qDebug() << "Found binary at " << hushdProgram;
main->logger->write("Found binary at " + hushdProgram);
}
ehushd = std::shared_ptr<QProcess>(new QProcess(main));
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),
@ -396,6 +419,10 @@ bool ConnectionLoader::startEmbeddedHushd() {
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(" ");
@ -557,6 +584,21 @@ void ConnectionLoader::showError(QString explanation) {
}
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
auto confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, ".hush/HUSH3/HUSH3.conf");
if(!QFile(confLocation).exists()) {
@ -585,10 +627,19 @@ QString ConnectionLoader::locateHushConfFile() {
QString ConnectionLoader::hushConfWritableLocation() {
#ifdef Q_OS_LINUX
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)
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
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
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() {
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 (hushconf->port.isEmpty()) hushconf->port = "18031";
if (hushconf->port.isEmpty()) {
if(isdragonx) {
hushconf->port = "21769";
} else {
hushconf->port = "18031";
}
}
file.close();
// Save to Qsettings

2
src/createhushconfdialog.ui

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

24
src/main.cpp

@ -7,6 +7,8 @@
#include "settings.h"
#include "version.h"
bool isdragonx = 0;
class SignalHandler
{
public:
@ -140,6 +142,14 @@ public:
~Application() {}
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_EnableHighDpiScaling);
@ -173,14 +183,18 @@ public:
}
QCoreApplication::setOrganizationName("Hush");
QCoreApplication::setApplicationName("SilentDragon");
QCoreApplication::setApplicationName(isdragonx ? "SilentDragonX" : "SilentDragon");
QString locale = QLocale::system().name();
locale.truncate(locale.lastIndexOf('_')); // Get the language code
qDebug() << "Loading locale " << locale;
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);
QIcon icon(":/icons/res/icon.ico");
@ -218,7 +232,11 @@ public:
}
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 (parser.positionalArguments().length() > 0) {

75
src/mainwindow.cpp

@ -24,6 +24,8 @@
#include "requestdialog.h"
#include "websockets.h"
extern bool isdragonx;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
@ -42,7 +44,7 @@ MainWindow::MainWindow(QWidget *parent) :
this->slot_change_theme(theme_name);
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
setupStatusBar();
@ -52,7 +54,6 @@ MainWindow::MainWindow(QWidget *parent) :
// Set up actions
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->actionReportBug, &QAction::triggered, this, &MainWindow::reportbug);
QObject::connect(ui->actionWebsite, &QAction::triggered, this, &MainWindow::website);
@ -527,7 +528,7 @@ void MainWindow::setupSettingsModal() {
settings.rpcuser->setReadOnly(true);
settings.rpcpassword->setReadOnly(true);
} 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.port->setEnabled(true);
settings.rpcuser->setEnabled(true);
@ -789,33 +790,26 @@ void MainWindow::addressBook() {
void MainWindow::telegram() {
QString url = "https://hush.is/tg";
if (isdragonx) {
url = "https://dragonx.is/tg";
}
QDesktopServices::openUrl(QUrl(url));
}
void MainWindow::reportbug() {
// dragonx doesn't have it's own support, for now
QString url = "https://hush.is/tg_support";
QDesktopServices::openUrl(QUrl(url));
}
void MainWindow::website() {
QString url = "https://hush.is";
if (isdragonx) {
url = "https://dragonx.is";
}
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
void MainWindow::validateAddress() {
// Make sure everything is up and running
@ -940,6 +934,10 @@ void MainWindow::payHushURI(QString uri, QString myAddr) {
if (uri.isEmpty()) {
uri = QInputDialog::getText(this, tr("Paste HUSH URI"),
"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
@ -950,8 +948,13 @@ void MainWindow::payHushURI(QString uri, QString myAddr) {
qDebug() << "Received URI " << uri;
PaymentURI paymentInfo = Settings::parseURI(uri);
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);
}
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"), [=] () {
QString url;
auto explorer = Settings::getInstance()->getExplorer();
@ -1435,6 +1461,7 @@ void MainWindow::setupBalancesTab() {
//TODO: should this be kept?
menu.addAction(tr("Convert Address"), [=] () {
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;
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 ...
QFile debuglog = "";
#ifdef Q_OS_LINUX
debuglog = "~/.komodo/HUSH3/debug.log";
debuglog = "~/.hush/HUSH3/debug.log";
#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)
// "C:/Users/<USER>/AppData/Roaming/<APPNAME>",
// 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
// Bless Your Heart, You Like Danger!
// There are open bounties to port HUSH softtware to OpenBSD and friends:
// git.hush.is/hush/tasks
debuglog = "~/.komodo/HUSH3/debug.log";
debuglog = "~/.hush/HUSH3/debug.log";
#endif // Q_OS_LINUX
if(debuglog.exists()) {
@ -1801,7 +1828,7 @@ void MainWindow::setupTransactionsTab() {
*/
// Payment Request
if (!memo.isEmpty() && memo.startsWith("hush:")) {
if (!memo.isEmpty() && memo.startsWith(isdragonx ? "drgx:" : "hush:")) {
menu.addAction(tr("View Payment Request"), [=] () {
RequestDialog::showPaymentConfirmation(this, memo);
});

26
src/mainwindow.ui

@ -1061,7 +1061,7 @@
</font>
</property>
<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>
</widget>
</item>
@ -1132,7 +1132,7 @@
</widget>
<widget class="QWidget" name="tab_5">
<attribute name="title">
<string>hushd</string>
<string>Node info</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
@ -1609,7 +1609,6 @@
<property name="title">
<string>&amp;Help</string>
</property>
<addaction name="actionDonate"/>
<addaction name="actionTelegram"/>
<addaction name="actionWebsite"/>
<addaction name="actionCheck_for_Updates"/>
@ -1660,19 +1659,14 @@
<string>Ctrl+P</string>
</property>
</action>
<action name="actionDonate">
<property name="text">
<string>&amp;Send Duke Feedback</string>
</property>
</action>
<action name="actionTelegram">
<property name="text">
<string>&amp;Hush Telegram</string>
<string>&amp;Telegram</string>
</property>
</action>
<action name="actionWebsite">
<property name="text">
<string>&amp;Hush Website</string>
<string>&amp;Website</string>
</property>
</action>
<action name="actionCheck_for_Updates">
@ -1690,14 +1684,6 @@
<string>&amp;Export all private keys</string>
</property>
</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">
<property name="text">
<string>Address &amp;book</string>
@ -1718,7 +1704,7 @@
</action>
<action name="actionPay_URI">
<property name="text">
<string>Pay HUSH &amp;URI...</string>
<string>Pay URI...</string>
</property>
</action>
<action name="actionConnect_Mobile_App">
@ -1731,7 +1717,7 @@
</action>
<action name="actionRequest_hush">
<property name="text">
<string>Request HUSH...</string>
<string>Request funds...</string>
</property>
</action>
<action name="actionValidate_Address">

13
src/requestdialog.cpp

@ -7,8 +7,8 @@
#include "mainwindow.h"
#include "rpc.h"
#include "settings.h"
#include "precompiled.h"
extern bool isdragonx;
RequestDialog::RequestDialog(QWidget *parent) :
QDialog(parent),
@ -49,8 +49,13 @@ void RequestDialog::setupDialog(MainWindow* main, QDialog* d, Ui_RequestDialog*
void RequestDialog::showPaymentConfirmation(MainWindow* main, QString paymentURI) {
PaymentURI payInfo = Settings::parseURI(paymentURI);
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);
}
return;
}
@ -126,11 +131,11 @@ void RequestDialog::showRequestZcash(MainWindow* main) {
if (d.exec() == QDialog::Accepted) {
// 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())
+ "&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"
+ "&memo=" + QUrl::toPercentEncoding(memoURI);

2
src/requestdialog.ui

@ -216,7 +216,7 @@
<item row="0" column="2" colspan="2">
<widget class="QLabel" name="lblHeader">
<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 name="wordWrap">
<bool>true</bool>

41
src/rpc.cpp

@ -7,6 +7,8 @@
#include "version.h"
#include "websockets.h"
extern bool isdragonx;
RPC::RPC(MainWindow* main) {
auto cl = new ConnectionLoader(main, this);
@ -729,6 +731,10 @@ void RPC::getInfoThenRefresh(bool force) {
int blocks_until_halving= 2020000 - curBlock;
char halving_days[8];
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) );
QString ntzhash = reply["notarizedhash"].toString();
QString ntztxid = reply["notarizedtxid"].toString();
@ -776,7 +782,11 @@ void RPC::getInfoThenRefresh(bool force) {
qint64 solrate = reply.toInt();
//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
@ -833,14 +843,18 @@ void RPC::getInfoThenRefresh(bool force) {
ui->heightLabel->setText(QObject::tr("Block height"));
}
auto ticker_price = s->get_price(ticker);
QString extra = "";
if(ticker_price > 0 && ticker != "BTC") {
extra = QString::number( s->getBTCPrice() ) % "sat";
}
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
@ -857,14 +871,13 @@ void RPC::getInfoThenRefresh(bool force) {
auto hushPrice = Settings::getUSDFormat(1);
QString tooltip;
if (connections > 0) {
tooltip = QObject::tr("Connected to hushd");
}
else {
tooltip = QObject::tr("hushd has no peer connections! Network issues?");
tooltip = QObject::tr("Connected");
} else {
tooltip = QObject::tr("No peer connections! Network issues?");
}
tooltip = tooltip % "(v" % QString::number(Settings::getInstance()->getHushdVersion()) % ")";
if (!hushPrice.isEmpty()) {
if (!isdragonx && !hushPrice.isEmpty()) {
tooltip = "1 HUSH = " % hushPrice % "\n" % tooltip;
}
main->statusLabel->setToolTip(tooltip);
@ -1363,6 +1376,10 @@ void RPC::refreshPrice() {
if (conn == nullptr)
return noConnection();
if (isdragonx) {
return;
}
auto s = Settings::getInstance();
if (s->getAllowFetchPrices() == false) {

5
src/senttxstore.cpp

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

29
src/settings.cpp

@ -3,6 +3,8 @@
#include "mainwindow.h"
#include "settings.h"
extern bool isdragonx;
Settings* Settings::instance = nullptr;
Settings* Settings::init() {
@ -39,6 +41,10 @@ Explorer Settings::getExplorer() {
//TODO: make it easy for people to use other explorers
QString explorer = "https://explorer.hush.is";
if(isdragonx) {
explorer = "https://explorer.dragonx.is";
}
auto txExplorerUrl = s.value("explorer/txExplorerUrl", explorer + "/tx/").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:"));
QString Settings::getTokenName() {
if (isdragonx) {
return "DRGX";
}
if (Settings::getInstance()->isTestnet()) {
return "TUSH";
} else {
@ -449,12 +458,26 @@ QString Settings::paymentURIPretty(PaymentURI uri) {
PaymentURI Settings::parseURI(QString uri) {
PaymentURI ans;
if (!uri.startsWith("hush:")) {
ans.error = "Not a HUSH payment URI";
return ans;
auto proto="";
if (isdragonx) {
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());
if(isdragonx) {
uri = uri.right(uri.length() - QString("drgx:").length());
}
QRegExp re("([a-zA-Z0-9]+)");
int pos;

4
src/settings.ui

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

19
src/txtablemodel.cpp

@ -5,6 +5,8 @@
#include "rpc.h"
#include "guiconstants.h"
extern bool isdragonx;
TxTableModel::TxTableModel(QObject *parent)
: QAbstractTableModel(parent) {
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 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");
return QVariant(icon.pixmap(16, 16));
} else {
// Return the info pixmap to indicate memo
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
return QVariant(icon.pixmap(16, 16));
}
}
// Return the info pixmap to indicate memo
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
return QVariant(icon.pixmap(16, 16));
} else {
// 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());

Loading…
Cancel
Save