diff --git a/.gitignore b/.gitignore index 4a21c30..248a400 100644 --- a/.gitignore +++ b/.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 diff --git a/README.md b/README.md index 958d1ad..d43fe20 100644 --- a/README.md +++ b/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. diff --git a/build-sdx.sh b/build-sdx.sh new file mode 100755 index 0000000..d1ebf38 --- /dev/null +++ b/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 diff --git a/build.sh b/build.sh index 7cb8668..04c5cb6 100755 --- a/build.sh +++ b/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 diff --git a/silentdragonx.pro b/silentdragonx.pro new file mode 100644 index 0000000..c611772 --- /dev/null +++ b/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 diff --git a/src/addressbook.cpp b/src/addressbook.cpp index 64bc38e..c61e302 100644 --- a/src/addressbook.cpp +++ b/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()) diff --git a/src/connection.cpp b/src/connection.cpp index b826496..ac536a6 100644 --- a/src/connection.cpp +++ b/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(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::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 ConnectionLoader::autoDetectHushConf() { auto confLocation = locateHushConfFile(); @@ -728,7 +780,13 @@ std::shared_ptr 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 diff --git a/src/createhushconfdialog.ui b/src/createhushconfdialog.ui index 9306a67..07ff088 100644 --- a/src/createhushconfdialog.ui +++ b/src/createhushconfdialog.ui @@ -11,7 +11,7 @@ - Configure HUSH3.conf + Configuration diff --git a/src/main.cpp b/src/main.cpp index c4f4c57..ca3c873 100644 --- a/src/main.cpp +++ b/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) { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 84ff2f3..021e1cd 100755 --- a/src/mainwindow.cpp +++ b/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:?amt=x&memo=y") + "\n" + paymentInfo.error); + } else { + QMessageBox::critical(this, tr("Error paying Hush URI"), tr("URI should be of the form 'hush:?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//AppData/Roaming/", // TODO: get current username - debuglog = "C:/Users//AppData/Roaming/Komodo/HUSH3/debug.log"; + debuglog = "C:/Users//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); }); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 092ccdc..008acf1 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -1061,7 +1061,7 @@ - <html><head/><body><p align="center"><span style=" font-weight:600;">Hush Market Information</span></p></body></html> + <html><head/><body><p align="center"><span style=" font-weight:600;">Market Information</span></p></body></html> @@ -1132,7 +1132,7 @@ - hushd + Node info @@ -1609,7 +1609,6 @@ &Help - @@ -1660,19 +1659,14 @@ Ctrl+P - - - &Send Duke Feedback - - - &Hush Telegram + &Telegram - &Hush Website + &Website @@ -1690,14 +1684,6 @@ &Export all private keys - - - &z-board.net - - - Ctrl+A, Ctrl+Z - - Address &book @@ -1718,7 +1704,7 @@ - Pay HUSH &URI... + Pay URI... @@ -1731,7 +1717,7 @@ - Request HUSH... + Request funds... diff --git a/src/requestdialog.cpp b/src/requestdialog.cpp index 2d37d41..10e26bc 100644 --- a/src/requestdialog.cpp +++ b/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:?amt=x&memo=y") + "\n" + payInfo.error); + } else { + QMessageBox::critical(main, tr("Error paying HUSH URI"), tr("URI should be of the form 'hush:?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); diff --git a/src/requestdialog.ui b/src/requestdialog.ui index bd3139a..35f395b 100644 --- a/src/requestdialog.ui +++ b/src/requestdialog.ui @@ -216,7 +216,7 @@ - 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. + 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. true diff --git a/src/rpc.cpp b/src/rpc.cpp index 5a1b5cc..42c0117 100644 --- a/src/rpc.cpp +++ b/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) { diff --git a/src/senttxstore.cpp b/src/senttxstore.cpp index e9f8505..407552d 100644 --- a/src/senttxstore.cpp +++ b/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()) diff --git a/src/settings.cpp b/src/settings.cpp index e3fd871..38947c6 100644 --- a/src/settings.cpp +++ b/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; diff --git a/src/settings.ui b/src/settings.ui index e1cc096..5fd4fda 100644 --- a/src/settings.ui +++ b/src/settings.ui @@ -588,14 +588,14 @@ - Connect to the internet to fetch HUSH prices + Connect to the internet to fetch prices - Fetch HUSH prices + Fetch prices diff --git a/src/txtablemodel.cpp b/src/txtablemodel.cpp index f43e4ef..b1803c8 100644 --- a/src/txtablemodel.cpp +++ b/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());