mirror of https://github.com/layters/testshop
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
396 lines
16 KiB
396 lines
16 KiB
#include "wallet_controller.hpp"
|
|
|
|
neroshop::WalletController::WalletController(QObject *parent) : QObject(parent)
|
|
{
|
|
_wallet = std::make_unique<neroshop::Wallet>();
|
|
}
|
|
|
|
neroshop::WalletController::~WalletController() {
|
|
#ifdef NEROSHOP_DEBUG
|
|
std::cout << "wallet controller deleted\n";
|
|
#endif
|
|
}
|
|
|
|
neroshop::Wallet * neroshop::WalletController::getWallet() const {
|
|
return _wallet.get();
|
|
}
|
|
|
|
// TODO: replace function return type with enum
|
|
int neroshop::WalletController::createRandomWallet(const QString& password, const QString& confirm_pwd, const QString& path) {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
auto error = _wallet->create_random(password.toStdString(),
|
|
confirm_pwd.toStdString(),
|
|
path.toStdString());
|
|
emit walletChanged();
|
|
if(error == neroshop::wallet_error::WALLET_SUCCESS) emit isOpenedChanged();
|
|
return static_cast<int>(error);
|
|
}
|
|
|
|
bool neroshop::WalletController::restoreFromMnemonic(const QString& mnemonic) {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
bool restored = _wallet->restore_from_mnemonic(mnemonic.toStdString());
|
|
emit walletChanged();
|
|
if(restored) emit isOpenedChanged();
|
|
return restored;
|
|
}
|
|
|
|
bool neroshop::WalletController::restoreFromKeys(const QString& primary_address, const QString& private_view_key, const QString& private_spend_key) {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
bool restored = _wallet->restore_from_keys(primary_address.toStdString(),
|
|
private_view_key.toStdString(),
|
|
private_spend_key.toStdString());
|
|
emit walletChanged();
|
|
if(restored) emit isOpenedChanged();
|
|
return restored;
|
|
}
|
|
|
|
bool neroshop::WalletController::open(const QString& path, const QString& password) {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
bool opened = _wallet->open(path.toStdString(), password.toStdString());
|
|
emit walletChanged();
|
|
if(opened) emit isOpenedChanged();
|
|
return opened;
|
|
}
|
|
|
|
void neroshop::WalletController::close(bool save) {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
_wallet->get_monero_wallet()->close(save);
|
|
// set monero_wallet to nullptr so that we know it has been deleted
|
|
_wallet->monero_wallet_obj.reset();
|
|
emit walletChanged();
|
|
emit isOpenedChanged();
|
|
}
|
|
|
|
QVariantMap neroshop::WalletController::createUniqueSubaddressObject(unsigned int account_idx, const QString & label) {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
QVariantMap subaddress_object;
|
|
monero::monero_subaddress subaddress = _wallet->create_subaddress(account_idx,
|
|
label.toStdString());
|
|
double piconero = 0.000000000001;
|
|
subaddress_object.insert("account_index", subaddress.m_account_index.get());
|
|
subaddress_object.insert("index", subaddress.m_index.get());
|
|
subaddress_object.insert("address", QString::fromStdString(subaddress.m_address.get()));
|
|
subaddress_object.insert("label", QString::fromStdString(subaddress.m_label.get()));
|
|
subaddress_object.insert("balance", (qulonglong(subaddress.m_balance.get()) * piconero));
|
|
subaddress_object.insert("unlocked_balance", (qulonglong(subaddress.m_unlocked_balance.get()) * piconero));
|
|
subaddress_object.insert("num_unspent_outputs", qulonglong(subaddress.m_num_unspent_outputs.get()));
|
|
subaddress_object.insert("is_used", subaddress.m_is_used.get());
|
|
subaddress_object.insert("num_blocks_to_unlock", qulonglong(subaddress.m_num_blocks_to_unlock.get())); // uint64_t is an unsigned long long so we have to convert it into a qulonglong
|
|
// Usage: console.log("subaddress: ", (!Wallet.isGenerated()) ? "" : Wallet.createUniqueSubaddressObject(0).address)
|
|
return subaddress_object;
|
|
}
|
|
|
|
|
|
void neroshop::WalletController::transfer(const QString& address, double amount) {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
_wallet->transfer(address.toStdString(), amount);
|
|
}
|
|
|
|
QString neroshop::WalletController::signMessage(const QString& message) const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
return QString::fromStdString(
|
|
_wallet->sign_message(message.toStdString(),
|
|
monero_message_signature_type::SIGN_WITH_SPEND_KEY));
|
|
}
|
|
|
|
bool neroshop::WalletController::verifyMessage(const QString& message, const QString& signature) const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
return _wallet->verify_message(message.toStdString(), signature.toStdString());
|
|
}
|
|
|
|
|
|
int neroshop::WalletController::getNetworkType() const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
return static_cast<int>(_wallet->get_network_type());
|
|
}
|
|
|
|
QString neroshop::WalletController::getNetworkTypeString() const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
return QString::fromStdString(_wallet->get_network_type_string());
|
|
}
|
|
|
|
QString neroshop::WalletController::getMnemonic() const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
if (!_wallet->get_monero_wallet())
|
|
return "";
|
|
return QString::fromStdString(_wallet->get_monero_wallet()->get_mnemonic());
|
|
}
|
|
|
|
QStringList neroshop::WalletController::getMnemonicList() const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
QStringList seed_phrase = QString::fromStdString(_wallet->get_monero_wallet()->get_mnemonic())
|
|
.split(' ');
|
|
return seed_phrase;
|
|
}
|
|
|
|
QString neroshop::WalletController::getPrimaryAddress() const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
if (!_wallet->get_monero_wallet())
|
|
throw std::runtime_error("monero_wallet_full is not opened");
|
|
return QString::fromStdString(_wallet->get_monero_wallet()->get_primary_address());
|
|
}
|
|
|
|
QStringList neroshop::WalletController::getAddressesAll() const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
QStringList addresses;
|
|
for (auto address : _wallet->get_addresses_all(0)) {
|
|
addresses << QString::fromStdString(address.m_address.get());//std::cout << address << std::endl;
|
|
}
|
|
return addresses;
|
|
}
|
|
|
|
QStringList neroshop::WalletController::getAddressesUsed() const{
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
QStringList addresses;
|
|
for (auto address : _wallet->get_addresses_used(0)) {
|
|
addresses << QString::fromStdString(address.m_address.get());//std::cout << address << " (used)" << std::endl;
|
|
}
|
|
return addresses;
|
|
}
|
|
|
|
QStringList neroshop::WalletController::getAddressesUnused() const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
QStringList addresses;
|
|
for (auto address : _wallet->get_addresses_unused(0)) {
|
|
addresses << QString::fromStdString(address.m_address.get());//std::cout << address << std::endl;
|
|
}
|
|
return addresses;
|
|
}
|
|
|
|
double neroshop::WalletController::getBalanceLocked() const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
if (!_wallet->get_monero_wallet())
|
|
throw std::runtime_error("monero_wallet_full is not opened");
|
|
double piconero = 0.000000000001;
|
|
return _wallet->get_monero_wallet()->get_balance() * piconero;
|
|
}
|
|
|
|
double neroshop::WalletController::getBalanceLocked(unsigned int account_index) const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
if (!_wallet->get_monero_wallet())
|
|
throw std::runtime_error("monero_wallet_full is not opened");
|
|
double piconero = 0.000000000001;
|
|
// primary address balance
|
|
return _wallet->get_monero_wallet()->get_balance(account_index) * piconero;
|
|
}
|
|
|
|
double neroshop::WalletController::getBalanceLocked(unsigned int account_index, unsigned int subaddress_index) const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
if (!_wallet->get_monero_wallet())
|
|
throw std::runtime_error("monero_wallet_full is not opened");
|
|
double piconero = 0.000000000001;
|
|
// subaddress balance
|
|
return _wallet->get_monero_wallet()->get_balance(account_index, subaddress_index) * piconero;
|
|
}
|
|
|
|
double neroshop::WalletController::getBalanceUnlocked() const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
if (!_wallet->get_monero_wallet())
|
|
throw std::runtime_error("monero_wallet_full is not opened");
|
|
double piconero = 0.000000000001;
|
|
return _wallet->get_monero_wallet()->get_unlocked_balance() * piconero;
|
|
}
|
|
|
|
double neroshop::WalletController::getBalanceUnlocked(unsigned int account_index) const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
if (!_wallet->get_monero_wallet())
|
|
throw std::runtime_error("monero_wallet_full is not opened");
|
|
double piconero = 0.000000000001;
|
|
// primary address balance unlocked
|
|
return _wallet->get_monero_wallet()->get_unlocked_balance(account_index) * piconero;
|
|
}
|
|
|
|
double neroshop::WalletController::getBalanceUnlocked(unsigned int account_index, unsigned int subaddress_index) const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
if (!_wallet->get_monero_wallet())
|
|
throw std::runtime_error("monero_wallet_full is not opened");
|
|
double piconero = 0.000000000001;
|
|
// subaddress balance unlocked
|
|
return _wallet->get_monero_wallet()->get_unlocked_balance(account_index, subaddress_index)
|
|
* piconero;
|
|
}
|
|
|
|
|
|
QVariantList neroshop::WalletController::getTransfers() const {
|
|
if (!_wallet.get()) throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
if (!_wallet->get_monero_wallet()) throw std::runtime_error("monero_wallet_full is not opened");
|
|
// TODO: make this function async or put in a separate thread
|
|
std::packaged_task<QVariantList(void)> get_transfers_task([this]() -> QVariantList {
|
|
double piconero = 0.000000000001;
|
|
monero_transfer_query transfer_query; // optional
|
|
auto transfers = _wallet->get_monero_wallet()->get_transfers(transfer_query);
|
|
|
|
QVariantList transfers_list;
|
|
|
|
for (auto transfer : transfers) { /*for(int i = 0; i < transfers.size(); i++) {
|
|
monero_transfer * transfer = transfers[i].get();*/
|
|
|
|
QVariantMap transfer_object;
|
|
transfer_object.insert("amount", (transfer->m_amount.get() * piconero));
|
|
transfer_object.insert("account_index", transfer->m_account_index.get()); // obviously account index 0
|
|
transfer_object.insert("is_incoming", transfer->is_incoming().get());
|
|
transfer_object.insert("is_outgoing", transfer->is_outgoing().get());
|
|
monero_tx_wallet * tx_wallet = transfer->m_tx.get();
|
|
////transfer_object.insert("", tx_wallet->);
|
|
//std::cout << ": " << tx_wallet-> << "\n";
|
|
|
|
transfers_list.append(transfer_object);
|
|
}
|
|
return transfers_list;
|
|
});
|
|
|
|
std::future<QVariantList> future_result = get_transfers_task.get_future();
|
|
// move the task (function) to a separate thread to prevent blocking of the main thread
|
|
std::thread worker(std::move(get_transfers_task));
|
|
worker.detach(); // join may block but detach won't
|
|
QVariantList transfers_result = future_result.get();
|
|
|
|
return transfers_result;
|
|
}
|
|
|
|
|
|
void neroshop::WalletController::nodeConnect(const QString& ip, const QString& port, const QString& username, const QString& password) {
|
|
_wallet->daemon_connect_remote(ip.toStdString(),
|
|
port.toStdString(),
|
|
username.toStdString(),
|
|
password.toStdString(),
|
|
this);//_wallet.get());
|
|
}
|
|
|
|
void neroshop::WalletController::daemonConnect(const QString& username, const QString& password) {
|
|
_wallet->daemon_connect_local(username.toStdString(), password.toStdString());
|
|
}
|
|
|
|
void neroshop::WalletController::daemonExecute(const QString& daemon_dir, bool confirm_external_bind, bool restricted_rpc, QString data_dir, unsigned int restore_height) {//const {
|
|
_wallet->daemon_open(daemon_dir.toStdString(),
|
|
confirm_external_bind,
|
|
restricted_rpc,
|
|
data_dir.toStdString(),
|
|
restore_height);
|
|
}
|
|
|
|
|
|
double neroshop::WalletController::getSyncPercentage() const {
|
|
std::lock_guard<std::mutex> lock(_wallet->wallet_data_mutex);
|
|
return _wallet->percentage; //wallet->get_sync_percentage();
|
|
}
|
|
|
|
unsigned int neroshop::WalletController::getSyncHeight() const {
|
|
std::lock_guard<std::mutex> lock(_wallet->wallet_data_mutex);
|
|
return _wallet->height; //wallet->get_sync_height();
|
|
}
|
|
|
|
unsigned int neroshop::WalletController::getSyncStartHeight() const {
|
|
std::lock_guard<std::mutex> lock(_wallet->wallet_data_mutex);
|
|
return _wallet->start_height; //wallet->get_sync_start_height();
|
|
}
|
|
|
|
unsigned int neroshop::WalletController::getSyncEndHeight() const {
|
|
std::lock_guard<std::mutex> lock(_wallet->wallet_data_mutex);
|
|
return _wallet->end_height; //wallet->get_sync_end_height();
|
|
}
|
|
|
|
QString neroshop::WalletController::getSyncMessage() const {
|
|
std::lock_guard<std::mutex> lock(_wallet->wallet_data_mutex);
|
|
return QString::fromStdString(
|
|
_wallet->message); //QString::fromStdString(wallet->get_sync_message());
|
|
}
|
|
|
|
|
|
void neroshop::WalletController::setNetworkTypeByString(const QString& network_type) {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
_wallet->set_network_type_by_string(network_type.toLower().toStdString());
|
|
}
|
|
|
|
|
|
bool neroshop::WalletController::isConnectedToDaemon() const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
if (!_wallet->get_monero_wallet())
|
|
throw std::runtime_error("monero_wallet_full is not opened");
|
|
return _wallet->get_monero_wallet()->is_connected_to_daemon();
|
|
}
|
|
|
|
bool neroshop::WalletController::isSynced() const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
if (!_wallet->get_monero_wallet())
|
|
throw std::runtime_error("monero_wallet_full is not opened");
|
|
return _wallet->get_monero_wallet()->is_synced();
|
|
}
|
|
|
|
bool neroshop::WalletController::isDaemonSynced() const {
|
|
if (!_wallet)
|
|
throw std::runtime_error("neroshop::Wallet is not initialized");
|
|
if (!_wallet->get_monero_wallet())
|
|
throw std::runtime_error("monero_wallet_full is not opened");
|
|
if (!_wallet->get_monero_wallet()->is_connected_to_daemon()) {
|
|
return false;
|
|
}
|
|
return _wallet->get_monero_wallet()
|
|
->is_daemon_synced(); // will cause crash if wallet is not connected to daemon
|
|
}
|
|
|
|
bool neroshop::WalletController::isOpened() const {
|
|
return (_wallet->get_monero_wallet() != nullptr);
|
|
}
|
|
|
|
bool neroshop::WalletController::fileExists(const QString& filename) const {
|
|
return _wallet->file_exists(filename.toStdString());
|
|
}
|
|
|
|
// Callbacks
|
|
void neroshop::WalletController::on_sync_progress(uint64_t height, uint64_t start_height, uint64_t end_height, double percent_done, const std::string& message) {
|
|
std::lock_guard<std::mutex> lock(_wallet->wallet_data_mutex);
|
|
|
|
_wallet->percentage = percent_done;
|
|
_wallet->height = height;
|
|
_wallet->start_height = start_height;
|
|
_wallet->end_height = end_height;
|
|
_wallet->message = message;
|
|
|
|
//if(percent_done >= 1.0) emit daemonSynced();
|
|
}
|
|
|
|
void neroshop::WalletController::on_new_block (uint64_t height) {
|
|
}
|
|
|
|
void neroshop::WalletController::on_balances_changed(uint64_t new_balance, uint64_t new_unlocked_balance) {
|
|
emit balanceChanged();
|
|
}
|
|
|
|
void neroshop::WalletController::on_output_received(const monero_output_wallet& output) {
|
|
//emit balanceChanged();
|
|
emit transfersChanged();
|
|
}
|
|
|
|
void neroshop::WalletController::on_output_spent (const monero_output_wallet &output) {
|
|
//emit balanceChanged();
|
|
emit transfersChanged();
|
|
}
|
|
|