|
|
@ -9,6 +9,9 @@ |
|
|
|
#include "camount.h" |
|
|
|
#include "Model/ChatItem.h" |
|
|
|
#include "DataStore/DataStore.h" |
|
|
|
#include <future> |
|
|
|
#include <vector> |
|
|
|
#include <thread> |
|
|
|
|
|
|
|
ChatModel *chatModel = new ChatModel(); |
|
|
|
Chat *chat = new Chat(); |
|
|
@ -19,12 +22,12 @@ using json = nlohmann::json; |
|
|
|
Controller::Controller(MainWindow* main) |
|
|
|
{ |
|
|
|
auto cl = new ConnectionLoader(main, this); |
|
|
|
qDebug() << __func__ << ": cl=" << cl << endl; |
|
|
|
//qDebug() << __func__ << ": cl=" << cl << endl;
|
|
|
|
|
|
|
|
// Execute the load connection async, so we can set up the rest of RPC properly.
|
|
|
|
QTimer::singleShot(1, [=]() { cl->loadConnection(); }); |
|
|
|
|
|
|
|
qDebug() << __func__ << "after loadConnection" << endl; |
|
|
|
// qDebug() << __func__ << "after loadConnection" << endl;
|
|
|
|
|
|
|
|
this->main = main; |
|
|
|
this->ui = main->ui; |
|
|
@ -122,6 +125,10 @@ void Controller::setConnection(Connection* c) |
|
|
|
|
|
|
|
ui->listChat->verticalScrollBar()->setValue( |
|
|
|
ui->listChat->verticalScrollBar()->maximum()); |
|
|
|
|
|
|
|
//fetch amounts of notes at startup
|
|
|
|
fetchAndProcessUnspentNotes(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Build the RPC JSON Parameters for this tx
|
|
|
@ -133,8 +140,10 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx) |
|
|
|
json rec = json::object(); |
|
|
|
|
|
|
|
//creating the JSON dust parameters in a std::vector to iterate over there during tx
|
|
|
|
std::vector<json> dust(8); |
|
|
|
dust.resize(8, json::object()); |
|
|
|
std::vector<json> dustTransactions(8); |
|
|
|
for (auto& dust : dustTransactions) { |
|
|
|
dust = json::object(); |
|
|
|
} |
|
|
|
|
|
|
|
// Create Sietch zdust addr again to not use it twice.
|
|
|
|
// Using DataStore singelton, to store the data outside of lambda, bing bada boom :D
|
|
|
@ -149,11 +158,20 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx) |
|
|
|
// Using DataStore singelton, to store the data into the dust.
|
|
|
|
for(uint8_t i = 0; i < 8; i++) |
|
|
|
{ |
|
|
|
dust.at(i)["address"] = DataStore::getSietchDataStore()->getData(QString("Sietch" + QString(i))).toStdString(); |
|
|
|
dustTransactions.at(i)["address"] = DataStore::getSietchDataStore()->getData(QString("Sietch" + QString(i))).toStdString(); |
|
|
|
} |
|
|
|
|
|
|
|
DataStore::getSietchDataStore()->clear(); // clears the datastore
|
|
|
|
|
|
|
|
// Only for Debugging/Testing: How many free Notes are available?
|
|
|
|
int spendableNotesCount = NoteCountDataStore::getInstance()->getSpendableNotesCount(); |
|
|
|
QString addressWithMaxValue = NoteCountDataStore::getInstance()->getAddressWithMaxValue(); |
|
|
|
|
|
|
|
qDebug() << "Available notes over fee:" << spendableNotesCount; |
|
|
|
|
|
|
|
// Clear NoteCountDataStore
|
|
|
|
DataStore::getNoteCountDataStore()->clear(); |
|
|
|
|
|
|
|
const QString possibleCharacters("0123456789abcdef"); |
|
|
|
int sizerandomString = 512; |
|
|
|
const int randomStringLength = sizerandomString; |
|
|
@ -168,19 +186,36 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx) |
|
|
|
randomString.append(nextChar); |
|
|
|
} |
|
|
|
|
|
|
|
dust.at(i)["memo"] = randomString.toStdString(); |
|
|
|
dustTransactions.at(i)["memo"] = randomString.toStdString(); |
|
|
|
|
|
|
|
} |
|
|
|
CAmount balanceAvailable = getModel()->getBalVerified(); |
|
|
|
|
|
|
|
for(auto &it: dust) |
|
|
|
{ |
|
|
|
// Create more Notes if spendableNotesCount < 30 and enough funds are available
|
|
|
|
if (spendableNotesCount < 30 && balanceAvailable.toDecimalString().toDouble() > (dustTransactions.size() * 0.0001)) { |
|
|
|
// Create extra transaction
|
|
|
|
for (size_t i = 0; i < dustTransactions.size(); ++i) { |
|
|
|
// Generate random memo
|
|
|
|
QString randomMemo; |
|
|
|
for (int j = 0; j < randomStringLength; ++j) { |
|
|
|
int index = QRandomGenerator::system()->bounded(0, possibleCharacters.length()); |
|
|
|
randomMemo.append(possibleCharacters.at(index)); |
|
|
|
} |
|
|
|
|
|
|
|
dustTransactions.at(i)["address"] = addressWithMaxValue.toStdString(); |
|
|
|
dustTransactions.at(i)["amount"] = 10000; |
|
|
|
dustTransactions.at(i)["memo"] = randomMemo.toStdString(); |
|
|
|
} |
|
|
|
} else { |
|
|
|
// Set amount for real Sietch transaction to 0
|
|
|
|
for (auto &it : dustTransactions) { |
|
|
|
it["amount"] = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 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]; |
|
|
|
for (const auto& toAddr : tx.toAddrs) { |
|
|
|
json rec = json::object(); |
|
|
|
rec["address"] = toAddr.addr.toStdString(); |
|
|
|
rec["amount"] = toAddr.amount.toqint64(); |
|
|
|
if (Settings::isZAddress(toAddr.addr) && !toAddr.memo.trimmed().isEmpty()) |
|
|
@ -189,59 +224,21 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx) |
|
|
|
allRecepients.push_back(rec); |
|
|
|
} |
|
|
|
|
|
|
|
int decider = rand() % 100 + 1 ; ; // random int between 1 and 100
|
|
|
|
int decider = rand() % 100 + 1; |
|
|
|
|
|
|
|
int dustCount = (decider % 4 == 3) ? 5 : 6; |
|
|
|
if (tx.toAddrs.size() < 2) { |
|
|
|
|
|
|
|
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) |
|
|
|
}) ; |
|
|
|
|
|
|
|
} 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) |
|
|
|
}) ; |
|
|
|
dustCount++; |
|
|
|
} |
|
|
|
} else { |
|
|
|
|
|
|
|
if(decider % 4 == 3) { |
|
|
|
allRecepients.insert(std::begin(allRecepients), { |
|
|
|
dust.at(0), |
|
|
|
dust.at(1), |
|
|
|
dust.at(2), |
|
|
|
dust.at(3), |
|
|
|
dust.at(4) |
|
|
|
}) ; |
|
|
|
} else { |
|
|
|
allRecepients.insert(std::begin(allRecepients), { |
|
|
|
dust.at(0), |
|
|
|
dust.at(1), |
|
|
|
dust.at(2), |
|
|
|
dust.at(3), |
|
|
|
dust.at(4), |
|
|
|
dust.at(5) |
|
|
|
}) ; |
|
|
|
} |
|
|
|
for (int i = 0; i < dustCount; ++i) { |
|
|
|
allRecepients.insert(allRecepients.begin(), dustTransactions.at(i)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
void Controller::noConnection() |
|
|
|
{ |
|
|
|
qDebug()<< __func__; |
|
|
|
//qDebug()<< __func__;
|
|
|
|
QIcon i = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical); |
|
|
|
main->statusIcon->setPixmap(i.pixmap(16, 16)); |
|
|
|
main->statusIcon->setToolTip(""); |
|
|
@ -274,7 +271,7 @@ void Controller::noConnection() |
|
|
|
/// This will refresh all the balance data from hushd
|
|
|
|
void Controller::refresh(bool force) |
|
|
|
{ |
|
|
|
qDebug()<< __func__; |
|
|
|
//qDebug()<< __func__;
|
|
|
|
if (!zrpc->haveConnection()) |
|
|
|
return; |
|
|
|
|
|
|
@ -301,7 +298,7 @@ void Controller::processInfo(const json& info) |
|
|
|
|
|
|
|
void Controller::getInfoThenRefresh(bool force) |
|
|
|
{ |
|
|
|
qDebug()<< __func__; |
|
|
|
//qDebug()<< __func__;
|
|
|
|
if (!zrpc->haveConnection()) |
|
|
|
return noConnection(); |
|
|
|
|
|
|
@ -635,7 +632,7 @@ void Controller::setLag(int lag) |
|
|
|
|
|
|
|
void Controller::refreshAddresses() |
|
|
|
{ |
|
|
|
qDebug()<< __func__; |
|
|
|
//qDebug()<< __func__;
|
|
|
|
if (!zrpc->haveConnection()) |
|
|
|
return noConnection(); |
|
|
|
|
|
|
@ -680,7 +677,7 @@ void Controller::updateUI(bool anyUnconfirmed) |
|
|
|
|
|
|
|
void Controller::supplyUpdate() { |
|
|
|
|
|
|
|
qDebug()<< __func__ << ": updating supply"; |
|
|
|
// qDebug()<< __func__ << ": updating supply";
|
|
|
|
|
|
|
|
// Get the total supply and render it with thousand decimal
|
|
|
|
zrpc->fetchSupply([=] (const json& reply) { |
|
|
@ -701,7 +698,7 @@ void Controller::supplyUpdate() { |
|
|
|
ui->supply_zaddr->setText("HUSH " +(QLocale(QLocale::English).toString(zfunds))); |
|
|
|
ui->supply_total->setText("HUSH " +(QLocale(QLocale::English).toString(total))); |
|
|
|
} |
|
|
|
qDebug() << __func__ << ": supply=" << supply; |
|
|
|
//qDebug() << __func__ << ": supply=" << supply;
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
@ -890,7 +887,7 @@ void Controller::updateUIBalances() |
|
|
|
|
|
|
|
void Controller::refreshBalances() |
|
|
|
{ |
|
|
|
qDebug()<< __func__; |
|
|
|
//qDebug()<< __func__;
|
|
|
|
if (!zrpc->haveConnection()) |
|
|
|
return noConnection(); |
|
|
|
|
|
|
@ -963,11 +960,11 @@ void printJsonValue(QTextStream& out, const nlohmann::json& j, int depth = 0) { |
|
|
|
|
|
|
|
|
|
|
|
void Controller::refreshTransactions() { |
|
|
|
qDebug()<< __func__; |
|
|
|
//qDebug()<< __func__;
|
|
|
|
if (!zrpc->haveConnection()) |
|
|
|
return noConnection(); |
|
|
|
|
|
|
|
qDebug() << __func__ << ": fetchTransactions"; |
|
|
|
// qDebug() << __func__ << ": fetchTransactions";
|
|
|
|
zrpc->fetchTransactions([=] (json reply) { |
|
|
|
QList<TransactionItem> txdata; |
|
|
|
|
|
|
@ -1079,7 +1076,7 @@ void Controller::refreshTransactions() { |
|
|
|
if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) |
|
|
|
{ |
|
|
|
main->logger->write("Keypair outgoing error"); |
|
|
|
qDebug() << "refreshTransactions: crypto_kx_seed_keypair error"; |
|
|
|
// qDebug() << "refreshTransactions: crypto_kx_seed_keypair error";
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
@ -1090,7 +1087,7 @@ void Controller::refreshTransactions() { |
|
|
|
if (crypto_kx_server_session_keys(server_rx, server_tx, pk, sk, pubkeyBob) != 0) |
|
|
|
{ |
|
|
|
main->logger->write("Suspicious client public outgoing key, bail out "); |
|
|
|
qDebug() << "refreshTransactions: Suspicious client public outgoing key, aborting!"; |
|
|
|
// qDebug() << "refreshTransactions: Suspicious client public outgoing key, aborting!";
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
@ -1119,13 +1116,13 @@ void Controller::refreshTransactions() { |
|
|
|
|
|
|
|
if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, server_tx) != 0) { |
|
|
|
/* Invalid header, no need to go any further */ |
|
|
|
qDebug() << "refreshTransactions: crypto_secretstream_xchacha20poly1305_init_pull error! Invalid header"; |
|
|
|
// qDebug() << "refreshTransactions: crypto_secretstream_xchacha20poly1305_init_pull error! Invalid header";
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (crypto_secretstream_xchacha20poly1305_pull(&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) { |
|
|
|
/* Invalid/incomplete/corrupted ciphertext - abort */ |
|
|
|
qDebug() << "refreshTransactions: crypto_secretstream_xchacha20poly1305_pull error! Invalid ciphertext"; |
|
|
|
// qDebug() << "refreshTransactions: crypto_secretstream_xchacha20poly1305_pull error! Invalid ciphertext";
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
@ -1155,7 +1152,7 @@ void Controller::refreshTransactions() { |
|
|
|
false |
|
|
|
); |
|
|
|
|
|
|
|
qDebug() << "refreshTransactions: adding chatItem with memodecrypt=" << memodecrypt; |
|
|
|
// qDebug() << "refreshTransactions: adding chatItem with memodecrypt=" << memodecrypt;
|
|
|
|
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); |
|
|
|
// updateUIBalances();
|
|
|
|
} |
|
|
@ -1269,8 +1266,8 @@ void Controller::refreshTransactions() { |
|
|
|
|
|
|
|
int position = it["position"].get<json::number_integer_t>(); |
|
|
|
int ciphercheck = memo.length() - crypto_secretstream_xchacha20poly1305_ABYTES; |
|
|
|
qDebug() << __func__ << ": position=" << position << " headerbytes=" << headerbytes |
|
|
|
<< " ciphercheck=" << ciphercheck << " for memo=" << memo; |
|
|
|
// qDebug() << __func__ << ": position=" << position << " headerbytes=" << headerbytes
|
|
|
|
// << " ciphercheck=" << ciphercheck << " for memo=" << memo;
|
|
|
|
|
|
|
|
if ((memo.startsWith("{") == false) && (headerbytes > 0) && (ciphercheck > 0)) |
|
|
|
{ |
|
|
@ -1301,7 +1298,7 @@ void Controller::refreshTransactions() { |
|
|
|
if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) |
|
|
|
{ |
|
|
|
main->logger->write("Suspicious outgoing key pair, bail out "); |
|
|
|
qDebug() << "refreshTransactions: (incoming) crypto_kx_seed_keypair error!"; |
|
|
|
// qDebug() << "refreshTransactions: (incoming) crypto_kx_seed_keypair error!";
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
@ -1312,7 +1309,7 @@ void Controller::refreshTransactions() { |
|
|
|
if (crypto_kx_client_session_keys(client_rx, client_tx, pk, sk, pubkeyBob) != 0) |
|
|
|
{ |
|
|
|
main->logger->write("Suspicious client public incoming key, bail out "); |
|
|
|
qDebug() << "refreshTransactions: (incoming) crypto_kx_client_session_keys error!"; |
|
|
|
// qDebug() << "refreshTransactions: (incoming) crypto_kx_client_session_keys error!";
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
@ -1340,13 +1337,13 @@ void Controller::refreshTransactions() { |
|
|
|
// crypto_secretstream_xchacha20poly1305_keygen(client_rx);
|
|
|
|
if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, client_rx) != 0) { |
|
|
|
main->logger->write("Invalid header incoming, no need to go any further "); |
|
|
|
qDebug() <<"refreshTransactions: (incoming) crypto_secretstream_xchacha20poly1305_init_pull error! memo=" << memo; |
|
|
|
//qDebug() <<"refreshTransactions: (incoming) crypto_secretstream_xchacha20poly1305_init_pull error! memo=" << memo;
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (crypto_secretstream_xchacha20poly1305_pull(&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) { |
|
|
|
main->logger->write("Invalid/incomplete/corrupted ciphertext - abort"); |
|
|
|
qDebug() << "refreshTransactions: (incoming) crypto_secretstream_xchacha20poly1305_pull error! memo=" << memo; |
|
|
|
// qDebug() << "refreshTransactions: (incoming) crypto_secretstream_xchacha20poly1305_pull error! memo=" << memo;
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
@ -1374,11 +1371,11 @@ void Controller::refreshTransactions() { |
|
|
|
); |
|
|
|
|
|
|
|
auto iid = ChatIDGenerator::getInstance()->generateID(item); |
|
|
|
qDebug() << "refreshTransactions: adding chatItem with item id=" << iid << " memodecrypt=" << memodecrypt; |
|
|
|
// qDebug() << "refreshTransactions: adding chatItem with item id=" << iid << " memodecrypt=" << memodecrypt;
|
|
|
|
DataStore::getChatDataStore()->setData(iid, item); |
|
|
|
|
|
|
|
} else { |
|
|
|
qDebug() << __func__ << ": ignoring txid="<< txid; |
|
|
|
// qDebug() << __func__ << ": ignoring txid="<< txid;
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
@ -1398,7 +1395,7 @@ void Controller::refreshTransactions() { |
|
|
|
isContact |
|
|
|
); |
|
|
|
auto iid = ChatIDGenerator::getInstance()->generateID(item); |
|
|
|
qDebug() << "refreshTransactions: adding chatItem for initial CR with item id="<< iid << " memo='" << memo << "'"; |
|
|
|
// qDebug() << "refreshTransactions: adding chatItem for initial CR with item id="<< iid << " memo='" << memo << "'";
|
|
|
|
DataStore::getChatDataStore()->setData(iid, item); |
|
|
|
} |
|
|
|
} |
|
|
@ -1425,7 +1422,7 @@ void Controller::refreshTransactions() { |
|
|
|
|
|
|
|
// Update model data, which updates the table view
|
|
|
|
transactionsTableModel->replaceData(txdata); |
|
|
|
qDebug() << __func__ << ": calling renderChatBox"; |
|
|
|
// qDebug() << __func__ << ": calling renderChatBox";
|
|
|
|
chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat); |
|
|
|
ui->listChat->verticalScrollBar()->setValue(ui->listChat->verticalScrollBar()->maximum()); |
|
|
|
|
|
|
@ -1435,7 +1432,7 @@ void Controller::refreshTransactions() { |
|
|
|
|
|
|
|
void Controller::refreshChat(QListView *listWidget, QLabel *label) |
|
|
|
{ |
|
|
|
qDebug() << __func__ << ": calling renderChatBox"; |
|
|
|
// qDebug() << __func__ << ": calling renderChatBox";
|
|
|
|
chat->renderChatBox(ui, listWidget, label); |
|
|
|
ui->listChat->verticalScrollBar()->setValue(ui->listChat->verticalScrollBar()->maximum()); |
|
|
|
|
|
|
@ -1528,12 +1525,14 @@ void Controller::executeStandardUITransaction(Tx tx) |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Execute a transaction!
|
|
|
|
void Controller::executeTransaction(Tx tx, |
|
|
|
const std::function<void(QString txid)> submitted, |
|
|
|
const std::function<void(QString txid, QString errStr)> error) |
|
|
|
{ |
|
|
|
// Refresh the available unspent notes
|
|
|
|
fetchAndProcessUnspentNotes(); |
|
|
|
|
|
|
|
unlockIfEncrypted([=] () { |
|
|
|
// First, create the json params
|
|
|
|
json params = json::array(); |
|
|
@ -1559,10 +1558,9 @@ void Controller::executeTransaction(Tx tx, |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Controller::checkForUpdate(bool silent) |
|
|
|
{ |
|
|
|
qDebug()<< __func__; |
|
|
|
// qDebug()<< __func__;
|
|
|
|
// No checking for updates, needs testing with Gitea
|
|
|
|
return; |
|
|
|
if (!zrpc->haveConnection()) |
|
|
@ -1653,7 +1651,7 @@ void Controller::checkForUpdate(bool silent) |
|
|
|
// Get the hush->USD price from coinmarketcap using their API
|
|
|
|
void Controller::refreshHUSHPrice() |
|
|
|
{ |
|
|
|
qDebug()<< __func__; |
|
|
|
// qDebug()<< __func__;
|
|
|
|
if (!zrpc->haveConnection()) |
|
|
|
return; |
|
|
|
|
|
|
@ -2009,7 +2007,7 @@ void Controller::shutdownhushd() |
|
|
|
// Save the wallet and exit the lightclient library cleanly.
|
|
|
|
if (!zrpc) { |
|
|
|
zrpc = new LiteInterface(); |
|
|
|
qDebug() << __func__ << ": created new rpc connection zrpc=" << zrpc; |
|
|
|
// qDebug() << __func__ << ": created new rpc connection zrpc=" << zrpc;
|
|
|
|
} |
|
|
|
|
|
|
|
if (zrpc && zrpc->haveConnection()) |
|
|
@ -2076,3 +2074,42 @@ QString Controller::getDefaultTAddress() |
|
|
|
return QString(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
void Controller::fetchAndProcessUnspentNotes() { |
|
|
|
zrpc->fetchUnspent([=] (json reply) { |
|
|
|
|
|
|
|
if (reply.find("unspent_notes") == reply.end() || !reply["unspent_notes"].is_array()) { |
|
|
|
qDebug() << "Fehler: 'unspent_notes' fehlt oder ist kein Array"; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
int spendableNotesCount = 0; |
|
|
|
std::map<std::string, int> addressValues; |
|
|
|
std::string addressWithMaxValue; |
|
|
|
int maxValue = 0; |
|
|
|
|
|
|
|
for (const auto& note : reply["unspent_notes"]) { |
|
|
|
if (note.find("spendable") != note.end() && note.find("value") != note.end() && |
|
|
|
note["spendable"].is_boolean() && note["value"].is_number_integer()) { |
|
|
|
|
|
|
|
if (note["spendable"] && note["value"] >= 10000) { |
|
|
|
spendableNotesCount++; |
|
|
|
} |
|
|
|
|
|
|
|
std::string address = note["address"]; |
|
|
|
int value = note["value"]; |
|
|
|
addressValues[address] += value; |
|
|
|
if (addressValues[address] > maxValue) { |
|
|
|
maxValue = addressValues[address]; |
|
|
|
addressWithMaxValue = address; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
NoteCountDataStore::getInstance()->setSpendableNotesCount(spendableNotesCount); |
|
|
|
|
|
|
|
if (!addressWithMaxValue.empty()) { |
|
|
|
NoteCountDataStore::getInstance()->setAddressWithMaxValue(QString::fromStdString(addressWithMaxValue), maxValue); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|