Browse Source

Merge pull request #100 from strider-paff-shell/denio

Denio
pull/105/head
Denio 4 years ago
committed by GitHub
parent
commit
5d91a76839
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .gitignore
  2. 229
      src/addressbook.cpp
  3. 27
      src/addresscombo.cpp
  4. 90
      src/balancestablemodel.cpp
  5. 160
      src/camount.cpp
  6. 1
      src/camount.h
  7. 151
      src/connection.cpp
  8. 646
      src/controller.cpp

1
.gitignore

@ -40,3 +40,4 @@ silentdragonlite.pro.user.4.10-pre1
silentdragonlite
silentdragonlite_plugin_import.cpp
silentdragonlite_resource.rc
SilentDragonLite

229
src/addressbook.cpp

@ -6,85 +6,99 @@
#include "controller.h"
AddressBookModel::AddressBookModel(QTableView *parent)
: QAbstractTableModel(parent) {
AddressBookModel::AddressBookModel(QTableView *parent) : QAbstractTableModel(parent)
{
headers << tr("Label") << tr("Address");
this->parent = parent;
loadData();
}
AddressBookModel::~AddressBookModel() {
AddressBookModel::~AddressBookModel()
{
saveData();
}
void AddressBookModel::saveData() {
void AddressBookModel::saveData()
{
// Save column positions
QSettings().setValue("addresstablegeometry", parent->horizontalHeader()->saveState());
QSettings().setValue(
"addresstablegeometry",
parent->horizontalHeader()->saveState()
);
}
void AddressBookModel::loadData() {
void AddressBookModel::loadData()
{
labels = AddressBook::getInstance()->getAllAddressLabels();
parent->horizontalHeader()->restoreState(QSettings().value("addresstablegeometry").toByteArray());
parent->horizontalHeader()->restoreState(
QSettings().value(
"addresstablegeometry"
).toByteArray()
);
}
void AddressBookModel::addNewLabel(QString label, QString addr) {
void AddressBookModel::addNewLabel(QString label, QString addr)
{
//labels.push_back(QPair<QString, QString>(label, addr));
AddressBook::getInstance()->addAddressLabel(label, addr);
labels.clear();
labels = AddressBook::getInstance()->getAllAddressLabels();
dataChanged(index(0, 0), index(labels.size()-1, columnCount(index(0,0))-1));
layoutChanged();
}
void AddressBookModel::removeItemAt(int row) {
void AddressBookModel::removeItemAt(int row)
{
if (row >= labels.size())
return;
AddressBook::getInstance()->removeAddressLabel(labels[row].first, labels[row].second);
AddressBook::getInstance()->removeAddressLabel(labels[row].first, labels[row].second);
labels.clear();
labels = AddressBook::getInstance()->getAllAddressLabels();
dataChanged(index(0, 0), index(labels.size()-1, columnCount(index(0,0))-1));
layoutChanged();
}
QPair<QString, QString> AddressBookModel::itemAt(int row) {
if (row >= labels.size()) return QPair<QString, QString>();
QPair<QString, QString> AddressBookModel::itemAt(int row)
{
if (row >= labels.size())
return QPair<QString, QString>();
return labels.at(row);
}
int AddressBookModel::rowCount(const QModelIndex&) const {
int AddressBookModel::rowCount(const QModelIndex&) const
{
return labels.size();
}
int AddressBookModel::columnCount(const QModelIndex&) const {
int AddressBookModel::columnCount(const QModelIndex&) const
{
return headers.size();
}
QVariant AddressBookModel::data(const QModelIndex &index, int role) const {
if (role == Qt::DisplayRole) {
switch(index.column()) {
QVariant AddressBookModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole)
{
switch(index.column())
{
case 0: return labels.at(index.row()).first;
case 1: return labels.at(index.row()).second;
}
}
return QVariant();
}
QVariant AddressBookModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
QVariant AddressBookModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
return headers.at(section);
}
return QVariant();
}
@ -93,28 +107,27 @@ QVariant AddressBookModel::headerData(int section, Qt::Orientation orientation,
//===============
// AddressBook
//===============
void AddressBook::open(MainWindow* parent, QLineEdit* target) {
void AddressBook::open(MainWindow* parent, QLineEdit* target)
{
QDialog d(parent);
Ui_addressBook ab;
ab.setupUi(&d);
Settings::saveRestore(&d);
QRegExpValidator v(QRegExp(Settings::labelRegExp), ab.label);
ab.label->setValidator(&v);
AddressBookModel model(ab.addresses);
ab.addresses->setModel(&model);
// If there is no target, the we'll call the button "Ok", else "Pick"
if (target != nullptr) {
if (target != nullptr)
ab.buttonBox->button(QDialogButtonBox::Ok)->setText(QObject::tr("Pick"));
}
// Connect the dialog's closing to updating the label address completor
QObject::connect(&d, &QDialog::finished, [=] (auto) { parent->updateLabels(); });
// If there is a target then make it the addr for the "Add to" button
if (target != nullptr && Settings::isValidAddress(target->text())) {
if (target != nullptr && Settings::isValidAddress(target->text()))
{
ab.addr->setText(target->text());
ab.label->setFocus();
}
@ -124,26 +137,37 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
auto addr = ab.addr->text().trimmed();
QString newLabel = ab.label->text();
if (addr.isEmpty() || newLabel.isEmpty()) {
QMessageBox::critical(parent, QObject::tr("Address or Label Error"),
QObject::tr("Address or Label cannot be empty"), QMessageBox::Ok);
if (addr.isEmpty() || newLabel.isEmpty())
{
QMessageBox::critical(
parent,
QObject::tr("Address or Label Error"),
QObject::tr("Address or Label cannot be empty"),
QMessageBox::Ok
);
return;
}
// Test if address is valid.
if (!Settings::isValidAddress(addr)) {
QMessageBox::critical(parent, QObject::tr("Address Format Error"),
QObject::tr("%1 doesn't seem to be a valid hush address.")
.arg(addr),
QMessageBox::Ok);
if (!Settings::isValidAddress(addr))
{
QMessageBox::critical(
parent,
QObject::tr("Address Format Error"),
QObject::tr("%1 doesn't seem to be a valid hush address.").arg(addr),
QMessageBox::Ok
);
return;
}
// Don't allow duplicate address labels.
if (!getInstance()->getAddressForLabel(newLabel).isEmpty()) {
QMessageBox::critical(parent, QObject::tr("Label Error"),
QObject::tr("The label '%1' already exists. Please remove the existing label.")
.arg(newLabel),
QMessageBox::Ok);
if (!getInstance()->getAddressForLabel(newLabel).isEmpty())
{
QMessageBox::critical(
parent,
QObject::tr("Label Error"),
QObject::tr("The label '%1' already exists. Please remove the existing label.").arg(newLabel),
QMessageBox::Ok
);
return;
}
@ -153,21 +177,30 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
// Import Button
QObject::connect(ab.btnImport, &QPushButton::clicked, [&] () {
// Get the import file name.
auto fileName = QFileDialog::getOpenFileUrl(&d, QObject::tr("Import Address Book"), QUrl(),
"CSV file (*.csv)");
auto fileName = QFileDialog::getOpenFileUrl(
&d, QObject::tr("Import Address Book"),
QUrl(),
"CSV file (*.csv)"
);
if (fileName.isEmpty())
return;
QFile file(fileName.toLocalFile());
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::information(&d, QObject::tr("Unable to open file"), file.errorString());
if (!file.open(QIODevice::ReadOnly))
{
QMessageBox::information(
&d,
QObject::tr("Unable to open file"),
file.errorString()
);
return;
}
QTextStream in(&file);
QString line;
int numImported = 0;
while (in.readLineInto(&line)) {
while (in.readLineInto(&line))
{
QStringList items = line.split(",");
if (items.size() != 2)
continue;
@ -180,8 +213,11 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
numImported++;
}
QMessageBox::information(&d, QObject::tr("Address Book Import Done"),
QObject::tr("Imported %1 new Address book entries").arg(numImported));
QMessageBox::information(
&d,
QObject::tr("Address Book Import Done"),
QObject::tr("Imported %1 new Address book entries").arg(numImported)
);
});
auto fnSetTargetLabelAddr = [=] (QLineEdit* target, QString label, QString addr) {
@ -194,7 +230,8 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
if (!target)
return;
if (index.row() < 0) return;
if (index.row() < 0)
return;
QString lbl = model.itemAt(index.row()).first;
QString addr = model.itemAt(index.row()).second;
@ -206,20 +243,19 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
ab.addresses->setContextMenuPolicy(Qt::CustomContextMenu);
QObject::connect(ab.addresses, &QTableView::customContextMenuRequested, [&] (QPoint pos) {
QModelIndex index = ab.addresses->indexAt(pos);
if (index.row() < 0) return;
if (index.row() < 0)
return;
QString lbl = model.itemAt(index.row()).first;
QString addr = model.itemAt(index.row()).second;
QMenu menu(parent);
if (target != nullptr) {
if (target != nullptr)
menu.addAction("Pick", [&] () {
d.accept();
fnSetTargetLabelAddr(target, lbl, addr);
});
}
menu.addAction(QObject::tr("Copy address"), [&] () {
QGuiApplication::clipboard()->setText(addr);
@ -248,27 +284,30 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
//=============
// AddressBook singleton class
//=============
AddressBook* AddressBook::getInstance() {
AddressBook* AddressBook::getInstance()
{
if (!instance)
instance = new AddressBook();
return instance;
}
AddressBook::AddressBook() {
AddressBook::AddressBook()
{
readFromStorage();
}
void AddressBook::readFromStorage() {
void AddressBook::readFromStorage()
{
QFile file(AddressBook::writeableFile());
if (file.exists()) {
if (file.exists())
{
allLabels.clear();
file.open(QIODevice::ReadOnly);
QDataStream in(&file); // read the data serialized from the file
QString version;
in >> version >> allLabels;
file.close();
}
@ -282,7 +321,8 @@ void AddressBook::readFromStorage() {
// }
}
void AddressBook::writeToStorage() {
void AddressBook::writeToStorage()
{
QFile file(AddressBook::writeableFile());
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
QDataStream out(&file); // we will serialize the data into the file
@ -290,42 +330,44 @@ void AddressBook::writeToStorage() {
file.close();
}
QString AddressBook::writeableFile() {
QString AddressBook::writeableFile()
{
auto filename = QStringLiteral("addresslabels.dat");
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
if (!dir.exists())
QDir().mkpath(dir.absolutePath());
if (Settings::getInstance()->isTestnet()) {
if (Settings::getInstance()->isTestnet())
return dir.filePath("testnet-" % filename);
} else {
else
return dir.filePath(filename);
}
}
// Add a new address/label to the database
void AddressBook::addAddressLabel(QString label, QString address) {
void AddressBook::addAddressLabel(QString label, QString address)
{
Q_ASSERT(Settings::isValidAddress(address));
// First, remove any existing label
// Iterate over the list and remove the label/address
for (int i=0; i < allLabels.size(); i++) {
if (allLabels[i].first == label) {
for (int i=0; i < allLabels.size(); i++)
if (allLabels[i].first == label)
removeAddressLabel(allLabels[i].first, allLabels[i].second);
}
}
allLabels.push_back(QPair<QString, QString>(label, address));
writeToStorage();
}
// Remove a new address/label from the database
void AddressBook::removeAddressLabel(QString label, QString address) {
void AddressBook::removeAddressLabel(QString label, QString address)
{
// Iterate over the list and remove the label/address
for (int i=0; i < allLabels.size(); i++) {
if (allLabels[i].first == label && allLabels[i].second == address) {
for (int i=0; i < allLabels.size(); i++)
{
if (allLabels[i].first == label && allLabels[i].second == address)
{
allLabels.removeAt(i);
writeToStorage();
return;
@ -333,10 +375,13 @@ void AddressBook::removeAddressLabel(QString label, QString address) {
}
}
void AddressBook::updateLabel(QString oldlabel, QString address, QString newlabel) {
void AddressBook::updateLabel(QString oldlabel, QString address, QString newlabel)
{
// Iterate over the list and update the label/address
for (int i = 0; i < allLabels.size(); i++) {
if (allLabels[i].first == oldlabel && allLabels[i].second == address) {
for (int i = 0; i < allLabels.size(); i++)
{
if (allLabels[i].first == oldlabel && allLabels[i].second == address)
{
allLabels[i].first = newlabel;
writeToStorage();
return;
@ -345,42 +390,46 @@ void AddressBook::updateLabel(QString oldlabel, QString address, QString newlabe
}
// Read all addresses
const QList<QPair<QString, QString>>& AddressBook::getAllAddressLabels() {
if (allLabels.isEmpty()) {
const QList<QPair<QString, QString>>& AddressBook::getAllAddressLabels()
{
if (allLabels.isEmpty())
readFromStorage();
}
return allLabels;
}
// Get the label for an address
QString AddressBook::getLabelForAddress(QString addr) {
for (auto i : allLabels) {
QString AddressBook::getLabelForAddress(QString addr)
{
for (auto i : allLabels)
if (i.second == addr)
return i.first;
}
return "";
}
// Get the address for a label
QString AddressBook::getAddressForLabel(QString label) {
for (auto i: allLabels) {
QString AddressBook::getAddressForLabel(QString label)
{
for (auto i: allLabels)
if (i.first == label)
return i.second;
}
return "";
}
QString AddressBook::addLabelToAddress(QString addr) {
QString AddressBook::addLabelToAddress(QString addr)
{
QString label = AddressBook::getInstance()->getLabelForAddress(addr);
if (!label.isEmpty())
return label + "/" + addr;
else
return addr;
}
QString AddressBook::addressFromAddressLabel(const QString& lblAddr) {
QString AddressBook::addressFromAddressLabel(const QString& lblAddr)
{
return lblAddr.trimmed().split("/").last();
}

27
src/addresscombo.cpp

@ -2,29 +2,31 @@
#include "addressbook.h"
#include "settings.h"
AddressCombo::AddressCombo(QWidget* parent) :
QComboBox(parent) {
}
AddressCombo::AddressCombo(QWidget* parent): QComboBox(parent)
{}
QString AddressCombo::itemText(int i) {
QString AddressCombo::itemText(int i)
{
QString txt = QComboBox::itemText(i);
return AddressBook::addressFromAddressLabel(txt.split("(")[0].trimmed());
}
QString AddressCombo::currentText() {
QString AddressCombo::currentText()
{
QString txt = QComboBox::currentText();
return AddressBook::addressFromAddressLabel(txt.split("(")[0].trimmed());
}
void AddressCombo::setCurrentText(const QString& text) {
for (int i=0; i < count(); i++) {
if (itemText(i) == text) {
void AddressCombo::setCurrentText(const QString& text)
{
for (int i=0; i < count(); i++)
if (itemText(i) == text)
QComboBox::setCurrentIndex(i);
}
}
}
void AddressCombo::addItem(const QString& text, CAmount bal) {
void AddressCombo::addItem(const QString& text, CAmount bal)
{
QString txt = AddressBook::addLabelToAddress(text);
if (bal.toqint64() > 0)
txt = txt % "(" % bal.toDecimalhushString() % ")";
@ -32,7 +34,8 @@ void AddressCombo::addItem(const QString& text, CAmount bal) {
QComboBox::addItem(txt);
}
void AddressCombo::insertItem(int index, const QString& text, CAmount bal) {
void AddressCombo::insertItem(int index, const QString& text, CAmount bal)
{
QString txt = AddressBook::addLabelToAddress(text) %
"(" % bal.toDecimalhushString() % ")";
QComboBox::insertItem(index, txt);

90
src/balancestablemodel.cpp

@ -3,9 +3,8 @@
#include "settings.h"
#include "camount.h"
BalancesTableModel::BalancesTableModel(QObject *parent)
: QAbstractTableModel(parent) {
}
BalancesTableModel::BalancesTableModel(QObject *parent): QAbstractTableModel(parent)
{}
void BalancesTableModel::setNewData(const QList<QString> zaddrs, const QList<QString> taddrs,
const QMap<QString, CAmount> balances, const QList<UnspentOutput> outputs)
@ -29,21 +28,19 @@ void BalancesTableModel::setNewData(const QList<QString> zaddrs, const QList<QSt
modeldata = new QList<std::tuple<QString, CAmount>>();
std::for_each(balances.keyBegin(), balances.keyEnd(), [=, &anyz, &anyt] (auto keyIt) {
modeldata->push_back(std::make_tuple(keyIt, balances.value(keyIt)));
if (Settings::isZAddress(keyIt)) {
if (Settings::isZAddress(keyIt))
anyz = true;
} else if (Settings::isTAddress(keyIt)) {
else if (Settings::isTAddress(keyIt))
anyt = true;
}
});
// Add all addresses that have no balances, if there are no existing addresses
if (!anyz && zaddrs.length() > 0) {
if (!anyz && zaddrs.length() > 0)
modeldata->push_back(std::make_tuple(zaddrs[0], CAmount::fromqint64(0)));
}
if (!anyt && taddrs.length() > 0) {
if (!anyt && taddrs.length() > 0)
modeldata->push_back(std::make_tuple(taddrs[0], CAmount::fromqint64(0)));
}
// And then update the data
dataChanged(index(0, 0), index(modeldata->size()-1, columnCount(index(0,0))-1));
@ -53,19 +50,17 @@ void BalancesTableModel::setNewData(const QList<QString> zaddrs, const QList<QSt
layoutChanged();
}
BalancesTableModel::~BalancesTableModel() {
BalancesTableModel::~BalancesTableModel()
{
delete modeldata;
delete unspentOutputs;
}
int BalancesTableModel::rowCount(const QModelIndex&) const
{
if (modeldata == nullptr) {
if (loading)
return 1;
else
return 0;
}
if (modeldata == nullptr)
return (loading) ? 1: 0;
return modeldata->size();
}
@ -76,25 +71,31 @@ int BalancesTableModel::columnCount(const QModelIndex&) const
QVariant BalancesTableModel::data(const QModelIndex &index, int role) const
{
if (loading) {
if (role == Qt::DisplayRole)
if (loading)
return (role == Qt::DisplayRole) ? "Loading..." : QVariant();
/*if (role == Qt::DisplayRole)
return "Loading...";
else
return QVariant();
}
return QVariant();*/
if (role == Qt::TextAlignmentRole && index.column() == 1) return QVariant(Qt::AlignRight | Qt::AlignVCenter);
if (role == Qt::TextAlignmentRole && index.column() == 1)
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
if (role == Qt::ForegroundRole) {
// If any of the UTXOs for this address has zero confirmations, paint it in red
const auto& addr = std::get<0>(modeldata->at(index.row()));
for (auto unconfirmedOutput : *unspentOutputs) {
if (unconfirmedOutput.address == addr &&
(!unconfirmedOutput.spendable || unconfirmedOutput.pending)) {
for (auto unconfirmedOutput : *unspentOutputs)
{
if (
unconfirmedOutput.address == addr &&
(!unconfirmedOutput.spendable || unconfirmedOutput.pending)
)
{
QBrush b;
b.setColor(Qt::red);
return b;
}
}
// Else, just return the default brush
@ -103,17 +104,21 @@ QVariant BalancesTableModel::data(const QModelIndex &index, int role) const
return b;
}
if (role == Qt::DisplayRole) {
switch (index.column()) {
case 0: return AddressBook::addLabelToAddress(std::get<0>(modeldata->at(index.row())));
case 1: return std::get<1>(modeldata->at(index.row())).toDecimalhushString();
if (role == Qt::DisplayRole)
{
switch (index.column())
{
case 0: return AddressBook::addLabelToAddress(std::get<0>(modeldata->at(index.row())));
case 1: return std::get<1>(modeldata->at(index.row())).toDecimalhushString();
}
}
if(role == Qt::ToolTipRole) {
switch (index.column()) {
case 0: return AddressBook::addLabelToAddress(std::get<0>(modeldata->at(index.row())));
case 1: return std::get<1>(modeldata->at(index.row())).toDecimalhushString();
if(role == Qt::ToolTipRole)
{
switch (index.column())
{
case 0: return AddressBook::addLabelToAddress(std::get<0>(modeldata->at(index.row())));
case 1: return std::get<1>(modeldata->at(index.row())).toDecimalhushString();
}
}
@ -123,11 +128,13 @@ QVariant BalancesTableModel::data(const QModelIndex &index, int role) const
QVariant BalancesTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::TextAlignmentRole && section == 1) {
if (role == Qt::TextAlignmentRole && section == 1)
{
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
}
if (role == Qt::FontRole) {
if (role == Qt::FontRole)
{
QFont f;
f.setBold(true);
return f;
@ -136,13 +143,16 @@ QVariant BalancesTableModel::headerData(int section, Qt::Orientation orientation
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal) {
switch (section) {
case 0: return tr("Address");
case 1: return tr("Amount");
default: return QVariant();
if (orientation == Qt::Horizontal)
{
switch (section)
{
case 0: return tr("Address");
case 1: return tr("Amount");
default: return QVariant();
}
}
return QVariant();
}

160
src/camount.cpp

@ -1,204 +1,230 @@
#include "camount.h"
#include "settings.h"
#include "precompiled.h"
const int NUMPLACES = 8;
const qint64 COIN = 100000000;
double CAmount::toDecimalDouble() const {
double CAmount::toDecimalDouble() const
{
return static_cast<double>(this->amount) / COIN;
}
QString CAmount::toDecimalString() const {
if (amount < 0) {
QString CAmount::toDecimalString() const
{
if (amount < 0)
{
CAmount negative(-1 * this->amount);
return "-" + negative.toDecimalString();
}
int wholePart = amount / COIN;
int decimalPart = amount % COIN;
QString r = QString::number(wholePart);
if (decimalPart > 0) {
if (decimalPart > 0)
{
QString decimalPartStr = QString::number(decimalPart);
r = r + "." + decimalPartStr.rightJustified(NUMPLACES, '0');
// Trim tailing 0s
while (r.right(1) == "0") {
while (r.right(1) == "0")
r = r.left(r.length() - 1);
}
}
return r;
}
QString CAmount::toDecimalUSDString() const {
double dblAmount = static_cast<double>(this->amount) / COIN;
double price = Settings::getInstance()->getZECPrice();
double CAmount::getDblAmount() const
{
return static_cast<double>(this->amount) / COIN;
}
return "$ " + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
QString CAmount::toDecimalUSDString() const
{
double price = Settings::getInstance()->getZECPrice();
return "$ " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
}
QString CAmount::toDecimalEURString() const {
double dblAmount = static_cast<double>(this->amount) / COIN;
QString CAmount::toDecimalEURString() const
{
double price = Settings::getInstance()->getEURPrice();
return QLocale(QLocale::German).toString(dblAmount*price, 'f', 2) + "";
return QLocale(QLocale::German).toString(this->getDblAmount() * price, 'f', 2) + "";
}
QString CAmount::toDecimalBTCString() const {
double dblAmount = static_cast<double>(this->amount) / COIN;
double price = Settings::getInstance()->getBTCPrice();
return "BTC " + QLocale(QLocale::English).toString(dblAmount*price, 'f', 9);
QString CAmount::toDecimalBTCString() const
{
double price = Settings::getInstance()->getBTCPrice();
return "BTC " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 9);
}
QString CAmount::toDecimalCNYString() const {
double dblAmount = static_cast<double>(this->amount) / COIN;
double price = Settings::getInstance()->getCNYPrice();
return "¥ /元 " + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
QString CAmount::toDecimalCNYString() const
{
double price = Settings::getInstance()->getCNYPrice();
return "¥ /元 " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
}
QString CAmount::toDecimalRUBString() const {
double dblAmount = static_cast<double>(this->amount) / COIN;
QString CAmount::toDecimalRUBString() const
{
double price = Settings::getInstance()->getRUBPrice();
return "" + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
return "" + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
}
QString CAmount::toDecimalCADString() const {
double dblAmount = static_cast<double>(this->amount) / COIN;
double price = Settings::getInstance()->getCADPrice();
return "$ " + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
QString CAmount::toDecimalCADString() const
{
double price = Settings::getInstance()->getCADPrice();
return "$ " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
}
QString CAmount::toDecimalSGDString() const {
double dblAmount = static_cast<double>(this->amount) / COIN;
double price = Settings::getInstance()->getSGDPrice();
return "$ " + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
QString CAmount::toDecimalSGDString() const
{
double price = Settings::getInstance()->getSGDPrice();
return "$ " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
}
QString CAmount::toDecimalCHFString() const {
double dblAmount = static_cast<double>(this->amount) / COIN;
double price = Settings::getInstance()->getCHFPrice();
return "CHF " + QLocale(QLocale::German).toString(dblAmount*price, 'f', 2);
QString CAmount::toDecimalCHFString() const
{
double price = Settings::getInstance()->getCHFPrice();
return "CHF " + QLocale(QLocale::German).toString(this->getDblAmount() * price, 'f', 2);
}
QString CAmount::toDecimalINRString() const {
double dblAmount = static_cast<double>(this->amount) / COIN;
double price = Settings::getInstance()->getINRPrice();
return "" + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
QString CAmount::toDecimalINRString() const
{
double price = Settings::getInstance()->getINRPrice();
return "" + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
}
QString CAmount::toDecimalGBPString() const {
double dblAmount = static_cast<double>(this->amount) / COIN;
QString CAmount::toDecimalGBPString() const
{
double price = Settings::getInstance()->getGBPPrice();
return "£ " + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
return "£ " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
}
QString CAmount::toDecimalAUDString() const {
double dblAmount = static_cast<double>(this->amount) / COIN;
QString CAmount::toDecimalAUDString() const
{
double price = Settings::getInstance()->getAUDPrice();
return " $" + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
return " $" + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
}
QString CAmount::toDecimalhushString() const {
QString CAmount::toDecimalhushString() const
{
return this->toDecimalString() % " " % Settings::getTokenName();
}
QString CAmount::toDecimalhushUSDString() const {
QString CAmount::toDecimalhushUSDString() const
{
auto usdString = this->toDecimalUSDString();
if (!usdString.isEmpty())
return this->toDecimalhushString() % " (" % usdString % ")";
else
return this->toDecimalhushString();
}
QString CAmount::toDecimalhushEURString() const {
QString CAmount::toDecimalhushEURString() const
{
auto eurString = this->toDecimalEURString();
if (!eurString.isEmpty())
return this->toDecimalhushString() % " (" % eurString % ")";
else
return this->toDecimalhushString();
}
QString CAmount::toDecimalhushBTCString() const {
QString CAmount::toDecimalhushBTCString() const
{
auto btcString = this->toDecimalBTCString();
if (!btcString.isEmpty())
return this->toDecimalhushString() % " (" % btcString % ")";
else
return this->toDecimalhushString();
}
QString CAmount::toDecimalhushCNYString() const {
QString CAmount::toDecimalhushCNYString() const
{
auto cnyString = this->toDecimalCNYString();
if (!cnyString.isEmpty())
return this->toDecimalhushString() % " (" % cnyString % ")";
else
return this->toDecimalhushString();
}
QString CAmount::toDecimalhushRUBString() const {
QString CAmount::toDecimalhushRUBString() const
{
auto rubString = this->toDecimalRUBString();
if (!rubString.isEmpty())
return this->toDecimalhushString() % " (" % rubString % ")";
else
return this->toDecimalhushString();
}
QString CAmount::toDecimalhushCADString() const {
QString CAmount::toDecimalhushCADString() const
{
auto cadString = this->toDecimalCADString();
if (!cadString.isEmpty())
return this->toDecimalhushString() % " (" % cadString % ")";
else
return this->toDecimalhushString();
}
QString CAmount::toDecimalhushSGDString() const {
QString CAmount::toDecimalhushSGDString() const
{
auto sgdString = this->toDecimalSGDString();
if (!sgdString.isEmpty())
return this->toDecimalhushString() % " (" % sgdString % ")";
else
return this->toDecimalhushString();
}
QString CAmount::toDecimalhushCHFString() const {
QString CAmount::toDecimalhushCHFString() const
{
auto chfString = this->toDecimalCHFString();
if (!chfString.isEmpty())
return this->toDecimalhushString() % " (" % chfString % ")";
else
return this->toDecimalhushString();
}
QString CAmount::toDecimalhushINRString() const {
QString CAmount::toDecimalhushINRString() const
{
auto inrString = this->toDecimalINRString();
if (!inrString.isEmpty())
return this->toDecimalhushString() % " (" % inrString % ")";
else
return this->toDecimalhushString();
}
QString CAmount::toDecimalhushGBPString() const {
QString CAmount::toDecimalhushGBPString() const
{
auto gbpString = this->toDecimalGBPString();
if (!gbpString.isEmpty())
return this->toDecimalhushString() % " (" % gbpString % ")";
else
return this->toDecimalhushString();
}
QString CAmount::toDecimalhushAUDString() const {
QString CAmount::toDecimalhushAUDString() const
{
auto audString = this->toDecimalAUDString();
if (!audString.isEmpty())
return this->toDecimalhushString() % " (" % audString % ")";
else
return this->toDecimalhushString();
}
CAmount CAmount::fromDecimalString(QString decimalString) {
CAmount CAmount::fromDecimalString(QString decimalString)
{
auto amtParts = decimalString.split(".");
qint64 r = amtParts[0].toULongLong() * COIN;
if (amtParts.length() == 2) {
if (amtParts.length() == 2)
{
auto trailingZeros = QString("0").repeated(NUMPLACES - amtParts[1].length());
r += QString(amtParts[1] + trailingZeros).toULongLong();
}

1
src/camount.h

@ -26,6 +26,7 @@ public:
double toDecimalDouble() const;
QString toDecimalString() const;
double getDblAmount() const;
QString toDecimalUSDString() const;
QString toDecimalEURString() const;
QString toDecimalBTCString() const;

151
src/connection.cpp

@ -5,42 +5,47 @@
#include "firsttimewizard.h"
#include "ui_createhushconfdialog.h"
#include "controller.h"
#include "../lib/silentdragonlitelib.h"
#include "precompiled.h"
using json = nlohmann::json;
ConnectionLoader::ConnectionLoader(MainWindow* main, Controller* rpc) {
ConnectionLoader::ConnectionLoader(MainWindow* main, Controller* rpc)
{
this->main = main;
this->rpc = rpc;
d = new QDialog(main);
connD = new Ui_ConnectionDialog();
connD->setupUi(d);
QPixmap logo(":/img/res/logobig.gif");
connD->topIcon->setBasePixmap(logo.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation));
connD->topIcon->setBasePixmap(
logo.scaled(
256,
256,
Qt::KeepAspectRatio,
Qt::SmoothTransformation
)
);
isSyncing = new QAtomicInteger<bool>();
}
ConnectionLoader::~ConnectionLoader() {
ConnectionLoader::~ConnectionLoader()
{
delete isSyncing;
delete connD;
delete d;
}
void ConnectionLoader::loadConnection() {
void ConnectionLoader::loadConnection()
{
QTimer::singleShot(1, [=]() { this->doAutoConnect(); });
if (!Settings::getInstance()->isHeadless())
d->exec();
}
void ConnectionLoader::doAutoConnect() {
void ConnectionLoader::doAutoConnect()
{
qDebug() << "Doing autoconnect";
auto config = std::shared_ptr<ConnectionConfig>(new ConnectionConfig());
config->dangerous = true;
config->server = Settings::getInstance()->getSettings().server;
@ -49,16 +54,24 @@ void ConnectionLoader::doAutoConnect() {
main->logger->write(QObject::tr("Attempting to initialize library with ") + config->server);
// Check to see if there's an existing wallet
if (litelib_wallet_exists(Settings::getDefaultChainName().toStdString().c_str())) {
if (litelib_wallet_exists(Settings::getDefaultChainName().toStdString().c_str()))
{
main->logger->write(QObject::tr("Using existing wallet."));
char* resp = litelib_initialize_existing(config->dangerous, config->server.toStdString().c_str());
char* resp = litelib_initialize_existing(
config->dangerous,
config->server.toStdString().c_str()
);
QString response = litelib_process_response(resp);
if (response.toUpper().trimmed() != "OK") {
if (response.toUpper().trimmed() != "OK")
{
showError(response);
return;
}
} else {
}
else
{
main->logger->write(QObject::tr("Create/restore wallet."));
createOrRestore(config->dangerous, config->server);
d->show();
@ -72,7 +85,6 @@ void ConnectionLoader::doAutoConnect() {
// If success, set the connection
main->logger->write("Connection is online.");
connection->setInfo(reply);
isSyncing = new QAtomicInteger<bool>();
isSyncing->store(true);
@ -80,10 +92,8 @@ void ConnectionLoader::doAutoConnect() {
syncTimer = new QTimer(main);
connection->doRPCWithDefaultErrorHandling("sync", "", [=](auto) {
isSyncing->store(false);
// Cancel the timer
syncTimer->deleteLater();
// When sync is done, set the connection
this->doRPCSetConnection(connection);
});
@ -94,10 +104,13 @@ void ConnectionLoader::doAutoConnect() {
if (isSyncing != nullptr && isSyncing->load()) {
// Get the sync status
connection->doRPC("syncstatus", "", [=](json reply) {
if (isSyncing != nullptr && reply.find("synced_blocks") != reply.end()) {
if (isSyncing != nullptr && reply.find("synced_blocks") != reply.end())
{
qint64 synced = reply["synced_blocks"].get<json::number_unsigned_t>();
qint64 total = reply["total_blocks"].get<json::number_unsigned_t>();
me->showInformation("Synced " + QString::number(synced) + " / " + QString::number(total));
me->showInformation(
"Synced " + QString::number(synced) + " / " + QString::number(total)
);
}
},
[=](QString err) {
@ -114,104 +127,110 @@ void ConnectionLoader::doAutoConnect() {
});
}
void ConnectionLoader::createOrRestore(bool dangerous, QString server) {
void ConnectionLoader::createOrRestore(bool dangerous, QString server)
{
// Close the startup dialog, since we'll be showing the wizard
d->hide();
// Create a wizard
FirstTimeWizard wizard(dangerous, server);
wizard.exec();
}
void ConnectionLoader::doRPCSetConnection(Connection* conn) {
void ConnectionLoader::doRPCSetConnection(Connection* conn)
{
qDebug() << "Connectionloader finished, setting connection";
rpc->setConnection(conn);
d->accept();
QTimer::singleShot(1, [=]() { delete this; });
}
Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> config) {
Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> config)
{
return new Connection(main, config);
}
// Update the UI with the status
void ConnectionLoader::showInformation(QString info, QString detail) {
void ConnectionLoader::showInformation(QString info, QString detail)
{
connD->status->setText(info);
connD->statusDetail->setText(detail);
}
/**
* Show error will close the loading dialog and show an error.
*/
void ConnectionLoader::showError(QString explanation) {
void ConnectionLoader::showError(QString explanation)
{
rpc->noConnection();
QMessageBox::critical(main, QObject::tr("Connection Error"), explanation, QMessageBox::Ok);
QMessageBox::critical(
main,
QObject::tr("Connection Error"),
explanation,
QMessageBox::Ok
);
d->close();
}
QString litelib_process_response(char* resp) {
QString litelib_process_response(char* resp)
{
char* resp_copy = new char[strlen(resp) + 1];
strcpy(resp_copy, resp);
//a safer version of strcpy
strncpy(resp_copy, resp, strlen(resp)+1);
litelib_rust_free_string(resp);
QString reply = QString::fromStdString(resp_copy);
memset(resp_copy, '-', strlen(resp_copy));
delete[] resp_copy;
return reply;
}
/***********************************************************************************
* Connection, Executor and Callback Class
************************************************************************************/
void Executor::run() {
void Executor::run()
{
char* resp = litelib_execute(this->cmd.toStdString().c_str(), this->args.toStdString().c_str());
QString reply = litelib_process_response(resp);
//qDebug() << "RPC Reply=" << reply;
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false);
if (parsed.is_discarded() || parsed.is_null()) {
auto parsed = json::parse(
reply.toStdString().c_str(),
nullptr,
false
);
if (parsed.is_discarded() || parsed.is_null())
emit handleError(reply);
} else {
else
emit responseReady(parsed);
}
}
void Callback::processRPCCallback(json resp) {
void Callback::processRPCCallback(json resp)
{
this->cb(resp);
// Destroy self
delete this;
}
void Callback::processError(QString resp) {
void Callback::processError(QString resp)
{
this->errCb(resp);
// Destroy self
delete this;
}
Connection::Connection(MainWindow* m, std::shared_ptr<ConnectionConfig> conf) {
Connection::Connection(MainWindow* m, std::shared_ptr<ConnectionConfig> conf)
{
this->config = conf;
this->main = m;
// Register the JSON type as a type that can be passed between signals and slots.
qRegisterMetaType<json>("json");
}
void Connection::doRPC(const QString cmd, const QString args, const std::function<void(json)>& cb,
const std::function<void(QString)>& errCb) {
if (shutdownInProgress) {
void Connection::doRPC(const QString cmd, const QString args, const std::function<void(json)>& cb, const std::function<void(QString)>& errCb)
{
if (shutdownInProgress)
// Ignoring RPC because shutdown in progress
return;
}
//qDebug() << "Doing RPC: " << cmd;
@ -223,24 +242,27 @@ void Connection::doRPC(const QString cmd, const QString args, const std::functio
QObject::connect(runner, &Executor::responseReady, c, &Callback::processRPCCallback);
QObject::connect(runner, &Executor::handleError, c, &Callback::processError);
QThreadPool::globalInstance()->start(runner);
}
void Connection::doRPCWithDefaultErrorHandling(const QString cmd, const QString args, const std::function<void(json)>& cb) {
void Connection::doRPCWithDefaultErrorHandling(const QString cmd, const QString args, const std::function<void(json)>& cb)
{
doRPC(cmd, args, cb, [=] (QString err) {
this->showTxError(err);
});
}
}
void Connection::doRPCIgnoreError(const QString cmd, const QString args, const std::function<void(json)>& cb) {
void Connection::doRPCIgnoreError(const QString cmd, const QString args, const std::function<void(json)>& cb)
{
doRPC(cmd, args, cb, [=] (auto) {
// Ignored error handling
});
}
void Connection::showTxError(const QString& error) {
if (error.isNull()) return;
void Connection::showTxError(const QString& error)
{
if (error.isNull())
return;
// Prevent multiple dialog boxes from showing, because they're all called async
static bool shown = false;
@ -248,14 +270,19 @@ void Connection::showTxError(const QString& error) {
return;
shown = true;
QMessageBox::critical(main, QObject::tr("Transaction Error"), QObject::tr("There was an error sending the transaction. The error was:") + "\n\n"
+ error, QMessageBox::StandardButton::Ok);
QMessageBox::critical(
main,
QObject::tr("Transaction Error"),
QObject::tr("There was an error sending the transaction. The error was:") + "\n\n" + error,
QMessageBox::StandardButton::Ok
);
shown = false;
}
/**
* Prevent all future calls from going through
*/
void Connection::shutdown() {
void Connection::shutdown()
{
shutdownInProgress = true;
}

646
src/controller.cpp

@ -9,7 +9,8 @@
using json = nlohmann::json;
Controller::Controller(MainWindow* main) {
Controller::Controller(MainWindow* main)
{
auto cl = new ConnectionLoader(main, this);
// Execute the load connection async, so we can set up the rest of RPC properly.
@ -49,24 +50,24 @@ Controller::Controller(MainWindow* main) {
zrpc = new LiteInterface();
}
Controller::~Controller() {
Controller::~Controller()
{
delete timer;
delete txTimer;
delete transactionsTableModel;
delete balancesTableModel;
delete model;
delete zrpc;
}
// Called when a connection to hushd is available.
void Controller::setConnection(Connection* c) {
if (c == nullptr) return;
void Controller::setConnection(Connection* c)
{
if (c == nullptr)
return;
this->zrpc->setConnection(c);
ui->statusBar->showMessage("");
// If we're allowed to get the Hush Price, get the prices
@ -81,473 +82,152 @@ void Controller::setConnection(Connection* c) {
// where we need to immediately refresh
refresh(true);
// Create Sietch zdust addr at startup.
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch1.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch2.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
// Create Sietch zdust addr at startup.
for(uint8_t i = 0; i < 10; i++)
{
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path = "";
if(i > 0)
path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch") + QString(i) + QString(".txt");
} );
else
path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch.txt");
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch3.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch4.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch5.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch6.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch7.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch8.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch9.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly))
{
file.close();
}
else
{
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
});
}
} );
}
// Build the RPC JSON Parameters for this tx
void Controller::fillTxJsonParams(json& allRecepients, Tx tx) {
void Controller::fillTxJsonParams(json& allRecepients, Tx tx)
{
Q_ASSERT(allRecepients.is_array());
// Construct the JSON params
json rec = json::object();
json dust = json::object();
json dust1 = json::object();
json dust2 = json::object();
json dust3 = json::object();
json dust4 = json::object();
json dust5 = json::object();
json dust6 = json::object();
json dust7 = json::object();
json dust8 = json::object();
json dust9 = json::object();
// Create Sietch zdust addr again to not use it twice.
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch1.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch2.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
// Construct the JSON params
json rec = json::object();
zrpc->createNewSietchZaddr( [=] (json reply) {
//creating the JSON dust parameters in a std::vector to iterate over there during tx
std::vector<json> dust(10);
dust.resize(10, json::object());
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch3.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch4.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
// Create Sietch zdust addr again to not use it twice.
for(uint8_t i = 0; i < 10; i++)
{
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path = "";
if(i > 0)
path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch") + QString(i) + QString(".txt");
else
path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly))
{
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch5.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
// Set sietch zdust addr to json.
for(uint8_t i = 0; i < 10; i++)
{
QString path = "";
if(i > 0)
path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch") + QString(i) + QString(".txt");
else
path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch.txt");
QFile inputFile(path);
if (inputFile.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile);
while (!in.atEnd())
{
QString line = in.readLine();
dust.at(i)["address"] = line.toStdString();
}
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch6.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
inputFile.close();
}
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch7.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch8.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch9.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
// Dust amt/memo, construct the JSON
for(uint8_t i = 0; i < 10; i++)
{
printf("Setting amount and memo to 0 for dust%i \n", i);
dust.at(i)["amount"] = 0;
dust.at(i)["memo"] = "";
}
} );
// Set sietch zdust addr to json.
QString path= (QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)) + QString("/Sietch.txt");
QFile inputFile(path);
if (inputFile.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile);
while (!in.atEnd())
{
QString line = in.readLine();
dust["address"] = line.toStdString();
}
inputFile.close();
}
QString path1= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch1.txt");
QFile inputFile1(path1);
if (inputFile1.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile1);
while (!in.atEnd())
{
QString line = in.readLine();
QString zdust = line;
dust1["address"] = zdust.toStdString();
}
inputFile1.close();
}
QString path2= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch2.txt");
QFile inputFile2(path2);
if (inputFile2.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile2);
while (!in.atEnd())
{
QString line = in.readLine();
dust2["address"] = line.toStdString();
}
inputFile2.close();
}
QString path3= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch3.txt");
QFile inputFile3(path3);
if (inputFile3.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile3);
while (!in.atEnd())
{
QString line = in.readLine();
dust3["address"] = line.toStdString();
}
inputFile3.close();
}
QString path4= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch4.txt");
QFile inputFile4(path4);
if (inputFile4.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile4);
while (!in.atEnd())
{
QString line = in.readLine();
dust4["address"] = line.toStdString();
}
inputFile4.close();
}
QString path5= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch5.txt");
QFile inputFile5(path5);
if (inputFile5.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile5);
while (!in.atEnd())
{
QString line = in.readLine();
dust5["address"] = line.toStdString();
}
inputFile5.close();
}
QString path6= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch6.txt");
QFile inputFile6(path6);
if (inputFile6.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile6);
while (!in.atEnd())
{
QString line = in.readLine();
dust6["address"] = line.toStdString();
}
inputFile6.close();
}
QString path7= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch7.txt");
QFile inputFile7(path7);
if (inputFile7.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile7);
while (!in.atEnd())
{
QString line = in.readLine();
dust7["address"] = line.toStdString();
}
inputFile7.close();
}
QString path8= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch8.txt");
QFile inputFile8(path8);
if (inputFile8.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile8);
while (!in.atEnd())
{
QString line = in.readLine();
dust8["address"] = line.toStdString();
}
inputFile.close();
}
QString path9= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch9.txt");
QFile inputFile9(path9);
if (inputFile9.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile9);
while (!in.atEnd())
{
QString line = in.readLine();
dust9["address"] = line.toStdString();
}
inputFile9.close();
}
// Dust amt/memo, construct the JSON
dust["amount"] = 0;
dust["memo"] = "";
dust1["amount"] = 0;
dust1["memo"] = "";
dust2["amount"] = 0;
dust2["memo"] = "";
dust3["amount"] = 0;
dust3["memo"] = "";
dust4["amount"] = 0;
dust4["memo"] = "";
dust5["amount"] = 0;
dust5["memo"] = "";
dust6["amount"] = 0;
dust6["memo"] = "";
dust7["amount"] = 0;
dust7["memo"] = "";
dust8["amount"] = 0;
dust8["memo"] = "";
dust9["amount"] = 0;
dust9["memo"] = "";
// For each addr/amt/memo, construct the JSON and also build the confirm dialog box
for (int i=0; i < tx.toAddrs.size(); i++) {
// For each addr/amt/memo, construct the JSON and also build the confirm dialog box
for (int i=0; i < tx.toAddrs.size(); i++)
{
auto toAddr = tx.toAddrs[i];
rec["address"] = toAddr.addr.toStdString();
rec["amount"] = toAddr.amount.toqint64();
rec["address"] = toAddr.addr.toStdString();
rec["amount"] = toAddr.amount.toqint64();
if (Settings::isZAddress(toAddr.addr) && !toAddr.memo.trimmed().isEmpty())
rec["memo"] = toAddr.memo.toStdString();
rec["memo"] = toAddr.memo.toStdString();
allRecepients.push_back(rec) ;
allRecepients.push_back(rec) ;
}
int decider = qrand() % ((100 + 1)-1)+ 1;// random int between 1 and 100
//50% chance of adding another zdust, shuffle.
int decider = qrand() % ((100 + 1)-1)+ 1;// random int between 1 and 100
//50% chance of adding another zdust, shuffle.
if(decider % 4 == 3) {
allRecepients.insert(std::begin(allRecepients),{dust,dust1,dust2,dust3,dust4,dust5,dust6,dust7,dust8}) ;
if(decider % 4 == 3)
allRecepients.insert(std::begin(allRecepients), {
dust.at(0),
dust.at(1),
dust.at(2),
dust.at(3),
dust.at(4),
dust.at(5),
dust.at(6),
dust.at(7),
dust.at(8)
}) ;
// std::shuffle(allRecepients.begin(),allRecepients.end(),std::random_device());
}else {
allRecepients.insert(std::begin(allRecepients),{dust,dust1,dust2,dust3,dust4,dust5,dust6,dust7,dust8,dust9}) ;
// std::shuffle(allRecepients.begin(),allRecepients.end(),std::random_device());
}
else
allRecepients.insert(std::begin(allRecepients), {
dust.at(0),
dust.at(1),
dust.at(2),
dust.at(3),
dust.at(4),
dust.at(5),
dust.at(6),
dust.at(7),
dust.at(8),
dust.at(9)
});
// std::shuffle(allRecepients.begin(),allRecepients.end(),std::random_device());
}
void Controller::noConnection() {
void Controller::noConnection()
{
QIcon i = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
main->statusIcon->setPixmap(i.pixmap(16, 16));
main->statusIcon->setToolTip("");
@ -576,21 +256,23 @@ void Controller::noConnection() {
}
/// This will refresh all the balance data from hushd
void Controller::refresh(bool force) {
void Controller::refresh(bool force)
{
if (!zrpc->haveConnection())
return noConnection();
getInfoThenRefresh(force);
}
void Controller::processInfo(const json& info) {
void Controller::processInfo(const json& info)
{
// Testnet?
QString chainName;
if (!info["chain_name"].is_null()) {
if (!info["chain_name"].is_null())
{
chainName = QString::fromStdString(info["chain_name"].get<json::string_t>());
Settings::getInstance()->setTestnet(chainName == "test");
};
}
QString version = QString::fromStdString(info["version"].get<json::string_t>());
Settings::getInstance()->sethushdVersion(version);
@ -600,7 +282,8 @@ void Controller::processInfo(const json& info) {
main->disableRecurring();
}
void Controller::getInfoThenRefresh(bool force) {
void Controller::getInfoThenRefresh(bool force)
{
if (!zrpc->haveConnection())
return noConnection();
@ -608,38 +291,59 @@ void Controller::getInfoThenRefresh(bool force) {
zrpc->fetchInfo([=] (const json& reply) {
prevCallSucceeded = true;
int curBlock = reply["latest_block_height"].get<json::number_integer_t>();
int longestchain = reply["longestchain"].get<json::number_integer_t>();
int notarized = reply["notarized"].get<json::number_integer_t>();
int difficulty = reply["difficulty"].get<json::number_integer_t>();
int blocks_until_halving= 340000 - curBlock;
int halving_days =
(blocks_until_halving * 150) / (60*60*24) ;
int halving_days = (blocks_until_halving * 150) / (60*60*24) ;
bool doUpdate = force || (model->getLatestBlock() != curBlock);
model->setLatestBlock(curBlock);
if (Settings::getInstance()->get_currency_name() == "EUR" || Settings::getInstance()->get_currency_name() == "CHF" || Settings::getInstance()->get_currency_name() == "RUB") {
ui->blockHeight->setText("Block: " + QLocale(QLocale::German).toString(curBlock));
ui->last_notarized->setText("Block: " + QLocale(QLocale::German).toString(notarized));
ui->longestchain->setText("Block: " + QLocale(QLocale::German).toString(longestchain));
ui->difficulty->setText(QLocale(QLocale::German).toString(difficulty));
ui->halvingTime->setText((QLocale(QLocale::German).toString(blocks_until_halving)) + " Blocks or , " + (QLocale(QLocale::German).toString(halving_days) + " days" ));
if (
Settings::getInstance()->get_currency_name() == "EUR" ||
Settings::getInstance()->get_currency_name() == "CHF" ||
Settings::getInstance()->get_currency_name() == "RUB"
)
{
ui->blockHeight->setText(
"Block: " + QLocale(QLocale::German).toString(curBlock)
);
ui->last_notarized->setText(
"Block: " + QLocale(QLocale::German).toString(notarized)
);
ui->longestchain->setText(
"Block: " + QLocale(QLocale::German).toString(longestchain)
);
ui->difficulty->setText(
QLocale(QLocale::German).toString(difficulty)
);
ui->halvingTime->setText(
(QLocale(QLocale::German).toString(blocks_until_halving)) +
" Blocks or , " + (QLocale(QLocale::German).toString(halving_days) + " days" )
);
}
else {
ui->blockHeight->setText("Block: " + QLocale(QLocale::English).toString(curBlock));
ui->last_notarized->setText("Block: " + QLocale(QLocale::English).toString(notarized));
ui->longestchain->setText("Block: " + QLocale(QLocale::English).toString(longestchain));
ui->difficulty->setText(QLocale(QLocale::English).toString(difficulty));
ui->halvingTime->setText((QLocale(QLocale::English).toString(blocks_until_halving)) + " Blocks or , " + (QLocale(QLocale::English).toString(halving_days) + " days" ));
else
{
ui->blockHeight->setText(
"Block: " + QLocale(QLocale::English).toString(curBlock)
);
ui->last_notarized->setText(
"Block: " + QLocale(QLocale::English).toString(notarized)
);
ui->longestchain->setText(
"Block: " + QLocale(QLocale::English).toString(longestchain)
);
ui->difficulty->setText(
QLocale(QLocale::English).toString(difficulty)
);
ui->halvingTime->setText(
(QLocale(QLocale::English).toString(blocks_until_halving)) +
" Blocks or , " + (QLocale(QLocale::English).toString(halving_days) + " days" )
);
}
ui->Version->setText(QString::fromStdString(reply["version"].get<json::string_t>()));
ui->Vendor->setText(QString::fromStdString(reply["vendor"].get<json::string_t>()));
main->logger->write(QString("Refresh. curblock ") % QString::number(curBlock) % ", update=" % (doUpdate ? "true" : "false") );
// Connected, so display checkmark.

Loading…
Cancel
Save