getAllMemos();
QString getPassword();
diff --git a/src/Model/ChatItem.cpp b/src/Model/ChatItem.cpp
index 3a190f0..4e1984f 100644
--- a/src/Model/ChatItem.cpp
+++ b/src/Model/ChatItem.cpp
@@ -158,6 +158,9 @@ QString ChatItem::toChatLine()
{
QDateTime myDateTime;
QString lock;
+ QString money;
+ QString moneyText;
+ QString moneyTextRequest;
myDateTime.setTime_t(_timestamp);
if (_notarize == true)
@@ -175,11 +178,43 @@ QString ChatItem::toChatLine()
{
lock = " ";
- }
+ }else{}
+
+ if (_memo.startsWith("Money transaction of :"))
+ {
+ if (_outgoing == true)
+ {
+
+ moneyText = QString("
") + QString("
") + QString(" Outgoing Money Transaction ") + QString(" ");
+ }else{
+
+
+ moneyText = QString("
") + QString("
") + QString(" Incoming Money Transaction ") + QString(" ");
+
+ }
+ }else{money = "";
+ moneyText = ""; }
+
+ if (_memo.startsWith("Request of :"))
+ {
+ if (_outgoing == true)
+ {
+
+ moneyTextRequest = QString("
") + QString("
") + QString(" Outgoing Hush Request ") + QString(" ");
+ }else{
+
+
+ moneyTextRequest = QString("
") + QString("
") + QString(" Incoming Hush Request ") + QString(" ");
+
+ }
+ }else{moneyTextRequest = "";
+ moneyTextRequest = ""; }
+
+
QString line = QString("") + myDateTime.toString("yyyy-MM-dd hh:mm");
- line += QString(lock) + QString("");
+ line += QString(lock) + QString(moneyText) + QString(moneyTextRequest) + QString("");
line +=QString("") + _memo.toHtmlEscaped() + QString("
");
return line;
}
diff --git a/src/addressbook.cpp b/src/addressbook.cpp
index 1f19fff..4271324 100644
--- a/src/addressbook.cpp
+++ b/src/addressbook.cpp
@@ -250,6 +250,9 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target)
);
+ parent->ui->listChat->verticalScrollBar()->setValue(
+ parent->ui->listChat->verticalScrollBar()->maximum());
+
});
// AddressBook::getInstance()->addAddressLabel(newLabel, ab.addr->text(), cid);
diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp
index a0012f9..a3b9775 100644
--- a/src/chatmodel.cpp
+++ b/src/chatmodel.cpp
@@ -466,6 +466,8 @@ Tx MainWindow::createTxFromChatPage() {
if (crypto_kx_seed_keypair(pk,sk,
MESSAGEAS1) !=0) {
+
+ this->logger->write("Suspicious keypair, bail out ");
}
////////////////Get the pubkey from Bob, so we can create the share key
@@ -475,7 +477,7 @@ Tx MainWindow::createTxFromChatPage() {
if (crypto_kx_server_session_keys(server_rx, server_tx,
pk, sk, pubkeyBob) != 0) {
- /* Suspicious client public key, bail out */
+ this->logger->write("Suspicious client public send key, bail out ");
}
@@ -542,6 +544,7 @@ void MainWindow::sendChat() {
QMessageBox msg(QMessageBox::Critical, tr("You have to select a contact and insert a Memo"),
tr("You have selected no Contact from Contactlist,\n") + tr("\nor your Memo is empty"),
QMessageBox::Ok, this);
+ ui->memoTxtChat->setEnabled(true);
msg.exec();
return;
@@ -571,6 +574,7 @@ void MainWindow::sendChat() {
QMessageBox::Ok, this);
msg.exec();
+ ui->memoTxtChat->setEnabled(true);
// abort the Tx
return;
@@ -590,6 +594,7 @@ void MainWindow::sendChat() {
movie->start();
ui->sendChatButton->show();
ui->sendChatButton->setEnabled(false);
+ ui->memoTxtChat->setEnabled(true);
} else {
@@ -599,6 +604,8 @@ void MainWindow::sendChat() {
movie1->start();
ui->sendChatButton->show();
ui->sendChatButton->setEnabled(false);
+ ui->memoTxtChat->setEnabled(true);
+
}
ui->memoTxtChat->clear();
@@ -617,6 +624,8 @@ void MainWindow::sendChat() {
ui->sendChatButton->setIcon(sendIcon);
movie->stop();
ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
+
}else{
QPixmap send(":/icons/res/sendBlack.png");
@@ -624,6 +633,7 @@ void MainWindow::sendChat() {
ui->sendChatButton->setIcon(sendIcon);
movie1->stop();
ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
}
});
@@ -636,6 +646,7 @@ void MainWindow::sendChat() {
// Errored out
[=] (QString opid, QString errStr) {
ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000);
+ ui->memoTxtChat->setEnabled(true);
if (!opid.isEmpty())
errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr;
@@ -650,6 +661,7 @@ void MainWindow::sendChat() {
ui->sendChatButton->setIcon(sendIcon);
movie->stop();
ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
}else{
QPixmap send(":/icons/res/sendBlack.png");
@@ -657,6 +669,7 @@ void MainWindow::sendChat() {
ui->sendChatButton->setIcon(sendIcon);
movie1->stop();
ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
}
@@ -674,6 +687,7 @@ QString MainWindow::doSendChatTxValidations(Tx tx) {
if (!Settings::isValidAddress(toAddr.addr)) {
QString addr = (toAddr.addr.length() > 100 ? toAddr.addr.left(100) + "..." : toAddr.addr);
return QString(tr("Recipient Address ")) % addr % tr(" is Invalid");
+ ui->memoTxtChat->setEnabled(true);
}
// This technically shouldn't be possible, but issue #62 seems to have discovered a bug
@@ -691,6 +705,7 @@ QString MainWindow::doSendChatTxValidations(Tx tx) {
if (available < total) {
return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 1 confirmations before they can be spent")
.arg(available.toDecimalhushString(), total.toDecimalhushString());
+ ui->memoTxtChat->setEnabled(true);
}
return "";
@@ -796,7 +811,7 @@ Tx MainWindow::createTxForSafeContactRequest()
unsigned char pk[crypto_kx_PUBLICKEYBYTES];
if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) {
- //
+ this->logger->write("Suspicious client public contact request key, bail out ");
}
QString publicKey = QByteArray(reinterpret_cast(pk), crypto_kx_PUBLICKEYBYTES).toHex();
@@ -828,8 +843,6 @@ void MainWindow::ContactRequest() {
if (size > max){
- // auto addr = "";
- // if (! Settings::isZAddress(AddressBook::addressFromAddressLabel(addr->text()))) {
QMessageBox msg(QMessageBox::Critical, tr("Your Message is too long"),
tr("You can only write messages with 512 character maximum \n") + tr("\n Please reduce your message to 235 character."),
QMessageBox::Ok, this);
diff --git a/src/connection.cpp b/src/connection.cpp
index 7cad23f..ca8c62e 100644
--- a/src/connection.cpp
+++ b/src/connection.cpp
@@ -67,7 +67,6 @@ void ConnectionLoader::doAutoConnect()
{
qDebug() << "Doing autoconnect";
auto config = std::shared_ptr(new ConnectionConfig());
- config->dangerous = false;
config->server = Settings::getInstance()->getSettings().server;
// Initialize the library
@@ -78,7 +77,6 @@ void ConnectionLoader::doAutoConnect()
{
main->logger->write(QObject::tr("Using existing wallet."));
char* resp = litelib_initialize_existing(
- config->dangerous,
config->server.toStdString().c_str()
);
QString response = litelib_process_response(resp);
@@ -93,7 +91,7 @@ void ConnectionLoader::doAutoConnect()
else
{
main->logger->write(QObject::tr("Create/restore wallet."));
- createOrRestore(config->dangerous, config->server);
+ createOrRestore(config->server);
d->show();
}
@@ -105,11 +103,14 @@ void ConnectionLoader::doAutoConnect()
// If success, set the connection
main->logger->write("Connection is online.");
connection->setInfo(reply);
+ main->logger->write("getting Connection reply");
isSyncing = new QAtomicInteger();
isSyncing->storeRelaxed(true);
+ main->logger->write("isSyncing");
// Do a sync at startup
syncTimer = new QTimer(main);
+ main->logger->write("Beginning sync");
connection->doRPCWithDefaultErrorHandling("sync", "", [=](QJsonValue) {
isSyncing->storeRelaxed(false);
// Cancel the timer
@@ -124,10 +125,13 @@ void ConnectionLoader::doAutoConnect()
if (isSyncing != nullptr && isSyncing->loadRelaxed()) {
// Get the sync status
connection->doRPC("syncstatus", "", [=](QJsonValue reply) {
+
if (isSyncing != nullptr && !reply.toObject()["synced_blocks"].isUndefined())
{
qint64 synced = reply["synced_blocks"].toInt();
+ main->logger->write("synced_blocks" + synced) ;
qint64 total = reply["total_blocks"].toInt();
+ main->logger->write("total_blocks" + total) ;
me->showInformation(
"Synced " + QString::number(synced) + " / " + QString::number(total)
);
@@ -141,30 +145,45 @@ void ConnectionLoader::doAutoConnect()
syncTimer->setInterval(1* 1000);
syncTimer->start();
+ main->logger->write("Start sync timer");
}, [=](QString err) {
showError(err);
});
}
-void ConnectionLoader::createOrRestore(bool dangerous, QString server)
+void ConnectionLoader::createOrRestore(QString server)
{
// Close the startup dialog, since we'll be showing the wizard
d->hide();
// Create a wizard
- FirstTimeWizard wizard(dangerous, server);
+ FirstTimeWizard wizard(server);
+ main->logger->write("Start new Wallet with FirstimeWizard");
wizard.exec();
}
void ConnectionLoader::doRPCSetConnection(Connection* conn)
{
qDebug() << "Connectionloader finished, setting connection";
+ main->logger->write("Connectionloader finished, setting connection");
rpc->setConnection(conn);
d->accept();
QTimer::singleShot(1, [=]() { delete this; });
+try
+{
+
QFile plaintextWallet(dirwalletconnection);
+ main->logger->write("Path to Wallet.dat : " );
plaintextWallet.remove();
+
+}catch (...)
+
+{
+
+ main->logger->write("no Plaintext wallet.dat");
+}
+
}
Connection* ConnectionLoader::makeConnection(std::shared_ptr config)
diff --git a/src/connection.h b/src/connection.h
index a253e2f..9076abd 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -10,7 +10,6 @@ class Controller;
struct ConnectionConfig {
QString server;
- bool dangerous;
QString proxy;
};
@@ -32,7 +31,7 @@ private:
void doAutoConnect();
- void createOrRestore(bool dangerous, QString server);
+ void createOrRestore(QString server);
void showError(QString explanation);
void showInformation(QString info, QString detail = "");
diff --git a/src/controller.cpp b/src/controller.cpp
index 7042a3f..a33a38f 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -101,6 +101,9 @@ void Controller::setConnection(Connection* c)
ui->listContactWidget
);
+
+ ui->listChat->verticalScrollBar()->setValue(
+ ui->listChat->verticalScrollBar()->maximum());
}
std::string Controller::encryptDecrypt(std::string toEncrypt)
@@ -635,7 +638,7 @@ void Controller::getInfoThenRefresh(bool force)
refreshAddresses(); // This calls refreshZSentTransactions() and refreshReceivedZTrans()
refreshTransactions();
}
-
+ refreshBalances();
int lag = longestchain - notarized ;
this->setLag(lag);
}, [=](QString err) {
@@ -727,7 +730,7 @@ void Controller::processUnspent(const QJsonValue& reply, QMap*
QString qsAddr = it["address"].toString();
int block = it["created_in_block"].toInt();
QString txid = it["created_in_txid"].toString();
- CAmount amount = CAmount::fromqint64(it["value"].toInt());
+ CAmount amount = CAmount::fromqint64(it["value"].toDouble());
bool spendable = it["unconfirmed_spent"].isNull() && it["spent"].isNull(); // TODO: Wait for 1 confirmations
bool pending = !it["unconfirmed_spent"].isNull();
@@ -738,7 +741,7 @@ void Controller::processUnspent(const QJsonValue& reply, QMap*
if (spendable)
{
(*balancesMap)[qsAddr] = (*balancesMap)[qsAddr] +
- CAmount::fromqint64(it["value"].toInt());
+ CAmount::fromqint64(it["value"].toDouble());
}
}
};
@@ -903,9 +906,9 @@ void Controller::refreshBalances()
// 1. Get the Balances
zrpc->fetchBalance([=] (QJsonValue reply) {
- CAmount balT = CAmount::fromqint64(reply["tbalance"].toInt());
- CAmount balZ = CAmount::fromqint64(reply["zbalance"].toInt());
- CAmount balVerified = CAmount::fromqint64(reply["verified_zbalance"].toInt());
+ CAmount balT = CAmount::fromqint64(reply["tbalance"].toDouble());
+ CAmount balZ = CAmount::fromqint64(reply["zbalance"].toDouble());
+ CAmount balVerified = CAmount::fromqint64(reply["verified_zbalance"].toDouble());
model->setBalT(balT);
model->setBalZ(balZ);
@@ -982,7 +985,7 @@ void Controller::refreshTransactions() {
address = o.toObject()["address"].toString();
// Sent items are -ve
- CAmount amount = CAmount::fromqint64(-1* o.toObject()["value"].toInt());
+ CAmount amount = CAmount::fromqint64(-1* o.toObject()["value"].toDouble());
// Check for Memos
@@ -990,7 +993,7 @@ void Controller::refreshTransactions() {
chatModel->addconfirmations(txid, confirmations);
}
- if ((confirmations == 1) && (chatModel->getConfirmationByTx(txid) != QString("0xdeadbeef"))) {
+ if ((confirmations > 0) && (chatModel->getConfirmationByTx(txid) != QString("0xdeadbeef"))) {
DataStore::getChatDataStore()->clear();
chatModel->killConfirmationCache();
chatModel->killMemoCache();
@@ -1083,7 +1086,7 @@ void Controller::refreshTransactions() {
if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0)
{
- // ?
+ main->logger->write("Keypair outgoing error");
}
unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
@@ -1095,7 +1098,7 @@ void Controller::refreshTransactions() {
if (crypto_kx_server_session_keys(server_rx, server_tx, pk, sk, pubkeyBob) != 0)
{
- /* Suspicious client public key, bail out */
+ main->logger->write("Suspicious client public outgoing key, bail out ");
}
const QByteArray ba = QByteArray::fromHex(memo.toUtf8());
@@ -1108,7 +1111,7 @@ void Controller::refreshTransactions() {
QString memodecrypt;
- if (encryptedMemoSize1 > 15)
+ if ((encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES) > 0)
{
//////unsigned char* as message from QString
#define MESSAGE2 (const unsigned char *) encryptedMemo
@@ -1143,6 +1146,7 @@ void Controller::refreshTransactions() {
}
else
{
+
memodecrypt = "";
}
@@ -1165,7 +1169,7 @@ void Controller::refreshTransactions() {
);
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
- updateUIBalances();
+ // updateUIBalances();
}
}
@@ -1190,18 +1194,18 @@ void Controller::refreshTransactions() {
}
else
{
- // Incoming Transaction
+
+ { // Incoming Transaction
address = (it.toObject()["address"].isNull() ? "" : it.toObject()["address"].toString());
model->markAddressUsed(address);
QString memo;
- if (!it.toObject()["memo"].isNull()) {
+ if (!it.toObject()["memo"].isNull())
memo = it.toObject()["memo"].toString();
- }
items.push_back(TransactionItemDetail{
address,
- CAmount::fromqint64(it.toObject()["amount"].toInt()),
+ CAmount::fromqint64(it.toObject()["amount"].toDouble()),
memo
});
@@ -1210,7 +1214,14 @@ void Controller::refreshTransactions() {
};
txdata.push_back(tx);
-
+ }
+
+ address = (it.toObject()["address"].isNull() ? "" : it.toObject()["address"].toString());
+ model->markAddressUsed(address);
+
+ QString memo;
+ if (!it.toObject()["memo"].isNull())
+ memo = it.toObject()["memo"].toString();
QString type;
QString publickey;
QString headerbytes;
@@ -1306,7 +1317,9 @@ void Controller::refreshTransactions() {
int position = it.toObject()["position"].toInt();
- if ((memo.startsWith("{") == false) && (headerbytes > 0))
+ int ciphercheck = memo.length() - crypto_secretstream_xchacha20poly1305_ABYTES;
+
+ if ((memo.startsWith("{") == false) && (headerbytes > 0) && (ciphercheck > 0))
{
if (chatModel->getMemoByTx(txid) == QString("0xdeadbeef"))
{
@@ -1337,7 +1350,7 @@ void Controller::refreshTransactions() {
if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0)
{
- //
+ main->logger->write("Suspicious outgoing key pair, bail out ");
}
unsigned char client_rx[crypto_kx_SESSIONKEYBYTES], client_tx[crypto_kx_SESSIONKEYBYTES];
@@ -1348,7 +1361,7 @@ void Controller::refreshTransactions() {
if (crypto_kx_client_session_keys(client_rx, client_tx, pk, sk, pubkeyBob) != 0)
{
- /* Suspicious client public key, bail out */
+ main->logger->write("Suspicious client public incoming key, bail out ");
}
const QByteArray ba = QByteArray::fromHex(memo.toUtf8());
@@ -1379,12 +1392,12 @@ void Controller::refreshTransactions() {
/////Only the QString gives weird data, so convert first to std::string
// crypto_secretstream_xchacha20poly1305_keygen(client_rx);
if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, client_rx) != 0) {
- /* Invalid header, no need to go any further */
+ main->logger->write("Invalid header incoming, no need to go any further ");
}
if (crypto_secretstream_xchacha20poly1305_pull
(&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) {
- /* Invalid/incomplete/corrupted ciphertext - abort */
+ main->logger->write("Invalid/incomplete/corrupted ciphertext - abort");
}
std::string decryptedMemo(reinterpret_cast(decrypted),MESSAGE1_LEN);
@@ -1464,8 +1477,9 @@ void Controller::refreshTransactions() {
chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat);
ui->listChat->verticalScrollBar()->setValue(
ui->listChat->verticalScrollBar()->maximum());
-
+
});
+
}
void Controller::refreshChat(QListView *listWidget, QLabel *label)
@@ -1479,6 +1493,8 @@ void Controller::refreshChat(QListView *listWidget, QLabel *label)
void Controller::refreshContacts(QListView *listWidget)
{
contactModel->renderContactList(listWidget);
+ ui->listChat->verticalScrollBar()->setValue(
+ ui->listChat->verticalScrollBar()->maximum());
}
// If the wallet is encrpyted and locked, we need to unlock it
diff --git a/src/emoji.ui b/src/emoji.ui
new file mode 100644
index 0000000..8118466
--- /dev/null
+++ b/src/emoji.ui
@@ -0,0 +1,339 @@
+
+
+ emojiDialog
+
+
+
+ 0
+ 0
+ 261
+ 150
+
+
+
+ Emoji
+
+
+ -
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+
+
+
+
+ :/emoji/res/emoji/emoji1.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/laughing.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/sweet_smile.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/joy.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/innocent.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/partying_face.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/icons/res/money-mouth.png
+
+
+
+ true
+
+
+
+
+
+ -
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+
+
+
+
+ :/emoji/res/emoji/face-with-rolling-eyes.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/face-with-tongue.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/face_with_3hearts.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/heart_shaped_eyes.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/nauseated-face.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/pile-of-poo.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/serious-face-with-symbols-covering-mouth.png
+
+
+
+ true
+
+
+
+
+
+ -
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+
+
+
+
+ :/emoji/res/emoji/smiling-face-with-sunglasses.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/stuck-out.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/hush-money-white.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/SD.png
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/src/firsttimewizard.cpp b/src/firsttimewizard.cpp
index 20e7d46..38901c9 100644
--- a/src/firsttimewizard.cpp
+++ b/src/firsttimewizard.cpp
@@ -9,10 +9,9 @@
#include "../lib/silentdragonlitelib.h"
-FirstTimeWizard::FirstTimeWizard(bool dangerous, QString server)
+FirstTimeWizard::FirstTimeWizard(QString server)
{
setWindowTitle("New wallet wizard");
- this->dangerous = dangerous;
this->server = server;
////backup addresslabels.dat if there is one, to restore it later
@@ -65,12 +64,23 @@ NewOrRestorePage::NewOrRestorePage(FirstTimeWizard *parent) : QWizardPage(parent
parent->button(QWizard::CommitButton)->setEnabled(false);
setButtonText(QWizard::CommitButton, "Next");
+ form.txtPassword->setEnabled(false);
+ form.txtConfirmPassword->setEnabled(false);
+
+ QObject::connect(form.TOS, &QRadioButton::clicked, [=](bool checked) {
+ if (checked) {
+
+ form.txtPassword->setEnabled(true);
+ form.txtConfirmPassword->setEnabled(true);
+
+ }
+ });
auto fnPasswordEdited = [=](const QString&) {
// Enable the Finish button if the passwords match.
QString passphraseBlank = form.txtPassword->text();
-
+
QString passphrase = QString("HUSH3") + passphraseBlank + QString("SDL");
@@ -83,6 +93,7 @@ NewOrRestorePage::NewOrRestorePage(FirstTimeWizard *parent) : QWizardPage(parent
form.radioRestoreWallet->setEnabled(true);
form.radioNewWallet->setEnabled(true);
form.radioNewWallet->setChecked(true);
+ parent->button(QWizard::CommitButton)->setEnabled(true);
int length = passphrase.length();
@@ -134,12 +145,7 @@ NewOrRestorePage::NewOrRestorePage(FirstTimeWizard *parent) : QWizardPage(parent
}
});
- QObject::connect(form.TOS, &QRadioButton::clicked, [=](bool checked) {
- if (checked) {
- parent->button(QWizard::CommitButton)->setEnabled(true);
-
- }
- });
+
@@ -187,7 +193,7 @@ NewSeedPage::NewSeedPage(FirstTimeWizard *parent) : QWizardPage(parent) {
void NewSeedPage::initializePage() {
// Call the library to create a new wallet.
- char* resp = litelib_initialize_new(parent->dangerous, parent->server.toStdString().c_str());
+ char* resp = litelib_initialize_new(parent->server.toStdString().c_str());
QString reply = litelib_process_response(resp);
QByteArray ba_reply = reply.toUtf8();
@@ -266,7 +272,7 @@ QString number_str = form.number->text();
qint64 number = number_str.toUInt();
// 3. Attempt to restore wallet with the seed phrase
{
- char* resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(),
+ char* resp = litelib_initialize_new_from_phrase(parent->server.toStdString().c_str(),
seed.toStdString().c_str(), birthday, number);
QString reply = litelib_process_response(resp);
diff --git a/src/firsttimewizard.h b/src/firsttimewizard.h
index 324f115..8b6de40 100644
--- a/src/firsttimewizard.h
+++ b/src/firsttimewizard.h
@@ -16,7 +16,7 @@ class FirstTimeWizard: public QWizard
public:
- FirstTimeWizard(bool dangerous, QString server);
+ FirstTimeWizard(QString server);
protected:
@@ -29,7 +29,6 @@ private:
Page_Restore
};
- bool dangerous;
QString server;
friend class NewOrRestorePage;
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 6910eff..84aa862 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -17,13 +17,16 @@
#include "settings.h"
#include "version.h"
#include "connection.h"
+#include "ui_sendHushTransactionChat.h"
#include "ui_contactrequest.h"
#include "ui_deposithush.h"
+#include "ui_emoji.h"
#include "ui_requestContactDialog.h"
#include "chatmodel.h"
#include "requestdialog.h"
#include "ui_startupencryption.h"
#include "ui_removeencryption.h"
+#include "ui_seedrestore.h"
#include "websockets.h"
#include "sodium.h"
#include "sodium/crypto_generichash_blake2b.h"
@@ -34,6 +37,9 @@
#include "DataStore/DataStore.h"
#include "firsttimewizard.h"
#include "../lib/silentdragonlitelib.h"
+#include
+#include
+#include
#ifdef Q_OS_WIN
@@ -157,17 +163,124 @@ MainWindow::MainWindow(QWidget *parent) :
// Rescan
QObject::connect(ui->actionRescan, &QAction::triggered, [=]() {
- // To rescan, we clear the wallet state, and then reload the connection
+
+ QFile file(dirwalletenc);
+ QFile file1(dirwallet);
+
+ if(fileExists(dirwalletenc))
+
+ {
+ file.remove();
+ file1.remove();
+ }
+
+
+ Ui_Restore restoreSeed;
+ QDialog dialog(this);
+ restoreSeed.setupUi(&dialog);
+ Settings::saveRestore(&dialog);
+
+
+ rpc->fetchSeed([&](QJsonValue reply) {
+ if (isJsonError(reply)) {
+ return;
+ }
+
+ restoreSeed.seed->setReadOnly(true);
+ restoreSeed.seed->setLineWrapMode(QPlainTextEdit::LineWrapMode::NoWrap);
+ QString seedJson = QLatin1String(QJsonDocument(reply.toObject()).toJson(QJsonDocument::Compact));
+ int startPos = seedJson.indexOf("seed") +7;
+ int endPos = seedJson.indexOf("}") -1;
+ int length = endPos - startPos;
+ QString seed = seedJson.mid(startPos, length);
+ restoreSeed.seed->setPlainText(seed);
+
+ int startPosB = seedJson.indexOf("birthday") +10;
+ int endPosB = seedJson.indexOf("seed") -2;
+ int lengthB = endPosB - startPosB;
+ QString birthday = seedJson.mid(startPosB, lengthB);
+ restoreSeed.birthday->setPlainText(birthday);
+ });
+
+ QObject::connect(restoreSeed.restore, &QPushButton::clicked, [&](){
+
+ QString seed = restoreSeed.seed->toPlainText();
+ if (seed.trimmed().split(" ").length() != 24) {
+ QMessageBox::warning(this, tr("Failed to restore wallet"),
+ tr("SilentDragonLite needs 24 words to restore wallet"),
+ QMessageBox::Ok);
+ return false;
+ }
+
+
+ // 2. Validate birthday
+ QString birthday_str = restoreSeed.birthday->toPlainText();
+ bool ok;
+ qint64 birthday = birthday_str.toUInt(&ok);
+ if (!ok) {
+ QMessageBox::warning(this, tr("Failed to parse wallet birthday"),
+ tr("Couldn't understand wallet birthday. This should be a block height from where to rescan the wallet. You can leave it as '0' if you don't know what it should be."),
+ QMessageBox::Ok);
+ return false;
+ }
+
+
+ QString number_str = restoreSeed.quantity->text();
+ qint64 number = number_str.toUInt();
+
+ auto config = std::shared_ptr(new ConnectionConfig());
+ config->server = Settings::getInstance()->getSettings().server;
+ // 3. Attempt to restore wallet with the seed phrase
+ {
+ char* resp = litelib_initialize_new_from_phrase(config->server.toStdString().c_str(),
+ seed.toStdString().c_str(), birthday, number);
+ QString reply = litelib_process_response(resp);
+
+ if (reply.toUpper().trimmed() != "OK") {
+ QMessageBox::warning(this, tr("Failed to restore wallet"),
+ tr("Couldn't restore the wallet") + "\n" + reply,
+ QMessageBox::Ok);
+
+ }
+ }
+
+ // 4. Finally attempt to save the wallet
+ {
+ char* resp = litelib_execute("save", "");
+ QString reply = litelib_process_response(resp);
+
+ QByteArray ba_reply = reply.toUtf8();
+ QJsonDocument jd_reply = QJsonDocument::fromJson(ba_reply);
+ QJsonObject parsed = jd_reply.object();
+
+ if (parsed.isEmpty() || parsed["result"].isNull()) {
+ QMessageBox::warning(this, tr("Failed to save wallet"),
+ tr("Couldn't save the wallet") + "\n" + reply,
+ QMessageBox::Ok);
+
+ } else {}
+
+ dialog.close();
+ // To rescan, we clear the wallet state, and then reload the connection
// This will start a sync, and show the scanning status.
this->getRPC()->clearWallet([=] (auto) {
// Save the wallet
this->getRPC()->saveWallet([=] (auto) {
// Then reload the connection. The ConnectionLoader deletes itself.
- auto cl = new ConnectionLoader(this, rpc);
+ auto cl = new ConnectionLoader(this, rpc);
cl->loadConnection();
- });
- });
- });
+ });
+ });
+
+
+ }
+
+ });
+
+ // });
+
+ dialog.exec();
+});
// Address Book
QObject::connect(ui->action_Address_Book, &QAction::triggered, this, &MainWindow::addressBook);
@@ -605,6 +718,30 @@ void MainWindow::setPassword(QString password)
_password = password;
}
+QString MainWindow::getAmt()
+{
+
+ return _amt;
+}
+
+void MainWindow::setAmt(QString amt)
+{
+
+ _amt = amt;
+}
+
+QString MainWindow::getMoneyMemo()
+{
+
+ return _moneymemo;
+}
+
+void MainWindow::setMoneyMemo(QString moneymemo)
+{
+
+ _moneymemo = moneymemo;
+}
+
void MainWindow::setupStatusBar() {
// Status Bar
loadingLabel = new QLabel();
@@ -1338,6 +1475,11 @@ void MainWindow::setupchatTab() {
}
QObject::connect(ui->sendChatButton, &QPushButton::clicked, this, &MainWindow::sendChat);
+ QObject::connect(ui->sendChatButton, &QPushButton::clicked, [&] () {
+
+ ui->memoTxtChat->setEnabled(false);
+
+ });
QObject::connect(ui->safeContactRequest, &QPushButton::clicked, this, &MainWindow::addContact);
QObject::connect(ui->pushContact, &QPushButton::clicked, this , &MainWindow::renderContactRequest);
@@ -1361,6 +1503,8 @@ void MainWindow::setupchatTab() {
ui->listChat->addAction(viewexplorer);
ui->listChat->addAction(copytxid);
+ });
+
QObject::connect(copymessage, &QAction::triggered, [=] {
@@ -1453,7 +1597,7 @@ void MainWindow::setupchatTab() {
}
});
-});
+
///////// Add contextmenu
QMenu* contextMenu;
@@ -1463,10 +1607,8 @@ void MainWindow::setupchatTab() {
QAction* requestHushAction;
QAction* subatomicAction;
contextMenu = new QMenu(ui->listContactWidget);
- requestAction = new QAction("Send a contact request - coming soon",contextMenu);
+ HushAction = new QAction("Send or Request Hush ",contextMenu);
editAction = new QAction("Delete this contact",contextMenu);
- HushAction = new QAction("Send a friend some Hush - coming soon",contextMenu);
- requestHushAction = new QAction("Request some Hush - coming soon",contextMenu);
subatomicAction = new QAction("Make a subatomic swap with a friend- coming soon",contextMenu);
@@ -1475,26 +1617,86 @@ void MainWindow::setupchatTab() {
QObject::connect(ui->listContactWidget, &QTableView::clicked, [=] () {
ui->listContactWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
- ui->listContactWidget->addAction(requestAction);
- ui->listContactWidget->addAction(editAction);
ui->listContactWidget->addAction(HushAction);
- ui->listContactWidget->addAction(requestHushAction);
+ ui->listContactWidget->addAction(editAction);
ui->listContactWidget->addAction(subatomicAction);
ui->memoTxtChat->setEnabled(true);
- /*QObject::connect(requestHushAction, &QAction::triggered, [=]() {
QModelIndex index = ui->listContactWidget->currentIndex();
- QString label_contact = index.data(Qt::DisplayRole).toString();
+ QString label_contact = index.data(Qt::DisplayRole).toString();
for(auto &p : AddressBook::getInstance()->getAllAddressLabels())
if (label_contact == p.getName()) {
ui->contactNameMemo->setText(p.getName());
rpc->refresh(true);
+
+ }
+ });
+
+ QObject::connect(HushAction, &QAction::triggered, [=]() {
+
+ QModelIndex index = ui->listContactWidget->currentIndex();
+ QString label_contact = index.data(Qt::DisplayRole).toString();
+
+ Ui_transactionHush transaction;
+ QDialog transactionDialog(this);
+ transaction.setupUi(&transactionDialog);
+ Settings::saveRestore(&transactionDialog);
+ // transaction.requestHush->setEnabled(false);
+ // transaction.requestHush->setVisible(false);
+ transaction.amountChat->setValidator(this->getAmountValidator());
+ QString icon = ":icons/res/hush-money-white.png";
+ QPixmap hush(icon);
+ transaction.label_3->setPixmap(hush);
+
+
+
+ for(auto &p : AddressBook::getInstance()->getAllAddressLabels())
+ if (label_contact == p.getName()) {
+
+ QStandardItemModel* contact = new QStandardItemModel();
+ QString avatar = p.getAvatar();
+ QStandardItem* Items1 = new QStandardItem(p.getName());
+ Items1->setData(QIcon(avatar),Qt::DecorationRole);
+ contact->appendRow(Items1);
+ transaction.contactName->setModel(contact);
+ transaction.contactName->setIconSize(QSize(60,70));
+ transaction.contactName->setUniformItemSizes(true);
+ transaction.contactName->setDragDropMode(QAbstractItemView::DropOnly);
+ transaction.contactName->show();
+
}
- MainWindow::showRequesthush();
-
- }); */
+
+ QObject::connect(transaction.sendHush, &QPushButton::clicked, [&] (){
+
+ QString amt = transaction.amountChat->text();
+ QString memo = transaction.MemoMoney->text();
+ this->setAmt(amt);
+ this->setMoneyMemo(memo);
+ transactionDialog.close();
+ });
+
+ QObject::connect(transaction.sendHush, &QPushButton::clicked, this , &MainWindow::sendMoneyChat);
+
+
+
+ QObject::connect(transaction.requestHush, &QPushButton::clicked, [&] (){
+
+ QString amt = transaction.amountChat->text();
+ QString memo = transaction.MemoMoney->text();
+ this->setAmt(amt);
+ this->setMoneyMemo(memo);
+ transactionDialog.close();
+ });
+
+ QObject::connect(transaction.requestHush, &QPushButton::clicked, this , &MainWindow::sendMoneyRequestChat);
+
+
+
+ transactionDialog.exec();
+
+ });
QObject::connect(editAction, &QAction::triggered, [=]() {
QModelIndex index = ui->listContactWidget->currentIndex();
@@ -1517,21 +1719,579 @@ void MainWindow::setupchatTab() {
}
});
+
+
+ui->memoTxtChat->setLenDisplayLabelChat(ui->memoSizeChat);
+
+}
+
+// Create a Tx from the current state of the Chat page.
+Tx MainWindow::createTxFromSendChatPage() {
+ Tx tx;
+ CAmount totalAmt;
+ // For each addr/amt in the Chat tab
+ {
+
+ QString amtStr = this->getAmt();
+ CAmount amt;
+ CAmount amtHm;
+
+ amt = CAmount::fromDecimalString(amtStr);
+ amtHm = CAmount::fromDecimalString("0");
+ totalAmt = totalAmt + amt;
+
QModelIndex index = ui->listContactWidget->currentIndex();
QString label_contact = index.data(Qt::DisplayRole).toString();
-
- for(auto &p : AddressBook::getInstance()->getAllAddressLabels())
- if (label_contact == p.getName()) {
- ui->contactNameMemo->setText(p.getName());
- rpc->refresh(true);
+
+ for(auto &c : AddressBook::getInstance()->getAllAddressLabels())
+
+ if (label_contact == c.getName()) {
+
+ QString cid = c.getCid();
+ QString myAddr = c.getMyAddress();
+ QString type = "Money";
+ QString addr = c.getPartnerAddress();
+ QString moneymemo = this->getMoneyMemo();
+
+ /////////User input for chatmemos
+ QString memoplain = QString("Money transaction of : ") + amtStr + QString(" HUSH") + QString("\n") + QString("\n") + moneymemo;
+
+ /////////We convert the user input from QString to unsigned char*, so we can encrypt it later
+ int lengthmemo = memoplain.length();
+
+ char *memoplainchar = NULL;
+ memoplainchar = new char[lengthmemo+2];
+ strncpy(memoplainchar, memoplain.toUtf8(), lengthmemo +1);
+
+ QString pubkey = this->getPubkeyByAddress(addr);
+ QString passphraseHash = DataStore::getChatDataStore()->getPassword();
+ int length = passphraseHash.length();
+
+ ////////////////Generate the secretkey for our message encryption
+
+ char *hashEncryptionKeyraw = NULL;
+ hashEncryptionKeyraw = new char[length+1];
+ strncpy(hashEncryptionKeyraw, passphraseHash.toUtf8(), length+1);
+
+ #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)
+ #define MESSAGEAS1_LEN length
+
+
+ unsigned char sk[crypto_kx_SECRETKEYBYTES];
+ unsigned char pk[crypto_kx_PUBLICKEYBYTES];
+ unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
+
+ if (crypto_kx_seed_keypair(pk,sk,
+ MESSAGEAS1) !=0) {
+
+ this->logger->write("Suspicious keypair, bail out ");
+ }
+ ////////////////Get the pubkey from Bob, so we can create the share key
+
+ const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1());
+ const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData());
+ /////Create the shared key for sending the message
+
+ if (crypto_kx_server_session_keys(server_rx, server_tx,
+ pk, sk, pubkeyBob) != 0) {
+ this->logger->write("Suspicious client public send key, bail out ");
+ }
+
+ // Let's try to preserve Unicode characters
+ QByteArray ba_memo = memoplain.toUtf8();
+ int ba_memo_length = ba_memo.size();
+
+ #define MESSAGEMoney (const unsigned char *) ba_memo.data()
+ #define MESSAGE_LENMoney ba_memo_length
+
+
+ ////////////Now lets encrypt the message Alice send to Bob//////////////////////////////
+ //#define MESSAGE (const unsigned char *) memoplainchar
+ //#define MESSAGE_LEN lengthmemo
+ #define CIPHERTEXT_LEN (crypto_secretstream_xchacha20poly1305_ABYTES + MESSAGE_LENMoney)
+ unsigned char ciphertext[CIPHERTEXT_LEN];
+ unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
+
+ crypto_secretstream_xchacha20poly1305_state state;
+
+ /* Set up a new stream: initialize the state and create the header */
+ crypto_secretstream_xchacha20poly1305_init_push(&state, header, server_tx);
+
+
+ /* Now, encrypt the first chunk. `c1` will contain an encrypted,
+ * authenticated representation of `MESSAGE_PART1`. */
+ crypto_secretstream_xchacha20poly1305_push
+ (&state, ciphertext, NULL, MESSAGEMoney, MESSAGE_LENMoney, NULL, 0, crypto_secretstream_xchacha20poly1305_TAG_FINAL);
+
+ ////Create the HM for this message
+ QString headerbytes = QByteArray(reinterpret_cast(header), crypto_secretstream_xchacha20poly1305_HEADERBYTES).toHex();
+ QString publickeyAlice = QByteArray(reinterpret_cast(pk), crypto_kx_PUBLICKEYBYTES).toHex();
+
+
+ QString hmemo= createHeaderMemo(type,cid,myAddr,headerbytes,publickeyAlice,1,0);
+
+ /////Ciphertext Memo
+ QString memo = QByteArray(reinterpret_cast(ciphertext), CIPHERTEXT_LEN).toHex();
+
+
+ tx.toAddrs.push_back(ToFields{addr, amtHm, hmemo});
+ tx.toAddrs.push_back(ToFields{addr, amt, memo});
+
+ }
+ }
+
+ tx.fee = Settings::getMinerFee();
+
+ return tx;
+
+}
+
+void MainWindow::sendMoneyChat() {
+
+////////////////////////////Todo: Check if a Contact is selected//////////
+
+ // Create a Tx from the values on the send tab. Note that this Tx object
+ // might not be valid yet.
+
+ /* QString Name = ui->contactNameMemo->text();
+
+ if ((ui->contactNameMemo->text().isEmpty()) || (ui->memoTxtChat->toPlainText().trimmed().isEmpty())) {
+
+ QMessageBox msg(QMessageBox::Critical, tr("You have to select a contact and insert a Memo"),
+ tr("You have selected no Contact from Contactlist,\n") + tr("\nor your Memo is empty"),
+ QMessageBox::Ok, this);
+
+ msg.exec();
+ return;
+ }*/
+
+
+ Tx tx = createTxFromSendChatPage();
+
+ QString error = doSendChatMoneyTxValidations(tx);
+
+ if (!error.isEmpty()) {
+ // Something went wrong, so show an error and exit
+ QMessageBox msg(QMessageBox::Critical, tr("Message Error"), error,
+ QMessageBox::Ok, this);
+
+ msg.exec();
+ ui->memoTxtChat->setEnabled(true);
+
+ // abort the Tx
+ return;
+ }
+
+ auto movie = new QMovie(this);
+ auto movie1 = new QMovie(this);
+ movie->setFileName(":/img/res/loaderblack.gif");
+ movie1->setFileName(":/img/res/loaderwhite.gif");
+
+ auto theme = Settings::getInstance()->get_theme_name();
+ if (theme == "Dark" || theme == "Midnight") {
+
+ connect(movie, &QMovie::frameChanged, [=]{
+ ui->sendChatButton->setIcon(movie->currentPixmap());
+ });
+ movie->start();
+ ui->sendChatButton->show();
+ ui->sendChatButton->setEnabled(false);
+
+ } else {
+
+ connect(movie1, &QMovie::frameChanged, [=]{
+ ui->sendChatButton->setIcon(movie1->currentPixmap());
+ });
+ movie1->start();
+ ui->sendChatButton->show();
+ ui->sendChatButton->setEnabled(false);
+ ui->memoTxtChat->setEnabled(false);
}
- });
+
+ ui->memoTxtChat->clear();
+
+ // And send the Tx
+ rpc->executeTransaction(tx,
+ [=] (QString txid) {
+ ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
+
+
+ QTimer::singleShot(1000, [=]() {
+
+ if (theme == "Dark" || theme == "Midnight") {
+ QPixmap send(":/icons/res/send-white.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie->stop();
+ ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
+ }else{
+
+ QPixmap send(":/icons/res/sendBlack.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie1->stop();
+ ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
+ }
+
+ });
+
+ // Force a UI update so we get the unconfirmed Tx
+ rpc->refresh(true);
+ ui->memoTxtChat->clear();
+ // ui->memoTxtChat->setEnabled(true);
+
+ },
+ // Errored out
+ [=] (QString opid, QString errStr) {
+ ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000);
+ ui->memoTxtChat->setEnabled(true);
+
+ if (!opid.isEmpty())
+ errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr;
+
+ QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok);
+ movie->stop();
+ ui->memoTxtChat->setEnabled(true);
+
+
+ if (theme == "Dark" || theme == "Midnight") {
+ QPixmap send(":/icons/res/send-white.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie->stop();
+ ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
+ }else{
+
+ QPixmap send(":/icons/res/sendBlack.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie1->stop();
+ ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
+ }
+
+
+ }
+ );
+
+ }
+
+QString MainWindow::doSendChatMoneyTxValidations(Tx tx) {
+ // Check to see if we have enough verified funds to send the Tx.
+
+ CAmount total;
+ for (auto toAddr : tx.toAddrs) {
+ if (!Settings::isValidAddress(toAddr.addr)) {
+ QString addr = (toAddr.addr.length() > 100 ? toAddr.addr.left(100) + "..." : toAddr.addr);
+ return QString(tr("Recipient Address ")) % addr % tr(" is Invalid");
+ ui->memoTxtChat->setEnabled(true);
+ }
+
+ // This technically shouldn't be possible, but issue #62 seems to have discovered a bug
+ // somewhere, so just add a check to make sure.
+ if (toAddr.amount.toqint64() < 0) {
+ return QString(tr("Amount for address '%1' is invalid!").arg(toAddr.addr));
+ ui->memoTxtChat->setEnabled(true);
+ }
+
+ total = total + toAddr.amount;
+ }
+ total = total + tx.fee;
+
+ auto available = rpc->getModel()->getAvailableBalance();
+
+ if (available < total) {
+ return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 1 confirmations before they can be spent")
+ .arg(available.toDecimalhushString(), total.toDecimalhushString());
+ ui->memoTxtChat->setEnabled(true);
+
+ }
+
+ return "";
+}
+
+// Create a Tx from the current state of the Chat page.
+Tx MainWindow::createTxFromSendRequestChatPage() {
+ Tx tx;
+ CAmount totalAmt;
+ // For each addr/amt in the Chat tab
+ {
+
+ QString amtStr = this->getAmt();
+ CAmount amt;
+ CAmount amtHm;
+
+ amt = CAmount::fromDecimalString("0");
+ amtHm = CAmount::fromDecimalString("0");
+ totalAmt = totalAmt + amt;
+
+ QModelIndex index = ui->listContactWidget->currentIndex();
+ QString label_contact = index.data(Qt::DisplayRole).toString();
+
+ for(auto &c : AddressBook::getInstance()->getAllAddressLabels())
+
+ if (label_contact == c.getName()) {
+
+ QString cid = c.getCid();
+ QString myAddr = c.getMyAddress();
+ QString type = "Money";
+ QString addr = c.getPartnerAddress();
+ QString moneymemo = this->getMoneyMemo();
+
+ /////////User input for chatmemos
+ QString memoplain = QString("Request of : ") + amtStr + QString(" HUSH ") + QString("\n") + QString("\n") + moneymemo;
+
+ /////////We convert the user input from QString to unsigned char*, so we can encrypt it later
+ int lengthmemo = memoplain.length();
+
+ char *memoplainchar = NULL;
+ memoplainchar = new char[lengthmemo+2];
+ strncpy(memoplainchar, memoplain.toUtf8(), lengthmemo +1);
+
+ QString pubkey = this->getPubkeyByAddress(addr);
+ QString passphraseHash = DataStore::getChatDataStore()->getPassword();
+ int length = passphraseHash.length();
+
+ ////////////////Generate the secretkey for our message encryption
+
+ char *hashEncryptionKeyraw = NULL;
+ hashEncryptionKeyraw = new char[length+1];
+ strncpy(hashEncryptionKeyraw, passphraseHash.toUtf8(), length+1);
+
+ #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)
+ #define MESSAGEAS1_LEN length
+
+
+ unsigned char sk[crypto_kx_SECRETKEYBYTES];
+ unsigned char pk[crypto_kx_PUBLICKEYBYTES];
+ unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
+
+ if (crypto_kx_seed_keypair(pk,sk,
+ MESSAGEAS1) !=0) {
+
+ this->logger->write("Suspicious keypair, bail out ");
+ }
+ ////////////////Get the pubkey from Bob, so we can create the share key
+
+ const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1());
+ const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData());
+ /////Create the shared key for sending the message
+
+ if (crypto_kx_server_session_keys(server_rx, server_tx,
+ pk, sk, pubkeyBob) != 0) {
+ this->logger->write("Suspicious client public send key, bail out ");
+ }
+
+
+ // Let's try to preserve Unicode characters
+ QByteArray ba_memo = memoplain.toUtf8();
+ int ba_memo_length = ba_memo.size();
+
+ #define MESSAGEMoney (const unsigned char *) ba_memo.data()
+ #define MESSAGE_LENMoney ba_memo_length
+
+
+ ////////////Now lets encrypt the message Alice send to Bob//////////////////////////////
+ //#define MESSAGE (const unsigned char *) memoplainchar
+ //#define MESSAGE_LEN lengthmemo
+ #define CIPHERTEXT_LEN (crypto_secretstream_xchacha20poly1305_ABYTES + MESSAGE_LENMoney)
+ unsigned char ciphertext[CIPHERTEXT_LEN];
+ unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
+
+ crypto_secretstream_xchacha20poly1305_state state;
+
+ /* Set up a new stream: initialize the state and create the header */
+ crypto_secretstream_xchacha20poly1305_init_push(&state, header, server_tx);
+
+
+ /* Now, encrypt the first chunk. `c1` will contain an encrypted,
+ * authenticated representation of `MESSAGE_PART1`. */
+ crypto_secretstream_xchacha20poly1305_push
+ (&state, ciphertext, NULL, MESSAGEMoney, MESSAGE_LENMoney, NULL, 0, crypto_secretstream_xchacha20poly1305_TAG_FINAL);
+
+ ////Create the HM for this message
+ QString headerbytes = QByteArray(reinterpret_cast(header), crypto_secretstream_xchacha20poly1305_HEADERBYTES).toHex();
+ QString publickeyAlice = QByteArray(reinterpret_cast(pk), crypto_kx_PUBLICKEYBYTES).toHex();
+
+
+ QString hmemo= createHeaderMemo(type,cid,myAddr,headerbytes,publickeyAlice,1,0);
+
+ /////Ciphertext Memo
+ QString memo = QByteArray(reinterpret_cast(ciphertext), CIPHERTEXT_LEN).toHex();
+
-ui->memoTxtChat->setLenDisplayLabelChat(ui->memoSizeChat);
+ tx.toAddrs.push_back(ToFields{addr, amtHm, hmemo});
+ tx.toAddrs.push_back(ToFields{addr, amt, memo});
+
+ }
+ }
+
+ tx.fee = Settings::getMinerFee();
+
+ return tx;
}
+void MainWindow::sendMoneyRequestChat() {
+
+////////////////////////////Todo: Check if a Contact is selected//////////
+
+ // Create a Tx from the values on the send tab. Note that this Tx object
+ // might not be valid yet.
+
+ /* QString Name = ui->contactNameMemo->text();
+
+ if ((ui->contactNameMemo->text().isEmpty()) || (ui->memoTxtChat->toPlainText().trimmed().isEmpty())) {
+
+ QMessageBox msg(QMessageBox::Critical, tr("You have to select a contact and insert a Memo"),
+ tr("You have selected no Contact from Contactlist,\n") + tr("\nor your Memo is empty"),
+ QMessageBox::Ok, this);
+
+ msg.exec();
+ return;
+ }*/
+
+
+ Tx tx = createTxFromSendRequestChatPage();
+
+ QString error = doSendChatMoneyRequestTxValidations(tx);
+
+ if (!error.isEmpty()) {
+ // Something went wrong, so show an error and exit
+ QMessageBox msg(QMessageBox::Critical, tr("Message Error"), error,
+ QMessageBox::Ok, this);
+
+ msg.exec();
+
+ // abort the Tx
+ return;
+ }
+
+ auto movie = new QMovie(this);
+ auto movie1 = new QMovie(this);
+ movie->setFileName(":/img/res/loaderblack.gif");
+ movie1->setFileName(":/img/res/loaderwhite.gif");
+
+ auto theme = Settings::getInstance()->get_theme_name();
+ if (theme == "Dark" || theme == "Midnight") {
+
+ connect(movie, &QMovie::frameChanged, [=]{
+ ui->sendChatButton->setIcon(movie->currentPixmap());
+ });
+ movie->start();
+ ui->sendChatButton->show();
+ ui->sendChatButton->setEnabled(false);
+
+ } else {
+
+ connect(movie1, &QMovie::frameChanged, [=]{
+ ui->sendChatButton->setIcon(movie1->currentPixmap());
+ });
+ movie1->start();
+ ui->sendChatButton->show();
+ ui->sendChatButton->setEnabled(false);
+ }
+
+ ui->memoTxtChat->clear();
+
+ // And send the Tx
+ rpc->executeTransaction(tx,
+ [=] (QString txid) {
+ ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
+
+
+ QTimer::singleShot(1000, [=]() {
+
+ if (theme == "Dark" || theme == "Midnight") {
+ QPixmap send(":/icons/res/send-white.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie->stop();
+ ui->sendChatButton->setEnabled(true);
+ }else{
+
+ QPixmap send(":/icons/res/sendBlack.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie1->stop();
+ ui->sendChatButton->setEnabled(true);
+ }
+
+ });
+
+ // Force a UI update so we get the unconfirmed Tx
+ rpc->refresh(true);
+ ui->memoTxtChat->clear();
+
+ },
+ // Errored out
+ [=] (QString opid, QString errStr) {
+ ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000);
+
+ if (!opid.isEmpty())
+ errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr;
+
+ QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok);
+ movie->stop();
+
+
+ if (theme == "Dark" || theme == "Midnight") {
+ QPixmap send(":/icons/res/send-white.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie->stop();
+ ui->sendChatButton->setEnabled(true);
+ }else{
+
+ QPixmap send(":/icons/res/sendBlack.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie1->stop();
+ ui->sendChatButton->setEnabled(true);
+ }
+
+
+
+ }
+ );
+
+ }
+
+QString MainWindow::doSendChatMoneyRequestTxValidations(Tx tx) {
+ // Check to see if we have enough verified funds to send the Tx.
+
+ CAmount total;
+ for (auto toAddr : tx.toAddrs) {
+ if (!Settings::isValidAddress(toAddr.addr)) {
+ QString addr = (toAddr.addr.length() > 100 ? toAddr.addr.left(100) + "..." : toAddr.addr);
+ return QString(tr("Recipient Address ")) % addr % tr(" is Invalid");
+ }
+
+ // This technically shouldn't be possible, but issue #62 seems to have discovered a bug
+ // somewhere, so just add a check to make sure.
+ if (toAddr.amount.toqint64() < 0) {
+ return QString(tr("Amount for address '%1' is invalid!").arg(toAddr.addr));
+ }
+
+ total = total + toAddr.amount;
+ }
+ total = total + tx.fee;
+
+ auto available = rpc->getModel()->getAvailableBalance();
+
+ if (available < total) {
+ return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 1 confirmations before they can be spent")
+ .arg(available.toDecimalhushString(), total.toDecimalhushString());
+ }
+
+ return "";
+}
+
+
void MainWindow::updateChat()
{
rpc->refreshChat(ui->listChat,ui->memoSizeChat);
@@ -1981,3 +2741,125 @@ void MainWindow::on_givemeZaddr_clicked()
});
}
+
+void MainWindow::on_emojiButton_clicked()
+{
+
+ QDialog emojiDialog(this);
+ Ui_emojiDialog emoji;
+ emoji.setupUi(&emojiDialog);
+ Settings::saveRestore(&emojiDialog);
+
+QObject::connect(emoji.smiley, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":smiley:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.money, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":money_mouth:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.laughing, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":laughing:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.sweet_smile, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":sweet_smile:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.joy, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":joy:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.innocent, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":innocent:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.partying_face, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":partying_face:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.rolling_eyes, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":rolling_eyes:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.tongue, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":stuck_out_tongue:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.hearts3, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":face_with_3hearts:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.heart_eyes, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":heart_eyes:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.nauseated, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":nauseated:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.poop, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":poop:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.symbols_mouth, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":symbols_mouth:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.sunglass, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":sunglass:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.stuck_out, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":stuck_out:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.hush_white, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":hush_white:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.sd, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":sd:");
+
+ emojiDialog.close();
+});
+
+
+
+ emojiDialog.exec();
+}
+
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 3550b5a..ac77d8b 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -49,12 +49,18 @@ public:
QString doSendTxValidations(Tx tx);
QString doSendChatTxValidations(Tx tx);
+ QString doSendChatMoneyTxValidations(Tx tx);
QString doSendRequestTxValidations(Tx tx);
+ QString doSendChatMoneyRequestTxValidations(Tx tx);
QString getCid();
+ QString getAmt();
+ QString getMoneyMemo();
QString getPassword();
std::map pubkeyMap;
QString getPubkeyByAddress(QString requestZaddr);
void setPassword(QString Password);
+ void setAmt(QString Amt);
+ void setMoneyMemo(QString MoneyMemo);
void addPubkey(QString requestZaddr, QString pubkey);
@@ -105,12 +111,15 @@ private slots:
void on_givemeZaddr_clicked();
+ void on_emojiButton_clicked();
private:
bool fileExists(QString path);
void closeEvent(QCloseEvent* event);
void closeEventpw(QCloseEvent* event);
QString _password;
+ QString _amt;
+ QString _moneymemo;
void setupSendTab();
@@ -135,7 +144,8 @@ private:
Tx createTxFromChatPage();
Tx createTxForSafeContactRequest();
-
+ Tx createTxFromSendChatPage();
+ Tx createTxFromSendRequestChatPage();
void encryptWallet();
void removeWalletEncryption();
@@ -144,6 +154,8 @@ private:
void cancelButton();
void sendButton();
void sendChat();
+ void sendMoneyChat();
+ void sendMoneyRequestChat();
void addContact();
void ContactRequest();
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
index f771bc4..4e62995 100644
--- a/src/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -6,7 +6,7 @@
0
0
- 1274
+ 1308
779
@@ -59,7 +59,7 @@
-
- 5
+ 0
@@ -428,7 +428,7 @@
0
0
- 1226
+ 1260
509
@@ -1341,8 +1341,8 @@
HushChat
-
-
-
+
+
-
-
@@ -1546,7 +1546,7 @@
- -
+
-
QLayout::SetDefaultConstraint
@@ -1683,6 +1683,12 @@
0
+
+
+ 850
+ 0
+
+
false
@@ -1706,9 +1712,48 @@
+ -
+
+
+
+ 20
+ 0
+
+
+
+
+
+
+
+ :/emoji/res/emoji/emoji1.png
+
+
+
+
+ 17
+ 17
+
+
+
+ true
+
+
+
-
-
-
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
@@ -1716,6 +1761,12 @@
0
+
+
+ 16777215
+ 50
+
+
100
@@ -1747,7 +1798,7 @@
- -
+
-
@@ -1783,7 +1834,7 @@
0
0
- 1274
+ 1308
22
diff --git a/src/restoreSeed.ui b/src/restoreSeed.ui
new file mode 100644
index 0000000..fb923db
--- /dev/null
+++ b/src/restoreSeed.ui
@@ -0,0 +1,72 @@
+
+
+
+
+ Dialog
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ Dialog
+
+
+
+
+ 30
+ 240
+ 341
+ 32
+
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ Dialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ Dialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
+
diff --git a/src/scripts/mkrelease.sh b/src/scripts/mkrelease.sh
index 15e22ac..1a965df 100755
--- a/src/scripts/mkrelease.sh
+++ b/src/scripts/mkrelease.sh
@@ -35,6 +35,15 @@ rm -rf bin/SilentDragonLite* > /dev/null
# Build the lib first
cd lib && make release && cd ..
make -j$(nproc) > /dev/null
+make install INSTALL_ROOT=AppDir
+
+# now, build AppImage using linuxdeploy and linuxdeploy-plugin-qt
+# download linuxdeploy and its Qt plugin
+wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
+wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
+
+# make them executable
+chmod +x linuxdeploy*.AppImage
echo "[OK]"
diff --git a/src/seedrestore.ui b/src/seedrestore.ui
new file mode 100644
index 0000000..697c2c2
--- /dev/null
+++ b/src/seedrestore.ui
@@ -0,0 +1,114 @@
+
+
+ Restore
+
+
+
+ 0
+ 0
+ 637
+ 429
+
+
+
+ Restore your Wallet
+
+
+
-
+
+
+
+ 0
+ 284
+
+
+
+
+ -
+
+
-
+
+
+ Birthday :
+
+
+
+ -
+
+
+ Quantity :
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 529
+ 0
+
+
+
+
+ 16777215
+ 25
+
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+
+ -
+
+
+
+ 529
+ 0
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 521
+ 20
+
+
+
+
+ -
+
+
+
+ 89
+ 16777215
+
+
+
+ Restore
+
+
+
+
+
+
+
+
diff --git a/src/sendHushTransactionChat.ui b/src/sendHushTransactionChat.ui
new file mode 100644
index 0000000..94bc851
--- /dev/null
+++ b/src/sendHushTransactionChat.ui
@@ -0,0 +1,276 @@
+
+
+ transactionHush
+
+
+
+ 0
+ 0
+ 212
+ 405
+
+
+
+ Send or Request Hush
+
+
+ -
+
+
+ To :
+
+
+
+ -
+
+
+ QLayout::SetFixedSize
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+
+ 16777215
+ 70
+
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ false
+
+
+
+
+
+ -
+
+
+ QLayout::SetFixedSize
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+
+ 80
+ 16777215
+
+
+
+ Amount:
+
+
+
+ -
+
+
+
+ 80
+ 16777215
+
+
+
+
+ 200
+ 0
+
+
+
+ 9
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ Amount
+
+
+
+ -
+
+
+
+ 35
+ 16777215
+
+
+
+ Hush
+
+
+
+
+
+ -
+
+
+ Memo :
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+
+ 0
+ 41
+
+
+
+
+ 16777215
+ 41
+
+
+
+ 100
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 39
+
+
+
+
+ -
+
+
+ QLayout::SetFixedSize
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+ Request Hush
+
+
+
+ -
+
+
+
+ 16777215
+ 25
+
+
+
+ Send Hush
+
+
+
+
+
+ -
+
+
+ QLayout::SetFixedSize
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ rejected()
+ transactionHush
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/src/version.h b/src/version.h
index fa69420..06e80b4 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1 +1 @@
-#define APP_VERSION "1.3.6"
+#define APP_VERSION "1.3.8"