#include "liteinterface.h" LiteInterface::LiteInterface() { } LiteInterface::~LiteInterface() { delete conn; } void LiteInterface::setConnection(Connection* c) { if (conn) { delete conn; } conn = c; } bool LiteInterface::haveConnection() { return conn != nullptr; } void LiteInterface::fetchAddresses(const std::function& cb) { if (conn == nullptr) return; conn->doRPCWithDefaultErrorHandling("addresses", "", cb); } void LiteInterface::fetchUnspent(const std::function& cb) { if (conn == nullptr) return; conn->doRPCWithDefaultErrorHandling("notes", "", cb); // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "listunspent"}, // {"params", {0}} // Get UTXOs with 0 confirmations as well. // }; // conn->doRPCWithDefaultErrorHandling(payload, cb); } void LiteInterface::createNewZaddr(bool sapling, const std::function& cb) { if (conn == nullptr) return; // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "z_getnewaddress"}, // {"params", { sapling ? "sapling" : "sprout" }}, // }; // conn->doRPCWithDefaultErrorHandling(payload, cb); } void LiteInterface::createNewTaddr(const std::function& cb) { if (conn == nullptr) return; // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "getnewaddress"}, // }; // conn->doRPCWithDefaultErrorHandling(payload, cb); } void LiteInterface::fetchZPrivKey(QString addr, const std::function& cb) { if (conn == nullptr) return; // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "z_exportkey"}, // {"params", { addr.toStdString() }}, // }; // conn->doRPCWithDefaultErrorHandling(payload, cb); } void LiteInterface::fetchTPrivKey(QString addr, const std::function& cb) { if (conn == nullptr) return; // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "dumpprivkey"}, // {"params", { addr.toStdString() }}, // }; // conn->doRPCWithDefaultErrorHandling(payload, cb); } void LiteInterface::importZPrivKey(QString addr, bool rescan, const std::function& cb) { if (conn == nullptr) return; // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "z_importkey"}, // {"params", { addr.toStdString(), (rescan? "yes" : "no") }}, // }; // conn->doRPCWithDefaultErrorHandling(payload, cb); } void LiteInterface::importTPrivKey(QString addr, bool rescan, const std::function& cb) { if (conn == nullptr) return; // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "importprivkey"}, // {"params", { addr.toStdString(), (rescan? "yes" : "no") }}, // }; // conn->doRPCWithDefaultErrorHandling(payload, cb); } void LiteInterface::validateAddress(QString address, const std::function& cb) { if (conn == nullptr) return; // QString method = Settings::isZAddress(address) ? "z_validateaddress" : "validateaddress"; // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", method.toStdString() }, // {"params", { address.toStdString() } }, // }; // conn->doRPCWithDefaultErrorHandling(payload, cb); } void LiteInterface::fetchBalance(const std::function& cb) { if (conn == nullptr) return; conn->doRPCWithDefaultErrorHandling("balance", "", cb); } void LiteInterface::fetchTransactions(const std::function& cb) { if (conn == nullptr) return; conn->doRPCWithDefaultErrorHandling("list", "", cb); } void LiteInterface::sendTransaction(QString params, const std::function& cb, const std::function& err) { if (conn == nullptr) return; conn->doRPC("send", params, cb, err); } void LiteInterface::fetchInfo(const std::function& cb, const std::function& err) { if (conn == nullptr) return; conn->doRPC("info", "", cb, err); } void LiteInterface::fetchBlockchainInfo(const std::function& cb) { if (conn == nullptr) return; // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "getblockchaininfo"} // }; // conn->doRPCIgnoreError(payload, cb); } void LiteInterface::fetchNetSolOps(const std::function cb) { if (conn == nullptr) return; // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "getnetworksolps"} // }; // conn->doRPCIgnoreError(payload, [=](const json& reply) { // qint64 solrate = reply.get(); // cb(solrate); // }); } void LiteInterface::fetchMigrationStatus(const std::function& cb) { if (conn == nullptr) return; // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "z_getmigrationstatus"}, // }; // conn->doRPCWithDefaultErrorHandling(payload, cb); } void LiteInterface::setMigrationStatus(bool enabled) { if (conn == nullptr) return; // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "z_setmigration"}, // {"params", {enabled}} // }; // conn->doRPCWithDefaultErrorHandling(payload, [=](json) { // // Ignore return value. // }); } /** * Method to get all the private keys for both z and t addresses. It will make 2 batch calls, * combine the result, and call the callback with a single list containing both the t-addr and z-addr * private keys */ void LiteInterface::fetchAllPrivKeys(const std::function>)> cb) { if (conn == nullptr) { // No connection, just return return; } // // A special function that will call the callback when two lists have been added // auto holder = new QPair>>(); // holder->first = 0; // This is the number of times the callback has been called, initialized to 0 // auto fnCombineTwoLists = [=] (QList> list) { // // Increment the callback counter // holder->first++; // // Add all // std::copy(list.begin(), list.end(), std::back_inserter(holder->second)); // // And if the caller has been called twice, do the parent callback with the // // collected list // if (holder->first == 2) { // // Sort so z addresses are on top // std::sort(holder->second.begin(), holder->second.end(), // [=] (auto a, auto b) { return a.first > b.first; }); // cb(holder->second); // delete holder; // } // }; // // A utility fn to do the batch calling // auto fnDoBatchGetPrivKeys = [=](json getAddressPayload, std::string privKeyDumpMethodName) { // conn->doRPCWithDefaultErrorHandling(getAddressPayload, [=] (json resp) { // QList addrs; // for (auto addr : resp.get()) { // addrs.push_back(QString::fromStdString(addr.get())); // } // // Then, do a batch request to get all the private keys // conn->doBatchRPC( // addrs, // [=] (auto addr) { // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", privKeyDumpMethodName}, // {"params", { addr.toStdString() }}, // }; // return payload; // }, // [=] (QMap* privkeys) { // QList> allTKeys; // for (QString addr: privkeys->keys()) { // allTKeys.push_back( // QPair( // addr, // QString::fromStdString(privkeys->value(addr).get()))); // } // fnCombineTwoLists(allTKeys); // delete privkeys; // } // ); // }); // }; // // First get all the t and z addresses. // json payloadT = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "getaddressesbyaccount"}, // {"params", {""} } // }; // json payloadZ = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "z_listaddresses"} // }; // fnDoBatchGetPrivKeys(payloadT, "dumpprivkey"); // fnDoBatchGetPrivKeys(payloadZ, "z_exportkey"); } void LiteInterface::fetchOpStatus(const std::function& cb) { if (conn == nullptr) return; // Make an RPC to load pending operation statues // json payload = { // {"jsonrpc", "1.0"}, // {"id", "someid"}, // {"method", "z_getoperationstatus"}, // }; // conn->doRPCIgnoreError(payload, cb); } void LiteInterface::fetchReceivedTTrans(QList txids, QList sentZTxs, const std::function)> txdataFn) { if (conn == nullptr) return; // Look up all the txids to get the confirmation count for them. // conn->doBatchRPC(txids, // [=] (QString txid) { // json payload = { // {"jsonrpc", "1.0"}, // {"id", "senttxid"}, // {"method", "gettransaction"}, // {"params", {txid.toStdString()}} // }; // return payload; // }, // [=] (QMap* txidList) { // auto newSentZTxs = sentZTxs; // // Update the original sent list with the confirmation count // // TODO: This whole thing is kinda inefficient. We should probably just update the file // // with the confirmed block number, so we don't have to keep calling gettransaction for the // // sent items. // for (TransactionItem& sentTx: newSentZTxs) { // auto j = txidList->value(sentTx.txid); // if (j.is_null()) // continue; // auto error = j["confirmations"].is_null(); // if (!error) // sentTx.confirmations = j["confirmations"].get(); // } // txdataFn(newSentZTxs); // delete txidList; // } // ); } // Refresh received z txs by calling z_listreceivedbyaddress/gettransaction void LiteInterface::fetchReceivedZTrans(QList zaddrs, const std::function usedAddrFn, const std::function)> txdataFn) { if (conn == nullptr) return; // This method is complicated because z_listreceivedbyaddress only returns the txid, and // we have to make a follow up call to gettransaction to get details of that transaction. // Additionally, it has to be done in batches, because there are multiple z-Addresses, // and each z-Addr can have multiple received txs. // 1. For each z-Addr, get list of received txs // conn->doBatchRPC(zaddrs, // [=] (QString zaddr) { // json payload = { // {"jsonrpc", "1.0"}, // {"id", "z_lrba"}, // {"method", "z_listreceivedbyaddress"}, // {"params", {zaddr.toStdString(), 0}} // Accept 0 conf as well. // }; // return payload; // }, // [=] (QMap* zaddrTxids) { // // Process all txids, removing duplicates. This can happen if the same address // // appears multiple times in a single tx's outputs. // QSet txids; // QMap memos; // for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) { // auto zaddr = it.key(); // for (auto& i : it.value().get()) { // // Mark the address as used // usedAddrFn(zaddr); // // Filter out change txs // if (! i["change"].get()) { // auto txid = QString::fromStdString(i["txid"].get()); // txids.insert(txid); // // Check for Memos // QString memoBytes = QString::fromStdString(i["memo"].get()); // if (!memoBytes.startsWith("f600")) { // QString memo(QByteArray::fromHex( // QByteArray::fromStdString(i["memo"].get()))); // if (!memo.trimmed().isEmpty()) // memos[zaddr + txid] = memo; // } // } // } // } // // 2. For all txids, go and get the details of that txid. // conn->doBatchRPC(txids.toList(), // [=] (QString txid) { // json payload = { // {"jsonrpc", "1.0"}, // {"id", "gettx"}, // {"method", "gettransaction"}, // {"params", {txid.toStdString()}} // }; // return payload; // }, // [=] (QMap* txidDetails) { // QList txdata; // // Combine them both together. For every zAddr's txid, get the amount, fee, confirmations and time // for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) { // for (auto& i : it.value().get()) { // // Filter out change txs // if (i["change"].get()) // continue; // auto zaddr = it.key(); // auto txid = QString::fromStdString(i["txid"].get()); // // Lookup txid in the map // auto txidInfo = txidDetails->value(txid); // qint64 timestamp; // if (txidInfo.find("time") != txidInfo.end()) { // timestamp = txidInfo["time"].get(); // } else { // timestamp = txidInfo["blocktime"].get(); // } // auto amount = i["amount"].get(); // auto confirmations = static_cast(txidInfo["confirmations"].get()); // TransactionItem tx{ QString("receive"), timestamp, zaddr, txid, amount, // confirmations, "", memos.value(zaddr + txid, "") }; // txdata.push_front(tx); // } // } // txdataFn(txdata); // // Cleanup both responses; // delete zaddrTxids; // delete txidDetails; // } // ); // } // ); }