From f102d33abf4989d288be40005bb44a50a13104cf Mon Sep 17 00:00:00 2001 From: everoddandeven Date: Thu, 30 Apr 2026 00:58:41 +0200 Subject: [PATCH] Update to new monero-cpp --- CMakeLists.txt | 7 - external/monero-cpp | 2 +- src/cpp/common/py_monero_common.cpp | 560 +---- src/cpp/common/py_monero_common.h | 378 +-- src/cpp/daemon/py_monero_daemon.h | 408 ++- src/cpp/daemon/py_monero_daemon_model.cpp | 1330 ---------- src/cpp/daemon/py_monero_daemon_model.h | 393 --- src/cpp/daemon/py_monero_daemon_rpc.cpp | 825 ------- src/cpp/daemon/py_monero_daemon_rpc.h | 157 -- src/cpp/daemon/py_monero_daemon_rpc_model.cpp | 346 --- src/cpp/daemon/py_monero_daemon_rpc_model.h | 234 -- src/cpp/py_monero.cpp | 1038 ++++---- src/cpp/utils/py_monero_utils.cpp | 68 +- src/cpp/utils/py_monero_utils.h | 39 +- src/cpp/wallet/py_monero_wallet.cpp | 95 - src/cpp/wallet/py_monero_wallet.h | 70 +- src/cpp/wallet/py_monero_wallet_model.cpp | 1219 --------- src/cpp/wallet/py_monero_wallet_model.h | 278 --- src/cpp/wallet/py_monero_wallet_rpc.cpp | 2183 ----------------- src/cpp/wallet/py_monero_wallet_rpc.h | 263 -- src/cpp/wallet/py_monero_wallet_rpc_model.cpp | 794 ------ src/cpp/wallet/py_monero_wallet_rpc_model.h | 464 ---- src/python/monero_wallet_config.pyi | 2 + src/python/monero_wallet_full.pyi | 23 +- tests/test_monero_rpc_connection.py | 3 +- tests/test_monero_wallet_common.py | 10 +- tests/test_monero_wallet_full.py | 2 + tests/test_monero_wallet_interface.py | 1 - tests/test_monero_wallet_keys.py | 4 +- tests/test_monero_wallet_model.py | 1 - tests/utils/assert_utils.py | 43 +- tests/utils/test_utils.py | 6 +- tests/utils/wallet_utils.py | 1 - 33 files changed, 902 insertions(+), 10345 deletions(-) delete mode 100644 src/cpp/daemon/py_monero_daemon_model.cpp delete mode 100644 src/cpp/daemon/py_monero_daemon_model.h delete mode 100644 src/cpp/daemon/py_monero_daemon_rpc.cpp delete mode 100644 src/cpp/daemon/py_monero_daemon_rpc.h delete mode 100644 src/cpp/daemon/py_monero_daemon_rpc_model.cpp delete mode 100644 src/cpp/daemon/py_monero_daemon_rpc_model.h delete mode 100644 src/cpp/wallet/py_monero_wallet.cpp delete mode 100644 src/cpp/wallet/py_monero_wallet_model.cpp delete mode 100644 src/cpp/wallet/py_monero_wallet_model.h delete mode 100644 src/cpp/wallet/py_monero_wallet_rpc.cpp delete mode 100644 src/cpp/wallet/py_monero_wallet_rpc.h delete mode 100644 src/cpp/wallet/py_monero_wallet_rpc_model.cpp delete mode 100644 src/cpp/wallet/py_monero_wallet_rpc_model.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 79646a4..113c437 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,13 +33,6 @@ find_package(OpenSSL REQUIRED) set(SOURCES src/cpp/common/py_monero_common.cpp - src/cpp/daemon/py_monero_daemon_model.cpp - src/cpp/daemon/py_monero_daemon_rpc_model.cpp - src/cpp/daemon/py_monero_daemon_rpc.cpp - src/cpp/wallet/py_monero_wallet_model.cpp - src/cpp/wallet/py_monero_wallet.cpp - src/cpp/wallet/py_monero_wallet_rpc_model.cpp - src/cpp/wallet/py_monero_wallet_rpc.cpp src/cpp/utils/py_monero_utils.cpp src/cpp/py_monero.cpp ) diff --git a/external/monero-cpp b/external/monero-cpp index 21fd782..e2ab4e5 160000 --- a/external/monero-cpp +++ b/external/monero-cpp @@ -1 +1 @@ -Subproject commit 21fd7829ed70c28d58d56263536e1759d740c174 +Subproject commit e2ab4e526fb5bfeb1ebda9232c1e31b4e659946a diff --git a/src/cpp/common/py_monero_common.cpp b/src/cpp/common/py_monero_common.cpp index 565829d..5b3567c 100644 --- a/src/cpp/common/py_monero_common.cpp +++ b/src/cpp/common/py_monero_common.cpp @@ -51,93 +51,7 @@ * * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers */ -#include -#include -#include -#include -#include #include "py_monero_common.h" -#include "utils/monero_utils.h" - -// --------------------------- THREAD POLLER --------------------------- - -thread_poller::~thread_poller() { - set_is_polling(false); -} - -void thread_poller::init_common(const std::string& name) { - m_name = name; - m_is_polling = false; - m_poll_period_ms = 20000; - m_poll_loop_running = false; -} - -void thread_poller::set_is_polling(bool is_polling) { - if (is_polling == m_is_polling) return; - m_is_polling = is_polling; - - if (m_is_polling) { - run_poll_loop(); - } else { - if (m_poll_loop_running) { - m_poll_cv.notify_one(); - // TODO: in emscripten, m_poll_cv.notify_one() returns without waiting, so sleep; bug in emscripten upstream llvm? - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - if (m_thread.joinable()) m_thread.join(); - } - } -} - -void thread_poller::run_poll_loop() { - if (m_poll_loop_running.exchange(true)) return; // only run one loop at a time - - // start pool loop thread - // TODO: use global threadpool, background sync wasm wallet in c++ thread - m_thread = boost::thread([this]() { - - // poll while enabled - while (m_is_polling) { - try { poll(); } - catch (const std::exception& e) { MERROR(m_name << " failed to background poll: " << e.what()); } - catch (...) { MERROR(m_name << " failed to background poll"); } - - // only wait if polling still enabled - if (m_is_polling) { - boost::mutex::scoped_lock lock(m_polling_mutex); - boost::posix_time::milliseconds wait_for_ms(m_poll_period_ms.load()); - m_poll_cv.timed_wait(lock, wait_for_ms, [&]() { return !m_is_polling; }); - } - } - - m_poll_loop_running.exchange(false); - }); -} - -// --------------------------- KEY VALUE --------------------------- - -void key_value::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& attributes) { - attributes->m_key = boost::none; - attributes->m_value = boost::none; - - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("key")) attributes->m_key = it->second.data(); - else if (key == std::string("value")) attributes->m_value = it->second.data(); - } -} - -rapidjson::Value key_value::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_key != boost::none) monero_utils::add_json_member("key", m_key.get(), allocator, root, value_str); - if (m_value != boost::none) monero_utils::add_json_member("value", m_value.get(), allocator, root, value_str); - - // return root - return root; -} // --------------------------- GEN UTILS --------------------------- @@ -200,29 +114,9 @@ boost::property_tree::ptree PyGenUtils::parse_json_string(const std::string &jso return pt; } -// --------------------------- SSL OPTIONS --------------------------- - -rapidjson::Value ssl_options::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_ssl_private_key_path != boost::none) monero_utils::add_json_member("sslPrivateKeyPath", m_ssl_private_key_path.get(), allocator, root, value_str); - if (m_ssl_certificate_path != boost::none) monero_utils::add_json_member("sslCertificatePath", m_ssl_certificate_path.get(), allocator, root, value_str); - if (m_ssl_ca_file != boost::none) monero_utils::add_json_member("sslCaFile", m_ssl_ca_file.get(), allocator, root, value_str); - if (m_ssl_private_key_path != boost::none) monero_utils::add_json_member("sslPrivateKeyPath", m_ssl_private_key_path.get(), allocator, root, value_str); - if (!m_ssl_allowed_fingerprints.empty()) root.AddMember("sslAllowedFingerprints", monero_utils::to_rapidjson_val(allocator, m_ssl_allowed_fingerprints), allocator); - - // set bool values - if (m_ssl_allow_any_cert != boost::none) monero_utils::add_json_member("sslAllowAnyCert", m_ssl_allow_any_cert.get(), allocator, root); - - return root; -} - // --------------------------- MONERO REQUEST PARAMS --------------------------- -rapidjson::Value monero_request_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { +rapidjson::Value PyMoneroRequestParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); if (m_py_params != boost::none) { @@ -237,455 +131,3 @@ rapidjson::Value monero_request_params::to_rapidjson_val(rapidjson::Document::Al return root; } - -// --------------------------- MONERO RPC REQUEST --------------------------- - -monero_rpc_request::monero_rpc_request(const std::string& method, const boost::optional& params, bool json_rpc): m_method(method), m_params(std::make_shared(params)) { - if (json_rpc) { - m_id = "0"; - m_version = "2.0"; - } -} - -monero_rpc_request::monero_rpc_request(const std::string& method, const std::shared_ptr& params, bool json_rpc): m_method(method), m_params(params) { - if (params == nullptr) m_params = std::make_shared(); - if (json_rpc) { - m_id = "0"; - m_version = "2.0"; - } -} - -rapidjson::Value monero_rpc_request::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - if (!is_json_rpc()) { - if (m_params == boost::none) throw std::runtime_error("No params provided"); - return m_params.get()->to_rapidjson_val(allocator); - } - - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - - if (m_version != boost::none) monero_utils::add_json_member("version", m_version.get(), allocator, root, value_str); - if (m_id != boost::none) monero_utils::add_json_member("id", m_id.get(), allocator, root, value_str); - if (m_method != boost::none) monero_utils::add_json_member("method", m_method.get(), allocator, root, value_str); - if (m_params != boost::none) root.AddMember("params", m_params.get()->to_rapidjson_val(allocator), allocator); - - // return root - return root; -} - -std::string monero_rpc_request::to_binary_val() const { - std::string json_val = serialize(); - std::string binary_val; - monero_utils::json_to_binary(json_val, binary_val); - return binary_val; -} - -// --------------------------- MONERO GET BLOCKS BY HEIGHT REQUEST --------------------------- - -monero_get_blocks_by_height_request::monero_get_blocks_by_height_request(uint64_t num_blocks) { - m_method = "get_blocks_by_height.bin"; - m_heights.reserve(num_blocks); - for (uint64_t i = 0; i < num_blocks; i++) m_heights.push_back(i); -} - -rapidjson::Value monero_get_blocks_by_height_request::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - if (!m_heights.empty()) root.AddMember("heights", monero_utils::to_rapidjson_val(allocator, m_heights), allocator); - return root; -} - -// --------------------------- MONERO RPC RESPONSE --------------------------- - -void monero_rpc_response::raise_rpc_error(const boost::property_tree::ptree& error_node) { - std::string err_message = "Unknown error"; - int err_code = -1; - - for (auto it = error_node.begin(); it != error_node.end(); ++it) { - std::string key_err = it->first; - if (key_err == std::string("message")) { - err_message = it->second.data(); - } else if (key_err == std::string("code")) { - err_code = it->second.get_value(); - } - } - - throw monero_rpc_error(err_code, err_message); -} - -std::shared_ptr monero_rpc_response::deserialize(const std::string& response_json) { - // parse json to property node - boost::property_tree::ptree node; - monero_utils::deserialize(response_json, node); - auto response = std::make_shared(); - - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("error")) { - raise_rpc_error(it->second); - } - else if (key == std::string("jsonrpc")) { - response->m_jsonrpc = it->second.data(); - } - else if (key == std::string("result")) { - response->m_result = it->second; - } - } - - if (response->m_jsonrpc == boost::none) { - boost::property_tree::ptree node; - monero_utils::deserialize(response_json, node); - response->m_response = node; - } - - return response; -} - - -// --------------------------- MONERO RPC CONNECTION --------------------------- - -bool PyMoneroRpcConnection::before(const std::shared_ptr& c1, const std::shared_ptr& c2, const std::shared_ptr& current_connection) { - // current connection is first - if (c1 == current_connection) return true; - if (c2 == current_connection) return false; - - // order by availability then priority then by name - if (c1->m_is_online == c2->m_is_online) { - if (c1->m_priority == c2->m_priority) { - // order by priority in descending order - return c1->m_uri.value_or("") < c2->m_uri.value_or(""); - } - // order by priority in descending order - return !compare(c1->m_priority, c2->m_priority); - } else { - if (c1->m_is_online != boost::none && c1->m_is_online.get()) return true; - else if (c2->m_is_online != boost::none && c2->m_is_online.get()) return false; - else if (c1->m_is_online == boost::none) return true; - // c1 is offline - return false; - } -} - -bool PyMoneroRpcConnection::compare(int p1, int p2) { - if (p1 == p2) return false; - // 0 alway first - if (p1 == 0) return true; - if (p2 == 0) return false; - return p1 > p2; -} - -PyMoneroRpcConnection::PyMoneroRpcConnection(const std::string& uri, const std::string& username, const std::string& password, const std::string& proxy_uri, const std::string& zmq_uri, int priority, uint64_t timeout) { - if (!uri.empty()) m_uri = uri; - else m_uri = boost::none; - if (!proxy_uri.empty()) m_proxy_uri = proxy_uri; - else m_proxy_uri = boost::none; - if (!zmq_uri.empty()) m_zmq_uri = zmq_uri; - else m_zmq_uri = boost::none; - m_priority = priority; - m_timeout = timeout; - set_credentials(username, password); -} - -PyMoneroRpcConnection::PyMoneroRpcConnection(const monero::monero_rpc_connection& rpc) { - m_uri = rpc.m_uri; - m_proxy_uri = rpc.m_proxy_uri; - m_priority = 0; - m_timeout = 20000; - // TODO move this definitions to monero-cpp - //m_zmq_uri = rpc.m_zmq_uri; - //m_priority = rpc.m_priority; - //m_timeout = rpc.m_timeout; - //m_is_online = rpc.m_is_online; - //m_is_authenticated = rpc.m_is_authenticated; - //m_response_time = rpc.m_response_time; - set_credentials(rpc.m_username.value_or(""), rpc.m_password.value_or("")); -} - -rapidjson::Value PyMoneroRpcConnection::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root = monero_rpc_connection::to_rapidjson_val(allocator); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_zmq_uri != boost::none) monero_utils::add_json_member("zmqUri", m_zmq_uri.get(), allocator, root, value_str); - - // set num values - rapidjson::Value value_num(rapidjson::kNumberType); - monero_utils::add_json_member("priority", m_priority, allocator, root, value_num); - monero_utils::add_json_member("timeout", m_timeout, allocator, root, value_num); - if (m_response_time != boost::none) monero_utils::add_json_member("responseTime", m_response_time.get(), allocator, root, value_num); - - // set bool values - if (m_is_online != boost::none) monero_utils::add_json_member("isOnline", m_is_online.get(), allocator, root); - if (m_is_authenticated != boost::none) monero_utils::add_json_member("isAuthenticated", m_is_authenticated.get(), allocator, root); - - return root; -} - -bool PyMoneroRpcConnection::is_onion() const { - // check onion uri - return m_uri != boost::none && m_uri->size() >= 6 && m_uri->compare(m_uri->size() - 6, 6, ".onion") == 0; -} - -bool PyMoneroRpcConnection::is_i2p() const { - // check i2p uri - return m_uri != boost::none && m_uri->size() >= 8 && m_uri->compare(m_uri->size() - 8, 8, ".b32.i2p") == 0; -} - -void PyMoneroRpcConnection::set_credentials(const std::string& username, const std::string& password) { - // reset http client - if (m_http_client != nullptr) { - if (m_http_client->is_connected()) { - m_http_client->disconnect(); - } - } else { - auto factory = new net::http::client_factory(); - m_http_client = factory->create(); - } - - bool username_empty = username.empty(); - bool password_empty = password.empty(); - - // check username and password consistency - if (!username_empty || !password_empty) { - if (password_empty) { - throw monero_error("password cannot be empty because username is not empty"); - } - - if (username_empty) { - throw monero_error("username cannot be empty because password is not empty"); - } - } - - // check username and password changes - bool username_equals = (m_username == boost::none && username_empty) || (m_username != boost::none && *m_username == username); - bool password_equals = (m_password == boost::none && password_empty) || (m_password != boost::none && *m_password == password); - - // connection reset values - if (!username_equals || !password_equals) { - m_is_online = boost::none; - m_is_authenticated = boost::none; - } - - // setup username and password - if (!username_empty && !password_empty) { - m_username = username; - m_password = password; - } else { - m_username = boost::none; - m_password = boost::none; - } -} - -void PyMoneroRpcConnection::set_attribute(const std::string& key, const std::string& val) { - m_attributes[key] = val; -} - -std::string PyMoneroRpcConnection::get_attribute(const std::string& key) const { - std::unordered_map::const_iterator i = m_attributes.find(key); - if (i == m_attributes.end()) { - // attribute not found - return std::string(""); - } - return i->second; -} - -boost::optional PyMoneroRpcConnection::is_connected() const { - if (m_is_online == boost::none) return boost::none; - return m_is_online.get() && (m_is_authenticated == boost::none || m_is_authenticated.get()); -} - -void PyMoneroRpcConnection::reset() { - boost::lock_guard lock(m_mutex); - if (!m_http_client) throw std::runtime_error("http client not set"); - - // disconnect http client - if (m_http_client->is_connected()) { - m_http_client->disconnect(); - } - - // set empty proxy - if(!m_http_client->set_proxy(m_proxy_uri.value_or(""))) { - throw std::runtime_error("Could not set proxy"); - } - - // reset instance variables - m_is_online = boost::none; - m_is_authenticated = boost::none; - m_response_time = boost::none; -} - -bool PyMoneroRpcConnection::check_connection(const boost::optional& timeout_ms) { - boost::optional is_online_before = m_is_online; - boost::optional is_authenticated_before = m_is_authenticated; - boost::lock_guard lock(m_mutex); - auto start = std::chrono::high_resolution_clock::now(); - try { - reset(); - - // setup connection credentials - if(m_username != boost::none && !m_username->empty() && m_password != boost::none && !m_password->empty()) { - auto credentials = std::make_shared(); - credentials->username = *m_username; - credentials->password = *m_password; - m_credentials = *credentials; - } - else m_credentials = boost::none; - - if (!m_http_client->set_server(m_uri.value_or(""), m_credentials)) { - throw std::runtime_error("Could not set rpc connection: " + m_uri.get()); - } - - m_http_client->connect(std::chrono::milliseconds(timeout_ms == boost::none ? m_timeout : *timeout_ms)); - - // assume daemon connection - monero_get_blocks_by_height_request request(100); - send_binary_request(request); - m_is_online = true; - m_is_authenticated = true; - } - catch (const monero_rpc_error& ex) { - m_is_online = false; - m_is_authenticated = boost::none; - m_response_time = boost::none; - - if (ex.code == 401) { - // TODO monero-project epee http client doesn't propagate 401 error code - m_is_online = true; - m_is_authenticated = false; - } - else if (ex.code == 404) { - // fallback to latency check - m_is_online = true; - m_is_authenticated = true; - } - } - catch (const std::exception& ex) { - if(ex.what() == std::string("Network error") && m_http_client->is_connected()) { - // TODO implement custom epee http client with 401 error handler? - m_is_online = true; - m_is_authenticated = false; - } else { - m_is_online = false; - m_is_authenticated = boost::none; - m_response_time = boost::none; - } - } - - if (*m_is_online) { - // set response time - auto end = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration_cast(end - start); - m_response_time = duration.count(); - } - - return is_online_before != m_is_online || is_authenticated_before != m_is_authenticated; -} - -const boost::property_tree::ptree PyMoneroRpcConnection::send_json_request(const std::string& path, const std::shared_ptr& params) { - monero_rpc_request request(path, params); - // send JSON-RPC request - auto response = send_json_request(request); - // assert JSON-RPC response is defined - if (response.m_result == boost::none) throw std::runtime_error("Invalid Monero JSONRPC response"); - return response.m_result.get(); -} - -const monero_rpc_response PyMoneroRpcConnection::send_json_request(const monero_rpc_request &request, std::chrono::milliseconds timeout) { - monero_rpc_response response; - // invoke JSON-RPC method - int result = invoke_post("/json_rpc", request, response, timeout); - // check status code - if (result != 200) throw monero_rpc_error(result, "HTTP error: code " + std::to_string(result)); - // return JSON-RPC response - return response; -} - -const boost::property_tree::ptree PyMoneroRpcConnection::send_path_request(const std::string& path, const std::shared_ptr& params) { - monero_rpc_request request(path, params, false); - // send RPC request - auto response = send_path_request(request); - // assert RPC response is defined - if (response.m_response == boost::none) throw std::runtime_error("Invalid Monero RPC response"); - return response.m_response.get(); -} - -const monero_rpc_response PyMoneroRpcConnection::send_path_request(const monero_rpc_request &request, std::chrono::milliseconds timeout) { - // validate parameters - if (request.m_method == boost::none || request.m_method->empty()) throw std::runtime_error("No RPC method set in path request"); - monero_rpc_response response; - - // invoke RPC method - int result = invoke_post(std::string("/") + request.m_method.get(), request, response, timeout); - - // check status code - if (result != 200) throw monero_rpc_error(result, "HTTP error: code " + std::to_string(result)); - - // return RPC response - return response; -} - -const monero_rpc_response PyMoneroRpcConnection::send_binary_request(const monero_rpc_request &request, std::chrono::milliseconds timeout) { - // validate parameters - if (request.m_method == boost::none || request.m_method->empty()) throw std::runtime_error("No RPC method set in binary request"); - - // invoke Binary RPC method - std::string uri = std::string("/") + request.m_method.get(); - std::string body = request.to_binary_val(); - const epee::net_utils::http::http_response_info* info = invoke_post(uri, body, timeout); - - // check response code - if (info->m_response_code != 200) throw monero_rpc_error(info->m_response_code, "HTTP error: code " + std::to_string(info->m_response_code)); - - // return binary response - monero_rpc_response response; - response.m_binary = info->m_body; - return response; -} - -boost::optional PyMoneroRpcConnection::send_json_request(const std::string& method, const boost::optional& parameters) { - // send JSON-RPC request with py::object parameters - monero_rpc_request request(method, parameters); - auto response = send_json_request(request); - boost::optional res; - if (response.m_result != boost::none) res = PyGenUtils::ptree_to_pyobject(*response.m_result); - return res; -} - -boost::optional PyMoneroRpcConnection::send_path_request(const std::string& method, const boost::optional& parameters) { - // send RPC request with py::object parameters - monero_rpc_request request(method, parameters); - auto response = send_path_request(request); - boost::optional res; - if (response.m_response != boost::none) res = PyGenUtils::ptree_to_pyobject(*response.m_response); - return res; -} - -boost::optional PyMoneroRpcConnection::send_binary_request(const std::string& method, const boost::optional& parameters) { - // send Binary RPC request with py::object parameters - monero_rpc_request request(method, parameters, false); - auto response = send_binary_request(request); - if (response.m_binary == boost::none || response.m_binary->empty()) { - // return empty response - return boost::none; - } - - // convert binary string to py::bytes - return py::bytes(response.m_binary.get()); -} - -const epee::net_utils::http::http_response_info* PyMoneroRpcConnection::invoke_post(const boost::string_ref uri, const std::string& body, std::chrono::milliseconds timeout) const { - // assert internal http client is initialized - if (!m_http_client) throw std::runtime_error("http client not initialized."); - - boost::lock_guard lock(m_mutex); - const epee::net_utils::http::http_response_info* pri = NULL; - - // invoke http json - if (!m_http_client->invoke_post(uri, body, timeout, std::addressof(pri))) throw std::runtime_error("Network error"); - if (!pri) throw std::runtime_error("Could not get response info"); - // return response info - return pri; -} diff --git a/src/cpp/common/py_monero_common.h b/src/cpp/common/py_monero_common.h index 6d74db2..5e1eea6 100644 --- a/src/cpp/common/py_monero_common.h +++ b/src/cpp/common/py_monero_common.h @@ -57,9 +57,9 @@ #include #include -#include "net/http.h" #include "daemon/monero_daemon_model.h" +using namespace monero; namespace py = pybind11; // ------------------------------ Utilities --------------------------------- @@ -97,21 +97,14 @@ namespace pybind11 { namespace detail { }} -struct key_value : public monero::serializable_struct { -public: - boost::optional m_key; - boost::optional m_value; - - key_value() { } - key_value(const std::string& key): m_key(key) { } - key_value(const std::string& key, const std::string& value): m_key(key), m_value(value) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& attributes); -}; +PYBIND11_MAKE_OPAQUE(std::vector); +PYBIND11_MAKE_OPAQUE(std::vector>); +PYBIND11_MAKE_OPAQUE(std::vector>); +PYBIND11_MAKE_OPAQUE(std::vector>); +PYBIND11_MAKE_OPAQUE(std::vector>); /** - * Collection of generic utilities. + * Collection of python generic utilities. */ class PyGenUtils { public: @@ -120,363 +113,12 @@ class PyGenUtils { static boost::property_tree::ptree parse_json_string(const std::string &json); }; -class thread_poller { -public: - ~thread_poller(); - - bool is_polling() const { return m_is_polling; } - void set_is_polling(bool is_polling); - void set_period_in_ms(uint64_t period_ms) { m_poll_period_ms = period_ms; } - virtual void poll() = 0; - -protected: - std::string m_name; - boost::recursive_mutex m_mutex; - boost::mutex m_polling_mutex; - boost::thread m_thread; - std::atomic m_is_polling; - std::atomic m_poll_loop_running; - std::atomic m_poll_period_ms; - boost::condition_variable m_poll_cv; - - void init_common(const std::string& name); - void run_poll_loop(); -}; - -// ------------------------------ Errors --------------------------------- - -class monero_error : public std::exception { -public: - std::string message; - - monero_error() {} - monero_error(const std::string& msg) : message(msg) {} - - const char* what() const noexcept override { - return message.c_str(); - } -}; - -class monero_rpc_error : public monero_error { -public: - int code; - - monero_rpc_error(int error_code, const std::string& msg) : code(error_code) { message = msg; } - monero_rpc_error(const std::string& msg) : code(-1) { message = msg; } -}; - -// ------------------------------ Extended Data Model --------------------------------- - -struct ssl_options : public monero::serializable_struct { -public: - boost::optional m_ssl_private_key_path; - boost::optional m_ssl_certificate_path; - boost::optional m_ssl_ca_file; - std::vector m_ssl_allowed_fingerprints; - boost::optional m_ssl_allow_any_cert; - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -enum monero_connection_type : uint8_t { - INVALID = 0, - IPV4, - IPV6, - TOR, - I2P -}; - -struct monero_bandwidth_limits : public monero::serializable_struct { -public: - boost::optional m_up; - boost::optional m_down; - - monero_bandwidth_limits() { } - monero_bandwidth_limits(int up, int down): m_up(up), m_down(down) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& limits); -}; - -// ------------------------------ RPC Request --------------------------------- - -struct monero_rpc_request : public monero::serializable_struct { -public: - boost::optional m_id; - boost::optional m_version; - boost::optional m_method; - boost::optional> m_params; - - monero_rpc_request() { } - monero_rpc_request(const std::string& method, const std::shared_ptr& params, bool json_rpc = true); - // python only - monero_rpc_request(const std::string& method, const boost::optional& params = boost::none, bool json_rpc = true); - - bool is_json_rpc() const { return m_id != boost::none && m_version != boost::none; } - - std::string to_binary_val() const; - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_request_params : public monero::serializable_struct { +struct PyMoneroRequestParams : public monero_request_params { public: boost::optional m_py_params; - monero_request_params() { } - monero_request_params(const boost::optional& py_params): m_py_params(py_params) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_get_blocks_by_height_request : public monero_rpc_request { -public: - std::vector m_heights; - - monero_get_blocks_by_height_request(uint64_t num_blocks); - monero_get_blocks_by_height_request(const std::vector& heights): m_heights(heights) { m_method = "get_blocks_by_height.bin"; } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -// ------------------------------ RPC Response --------------------------------- - -struct monero_rpc_response { -public: - boost::optional m_jsonrpc; - boost::optional m_result; - boost::optional m_response; - boost::optional m_binary; - - monero_rpc_response() { } - monero_rpc_response(const std::string &binary): m_binary(binary) { } - - static std::shared_ptr deserialize(const std::string& response_json); - static void raise_rpc_error(const boost::property_tree::ptree& error_node); -}; - -// ------------------------------ Custom RPC Connection --------------------------------- - -/** - * Maintains a connection and sends requests to a Monero RPC API. - * - * TODO: refactor monero_rpc_connection extends monero_connection? - */ -class PyMoneroRpcConnection : public monero::monero_rpc_connection { -public: - boost::optional m_zmq_uri; // TODO implement zmq listener - int m_priority; // priority relative to other connections. 1 is highest, then priority 2, etc. Default prorioty is 0, lowest priority. - uint64_t m_timeout; // RPC request timeout in milliseconds. - boost::optional m_response_time; // automatically set by calling check_connection() - - /** - * Checks rpc connection order. - * - * @param c1 first RPC connection to compare. - * @param c2 second RPC connection to compare. - * @param current_connection connection with highest priority. - */ - static bool before(const std::shared_ptr& c1, const std::shared_ptr& c2, const std::shared_ptr& current_connection); - - /** - * Checks connection priority order. - * - * @param c1 first priority to compare. - * @param c2 second priority to compare. - */ - static bool compare(int p1, int p2); - - /** - * Initialize a new RPC connection. - * - * @param uri RPC connection uri. - * @param username RPC connection authentication username. - * @param password RPC connection authentication password. - * @param proxy_uri RPC connection proxy uri. - * @param zmq_uri RPC connection zmq uri. - * @param priority RPC connection priority. - * @param timeout RPC connection timeout in milliseconds. - */ - PyMoneroRpcConnection(const std::string& uri = "", const std::string& username = "", const std::string& password = "", const std::string& proxy_uri = "", const std::string& zmq_uri = "", int priority = 0, uint64_t timeout = 20000); - - /** - * Copy a RPC connection. - * - * @param rpc RPC connection to copy. - */ - PyMoneroRpcConnection(const monero::monero_rpc_connection& rpc); - - /** - * Indicates if the connection uri is a TOR server. - * - * @return true or false to indicate if connection uri is a TOR server. - */ - bool is_onion() const; - - /** - * Indicates if the connection uri is a I2P server. - * - * @return true or false to indicate if connection uri is a I2P server. - */ - bool is_i2p() const; - - /** - * Set connection credentials. - * - * @param username username to use in RPC authentication. - * @param password password to use in RPC authentication. - */ - void set_credentials(const std::string& username, const std::string& password); - - /** - * Set connection attribute. - * - * @param key is the attribute key - * @param val is the attribute value - */ - void set_attribute(const std::string& key, const std::string& val); - - /** - * Get connection attribute. - * - * @param key is the attribute to get the value of - * @return key's value if set - */ - std::string get_attribute(const std::string& key) const; - - /** - * Indicates if the connection is online, which is set automatically by calling check_connection(). - * - * @return true or false to indicate if online, or null if check_connection() has not been called - */ - boost::optional is_online() const { return m_is_online; } - - /** - * Indicates if the connection is authenticated, which is set automatically by calling check_connection(). - * - * @return true if authenticated or no authentication, false if not authenticated, or null if not set - */ - boost::optional is_authenticated() const { return m_is_authenticated; } - - /** - * Indicates if the connection is connected, which is set automatically by calling check_connection(). - * - * @return true or false to indicate if connected, or null if check_connection() has not been called - */ - boost::optional is_connected() const; - - /** - * Check the connection and update online, authentication, and response time status. - * - * @param timeout_ms the maximum response time before considered offline - * @return - */ - bool check_connection(const boost::optional& timeout_ms = boost::none); - - /** - * Resets the current connection. - */ - void reset(); - - /** - * Send a request to the RPC API. - * - * @param path specifies the method to request - * @param params are the request's input parameters - * @return the RPC API response as a map - */ - const boost::property_tree::ptree send_json_request(const std::string& path, const std::shared_ptr& params = nullptr); - - /** - * Send a request to the RPC API. - * - * @param request specifies the method to request with parameters - * @param timeout request timeout in milliseconds - * @return the RPC API response as a map - */ - const monero_rpc_response send_json_request(const monero_rpc_request &request, std::chrono::milliseconds timeout = std::chrono::seconds(15)); - - /** - * Send a RPC request to the given path and with the given paramters. - * - * E.g. "/get_transactions" with params - * - * @param path is the url path of the request to invoke - * @param params are request parameters sent in the body - * @return the RPC API response as a map - */ - const boost::property_tree::ptree send_path_request(const std::string& path, const std::shared_ptr& params = nullptr); - - /** - * Send a RPC request to the given path and with the given paramters. - * - * @param request specifies the method to request with parameters - * @param timeout request timeout in milliseconds - * @return the request's deserialized response - */ - const monero_rpc_response send_path_request(const monero_rpc_request &request, std::chrono::milliseconds timeout = std::chrono::seconds(15)); - - /** - * Send a binary RPC request. - * - * @param request specifies the method to request with paramesters - * @param timeout request timeout in milliseconds - * @return the request's deserialized response - */ - const monero_rpc_response send_binary_request(const monero_rpc_request &request, std::chrono::milliseconds timeout = std::chrono::seconds(15)); - - // exposed python methods - - /** - * Send a request to the RPC API. - * - * @param method specifies the method to request - * @param parameters are the request's input parameters - * @return the RPC API response as a map - */ - boost::optional send_json_request(const std::string& method, const boost::optional& parameters); - - /** - * Send a RPC request to the given path and with the given paramters. - * - * E.g. "/get_transactions" with params - * - * @param method is the url path of the request to invoke - * @param parameters are request parameters sent in the body - * @return the RPC API response as a map - */ - boost::optional send_path_request(const std::string& method, const boost::optional& parameters); - - /** - * Send a binary RPC request. - * - * @param method specifies the method to request - * @param parameters are request parameters sent in the body - * @return the request's deserialized response - */ - boost::optional send_binary_request(const std::string& method, const boost::optional& parameters); + PyMoneroRequestParams() { } + PyMoneroRequestParams(const boost::optional& py_params): m_py_params(py_params) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; - -protected: - // instance variables - mutable boost::recursive_mutex m_mutex; - std::string m_server; - boost::optional m_credentials; - std::unique_ptr m_http_client; - std::unordered_map m_attributes; - boost::optional m_is_online; - boost::optional m_is_authenticated; - - const epee::net_utils::http::http_response_info* invoke_post(const boost::string_ref uri, const std::string& body, std::chrono::milliseconds timeout = std::chrono::seconds(15)) const; - - template - inline int invoke_post(const boost::string_ref uri, const t_request& request, t_response& res, std::chrono::milliseconds timeout = std::chrono::seconds(15)) const { - std::string body = request.serialize(); - const epee::net_utils::http::http_response_info* response = invoke_post(uri, body, timeout); - if (response->m_response_code == 200) { - res = *t_response::deserialize(response->m_body); - } - return response->m_response_code; - } - }; diff --git a/src/cpp/daemon/py_monero_daemon.h b/src/cpp/daemon/py_monero_daemon.h index 6f97ffe..3e1666b 100644 --- a/src/cpp/daemon/py_monero_daemon.h +++ b/src/cpp/daemon/py_monero_daemon.h @@ -53,139 +53,299 @@ */ #pragma once -#include "py_monero_daemon_model.h" - - -class monero_daemon_listener { -public: - virtual void on_block_header(const std::shared_ptr& header) { - m_last_header = header; - } - - std::shared_ptr m_last_header; -}; +#include +#include +#include "common/py_monero_common.h" +#include "daemon/monero_daemon.h" class PyMoneroDaemonListener : public monero_daemon_listener { public: - virtual void on_block_header(const std::shared_ptr& header) { + void on_block_header(const std::shared_ptr& header) override { PYBIND11_OVERRIDE(void, monero_daemon_listener, on_block_header, header); } }; -class monero_daemon { +class PyMoneroDaemon : public monero_daemon { public: /** * Virtual destructor. */ - virtual ~monero_daemon() {} - monero_daemon() { } - virtual void add_listener(monero_daemon_listener &listener) { throw std::runtime_error("monero_daemon: not supported"); } - virtual void remove_listener(monero_daemon_listener &listener) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::set get_listeners() { throw std::runtime_error("monero_daemon: not supported"); } - virtual void remove_listeners() { throw std::runtime_error("monero_daemon::remove_listeners(): not supported"); }; - virtual monero::monero_version get_version() { throw std::runtime_error("monero_daemon: not supported"); } - virtual bool is_trusted() { throw std::runtime_error("monero_daemon: not supported"); } - virtual uint64_t get_height() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::string get_block_hash(uint64_t height) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_block_template(const std::string& wallet_address, const boost::optional& reserve_size = boost::none) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_last_block_header() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_block_header_by_hash(const std::string& hash) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_block_header_by_height(uint64_t height) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_block_headers_by_range(uint64_t start_height, uint64_t end_height) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_block_by_hash(const std::string& hash) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_blocks_by_hash(const std::vector& block_hashes, uint64_t start_height, bool prune) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_block_by_height(uint64_t height) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_blocks_by_height(const std::vector& heights) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_blocks_by_range(boost::optional start_height, boost::optional end_height) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_blocks_by_range_chunked(boost::optional start_height, boost::optional end_height, boost::optional max_chunk_size) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector get_block_hashes(const std::vector& block_hashes, uint64_t start_height) { throw std::runtime_error("monero_daemon: not supported"); } - virtual boost::optional> get_tx(const std::string& tx_hash, bool prune = false) { - std::vector hashes; - hashes.push_back(tx_hash); - auto txs = get_txs(hashes, prune); - boost::optional> tx; - - if (txs.size() > 0) { - tx = txs[0]; - } - - return tx; - } - virtual std::vector> get_txs(const std::vector& tx_hashes, bool prune = false) { throw std::runtime_error("monero_daemon: not supported"); } - virtual boost::optional get_tx_hex(const std::string& tx_hash, bool prune = false) { - std::vector hashes; - hashes.push_back(tx_hash); - auto hexes = get_tx_hexes(hashes, prune); - boost::optional hex; - if (hexes.size() > 0) { - hex = hexes[0]; - } - - return hex; - } - virtual std::vector get_tx_hexes(const std::vector& tx_hashes, bool prune = false) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_miner_tx_sum(uint64_t height, uint64_t num_blocks) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_fee_estimate(uint64_t grace_blocks = 0) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr submit_tx_hex(const std::string& tx_hex, bool do_not_relay = false) { throw std::runtime_error("monero_daemon: not supported"); } - virtual void relay_tx_by_hash(const std::string& tx_hash) { - std::vector tx_hashes; - tx_hashes.push_back(tx_hash); - relay_txs_by_hash(tx_hashes); - } - virtual void relay_txs_by_hash(const std::vector& tx_hashes) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_tx_pool() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector get_tx_pool_hashes() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector get_tx_pool_backlog() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_tx_pool_stats() { throw std::runtime_error("monero_daemon: not supported"); } - virtual void flush_tx_pool() { throw std::runtime_error("monero_daemon: not supported"); } - virtual void flush_tx_pool(const std::vector &hashes) { throw std::runtime_error("monero_daemon: not supported"); } - virtual void flush_tx_pool(const std::string &hash) { throw std::runtime_error("monero_daemon: not supported"); } - virtual monero_key_image_spent_status get_key_image_spent_status(const std::string& key_image) { - std::vector key_images; - key_images.push_back(key_image); - auto statuses = get_key_image_spent_statuses(key_images); - if (statuses.empty()) throw std::runtime_error("Could not get key image spent status"); - return statuses[0]; - } - virtual std::vector get_key_image_spent_statuses(const std::vector& key_images) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_outputs(const std::vector& outputs) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_output_histogram(const std::vector& amounts, const boost::optional& min_count, const boost::optional& max_count, const boost::optional& is_unlocked, const boost::optional& recent_cutoff) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_output_distribution(const std::vector& amounts, const boost::optional& is_cumulative = boost::none, const boost::optional& start_height = boost::none, const boost::optional& end_height = boost::none) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_info() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_sync_info() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_hard_fork_info() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_alt_chains() { throw std::runtime_error("monero_daemon::get_alt_chains(): not supported"); } - virtual std::vector get_alt_block_hashes() { throw std::runtime_error("monero_daemon: not supported"); } - virtual int get_download_limit() { throw std::runtime_error("monero_daemon: not supported"); } - virtual int set_download_limit(int limit) { throw std::runtime_error("monero_daemon: not supported"); } - virtual int reset_download_limit() { throw std::runtime_error("monero_daemon: not supported"); } - virtual int get_upload_limit() { throw std::runtime_error("monero_daemon: not supported"); } - virtual int set_upload_limit(int limit) { throw std::runtime_error("monero_daemon: not supported"); } - virtual int reset_upload_limit() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_peers() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_known_peers() { throw std::runtime_error("monero_daemon: not supported"); } - virtual void set_outgoing_peer_limit(int limit) { throw std::runtime_error("monero_daemon: not supported"); } - virtual void set_incoming_peer_limit(int limit) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::vector> get_peer_bans() { throw std::runtime_error("monero_daemon: not supported"); } - virtual void set_peer_bans(const std::vector>& bans) { throw std::runtime_error("monero_daemon: not supported"); } - virtual void set_peer_ban(const std::shared_ptr& ban) { - if (ban == nullptr) throw std::runtime_error("Ban is none"); - std::vector> bans; - bans.push_back(ban); - set_peer_bans(bans); - } - virtual void start_mining(const std::string &address, int num_threads, bool is_background, bool ignore_battery) { throw std::runtime_error("monero_daemon: not supported"); } - virtual void stop_mining() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr get_mining_status() { throw std::runtime_error("monero_daemon: not supported"); } - virtual void submit_block(const std::string& block_blob) { - std::vector block_blobs; - block_blobs.push_back(block_blob); - return submit_blocks(block_blobs); - } - virtual void submit_blocks(const std::vector& block_blobs) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr prune_blockchain(bool check) { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr check_for_update() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr download_update(const std::string& path = "") { throw std::runtime_error("monero_daemon: not supported"); } - virtual void stop() { throw std::runtime_error("monero_daemon: not supported"); } - virtual std::shared_ptr wait_for_next_block_header() { throw std::runtime_error("monero_daemon: not supported"); } + ~PyMoneroDaemon() = default; + PyMoneroDaemon() { } + + void add_listener(monero_daemon_listener &listener) override { + PYBIND11_OVERRIDE(void, monero_daemon, add_listener, listener); + } + + void remove_listener(monero_daemon_listener &listener) override { + PYBIND11_OVERRIDE(void, monero_daemon, remove_listener, listener); + } + + std::set get_listeners() override { + PYBIND11_OVERRIDE(std::set, monero_daemon, get_listeners); + } + + void remove_listeners() override { + PYBIND11_OVERRIDE(void, monero_daemon, remove_listeners); + } + + monero_version get_version() override { + PYBIND11_OVERRIDE(monero_version, monero_daemon, get_version); + } + + bool is_trusted() override { + PYBIND11_OVERRIDE(bool, monero_daemon, is_trusted); + } + + uint64_t get_height() override { + PYBIND11_OVERRIDE(uint64_t, monero_daemon, get_height); + } + + std::string get_block_hash(uint64_t height) override { + PYBIND11_OVERRIDE(std::string, monero_daemon, get_block_hash, height); + } + + std::shared_ptr get_block_template(const std::string& wallet_address, const boost::optional& reserve_size = boost::none) override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_block_template, wallet_address, reserve_size); + } + + std::shared_ptr get_last_block_header() override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_last_block_header); + } + + std::shared_ptr get_block_header_by_hash(const std::string& hash) override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_block_header_by_hash, hash); + } + + std::shared_ptr get_block_header_by_height(uint64_t height) override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_block_header_by_height, height); + } + + std::vector> get_block_headers_by_range(uint64_t start_height, uint64_t end_height) override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_block_headers_by_range, start_height, end_height); + } + + std::shared_ptr get_block_by_hash(const std::string& hash) override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_block_by_hash, hash); + } + + std::vector> get_blocks_by_hash(const std::vector& block_hashes, uint64_t start_height, bool prune) override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_blocks_by_hash, block_hashes, start_height, prune); + } + + std::shared_ptr get_block_by_height(uint64_t height) override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_block_by_height, height); + } + + std::vector> get_blocks_by_height(const std::vector& heights) override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_blocks_by_height, heights); + } + + std::vector> get_blocks_by_range(boost::optional start_height, boost::optional end_height) override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_blocks_by_range, start_height, end_height); + } + + std::vector> get_blocks_by_range_chunked(boost::optional start_height, boost::optional end_height, boost::optional max_chunk_size) override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_blocks_by_range_chunked, start_height, end_height, max_chunk_size); + } + + std::vector get_block_hashes(const std::vector& block_hashes, uint64_t start_height) override { + PYBIND11_OVERRIDE(std::vector, monero_daemon, get_block_hashes, block_hashes, start_height); + } + + boost::optional> get_tx(const std::string& tx_hash, bool prune = false) override { + PYBIND11_OVERRIDE(boost::optional>, monero_daemon, get_tx, tx_hash, prune); + } + + std::vector> get_txs(const std::vector& tx_hashes, bool prune = false) override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_txs, tx_hashes, prune); + } + + boost::optional get_tx_hex(const std::string& tx_hash, bool prune = false) override { + PYBIND11_OVERRIDE(boost::optional, monero_daemon, get_tx_hex, tx_hash, prune); + } + + std::vector get_tx_hexes(const std::vector& tx_hashes, bool prune = false) override { + PYBIND11_OVERRIDE(std::vector, monero_daemon, get_tx_hexes, tx_hashes, prune); + } + + std::shared_ptr get_miner_tx_sum(uint64_t height, uint64_t num_blocks) override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_miner_tx_sum, height, num_blocks); + } + + std::shared_ptr get_fee_estimate(uint64_t grace_blocks = 0) override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_fee_estimate, grace_blocks); + } + + std::shared_ptr submit_tx_hex(const std::string& tx_hex, bool do_not_relay = false) override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, submit_tx_hex, tx_hex, do_not_relay); + } + + void relay_tx_by_hash(const std::string& tx_hash) override { + PYBIND11_OVERRIDE(void, monero_daemon, relay_tx_by_hash, tx_hash); + } + + void relay_txs_by_hash(const std::vector& tx_hashes) override { + PYBIND11_OVERRIDE(void, monero_daemon, relay_txs_by_hash, tx_hashes); + } + + std::vector> get_tx_pool() override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_tx_pool); + } + + std::vector get_tx_pool_hashes() override { + PYBIND11_OVERRIDE(std::vector, monero_daemon, get_tx_pool_hashes); + } + + std::vector get_tx_pool_backlog() override { + PYBIND11_OVERRIDE(std::vector, monero_daemon, get_tx_pool_backlog); + } + + std::shared_ptr get_tx_pool_stats() override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_tx_pool_stats); + } + + void flush_tx_pool() override { + PYBIND11_OVERRIDE(void, monero_daemon, flush_tx_pool); + } + + void flush_tx_pool(const std::vector &hashes) override { + PYBIND11_OVERRIDE(void, monero_daemon, flush_tx_pool, hashes); + } + + void flush_tx_pool(const std::string &hash) override { + PYBIND11_OVERRIDE(void, monero_daemon, flush_tx_pool, hash); + } + + monero_key_image_spent_status get_key_image_spent_status(const std::string& key_image) override { + PYBIND11_OVERRIDE(monero_key_image_spent_status, monero_daemon, get_key_image_spent_status, key_image); + } + + std::vector get_key_image_spent_statuses(const std::vector& key_images) override { + PYBIND11_OVERRIDE(std::vector, monero_daemon, get_key_image_spent_statuses, key_images); + } + + std::vector> get_outputs(const std::vector& outputs) override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_outputs, outputs); + } + + std::vector> get_output_histogram(const std::vector& amounts, const boost::optional& min_count, const boost::optional& max_count, const boost::optional& is_unlocked, const boost::optional& recent_cutoff) override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_output_histogram, amounts, min_count, max_count, is_unlocked, recent_cutoff); + } + + std::vector> get_output_distribution(const std::vector& amounts, const boost::optional& is_cumulative = boost::none, const boost::optional& start_height = boost::none, const boost::optional& end_height = boost::none) override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_output_distribution, amounts, is_cumulative, start_height, end_height); + } + + std::shared_ptr get_info() override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_info); + } + + std::shared_ptr get_sync_info() override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_sync_info); + } + + std::shared_ptr get_hard_fork_info() override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_hard_fork_info); + } + + std::vector> get_alt_chains() override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_alt_chains); + } + + std::vector get_alt_block_hashes() override { + PYBIND11_OVERRIDE(std::vector, monero_daemon, get_alt_block_hashes); + } + + int get_download_limit() override { + PYBIND11_OVERRIDE(int, monero_daemon, get_download_limit); + } + + int set_download_limit(int limit) override { + PYBIND11_OVERRIDE(int, monero_daemon, set_download_limit, limit); + } + + int reset_download_limit() override { + PYBIND11_OVERRIDE(int, monero_daemon, reset_download_limit); + } + + int get_upload_limit() override { + PYBIND11_OVERRIDE(int, monero_daemon, get_upload_limit); + } + + int set_upload_limit(int limit) override { + PYBIND11_OVERRIDE(int, monero_daemon, set_upload_limit, limit); + } + + int reset_upload_limit() override { + PYBIND11_OVERRIDE(int, monero_daemon, reset_upload_limit); + } + + std::vector> get_peers() override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_peers); + } + + std::vector> get_known_peers() override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_known_peers); + } + + void set_outgoing_peer_limit(int limit) override { + PYBIND11_OVERRIDE(void, monero_daemon, set_outgoing_peer_limit, limit); + } + + void set_incoming_peer_limit(int limit) override { + PYBIND11_OVERRIDE(void, monero_daemon, set_incoming_peer_limit, limit); + } + + std::vector> get_peer_bans() override { + PYBIND11_OVERRIDE(std::vector>, monero_daemon, get_peer_bans); + } + + void set_peer_bans(const std::vector>& bans) override { + PYBIND11_OVERRIDE(void, monero_daemon, set_peer_bans, bans); + } + + void set_peer_ban(const std::shared_ptr& ban) override { + PYBIND11_OVERRIDE(void, monero_daemon, set_peer_ban, ban); + } + + void start_mining(const std::string &address, int num_threads, bool is_background, bool ignore_battery) override { + PYBIND11_OVERRIDE(void, monero_daemon, start_mining, address, num_threads, is_background, ignore_battery); + } + + void stop_mining() override { + PYBIND11_OVERRIDE(void, monero_daemon, stop_mining); + } + + std::shared_ptr get_mining_status() override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, get_mining_status); + } + + void submit_block(const std::string& block_blob) override { + PYBIND11_OVERRIDE(void, monero_daemon, submit_block, block_blob); + } + + void submit_blocks(const std::vector& block_blobs) override { + PYBIND11_OVERRIDE(void, monero_daemon, submit_blocks, block_blobs); + } + + std::shared_ptr prune_blockchain(bool check) override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, prune_blockchain, check); + } + + std::shared_ptr check_for_update() override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, check_for_update); + } + + std::shared_ptr download_update(const std::string& path = "") override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, download_update, path); + } + + void stop() override { + PYBIND11_OVERRIDE(void, monero_daemon, stop); + } + + std::shared_ptr wait_for_next_block_header() override { + PYBIND11_OVERRIDE(std::shared_ptr, monero_daemon, wait_for_next_block_header); + } }; diff --git a/src/cpp/daemon/py_monero_daemon_model.cpp b/src/cpp/daemon/py_monero_daemon_model.cpp deleted file mode 100644 index 3687a96..0000000 --- a/src/cpp/daemon/py_monero_daemon_model.cpp +++ /dev/null @@ -1,1330 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ -#include "py_monero_daemon_model.h" -#include "utils/monero_utils.h" - -// --------------------------- Custom Data Model --------------------------- - -// Move to monero::monero_utils -rapidjson::Value to_rapidjson_vector_int_val(rapidjson::Document::AllocatorType& allocator, const std::vector& nums) { - rapidjson::Value value_arr(rapidjson::kArrayType); - rapidjson::Value value_num(rapidjson::kNumberType); - for (const auto& num : nums) { - value_num.SetInt(num); - value_arr.PushBack(value_num, allocator); - } - return value_arr; -} - -void PyMoneroBlockHeader::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& header) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("block_header")) { - PyMoneroBlockHeader::from_property_tree(it->second, header); - return; - } - else if (key == std::string("hash")) header->m_hash = it->second.data(); - else if (key == std::string("height")) header->m_height = it->second.get_value(); - else if (key == std::string("timestamp")) header->m_timestamp = it->second.get_value(); - else if (key == std::string("block_size")) header->m_size = it->second.get_value(); - else if (key == std::string("block_weight")) header->m_weight = it->second.get_value(); - else if (key == std::string("long_term_weight")) header->m_long_term_weight = it->second.get_value(); - else if (key == std::string("depth")) header->m_depth = it->second.get_value(); - else if (key == std::string("difficulty")) header->m_difficulty = it->second.get_value(); - else if (key == std::string("cumulative_difficulty")) header->m_cumulative_difficulty = it->second.get_value(); - else if (key == std::string("major_version")) header->m_major_version = it->second.get_value(); - else if (key == std::string("minor_version")) header->m_minor_version = it->second.get_value(); - else if (key == std::string("nonce")) header->m_nonce = it->second.get_value(); - else if (key == std::string("miner_tx_hash")) header->m_miner_tx_hash = it->second.data(); - else if (key == std::string("num_txes")) header->m_num_txs = it->second.get_value(); - else if (key == std::string("orphan_status")) header->m_orphan_status = it->second.get_value(); - else if (key == std::string("prev_hash") || key == std::string("prev_id")) header->m_prev_hash = it->second.data(); - else if (key == std::string("reward")) header->m_reward = it->second.get_value(); - else if (key == std::string("pow_hash")) { - std::string pow_hash = it->second.data(); - if (!pow_hash.empty()) header->m_pow_hash = pow_hash; - } - } -} - -void PyMoneroBlockHeader::from_property_tree(const boost::property_tree::ptree& node, std::vector>& headers) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("headers")) { - auto node2 = it->second; - - for(boost::property_tree::ptree::const_iterator it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto header = std::make_shared(); - PyMoneroBlockHeader::from_property_tree(it2->second, header); - headers.push_back(header); - } - } - } -} - -void PyMoneroBlock::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& block) { - PyMoneroBlockHeader::from_property_tree(node, block); - - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("blob")) block->m_hex = it->second.data(); - else if (key == std::string("tx_hashes")) { - for(const auto &hex : it->second) block->m_tx_hashes.push_back(hex.second.data()); - } - else if (key == std::string("txs")) { - for (const auto &tx_node : it->second) { - auto tx = std::make_shared(); - PyMoneroTx::from_property_tree(tx_node.second, tx); - block->m_txs.push_back(tx); - } - } - else if (key == std::string("miner_tx")) { - auto tx = std::make_shared(); - PyMoneroTx::from_property_tree(it->second, tx); - tx->m_is_miner_tx = true; - block->m_miner_tx = tx; - } - else if (key == std::string("json")) { - auto json = it->second.data(); - std::istringstream iss = json.empty() ? std::istringstream() : std::istringstream(json); - boost::property_tree::ptree json_node; - boost::property_tree::read_json(iss, json_node); - PyMoneroBlock::from_property_tree(json_node, block); - } - } -} - -void PyMoneroBlock::from_property_tree(const boost::property_tree::ptree& node, const std::vector& heights, std::vector>& blocks) { - // used by get_blocks_by_height - const auto& rpc_blocks = node.get_child("blocks"); - const auto& rpc_txs = node.get_child("txs"); - if (rpc_blocks.size() != rpc_txs.size()) { - throw std::runtime_error("blocks and txs size mismatch"); - } - - auto it_block = rpc_blocks.begin(); - auto it_txs = rpc_txs.begin(); - size_t idx = 0; - - for (; it_block != rpc_blocks.end(); ++it_block, ++it_txs, ++idx) { - // build block - auto block = std::make_shared(); - PyMoneroBlock::from_property_tree(it_block->second, block); - block->m_height = heights.at(idx); - blocks.push_back(block); - - // build transactions - std::vector> txs; - size_t tx_idx = 0; - for (const auto& tx_node : it_txs->second) { - auto tx = std::make_shared(); - tx->m_hash = block->m_tx_hashes.at(tx_idx++); - tx->m_is_confirmed = true; - tx->m_in_tx_pool = false; - tx->m_is_miner_tx = false; - tx->m_relay = true; - tx->m_is_relayed = true; - tx->m_is_failed = false; - tx->m_is_double_spend_seen = false; - PyMoneroTx::from_property_tree(tx_node.second, tx); - txs.push_back(tx); - } - // merge into one block - block->m_txs.clear(); - for (auto& tx : txs) { - if (tx->m_block != boost::none) block->merge(block, tx->m_block.get()); - else { - tx->m_block = block; - block->m_txs.push_back(tx); - } - } - } -} - -void PyMoneroOutput::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& output) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("gen")) throw std::runtime_error("Output with 'gen' from daemon rpc is miner tx which we ignore (i.e. each miner input is null)"); - else if (key == std::string("key")) { - auto key_node = it->second; - for (auto it2 = key_node.begin(); it2 != key_node.end(); ++it2) { - std::string key_key = it2->first; - if (key_key == std::string("amount")) output->m_amount = it2->second.get_value(); - else if (key_key == std::string("k_image")) { - if (!output->m_key_image) output->m_key_image = std::make_shared(); - output->m_key_image.get()->m_hex = it2->second.data(); - } - else if (key_key == std::string("key_offsets")) { - auto offsets_node = it2->second; - - for (auto it3 = offsets_node.begin(); it3 != offsets_node.end(); ++it3) { - output->m_ring_output_indices.push_back(it3->second.get_value()); - } - } - } - } - else if (key == std::string("amount")) output->m_amount = it->second.get_value(); - else if (key == std::string("target")) { - auto target_node = it->second; - - for(auto it2 = target_node.begin(); it2 != target_node.end(); ++it2) { - std::string target_key = it2->first; - - if (target_key == std::string("key")) { - output->m_stealth_public_key = it2->second.data(); - } - else if (target_key == std::string("tagged_key")) { - auto tagged_key_node = it2->second; - - for (auto it3 = tagged_key_node.begin(); it3 != tagged_key_node.end(); ++it3) { - std::string tagged_key_key = it3->first; - - if (tagged_key_key == std::string("key")) { - output->m_stealth_public_key = it3->second.data(); - } - } - } - } - } - } -} - -void PyMoneroTx::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& tx) { - std::shared_ptr block = tx->m_block == boost::none ? nullptr : tx->m_block.get(); - std::string as_json; - std::string tx_json; - - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("tx_hash") || key == std::string("id_hash")) { - std::string tx_hash = it->second.data(); - if (!tx_hash.empty()) tx->m_hash = tx_hash; - } - else if (key == std::string("block_timestamp")) { - if (block == nullptr) block = std::make_shared(); - block->m_timestamp = it->second.get_value(); - } - else if (key == std::string("block_height")) { - if (block == nullptr) block = std::make_shared(); - block->m_height = it->second.get_value(); - } - else if (key == std::string("last_relayed_time")) { - if (block == nullptr) block = std::make_shared(); - tx->m_last_relayed_timestamp = it->second.get_value(); - } - else if (key == std::string("receive_time") || key == std::string("received_timestamp")) { - if (block == nullptr) block = std::make_shared(); - tx->m_received_timestamp = it->second.get_value(); - } - else if (key == std::string("confirmations")) { - if (block == nullptr) block = std::make_shared(); - tx->m_num_confirmations = it->second.get_value(); - } - else if (key == std::string("in_pool")) { - if (block == nullptr) block = std::make_shared(); - bool in_pool = it->second.get_value(); - tx->m_is_confirmed = !in_pool; - tx->m_in_tx_pool = in_pool; - } - else if (key == std::string("double_spend_seen")) { - if (block == nullptr) block = std::make_shared(); - tx->m_is_double_spend_seen = it->second.get_value(); - } - else if (key == std::string("version")) { - if (block == nullptr) block = std::make_shared(); - tx->m_version = it->second.get_value(); - } - else if (key == std::string("vin")) { - auto &rpc_inputs = it->second; - bool is_miner_input = false; - - if (rpc_inputs.size() == 1) { - auto first = rpc_inputs.begin()->second; - if (first.get_child_optional("gen")) { - is_miner_input = true; - } - } - // ignore miner input - // TODO why? - if (!is_miner_input) { - std::vector> inputs; - for (auto &vin_entry : rpc_inputs) { - auto output = std::make_shared(); - PyMoneroOutput::from_property_tree(vin_entry.second, output); - output->m_tx = tx; - inputs.push_back(output); - } - - tx->m_inputs = inputs; - } - } - else if (key == std::string("vout")) { - auto node2 = it->second; - - for(auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto output = std::make_shared(); - PyMoneroOutput::from_property_tree(it2->second, output); - output->m_tx = tx; - tx->m_outputs.push_back(output); - } - } - else if (key == std::string("rct_signatures")) { - auto node2 = it->second; - - for(auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - std::string _key = it2->first; - - if (_key == std::string("txnFee")) { - tx->m_fee = it2->second.get_value(); - } - } - } - else if (key == std::string("rctsig_prunable")) { - // TODO: implement - } - else if (key == std::string("unlock_time")) { - if (block == nullptr) block = std::make_shared(); - tx->m_unlock_time = it->second.get_value(); - } - else if (key == std::string("as_json")) as_json = it->second.data(); - else if (key == std::string("tx_json")) tx_json = it->second.data(); - else if ((key == std::string("as_hex") || key == std::string("tx_blob")) && !it->second.data().empty()) tx->m_full_hex = it->second.data(); - else if (key == std::string("blob_size")) tx->m_size = it->second.get_value(); - else if (key == std::string("weight")) tx->m_weight = it->second.get_value(); - else if (key == std::string("fee")) tx->m_fee = it->second.get_value(); - else if (key == std::string("relayed")) tx->m_is_relayed = it->second.get_value(); - else if (key == std::string("output_indices")) { - auto node2 = it->second; - std::vector output_indices; - for(auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - output_indices.push_back(it2->second.get_value()); - } - tx->m_output_indices = output_indices; - } - else if (key == std::string("do_not_relay")) tx->m_relay = !it->second.get_value(); - else if (key == std::string("kept_by_block")) tx->m_is_kept_by_block = it->second.get_value(); - else if (key == std::string("signatures")) { - auto node2 = it->second; - for(auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - tx->m_signatures.push_back(it2->second.data()); - } - } - else if (key == std::string("last_failed_height")) { - uint64_t last_failed_height = it->second.get_value(); - if (last_failed_height == 0) tx->m_is_failed = false; - else { - tx->m_is_failed = true; - tx->m_last_failed_height = last_failed_height; - } - } - else if (key == std::string("last_failed_hash")) { - std::string hash = it->second.data(); - if (hash == DEFAULT_ID) tx->m_is_failed = false; - else { - tx->m_is_failed = true; - tx->m_last_failed_hash = hash; - } - } - else if (key == std::string("extra")) { - auto extra_node = it->second; - for(auto it_extra = extra_node.begin(); it_extra != extra_node.end(); ++it_extra) { - tx->m_extra.push_back(it_extra->second.get_value()); - } - } - else if (key == std::string("max_used_block_height")) tx->m_max_used_block_height = it->second.get_value(); - else if (key == std::string("max_used_block_id_hash") && !it->second.data().empty()) tx->m_max_used_block_hash = it->second.data(); - else if (key == std::string("prunable_hash") && !it->second.data().empty()) tx->m_prunable_hash = it->second.data(); - else if (key == std::string("prunable_as_hex") && !it->second.data().empty()) tx->m_prunable_hex = it->second.data(); - else if (key == std::string("pruned_as_hex") && !it->second.data().empty()) tx->m_pruned_hex = it->second.data(); - } - - bool is_confirmed = tx->m_is_confirmed != boost::none && tx->m_is_confirmed.get(); - - if (block != nullptr && is_confirmed) { - block->m_txs.push_back(tx); - tx->m_block = block; - } - - // initialize remaining known fields - if (is_confirmed) { - tx->m_relay = true; - tx->m_is_relayed = true; - tx->m_is_failed = false; - } else { - tx->m_num_confirmations = 0; - } - - if (tx->m_is_failed == boost::none) tx->m_is_failed = false; - if (!tx->m_output_indices.empty() && !tx->m_outputs.empty()) { - if (tx->m_output_indices.size() != tx->m_outputs.size()) throw std::runtime_error("Expected outputs count equal to indices count"); - int i = 0; - for (const auto &output : tx->m_outputs) { - output->m_index = tx->m_output_indices[i++]; - } - } - - if (!as_json.empty()) { - auto n = PyGenUtils::parse_json_string(as_json); - PyMoneroTx::from_property_tree(n, tx); - } - if (!tx_json.empty()) { - auto n = PyGenUtils::parse_json_string(tx_json); - PyMoneroTx::from_property_tree(n, tx); - } - - if (tx->m_is_relayed != boost::none && !tx->m_is_relayed.get()) tx->m_last_relayed_timestamp = boost::none; -} - -void PyMoneroTx::from_property_tree(const boost::property_tree::ptree& node, std::vector>& txs) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - bool pool_txs = key == std::string("transactions"); - - if (pool_txs || key == std::string("txs")) { - auto node2 = it->second; - - for(boost::property_tree::ptree::const_iterator it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto node3 = it2->second; - auto tx = std::make_shared(); - tx->m_is_miner_tx = false; - if (pool_txs) { - tx->m_is_confirmed = false; - tx->m_in_tx_pool = true; - tx->m_num_confirmations = 0; - } - from_property_tree(node3, tx); - txs.push_back(tx); - } - } - } -} - -void PyMoneroTx::from_property_tree(const boost::property_tree::ptree& node, std::vector& tx_hashes) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("tx_hashes")) { - auto node2 = it->second; - - for(boost::property_tree::ptree::const_iterator it2 = node2.begin(); it2 != node2.end(); ++it2) { - tx_hashes.push_back(it2->second.data()); - } - } - } -} - -void PyMoneroVersion::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& version) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("version")) version->m_number = it->second.get_value(); - else if (key == std::string("release")) version->m_is_release = it->second.get_value(); - } -} - -// --------------------------- MONERO RPC PAYMENT INFO --------------------------- - -void monero_rpc_payment_info::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& rpc_payment_info) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if ((key == std::string("top_hash") || key == std::string("top_block_hash")) && !it->second.data().empty()) rpc_payment_info->m_top_block_hash = it->second.data(); - else if (key == std::string("credits")) rpc_payment_info->m_credits = it->second.get_value(); - } -} - -rapidjson::Value monero_rpc_payment_info::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_top_block_hash != boost::none) monero_utils::add_json_member("topBlockHash", m_top_block_hash.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_credits != boost::none) monero_utils::add_json_member("credits", m_credits.get(), allocator, root, value_num); - - // return root - return root; -} - -// --------------------------- MONERO ALT CHAIN --------------------------- - -void monero_alt_chain::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& alt_chain) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("difficulty")) alt_chain->m_difficulty = it->second.get_value(); - else if (key == std::string("block_hashes")) { - for (const auto& child : it->second) alt_chain->m_block_hashes.push_back(child.second.data()); - } - else if (key == std::string("height")) alt_chain->m_height = it->second.get_value(); - else if (key == std::string("length")) alt_chain->m_length = it->second.get_value(); - else if (key == std::string("main_chain_parent_block")) alt_chain->m_main_chain_parent_block_hash = it->second.data(); - } -} - -rapidjson::Value monero_alt_chain::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_main_chain_parent_block_hash != boost::none) monero_utils::add_json_member("mainChainParentBlockHash", m_main_chain_parent_block_hash.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_difficulty != boost::none) monero_utils::add_json_member("difficulty", m_difficulty.get(), allocator, root, value_num); - if (m_height != boost::none) monero_utils::add_json_member("height", m_height.get(), allocator, root, value_num); - if (m_length != boost::none) monero_utils::add_json_member("length", m_length.get(), allocator, root, value_num); - - // set sub-arrays - if (!m_block_hashes.empty()) root.AddMember("blockHashes", monero_utils::to_rapidjson_val(allocator, m_block_hashes), allocator); - - // return root - return root; -} - -// --------------------------- MONERO BAN --------------------------- - -void monero_ban::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& ban) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("host")) ban->m_host = it->second.data(); - else if (key == std::string("ip")) ban->m_ip = it->second.get_value(); - else if (key == std::string("ban")) ban->m_is_banned = it->second.get_value(); - else if (key == std::string("seconds")) ban->m_seconds = it->second.get_value(); - } -} - -void monero_ban::from_property_tree(const boost::property_tree::ptree& node, std::vector>& bans) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("bans")) { - auto node2 = it->second; - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto ban = std::make_shared(); - monero_ban::from_property_tree(it2->second, ban); - bans.push_back(ban); - } - } - } -} - -rapidjson::Value monero_ban::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_host != boost::none) monero_utils::add_json_member("host", m_host.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_ip != boost::none) monero_utils::add_json_member("ip", m_ip.get(), allocator, root, value_num); - if (m_seconds != boost::none) monero_utils::add_json_member("seconds", m_seconds.get(), allocator, root, value_num); - - // set bool values - if (m_is_banned != boost::none) monero_utils::add_json_member("ban", m_is_banned.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO PRUNE RESULT --------------------------- - -void monero_prune_result::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& result) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("pruned")) result->m_is_pruned = it->second.get_value(); - else if (key == std::string("pruning_seed")) result->m_pruning_seed = it->second.get_value(); - } -} - -rapidjson::Value monero_prune_result::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_pruning_seed != boost::none) monero_utils::add_json_member("pruningSeed", m_pruning_seed.get(), allocator, root, value_num); - - // set bool values - if (m_is_pruned != boost::none) monero_utils::add_json_member("isPruned", m_is_pruned.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO MINING STATUS --------------------------- - -void monero_mining_status::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& status) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("active")) status->m_is_active = it->second.get_value(); - else if (key == std::string("is_background_mining_enabled")) status->m_is_background = it->second.get_value(); - else if (key == std::string("address") && !it->second.data().empty()) status->m_address = it->second.data(); - else if (key == std::string("speed")) status->m_speed = it->second.get_value(); - else if (key == std::string("threads_count")) status->m_num_threads = it->second.get_value(); - } - - if (status->m_is_active != boost::none && *status->m_is_active == false) { - status->m_is_background = boost::none; - status->m_address = boost::none; - } -} - -rapidjson::Value monero_mining_status::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_speed != boost::none) monero_utils::add_json_member("speed", m_speed.get(), allocator, root, value_num); - if (m_num_threads != boost::none) monero_utils::add_json_member("numThreads", m_num_threads.get(), allocator, root, value_num); - - // set bool values - if (m_is_active != boost::none) monero_utils::add_json_member("isActive", m_is_active.get(), allocator, root); - if (m_is_background != boost::none) monero_utils::add_json_member("isBackground", m_is_background.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO MINER TX SUM --------------------------- - -void monero_miner_tx_sum::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& sum) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("emission_amount")) sum->m_emission_sum = it->second.get_value(); - else if (key == std::string("fee_amount")) sum->m_fee_sum = it->second.get_value(); - } -} - -rapidjson::Value monero_miner_tx_sum::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_emission_sum != boost::none) monero_utils::add_json_member("emissionSum", m_emission_sum.get(), allocator, root, value_num); - if (m_fee_sum != boost::none) monero_utils::add_json_member("feeSum", m_fee_sum.get(), allocator, root, value_num); - - // return root - return root; -} - -// --------------------------- MONERO BLOCK TEMPLATE --------------------------- - -void monero_block_template::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& tmplt) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("blocktemplate_blob")) tmplt->m_block_template_blob = it->second.data(); - else if (key == std::string("blockhashing_blob")) tmplt->m_block_hashing_blob = it->second.data(); - else if (key == std::string("difficulty")) tmplt->m_difficulty = it->second.get_value(); - else if (key == std::string("expected_reward")) tmplt->m_expected_reward = it->second.get_value(); - else if (key == std::string("height")) tmplt->m_height = it->second.get_value(); - else if (key == std::string("prev_hash")) tmplt->m_prev_hash = it->second.data(); - else if (key == std::string("reserved_offset")) tmplt->m_reserved_offset = it->second.get_value(); - else if (key == std::string("seed_height")) tmplt->m_seed_height = it->second.get_value(); - else if (key == std::string("seed_hash")) tmplt->m_seed_hash = it->second.data(); - else if (key == std::string("next_seed_hash")) tmplt->m_next_seed_hash = it->second.data(); - } -} - -rapidjson::Value monero_block_template::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_block_template_blob != boost::none) monero_utils::add_json_member("blockTemplateBlob", m_block_template_blob.get(), allocator, root, value_str); - if (m_block_hashing_blob != boost::none) monero_utils::add_json_member("blockHashingBlob", m_block_hashing_blob.get(), allocator, root, value_str); - if (m_prev_hash != boost::none) monero_utils::add_json_member("prevHash", m_prev_hash.get(), allocator, root, value_str); - if (m_seed_hash != boost::none) monero_utils::add_json_member("seedHash", m_seed_hash.get(), allocator, root, value_str); - if (m_next_seed_hash != boost::none) monero_utils::add_json_member("nextSeedHash", m_next_seed_hash.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_difficulty != boost::none) monero_utils::add_json_member("difficulty", m_difficulty.get(), allocator, root, value_num); - if (m_expected_reward != boost::none) monero_utils::add_json_member("expectedReward", m_expected_reward.get(), allocator, root, value_num); - if (m_height != boost::none) monero_utils::add_json_member("height", m_height.get(), allocator, root, value_num); - if (m_reserved_offset != boost::none) monero_utils::add_json_member("reservedOffset", m_reserved_offset.get(), allocator, root, value_num); - if (m_seed_height != boost::none) monero_utils::add_json_member("seedHeight", m_seed_height.get(), allocator, root, value_num); - - // return root - return root; -} - -// --------------------------- MONERO CONNECTION SPAN --------------------------- - -void monero_connection_span::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& span) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("connection_id")) span->m_connection_id = it->second.data(); - else if (key == std::string("nblocks")) span->m_num_blocks = it->second.get_value(); - else if (key == std::string("remote_address")) span->m_remote_address = it->second.data(); - else if (key == std::string("rate")) span->m_rate = it->second.get_value(); - else if (key == std::string("speed")) span->m_speed = it->second.get_value(); - else if (key == std::string("size")) span->m_size = it->second.get_value(); - else if (key == std::string("start_block_height")) span->m_start_height = it->second.get_value(); - } -} - -rapidjson::Value monero_connection_span::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_connection_id != boost::none) monero_utils::add_json_member("connectionId", m_connection_id.get(), allocator, root, value_str); - if (m_remote_address != boost::none) monero_utils::add_json_member("remoteAddress", m_remote_address.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_num_blocks != boost::none) monero_utils::add_json_member("numBlocks", m_num_blocks.get(), allocator, root, value_num); - if (m_rate != boost::none) monero_utils::add_json_member("rate", m_rate.get(), allocator, root, value_num); - if (m_speed != boost::none) monero_utils::add_json_member("speed", m_speed.get(), allocator, root, value_num); - if (m_size != boost::none) monero_utils::add_json_member("size", m_size.get(), allocator, root, value_num); - if (m_start_height != boost::none) monero_utils::add_json_member("startHeight", m_start_height.get(), allocator, root, value_num); - - // return root - return root; -} - -// --------------------------- MONERO PEER --------------------------- - -void monero_peer::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& peer) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("host")) peer->m_host = it->second.data(); - else if (key == std::string("address")) peer->m_address = it->second.data(); - else if (key == std::string("current_download")) peer->m_current_download = it->second.get_value(); - else if (key == std::string("current_upload")) peer->m_current_upload = it->second.get_value(); - else if (key == std::string("avg_download")) peer->m_avg_download = it->second.get_value(); - else if (key == std::string("avg_upload")) peer->m_avg_upload = it->second.get_value(); - else if (key == std::string("connection_id")) peer->m_hash = it->second.data(); - else if (key == std::string("height")) peer->m_height = it->second.get_value(); - else if (key == std::string("incoming")) peer->m_is_incoming = it->second.get_value(); - else if (key == std::string("live_time")) peer->m_live_time = it->second.get_value(); - else if (key == std::string("local_ip")) peer->m_is_local_ip = it->second.get_value(); - else if (key == std::string("localhost")) peer->m_is_local_host = it->second.get_value(); - else if (key == std::string("recv_count")) peer->m_num_receives = it->second.get_value(); - else if (key == std::string("send_count")) peer->m_num_sends = it->second.get_value(); - else if (key == std::string("recv_idle_time")) peer->m_receive_idle_time = it->second.get_value(); - else if (key == std::string("send_idle_time")) peer->m_send_idle_time = it->second.get_value(); - else if (key == std::string("state")) peer->m_state = it->second.data(); - else if (key == std::string("support_flags")) peer->m_num_support_flags = it->second.get_value(); - else if (key == std::string("id") || key == std::string("peer_id")) peer->m_id = it->second.data(); - else if (key == std::string("last_seen")) peer->m_last_seen_timestamp = it->second.get_value(); - else if (key == std::string("port")) peer->m_port = it->second.get_value(); - else if (key == std::string("rpc_port")) peer->m_rpc_port = it->second.get_value(); - else if (key == std::string("pruning_seed")) peer->m_pruning_seed = it->second.get_value(); - else if (key == std::string("rpc_credits_per_hash")) peer->m_rpc_credits_per_hash = it->second.get_value(); - else if (key == std::string("address_type")) { - int rpc_type = it->second.get_value(); - if (rpc_type == 0) { - peer->m_connection_type = monero_connection_type::INVALID; - } - else if (rpc_type == 1) { - peer->m_connection_type = monero_connection_type::IPV4; - } - else if (rpc_type == 2) { - peer->m_connection_type = monero_connection_type::IPV6; - } - else if (rpc_type == 3) { - peer->m_connection_type = monero_connection_type::TOR; - } - else if (rpc_type == 4) { - peer->m_connection_type = monero_connection_type::I2P; - } - else throw std::runtime_error("Invalid RPC peer type, expected 0-4: " + std::to_string(rpc_type)); - } - } -} - -void monero_peer::from_property_tree(const boost::property_tree::ptree& node, std::vector>& peers) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - bool is_online = key == std::string("white_list"); - if (key == std::string("connections") || is_online || key == std::string("gray_list") ) { - auto node2 = it->second; - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto peer = std::make_shared(); - monero_peer::from_property_tree(it2->second, peer); - peer->m_is_online = is_online; - peers.push_back(peer); - } - } - } -} - -rapidjson::Value monero_peer::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_id != boost::none) monero_utils::add_json_member("id", m_id.get(), allocator, root, value_str); - if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); - if (m_host != boost::none) monero_utils::add_json_member("host", m_host.get(), allocator, root, value_str); - if (m_hash != boost::none) monero_utils::add_json_member("hash", m_hash.get(), allocator, root, value_str); - if (m_state != boost::none) monero_utils::add_json_member("state", m_state.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_port != boost::none) monero_utils::add_json_member("port", m_port.get(), allocator, root, value_num); - if (m_rpc_port != boost::none) monero_utils::add_json_member("rpcPort", m_rpc_port.get(), allocator, root, value_num); - if (m_last_seen_timestamp != boost::none) monero_utils::add_json_member("lastSeenTimestamp", m_last_seen_timestamp.get(), allocator, root, value_num); - if (m_pruning_seed != boost::none) monero_utils::add_json_member("pruningSeed", m_pruning_seed.get(), allocator, root, value_num); - if (m_rpc_credits_per_hash != boost::none) monero_utils::add_json_member("rpcCreditsPerHash", m_rpc_credits_per_hash.get(), allocator, root, value_num); - if (m_avg_download != boost::none) monero_utils::add_json_member("avgDownload", m_avg_download.get(), allocator, root, value_num); - if (m_avg_upload != boost::none) monero_utils::add_json_member("avgUpload", m_avg_upload.get(), allocator, root, value_num); - if (m_current_download != boost::none) monero_utils::add_json_member("currentDownload", m_current_download.get(), allocator, root, value_num); - if (m_current_upload != boost::none) monero_utils::add_json_member("currentUpload", m_current_upload.get(), allocator, root, value_num); - if (m_height != boost::none) monero_utils::add_json_member("height", m_height.get(), allocator, root, value_num); - if (m_live_time != boost::none) monero_utils::add_json_member("liveTime", m_live_time.get(), allocator, root, value_num); - if (m_num_receives != boost::none) monero_utils::add_json_member("numReceives", m_num_receives.get(), allocator, root, value_num); - if (m_num_sends != boost::none) monero_utils::add_json_member("numSends", m_num_sends.get(), allocator, root, value_num); - if (m_receive_idle_time != boost::none) monero_utils::add_json_member("receiveIdleTime", m_receive_idle_time.get(), allocator, root, value_num); - if (m_send_idle_time != boost::none) monero_utils::add_json_member("sendIdleTime", m_send_idle_time.get(), allocator, root, value_num); - if (m_num_support_flags != boost::none) monero_utils::add_json_member("numSupportFlags", m_num_support_flags.get(), allocator, root, value_num); - - // set bool values - if (m_is_online != boost::none) monero_utils::add_json_member("isOnline", m_is_online.get(), allocator, root); - if (m_is_incoming != boost::none) monero_utils::add_json_member("isIncoming", m_is_incoming.get(), allocator, root); - if (m_is_local_ip != boost::none) monero_utils::add_json_member("isLocalIp", m_is_local_ip.get(), allocator, root); - if (m_is_local_host != boost::none) monero_utils::add_json_member("isLocalHost", m_is_local_host.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO SUBMIT TX RESULT --------------------------- - -void monero_submit_tx_result::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& result) { - monero_rpc_payment_info::from_property_tree(node, result); - - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("double_spend")) result->m_is_double_spend = it->second.get_value(); - else if (key == std::string("fee_too_low")) result->m_is_fee_too_low = it->second.get_value(); - else if (key == std::string("invalid_input")) result->m_has_invalid_input = it->second.get_value(); - else if (key == std::string("invalid_output")) result->m_has_invalid_output = it->second.get_value(); - else if (key == std::string("too_few_outputs")) result->m_has_too_few_outputs = it->second.get_value(); - else if (key == std::string("low_mixin")) result->m_is_mixin_too_low = it->second.get_value(); - else if (key == std::string("not_relayed")) result->m_is_relayed = !it->second.get_value(); - else if (key == std::string("overspend")) result->m_is_overspend = it->second.get_value(); - else if (key == std::string("reason") && !it->second.data().empty()) result->m_reason = it->second.data(); - else if (key == std::string("too_big")) result->m_is_too_big = it->second.get_value(); - else if (key == std::string("sanity_check_failed")) result->m_sanity_check_failed = it->second.get_value(); - else if (key == std::string("tx_extra_too_big")) result->m_is_tx_extra_too_big = it->second.get_value(); - else if (key == std::string("nonzero_unlock_time")) result->m_is_nonzero_unlock_time = it->second.get_value(); - } -} - -rapidjson::Value monero_submit_tx_result::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root = monero_rpc_payment_info::to_rapidjson_val(allocator); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_reason != boost::none) monero_utils::add_json_member("reason", m_reason.get(), allocator, root, value_str); - - // set bool values - if (m_has_invalid_input != boost::none) monero_utils::add_json_member("hasInvalidInput", m_has_invalid_input.get(), allocator, root); - if (m_has_invalid_output != boost::none) monero_utils::add_json_member("hasInvalidOutput", m_has_invalid_output.get(), allocator, root); - if (m_has_too_few_outputs != boost::none) monero_utils::add_json_member("hasTooFewOutputs", m_has_too_few_outputs.get(), allocator, root); - if (m_is_good != boost::none) monero_utils::add_json_member("isGood", m_is_good.get(), allocator, root); - if (m_is_relayed != boost::none) monero_utils::add_json_member("isRelayed", m_is_relayed.get(), allocator, root); - if (m_is_double_spend != boost::none) monero_utils::add_json_member("isDoubleSpend", m_is_double_spend.get(), allocator, root); - if (m_is_fee_too_low != boost::none) monero_utils::add_json_member("isFeeTooLow", m_is_fee_too_low.get(), allocator, root); - if (m_is_mixin_too_low != boost::none) monero_utils::add_json_member("isMixinTooLow", m_is_mixin_too_low.get(), allocator, root); - if (m_is_overspend != boost::none) monero_utils::add_json_member("isOverspend", m_is_overspend.get(), allocator, root); - if (m_is_too_big != boost::none) monero_utils::add_json_member("isTooBig", m_is_too_big.get(), allocator, root); - if (m_is_tx_extra_too_big != boost::none) monero_utils::add_json_member("isTxExtraTooBig", m_is_tx_extra_too_big.get(), allocator, root); - if (m_is_nonzero_unlock_time != boost::none) monero_utils::add_json_member("isNonZeroUnlockTime", m_is_nonzero_unlock_time.get(), allocator, root); - if (m_sanity_check_failed != boost::none) monero_utils::add_json_member("sanityCheckFailed", m_sanity_check_failed.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO OUTPUT DISTRIBUTION ENTRY --------------------------- - -void monero_output_distribution_entry::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& entry) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("amount")) entry->m_amount = it->second.get_value(); - else if (key == std::string("base")) entry->m_base = it->second.get_value(); - else if (key == std::string("distribution")) { - auto node2 = it->second; - for(auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - entry->m_distribution.push_back(it2->second.get_value()); - } - } - else if (key == std::string("start_height")) entry->m_start_height = it->second.get_value(); - } -} - -void monero_output_distribution_entry::from_property_tree(const boost::property_tree::ptree& node, std::vector>& entries) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("distributions")) { - auto node2 = it->second; - for(boost::property_tree::ptree::const_iterator it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto entry = std::make_shared(); - from_property_tree(it2->second, entry); - entries.push_back(entry); - } - } - } -} - -rapidjson::Value monero_output_distribution_entry::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_amount != boost::none) monero_utils::add_json_member("amount", m_amount.get(), allocator, root, value_num); - if (m_base != boost::none) monero_utils::add_json_member("base", m_base.get(), allocator, root, value_num); - if (m_start_height != boost::none) monero_utils::add_json_member("startHeight", m_start_height.get(), allocator, root, value_num); - - // set sub-arrays - if (!m_distribution.empty()) root.AddMember("distribution", to_rapidjson_vector_int_val(allocator, m_distribution), allocator); - - // return root - return root; -} - -// --------------------------- MONERO OUTPUT HISTOGRAM ENTRY --------------------------- - -void monero_output_histogram_entry::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& entry) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("amount")) entry->m_amount = it->second.get_value(); - else if (key == std::string("total_instances")) entry->m_num_instances = it->second.get_value(); - else if (key == std::string("unlocked_instances")) entry->m_unlocked_instances = it->second.get_value(); - else if (key == std::string("recent_instances")) entry->m_recent_instances = it->second.get_value(); - } -} - -void monero_output_histogram_entry::from_property_tree(const boost::property_tree::ptree& node, std::vector>& entries) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("histogram")) { - auto node2 = it->second; - - for(boost::property_tree::ptree::const_iterator it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto entry = std::make_shared(); - from_property_tree(it2->second, entry); - entries.push_back(entry); - } - } - } -} - -rapidjson::Value monero_output_histogram_entry::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_amount != boost::none) monero_utils::add_json_member("amount", m_amount.get(), allocator, root, value_num); - if (m_num_instances != boost::none) monero_utils::add_json_member("numInstances", m_num_instances.get(), allocator, root, value_num); - if (m_unlocked_instances != boost::none) monero_utils::add_json_member("unlockedInstances", m_unlocked_instances.get(), allocator, root, value_num); - if (m_recent_instances != boost::none) monero_utils::add_json_member("recentInstances", m_recent_instances.get(), allocator, root, value_num); - - // return root - return root; -} - -// --------------------------- MONERO TX POOL STATS --------------------------- - -void monero_tx_pool_stats::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& stats) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("pool_stats")) { - monero_tx_pool_stats::from_property_tree(it->second, stats); - break; - } - else if (key == std::string("txs_total")) stats->m_num_txs = it->second.get_value(); - else if (key == std::string("num_not_relayed")) stats->m_num_not_relayed = it->second.get_value(); - else if (key == std::string("num_failing")) stats->m_num_failing = it->second.get_value(); - else if (key == std::string("num_double_spends")) stats->m_num_double_spends = it->second.get_value(); - else if (key == std::string("num_10m")) stats->m_num10m = it->second.get_value(); - else if (key == std::string("fee_total")) stats->m_fee_total = it->second.get_value(); - else if (key == std::string("bytes_max")) stats->m_bytes_max = it->second.get_value(); - else if (key == std::string("bytes_med")) stats->m_bytes_med = it->second.get_value(); - else if (key == std::string("bytes_min")) stats->m_bytes_min = it->second.get_value(); - else if (key == std::string("bytes_total")) stats->m_bytes_total = it->second.get_value(); - else if (key == std::string("histo_98pc")) stats->m_histo98pc = it->second.get_value(); - else if (key == std::string("oldest")) stats->m_oldest_timestamp = it->second.get_value(); - else if (key == std::string("histo")) { - for(const auto& elem : it->second) { - uint64_t bytes, txs = 0; - for(boost::property_tree::ptree::const_iterator elem_it = elem.second.begin(); elem_it != elem.second.end(); ++elem_it) { - std::string elem_key = elem_it->first; - if (elem_key == "bytes") bytes = elem_it->second.get_value(); - else if (elem_key == "txs") txs = elem_it->second.get_value(); - } - - stats->m_histo[bytes] = txs; - } - } - } - - // uninitialize some stats if not applicable - if (stats->m_histo98pc != boost::none && stats->m_histo98pc.get() == 0) stats->m_histo98pc = boost::none; - if (stats->m_num_txs != boost::none && stats->m_num_txs.get() == 0) { - stats->m_bytes_min = boost::none; - stats->m_bytes_max = boost::none; - stats->m_bytes_med = boost::none; - stats->m_histo98pc = boost::none; - stats->m_oldest_timestamp = boost::none; - } -} - -rapidjson::Value monero_tx_pool_stats::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_num_txs != boost::none) monero_utils::add_json_member("numTxs", m_num_txs.get(), allocator, root, value_num); - if (m_num_not_relayed != boost::none) monero_utils::add_json_member("numNotRelayed", m_num_not_relayed.get(), allocator, root, value_num); - if (m_num_failing != boost::none) monero_utils::add_json_member("numFailing", m_num_failing.get(), allocator, root, value_num); - if (m_num_double_spends != boost::none) monero_utils::add_json_member("numDoubleSpends", m_num_double_spends.get(), allocator, root, value_num); - if (m_num10m != boost::none) monero_utils::add_json_member("num10m", m_num10m.get(), allocator, root, value_num); - if (m_fee_total != boost::none) monero_utils::add_json_member("feeTotal", m_fee_total.get(), allocator, root, value_num); - if (m_bytes_max != boost::none) monero_utils::add_json_member("bytesMax", m_bytes_max.get(), allocator, root, value_num); - if (m_bytes_med != boost::none) monero_utils::add_json_member("bytesMed", m_bytes_med.get(), allocator, root, value_num); - if (m_bytes_min != boost::none) monero_utils::add_json_member("bytesMin", m_bytes_min.get(), allocator, root, value_num); - if (m_bytes_total != boost::none) monero_utils::add_json_member("bytesTotal", m_bytes_total.get(), allocator, root, value_num); - if (m_histo98pc != boost::none) monero_utils::add_json_member("histo98pc", m_histo98pc.get(), allocator, root, value_num); - if (m_oldest_timestamp != boost::none) monero_utils::add_json_member("oldestTimestamp", m_oldest_timestamp.get(), allocator, root, value_num); - - // set object values - rapidjson::Value histo(rapidjson::kObjectType); - for(const auto& kv : m_histo) { - std::string key = std::to_string(kv.first); - rapidjson::Value field_key(key.c_str(), key.size(), allocator); - histo.AddMember(field_key, kv.second, allocator); - } - root.AddMember("histo", histo, allocator); - - // return root - return root; -} - -// --------------------------- MONERO DAEMON UPDATE CHECK RESULT --------------------------- - -void monero_daemon_update_check_result::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& check) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("update")) check->m_is_update_available = it->second.get_value(); - else if (key == std::string("version") && !it->second.data().empty()) check->m_version = it->second.data(); - else if (key == std::string("hash") && !it->second.data().empty()) check->m_hash = it->second.data(); - else if (key == std::string("auto_uri") && !it->second.data().empty()) check->m_auto_uri = it->second.data(); - else if (key == std::string("user_uri") && !it->second.data().empty()) check->m_user_uri = it->second.data(); - } -} - -rapidjson::Value monero_daemon_update_check_result::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_version != boost::none) monero_utils::add_json_member("version", m_version.get(), allocator, root, value_str); - if (m_hash != boost::none) monero_utils::add_json_member("hash", m_hash.get(), allocator, root, value_str); - if (m_auto_uri != boost::none) monero_utils::add_json_member("autoUri", m_auto_uri.get(), allocator, root, value_str); - if (m_user_uri != boost::none) monero_utils::add_json_member("userUri", m_user_uri.get(), allocator, root, value_str); - - // set bool values - if (m_is_update_available != boost::none) monero_utils::add_json_member("isUpdateAvailable", m_is_update_available.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO DAEMON UPDATE DOWNLOAD RESULT --------------------------- - -void monero_daemon_update_download_result::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& check) { - monero_daemon_update_check_result::from_property_tree(node, check); - - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("download_path") && !it->second.data().empty()) check->m_download_path = it->second.data(); - } -} - -rapidjson::Value monero_daemon_update_download_result::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root = monero_daemon_update_check_result::to_rapidjson_val(allocator); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_download_path != boost::none) monero_utils::add_json_member("downloadPath", m_download_path.get(), allocator, root, value_str); - - // return root - return root; -} - -// --------------------------- MONERO FEE ESTIMATE --------------------------- - -void monero_fee_estimate::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& estimate) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("fee")) estimate->m_fee = it->second.get_value(); - else if (key == std::string("quantization_mask")) estimate->m_quantization_mask = it->second.get_value(); - else if (key == std::string("fees")) { - auto node2 = it->second; - for (boost::property_tree::ptree::const_iterator it2 = node2.begin(); it2 != node2.end(); ++it2) { - uint64_t fee = it2->second.get_value(); - estimate->m_fees.push_back(fee); - } - } - } -} - -rapidjson::Value monero_fee_estimate::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_fee != boost::none) monero_utils::add_json_member("fee", m_fee.get(), allocator, root, value_num); - if (m_quantization_mask != boost::none) monero_utils::add_json_member("quantizationMask", m_quantization_mask.get(), allocator, root, value_num); - - // set sub-arrays - if (!m_fees.empty()) root.AddMember("fees", monero_utils::to_rapidjson_val(allocator, m_fees), allocator); - - // return root - return root; -} - -// --------------------------- MONERO DAEMON INFO --------------------------- - -void monero_daemon_info::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& info) { - monero_rpc_payment_info::from_property_tree(node, info); - - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("version")) info->m_version = it->second.data(); - else if (key == std::string("alt_blocks_count")) info->m_num_alt_blocks = it->second.get_value(); - else if (key == std::string("block_size_limit")) info->m_block_size_limit = it->second.get_value(); - else if (key == std::string("block_size_median")) info->m_block_size_median = it->second.get_value(); - else if (key == std::string("block_weight_limit")) info->m_block_weight_limit = it->second.get_value(); - else if (key == std::string("block_weight_median")) info->m_block_weight_median = it->second.get_value(); - else if (key == std::string("bootstrap_daemon_address") && !it->second.data().empty()) info->m_bootstrap_daemon_address = it->second.data(); - else if (key == std::string("difficulty")) info->m_difficulty = it->second.get_value(); - else if (key == std::string("cumulative_difficulty")) info->m_cumulative_difficulty = it->second.get_value(); - else if (key == std::string("free_space")) info->m_free_space = it->second.get_value(); - else if (key == std::string("grey_peerlist_size")) info->m_num_offline_peers = it->second.get_value(); - else if (key == std::string("white_peerlist_size")) info->m_num_online_peers = it->second.get_value(); - else if (key == std::string("height")) info->m_height = it->second.get_value(); - else if (key == std::string("height_without_bootstrap")) info->m_height_without_bootstrap = it->second.get_value(); - else if (key == std::string("nettype")) { - std::string nettype = it->second.data(); - if (nettype == std::string("mainnet") || nettype == std::string("fakechain")) info->m_network_type = monero::monero_network_type::MAINNET; - else if (nettype == std::string("testnet")) info->m_network_type = monero::monero_network_type::TESTNET; - else if (nettype == std::string("stagenet")) info->m_network_type = monero::monero_network_type::STAGENET; - } - else if (key == std::string("offline")) info->m_is_offline = it->second.get_value(); - else if (key == std::string("incoming_connections_count")) info->m_num_incoming_connections = it->second.get_value(); - else if (key == std::string("outgoing_connections_count")) info->m_num_outgoing_connections = it->second.get_value(); - else if (key == std::string("rpc_connections_count")) info->m_num_rpc_connections = it->second.get_value(); - else if (key == std::string("start_time")) info->m_start_timestamp = it->second.get_value(); - else if (key == std::string("adjusted_time")) info->m_adjusted_timestamp = it->second.get_value(); - else if (key == std::string("target")) info->m_target = it->second.get_value(); - else if (key == std::string("target_height")) info->m_target_height = it->second.get_value(); - else if (key == std::string("tx_count")) info->m_num_txs = it->second.get_value(); - else if (key == std::string("tx_pool_size")) info->m_num_txs_pool = it->second.get_value(); - else if (key == std::string("was_bootstrap_ever_used")) info->m_was_bootstrap_ever_used = it->second.get_value(); - else if (key == std::string("database_size")) info->m_database_size = it->second.get_value(); - else if (key == std::string("update_available")) info->m_update_available = it->second.get_value(); - else if (key == std::string("busy_syncing")) info->m_is_busy_syncing = it->second.get_value(); - else if (key == std::string("synchronized")) info->m_is_synchronized = it->second.get_value(); - else if (key == std::string("restricted")) info->m_is_restricted = it->second.get_value(); - } -} - -rapidjson::Value monero_daemon_info::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_version != boost::none) monero_utils::add_json_member("version", m_version.get(), allocator, root, value_str); - if (m_bootstrap_daemon_address != boost::none) monero_utils::add_json_member("bootstrapDaemonAddress", m_bootstrap_daemon_address.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_num_alt_blocks != boost::none) monero_utils::add_json_member("numAltBlocks", m_num_alt_blocks.get(), allocator, root, value_num); - if (m_block_size_limit != boost::none) monero_utils::add_json_member("blockSizeLimit", m_block_size_limit.get(), allocator, root, value_num); - if (m_block_size_median != boost::none) monero_utils::add_json_member("blockSizeMedian", m_block_size_median.get(), allocator, root, value_num); - if (m_block_weight_limit != boost::none) monero_utils::add_json_member("blockWeightLimit", m_block_weight_limit.get(), allocator, root, value_num); - if (m_block_weight_median != boost::none) monero_utils::add_json_member("blockWeightMedian", m_block_weight_median.get(), allocator, root, value_num); - if (m_difficulty != boost::none) monero_utils::add_json_member("difficulty", m_difficulty.get(), allocator, root, value_num); - if (m_cumulative_difficulty != boost::none) monero_utils::add_json_member("cumulativeDifficulty", m_cumulative_difficulty.get(), allocator, root, value_num); - if (m_free_space != boost::none) monero_utils::add_json_member("freeSpace", m_free_space.get(), allocator, root, value_num); - if (m_num_offline_peers != boost::none) monero_utils::add_json_member("numOfflinePeers", m_num_offline_peers.get(), allocator, root, value_num); - if (m_num_online_peers != boost::none) monero_utils::add_json_member("numOnlinePeers", m_num_online_peers.get(), allocator, root, value_num); - if (m_height != boost::none) monero_utils::add_json_member("height", m_height.get(), allocator, root, value_num); - if (m_height_without_bootstrap != boost::none) monero_utils::add_json_member("heightWithoutBootstrap", m_height_without_bootstrap.get(), allocator, root, value_num); - if (m_network_type != boost::none) monero_utils::add_json_member("networkType", (uint8_t)m_network_type.get(), allocator, root, value_num); - if (m_num_incoming_connections != boost::none) monero_utils::add_json_member("numIncomingConnections", m_num_incoming_connections.get(), allocator, root, value_num); - if (m_num_outgoing_connections != boost::none) monero_utils::add_json_member("numOutgoingConnections", m_num_outgoing_connections.get(), allocator, root, value_num); - if (m_num_rpc_connections != boost::none) monero_utils::add_json_member("numRpcConnections", m_num_rpc_connections.get(), allocator, root, value_num); - if (m_start_timestamp != boost::none) monero_utils::add_json_member("startTimestamp", m_start_timestamp.get(), allocator, root, value_num); - if (m_adjusted_timestamp != boost::none) monero_utils::add_json_member("adjustedTimestamp", m_adjusted_timestamp.get(), allocator, root, value_num); - if (m_target != boost::none) monero_utils::add_json_member("target", m_target.get(), allocator, root, value_num); - if (m_target_height != boost::none) monero_utils::add_json_member("targetHeight", m_target_height.get(), allocator, root, value_num); - if (m_num_txs != boost::none) monero_utils::add_json_member("numTxs", m_num_txs.get(), allocator, root, value_num); - if (m_num_txs_pool != boost::none) monero_utils::add_json_member("numTxsPool", m_num_txs_pool.get(), allocator, root, value_num); - if (m_database_size != boost::none) monero_utils::add_json_member("databaseSize", m_database_size.get(), allocator, root, value_num); - - // set bool values - if (m_is_offline != boost::none) monero_utils::add_json_member("isOffline", m_is_offline.get(), allocator, root); - if (m_was_bootstrap_ever_used != boost::none) monero_utils::add_json_member("wasBootstrapEverUsed", m_was_bootstrap_ever_used.get(), allocator, root); - if (m_update_available != boost::none) monero_utils::add_json_member("updateAvailable", m_update_available.get(), allocator, root); - if (m_is_busy_syncing != boost::none) monero_utils::add_json_member("isBusySyncing", m_is_busy_syncing.get(), allocator, root); - if (m_is_synchronized != boost::none) monero_utils::add_json_member("isSynchronized", m_is_synchronized.get(), allocator, root); - if (m_is_restricted != boost::none) monero_utils::add_json_member("isRestricted", m_is_restricted.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO DAEMON SYNC INFO --------------------------- - -void monero_daemon_sync_info::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& info) { - monero_rpc_payment_info::from_property_tree(node, info); - - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("height")) info->m_height = it->second.get_value(); - else if (key == std::string("target_height")) info->m_target_height = it->second.get_value(); - else if (key == std::string("next_needed_pruning_seed")) info->m_next_needed_pruning_seed = it->second.get_value(); - else if (key == std::string("overview") && !it->second.data().empty() && it->second.data() != std::string("[]")) info->m_overview = it->second.data(); - } -} - -rapidjson::Value monero_daemon_sync_info::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_overview != boost::none) monero_utils::add_json_member("overview", m_overview.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_height != boost::none) monero_utils::add_json_member("height", m_height.get(), allocator, root, value_num); - if (m_target_height != boost::none) monero_utils::add_json_member("targetHeight", m_target_height.get(), allocator, root, value_num); - if (m_next_needed_pruning_seed != boost::none) monero_utils::add_json_member("nextNeededPruningSeed", m_next_needed_pruning_seed.get(), allocator, root, value_num); - - // set sub-arrays - if (!m_peers.empty()) root.AddMember("peers", monero_utils::to_rapidjson_val(allocator, m_peers), allocator); - if (!m_spans.empty()) root.AddMember("spans", monero_utils::to_rapidjson_val(allocator, m_spans), allocator); - - // return root - return root; -} - -// --------------------------- MONERO HARD FORK INFO --------------------------- - -void monero_hard_fork_info::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& info) { - monero_rpc_payment_info::from_property_tree(node, info); - - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("earliest_height")) info->m_earliest_height = it->second.get_value(); - else if (key == std::string("enabled")) info->m_is_enabled = it->second.get_value(); - else if (key == std::string("state")) info->m_state = it->second.get_value(); - else if (key == std::string("threshold")) info->m_threshold = it->second.get_value(); - else if (key == std::string("version")) info->m_version = it->second.get_value(); - else if (key == std::string("votes")) info->m_num_votes = it->second.get_value(); - else if (key == std::string("window")) info->m_window = it->second.get_value(); - else if (key == std::string("voting")) info->m_voting = it->second.get_value(); - } -} - -rapidjson::Value monero_hard_fork_info::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_earliest_height != boost::none) monero_utils::add_json_member("earliestHeight", m_earliest_height.get(), allocator, root, value_num); - if (m_state != boost::none) monero_utils::add_json_member("state", m_state.get(), allocator, root, value_num); - if (m_threshold != boost::none) monero_utils::add_json_member("threshold", m_threshold.get(), allocator, root, value_num); - if (m_version != boost::none) monero_utils::add_json_member("version", m_version.get(), allocator, root, value_num); - if (m_num_votes != boost::none) monero_utils::add_json_member("numVotes", m_num_votes.get(), allocator, root, value_num); - if (m_window != boost::none) monero_utils::add_json_member("window", m_window.get(), allocator, root, value_num); - if (m_voting != boost::none) monero_utils::add_json_member("voting", m_voting.get(), allocator, root, value_num); - - // set bool values - if (m_is_enabled != boost::none) monero_utils::add_json_member("isEnabled", m_is_enabled.get(), allocator, root); - - // return root - return root; -} diff --git a/src/cpp/daemon/py_monero_daemon_model.h b/src/cpp/daemon/py_monero_daemon_model.h deleted file mode 100644 index 23000fa..0000000 --- a/src/cpp/daemon/py_monero_daemon_model.h +++ /dev/null @@ -1,393 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ -#pragma once - -#include "common/py_monero_common.h" - -// ------------------------------ Custom Data Model --------------------------------- - -struct PyMoneroBlockHeader : public monero::monero_block_header { -public: - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& header); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector>& headers); -}; - -struct PyMoneroBlock : public PyMoneroBlockHeader { -public: - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& block); - static void from_property_tree(const boost::property_tree::ptree& node, const std::vector& heights, std::vector>& blocks); -}; - -struct PyMoneroOutput : public monero::monero_output { -public: - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& output); -}; - -struct PyMoneroTx : public monero::monero_tx { -public: - inline static const std::string DEFAULT_ID = "0000000000000000000000000000000000000000000000000000000000000000"; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& tx); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector>& txs); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector& tx_hashes); -}; - -struct PyMoneroVersion : public monero::monero_version { -public: - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& version); -}; - -// ------------------------------ Extended Data Model --------------------------------- - -enum monero_key_image_spent_status : uint8_t { - NOT_SPENT = 0, - CONFIRMED, - TX_POOL -}; - -/** - * Models a Monero RPC payment information. - */ -struct monero_rpc_payment_info : public monero::serializable_struct { -public: - boost::optional m_credits; - boost::optional m_top_block_hash; - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& rpc_payment_info); -}; - -struct monero_alt_chain : public monero::serializable_struct { -public: - std::vector m_block_hashes; - boost::optional m_difficulty; - boost::optional m_height; - boost::optional m_length; - boost::optional m_main_chain_parent_block_hash; - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& alt_chain); -}; - -struct monero_ban : public monero::serializable_struct { -public: - boost::optional m_host; - boost::optional m_ip; - boost::optional m_is_banned; - boost::optional m_seconds; - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& ban); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector>& bans); -}; - -struct monero_prune_result : public monero::serializable_struct { -public: - boost::optional m_is_pruned; - boost::optional m_pruning_seed; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& result); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_mining_status : public monero::serializable_struct { -public: - boost::optional m_is_active; - boost::optional m_is_background; - boost::optional m_address; - boost::optional m_speed; - boost::optional m_num_threads; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& status); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_miner_tx_sum : public monero::serializable_struct { -public: - boost::optional m_emission_sum; - boost::optional m_fee_sum; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& sum); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_block_template : public monero::serializable_struct { -public: - boost::optional m_block_template_blob; - boost::optional m_block_hashing_blob; - boost::optional m_prev_hash; - boost::optional m_seed_hash; - boost::optional m_next_seed_hash; - boost::optional m_difficulty; - boost::optional m_expected_reward; - boost::optional m_height; - boost::optional m_reserved_offset; - boost::optional m_seed_height; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& tmplt); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_connection_span : public monero::serializable_struct { -public: - boost::optional m_connection_id; - boost::optional m_remote_address; - boost::optional m_num_blocks; - boost::optional m_rate; - boost::optional m_speed; - boost::optional m_size; - boost::optional m_start_height; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& span); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_peer : public monero::serializable_struct { -public: - boost::optional m_id; - boost::optional m_address; - boost::optional m_host; - boost::optional m_port; - boost::optional m_is_online; - boost::optional m_last_seen_timestamp; - boost::optional m_pruning_seed; - boost::optional m_rpc_port; - boost::optional m_rpc_credits_per_hash; - boost::optional m_hash; - boost::optional m_avg_download; - boost::optional m_avg_upload; - boost::optional m_current_download; - boost::optional m_current_upload; - boost::optional m_height; - boost::optional m_is_incoming; - boost::optional m_live_time; - boost::optional m_is_local_ip; - boost::optional m_is_local_host; - boost::optional m_num_receives; - boost::optional m_num_sends; - boost::optional m_receive_idle_time; - boost::optional m_send_idle_time; - boost::optional m_state; - boost::optional m_num_support_flags; - boost::optional m_connection_type; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& peer); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector>& peers); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_submit_tx_result : public monero_rpc_payment_info { -public: - boost::optional m_has_invalid_input; - boost::optional m_has_invalid_output; - boost::optional m_has_too_few_outputs; - boost::optional m_is_good; - boost::optional m_is_relayed; - boost::optional m_is_double_spend; - boost::optional m_is_fee_too_low; - boost::optional m_is_mixin_too_low; - boost::optional m_is_overspend; - boost::optional m_is_too_big; - boost::optional m_sanity_check_failed; - boost::optional m_is_tx_extra_too_big; - boost::optional m_is_nonzero_unlock_time; - boost::optional m_reason; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& result); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_tx_backlog_entry { - // TODO -}; - -struct monero_output_distribution_entry : public monero::serializable_struct { -public: - boost::optional m_amount; - boost::optional m_base; - std::vector m_distribution; - boost::optional m_start_height; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& entry); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector>& entries); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_output_histogram_entry : public monero::serializable_struct { -public: - boost::optional m_amount; - boost::optional m_num_instances; - boost::optional m_unlocked_instances; - boost::optional m_recent_instances; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& entry); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector>& entries); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_tx_pool_stats : public monero::serializable_struct { -public: - boost::optional m_num_txs; - boost::optional m_num_not_relayed; - boost::optional m_num_failing; - boost::optional m_num_double_spends; - boost::optional m_num10m; - boost::optional m_fee_total; - boost::optional m_bytes_max; - boost::optional m_bytes_med; - boost::optional m_bytes_min; - boost::optional m_bytes_total; - std::map m_histo; - boost::optional m_histo98pc; - boost::optional m_oldest_timestamp; - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& stats); -}; - -struct monero_daemon_update_check_result : public monero::serializable_struct { -public: - boost::optional m_is_update_available; - boost::optional m_version; - boost::optional m_hash; - boost::optional m_auto_uri; - boost::optional m_user_uri; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& check); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_daemon_update_download_result : public monero_daemon_update_check_result { -public: - boost::optional m_download_path; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& check); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_fee_estimate : public monero::serializable_struct { -public: - boost::optional m_quantization_mask; - boost::optional m_fee; - std::vector m_fees; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& estimate); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_daemon_info : public monero_rpc_payment_info { -public: - boost::optional m_version; - boost::optional m_num_alt_blocks; - boost::optional m_block_size_limit; - boost::optional m_block_size_median; - boost::optional m_block_weight_limit; - boost::optional m_block_weight_median; - boost::optional m_bootstrap_daemon_address; - boost::optional m_difficulty; - boost::optional m_cumulative_difficulty; - boost::optional m_free_space; - boost::optional m_num_offline_peers; - boost::optional m_num_online_peers; - boost::optional m_height; - boost::optional m_height_without_bootstrap; - boost::optional m_network_type; - boost::optional m_is_offline; - boost::optional m_num_incoming_connections; - boost::optional m_num_outgoing_connections; - boost::optional m_num_rpc_connections; - boost::optional m_start_timestamp; - boost::optional m_adjusted_timestamp; - boost::optional m_target; - boost::optional m_target_height; - boost::optional m_num_txs; - boost::optional m_num_txs_pool; - boost::optional m_was_bootstrap_ever_used; - boost::optional m_database_size; - boost::optional m_update_available; - boost::optional m_is_busy_syncing; - boost::optional m_is_synchronized; - boost::optional m_is_restricted; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& info); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_daemon_sync_info : public monero_rpc_payment_info { -public: - boost::optional m_overview; - boost::optional m_height; - boost::optional m_target_height; - boost::optional m_next_needed_pruning_seed; - std::vector m_peers; - std::vector m_spans; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& info); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_hard_fork_info : public monero_rpc_payment_info { -public: - boost::optional m_is_enabled; - boost::optional m_earliest_height; - boost::optional m_state; - boost::optional m_threshold; - boost::optional m_version; - boost::optional m_num_votes; - boost::optional m_window; - boost::optional m_voting; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& info); - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; diff --git a/src/cpp/daemon/py_monero_daemon_rpc.cpp b/src/cpp/daemon/py_monero_daemon_rpc.cpp deleted file mode 100644 index 0a700c5..0000000 --- a/src/cpp/daemon/py_monero_daemon_rpc.cpp +++ /dev/null @@ -1,825 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ -#include "py_monero_daemon_rpc.h" -#include "py_monero_daemon_rpc_model.h" -#include "utils/py_monero_utils.h" - -static const uint64_t MAX_REQ_SIZE = 3000000; -static const uint64_t NUM_HEADERS_PER_REQ = 750; - -/** - * Polls daemon and sends notifications in order to notify external daemon listeners. - */ -class monero_daemon_poller: public thread_poller { -public: - - explicit monero_daemon_poller(monero_daemon* daemon, uint64_t poll_period_ms = 5000): m_daemon(daemon) { - init_common("monero_daemon_rpc"); - m_poll_period_ms = poll_period_ms; - } - - void poll() override { - if (!m_last_header) { - m_last_header = m_daemon->get_last_block_header(); - return; - } - - auto header = m_daemon->get_last_block_header(); - if (header->m_hash != m_last_header->m_hash) { - m_last_header = header; - announce_block_header(header); - } - } - -private: - monero_daemon* m_daemon; - std::shared_ptr m_last_header; - - void announce_block_header(const std::shared_ptr& header) { - auto listeners = m_daemon->get_listeners(); - for (auto& listener : listeners) { - try { - listener->on_block_header(header); - } catch (const std::exception& e) { - MERROR("Error calling listener on new block header: " << e.what()); - } - } - } -}; - -/** - * Sends a notification on a condition variable when a block is added to blockchain. - */ -class block_notifier : public monero_daemon_listener { -public: - block_notifier(boost::mutex* temp, boost::condition_variable* cv, bool* ready) { this->temp = temp; this->cv = cv; this->ready = ready; } - - void on_block_header(const std::shared_ptr& header) override { - boost::mutex::scoped_lock lock(*temp); - m_last_header = header; - *ready = true; - cv->notify_one(); - } - -private: - boost::mutex* temp; - boost::condition_variable* cv; - bool* ready; -}; - -monero_daemon_rpc::monero_daemon_rpc(const std::shared_ptr& rpc): m_rpc(rpc) { - if (!rpc->is_online() && rpc->m_uri != boost::none) rpc->check_connection(); -} - -monero_daemon_rpc::monero_daemon_rpc(const std::string& uri, const std::string& username, const std::string& password, const std::string& proxy_uri, const std::string& zmq_uri, uint64_t timeout): - m_rpc(std::make_shared(uri, username, password, proxy_uri, zmq_uri, 0, timeout)) { - if (!uri.empty()) m_rpc->check_connection(); -} - -std::set monero_daemon_rpc::get_listeners() { - boost::lock_guard lock(m_listeners_mutex); - return m_listeners; -} - -void monero_daemon_rpc::add_listener(monero_daemon_listener &listener) { - boost::lock_guard lock(m_listeners_mutex); - m_listeners.insert(&listener); - refresh_listening(); -} - -void monero_daemon_rpc::remove_listener(monero_daemon_listener &listener) { - boost::lock_guard lock(m_listeners_mutex); - m_listeners.erase(&listener); - refresh_listening(); -} - -void monero_daemon_rpc::remove_listeners() { - boost::lock_guard lock(m_listeners_mutex); - m_listeners.clear(); - refresh_listening(); -} - -std::shared_ptr monero_daemon_rpc::get_rpc_connection() const { - MTRACE("monero_daemon_rpc::get_rpc_connection()"); - return m_rpc; -} - -bool monero_daemon_rpc::is_connected() { - try { - get_version(); - return true; - } - catch (...) { - return false; - } -} - -monero::monero_version monero_daemon_rpc::get_version() { - auto res = m_rpc->send_json_request("get_version"); - check_response_status(res); - std::shared_ptr info = std::make_shared(); - PyMoneroVersion::from_property_tree(res, info); - return *info; -} - -bool monero_daemon_rpc::is_trusted() { - auto res = m_rpc->send_path_request("get_height"); - check_response_status(res); - auto get_height_response = std::make_shared(); - monero_get_block_result::from_property_tree(res, get_height_response); - return !get_height_response->m_untrusted.get(); -} - -uint64_t monero_daemon_rpc::get_height() { - auto res = m_rpc->send_json_request("get_block_count"); - check_response_status(res); - std::shared_ptr result = std::make_shared(); - monero_get_block_result::from_property_tree(res, result); - if (result->m_count == boost::none) throw std::runtime_error("Could not get height"); - return result->m_count.get(); -} - -std::string monero_daemon_rpc::get_block_hash(uint64_t height) { - std::shared_ptr params = std::make_shared(height); - auto res = m_rpc->send_json_request("on_get_block_hash", params); - return res.data(); -} - -std::shared_ptr monero_daemon_rpc::get_block_template(const std::string& wallet_address, const boost::optional& reserve_size) { - MTRACE("monero_daemon_rpc::get_block_template()"); - auto params = std::make_shared(wallet_address, reserve_size); - auto res = m_rpc->send_json_request("get_block_template", params); - check_response_status(res); - std::shared_ptr tmplt = std::make_shared(); - monero_block_template::from_property_tree(res, tmplt); - return tmplt; -} - -std::shared_ptr monero_daemon_rpc::get_last_block_header() { - auto res = m_rpc->send_json_request("get_last_block_header"); - check_response_status(res); - std::shared_ptr header = std::make_shared(); - PyMoneroBlockHeader::from_property_tree(res, header); - return header; -} - -std::shared_ptr monero_daemon_rpc::get_block_header_by_hash(const std::string& hash) { - std::shared_ptr params = std::make_shared(hash); - auto res = m_rpc->send_json_request("get_block_header_by_hash", params); - check_response_status(res); - std::shared_ptr header = std::make_shared(); - PyMoneroBlockHeader::from_property_tree(res, header); - return header; -} - -std::shared_ptr monero_daemon_rpc::get_block_header_by_height(uint64_t height) { - std::shared_ptr params = std::make_shared(height); - auto res = m_rpc->send_json_request("get_block_header_by_height", params); - check_response_status(res); - std::shared_ptr header = std::make_shared(); - PyMoneroBlockHeader::from_property_tree(res, header); - return header; -} - -std::vector> monero_daemon_rpc::get_block_headers_by_range(uint64_t start_height, uint64_t end_height) { - auto params = std::make_shared(start_height, end_height); - auto res = m_rpc->send_json_request("get_block_headers_range", params); - check_response_status(res); - std::vector> headers; - PyMoneroBlockHeader::from_property_tree(res, headers); - return headers; -} - -std::shared_ptr monero_daemon_rpc::get_block_by_hash(const std::string& hash) { - std::shared_ptr params = std::make_shared(hash); - auto res = m_rpc->send_json_request("get_block", params); - check_response_status(res); - auto block = std::make_shared(); - PyMoneroBlock::from_property_tree(res, block); - return block; -} - -std::shared_ptr monero_daemon_rpc::get_block_header_by_height_cached(uint64_t height, uint64_t max_height) { - // get header from cache - auto found = m_cached_headers.find(height); - if (found != m_cached_headers.end()) return found->second; - - // fetch and cache headers if not in cache - uint64_t end_height = std::min(max_height, height + NUM_HEADERS_PER_REQ - 1); - auto headers = get_block_headers_by_range(height, end_height); - - for(const auto& header : headers) { - m_cached_headers[header->m_height.get()] = header; - } - - return m_cached_headers[height]; -} - -std::vector> monero_daemon_rpc::get_blocks_by_hash(const std::vector& block_hashes, uint64_t start_height, bool prune) { - throw std::runtime_error("monero_daemon_rpc::get_blocks_by_hash(): not implemented"); -} - -std::shared_ptr monero_daemon_rpc::get_block_by_height(uint64_t height) { - std::shared_ptr params = std::make_shared(height); - auto res = m_rpc->send_json_request("get_block", params); - check_response_status(res); - auto block = std::make_shared(); - PyMoneroBlock::from_property_tree(res, block); - return block; -} - -std::vector> monero_daemon_rpc::get_blocks_by_height(const std::vector& heights) { - // fetch blocks in binary - monero_get_blocks_by_height_request request(heights); - auto response = m_rpc->send_binary_request(request); - if (response.m_binary == boost::none) throw std::runtime_error("Invalid Monero Binary response"); - boost::property_tree::ptree node; - PyMoneroUtils::binary_blocks_to_property_tree(response.m_binary.get(), node); - check_response_status(node); - std::vector> blocks; - PyMoneroBlock::from_property_tree(node, heights, blocks); - return blocks; -} - -std::vector> monero_daemon_rpc::get_blocks_by_range(boost::optional start_height, boost::optional end_height) { - if (start_height == boost::none) { - start_height = 0; - } - if (end_height == boost::none) { - end_height = get_height() - 1; - } - - std::vector heights; - for (uint64_t height = start_height.get(); height <= end_height.get(); height++) heights.push_back(height); - - return get_blocks_by_height(heights); -} - -std::vector> monero_daemon_rpc::get_blocks_by_range_chunked(boost::optional start_height, boost::optional end_height, boost::optional max_chunk_size) { - if (start_height == boost::none) start_height = 0; - if (end_height == boost::none) end_height = get_height() - 1; - uint64_t from_height = start_height.get(); - bool from_zero = from_height == 0; - uint64_t last_height = (!from_zero) ? from_height - 1 : from_height; - std::vector> blocks; - while (last_height < end_height) { - uint64_t height_to_get = last_height + 1; - if (from_zero) { - height_to_get = 0; - from_zero = false; - } - auto max_blocks = get_max_blocks(height_to_get, end_height, max_chunk_size); - if (!max_blocks.empty()) blocks.insert(blocks.end(), max_blocks.begin(), max_blocks.end()); - last_height = blocks[blocks.size() - 1]->m_height.get(); - } - return blocks; -} - -std::vector> monero_daemon_rpc::get_max_blocks(boost::optional start_height, boost::optional max_height, boost::optional chunk_size) { - if (start_height == boost::none) start_height = 0; - if (max_height == boost::none) max_height = get_height() - 1; - if (chunk_size == boost::none) chunk_size = MAX_REQ_SIZE; - - // determine end height to fetch - uint64_t req_size = 0; - uint64_t from_height = start_height.get(); - bool from_zero = from_height == 0; - uint64_t end_height = (!from_zero) ? from_height - 1 : 0; - - while (req_size < chunk_size && end_height < max_height) { - // get header of next block - uint64_t height_to_get = end_height + 1; - if (from_zero) { - height_to_get = 0; - from_zero = false; - } - auto header = get_block_header_by_height_cached(height_to_get, max_height.get()); - uint64_t header_size = header->m_size.get(); - // block cannot be bigger than max request size - if (header_size > chunk_size) throw std::runtime_error("Block exceeds maximum request size: " + std::to_string(header_size)); - - // done iterating if fetching block would exceed max request size - if (req_size + header_size > chunk_size) break; - - // otherwise block is included - req_size += header_size; - end_height++; - } - - if (end_height >= start_height) { - return get_blocks_by_range(start_height, end_height); - } - - return std::vector>(); -} - -std::vector monero_daemon_rpc::get_block_hashes(const std::vector& block_hashes, uint64_t start_height) { - throw std::runtime_error("monero_daemon_rpc::get_block_hashes(): not implemented"); -} - -std::vector> monero_daemon_rpc::get_txs(const std::vector& tx_hashes, bool prune) { - MTRACE("monero_daemon_rpc::get_txs()"); - if (tx_hashes.empty()) throw std::runtime_error("Must provide an array of transaction hashes"); - auto params = std::make_shared(tx_hashes, prune); - auto res = m_rpc->send_path_request("get_transactions", params); - try { check_response_status(res); } - catch (const std::exception& ex) { - if (std::string(ex.what()).find("Failed to parse hex representation of transaction hash") != std::string::npos) { - throw std::runtime_error("Invalid transaction hash"); - } - throw; - } - std::vector> txs; - PyMoneroTx::from_property_tree(res, txs); - return txs; -} - -std::vector monero_daemon_rpc::get_tx_hexes(const std::vector& tx_hashes, bool prune) { - MTRACE("monero_daemon_rpc::get_tx_hexes()"); - std::vector hexes; - for(const auto& tx : get_txs(tx_hashes, prune)) { - // tx may be pruned regardless of configuration - if (tx->m_pruned_hex == boost::none) { - if (tx->m_full_hex == boost::none) throw std::runtime_error("Tx has no hex"); - hexes.push_back(tx->m_full_hex.get()); - } else { - hexes.push_back(tx->m_pruned_hex.get()); - } - } - return hexes; -} - -std::shared_ptr monero_daemon_rpc::get_miner_tx_sum(uint64_t height, uint64_t num_blocks) { - auto params = std::make_shared(height, num_blocks); - auto res = m_rpc->send_json_request("get_coinbase_tx_sum", params); - check_response_status(res); - auto sum = std::make_shared(); - monero_miner_tx_sum::from_property_tree(res, sum); - return sum; -} - -std::shared_ptr monero_daemon_rpc::get_fee_estimate(uint64_t grace_blocks) { - auto params = std::make_shared(grace_blocks); - auto res = m_rpc->send_json_request("get_fee_estimate", params); - check_response_status(res); - auto estimate = std::make_shared(); - monero_fee_estimate::from_property_tree(res, estimate); - return estimate; -} - -std::shared_ptr monero_daemon_rpc::submit_tx_hex(const std::string& tx_hex, bool do_not_relay) { - MTRACE("monero_daemon_rpc::submit_tx_hex()"); - auto params = std::make_shared(tx_hex, do_not_relay); - auto res = m_rpc->send_path_request("send_raw_transaction", params); - auto sum = std::make_shared(); - monero_submit_tx_result::from_property_tree(res, sum); - - // set m_is_good based on status - try { - check_response_status(res); - sum->m_is_good = true; - } catch (...) { - sum->m_is_good = false; - } - return sum; -} - -void monero_daemon_rpc::relay_txs_by_hash(const std::vector& tx_hashes) { - MTRACE("monero_daemon_rpc::relay_txs_by_hash()"); - auto params = std::make_shared(tx_hashes); - auto res = m_rpc->send_json_request("relay_tx", params); - check_response_status(res); -} - -std::shared_ptr monero_daemon_rpc::get_tx_pool_stats() { - auto res = m_rpc->send_path_request("get_transaction_pool_stats"); - check_response_status(res); - auto stats = std::make_shared(); - monero_tx_pool_stats::from_property_tree(res, stats); - return stats; -} - -std::vector> monero_daemon_rpc::get_tx_pool() { - auto res = m_rpc->send_path_request("get_transaction_pool"); - check_response_status(res); - std::vector> pool; - PyMoneroTx::from_property_tree(res, pool); - return pool; -} - -std::vector monero_daemon_rpc::get_tx_pool_hashes() { - auto res = m_rpc->send_path_request("get_transaction_pool_hashes"); - check_response_status(res); - std::vector tx_hashes; - PyMoneroTx::from_property_tree(res, tx_hashes); - return tx_hashes; -} - -void monero_daemon_rpc::flush_tx_pool(const std::vector &hashes) { - MTRACE("monero_daemon_rpc::flush_tx_pool()"); - auto params = std::make_shared(hashes); - auto res = m_rpc->send_json_request("flush_txpool", params); - check_response_status(res); -} - -void monero_daemon_rpc::flush_tx_pool() { - std::vector hashes; - flush_tx_pool(hashes); -} - -void monero_daemon_rpc::flush_tx_pool(const std::string &hash) { - std::vector hashes; - hashes.push_back(hash); - flush_tx_pool(hashes); -} - -std::vector monero_daemon_rpc::get_key_image_spent_statuses(const std::vector& key_images) { - if (key_images.empty()) throw std::runtime_error("Must provide key images to check the status of"); - auto params = std::make_shared(key_images); - auto res = m_rpc->send_path_request("is_key_image_spent", params); - check_response_status(res); - std::vector statuses; - for (auto it = res.begin(); it != res.end(); ++it) { - std::string key = it->first; - if (key == std::string("spent_status")) { - auto spent_status_node = it->second; - for (auto it2 = spent_status_node.begin(); it2 != spent_status_node.end(); ++it2) { - auto value = it2->second.get_value(); - if (value == 0) { - statuses.push_back(monero_key_image_spent_status::NOT_SPENT); - } - else if (value == 1) { - statuses.push_back(monero_key_image_spent_status::CONFIRMED); - } - else if (value == 2) { - statuses.push_back(monero_key_image_spent_status::TX_POOL); - } - } - } - } - return statuses; -} - -std::vector> monero_daemon_rpc::get_outputs(const std::vector& outputs) { - throw std::runtime_error("monero_daemon_rpc::get_outputs(): not implemented"); -} - -std::vector> monero_daemon_rpc::get_output_histogram(const std::vector& amounts, const boost::optional& min_count, const boost::optional& max_count, const boost::optional& is_unlocked, const boost::optional& recent_cutoff) { - MTRACE("monero_daemon_rpc::get_output_histogram()"); - auto params = std::make_shared(amounts, min_count, max_count, is_unlocked, recent_cutoff); - auto res = m_rpc->send_json_request("get_output_histogram", params); - check_response_status(res); - std::vector> entries; - monero_output_histogram_entry::from_property_tree(res, entries); - return entries; -} - -std::vector> monero_daemon_rpc::get_output_distribution(const std::vector& amounts, const boost::optional& is_cumulative, const boost::optional& start_height, const boost::optional& end_height) { - MTRACE("monero_daemon_rpc::get_output_distribution()"); - auto params = std::make_shared(amounts, is_cumulative, start_height, end_height); - auto res = m_rpc->send_json_request("get_output_distribution", params); - check_response_status(res); - std::vector> entries; - monero_output_distribution_entry::from_property_tree(res, entries); - return entries; -} - -std::shared_ptr monero_daemon_rpc::get_info() { - auto res = m_rpc->send_json_request("get_info"); - check_response_status(res); - std::shared_ptr info = std::make_shared(); - monero_daemon_info::from_property_tree(res, info); - return info; -} - -std::shared_ptr monero_daemon_rpc::get_sync_info() { - auto res = m_rpc->send_json_request("sync_info"); - check_response_status(res); - std::shared_ptr info = std::make_shared(); - monero_daemon_sync_info::from_property_tree(res, info); - return info; -} - -std::shared_ptr monero_daemon_rpc::get_hard_fork_info() { - auto res = m_rpc->send_json_request("hard_fork_info"); - check_response_status(res); - std::shared_ptr info = std::make_shared(); - monero_hard_fork_info::from_property_tree(res, info); - return info; -} - -std::vector> monero_daemon_rpc::get_alt_chains() { - std::vector> result; - auto res = m_rpc->send_json_request("get_alternate_chains"); - check_response_status(res); - for (boost::property_tree::ptree::const_iterator it = res.begin(); it != res.end(); ++it) { - std::string key = it->first; - - if (key == std::string("chains")) { - boost::property_tree::ptree chains = it->second; - for (boost::property_tree::ptree::const_iterator it2 = chains.begin(); it2 != chains.end(); ++it2) { - std::shared_ptr alt_chain = std::make_shared(); - monero_alt_chain::from_property_tree(it2->second, alt_chain); - result.push_back(alt_chain); - } - } - } - - return result; -} - -std::vector monero_daemon_rpc::get_alt_block_hashes() { - auto res = m_rpc->send_path_request("get_alt_blocks_hashes"); - check_response_status(res); - std::vector hashes; - monero_get_block_result::from_property_tree(res, hashes); - return hashes; -} - -int monero_daemon_rpc::get_download_limit() { - MTRACE("monero_daemon_rpc::get_download_limit()"); - auto limits = get_bandwidth_limits(); - if (limits->m_down != boost::none) return limits->m_down.get(); - throw std::runtime_error("Could not get download limit"); -} - -int monero_daemon_rpc::set_download_limit(int limit) { - MTRACE("monero_daemon_rpc::set_download_limit()"); - if (limit == -1) return reset_download_limit(); - if (limit <= 0) throw std::runtime_error("Download limit must be an integer greater than 0"); - auto res = set_bandwidth_limits(0, limit); - if (res->m_down != boost::none) return res->m_down.get(); - throw std::runtime_error("Could not set download limit"); -} - -int monero_daemon_rpc::reset_download_limit() { - MTRACE("monero_daemon_rpc::reset_download_limit()"); - auto res = set_bandwidth_limits(0, -1); - if (res->m_down != boost::none) return res->m_down.get(); - throw std::runtime_error("Could not set download limit"); -} - -int monero_daemon_rpc::get_upload_limit() { - MTRACE("monero_daemon_rpc::get_upload_limit()"); - auto limits = get_bandwidth_limits(); - if (limits->m_up != boost::none) return limits->m_up.get(); - throw std::runtime_error("Could not get upload limit"); -} - -int monero_daemon_rpc::set_upload_limit(int limit) { - MTRACE("monero_daemon_rpc::set_upload_limit()"); - if (limit == -1) return reset_upload_limit(); - if (limit <= 0) throw std::runtime_error("Upload limit must be an integer greater than 0"); - auto res = set_bandwidth_limits(limit, 0); - if (res->m_up != boost::none) return res->m_up.get(); - throw std::runtime_error("Could not set download limit"); -} - -int monero_daemon_rpc::reset_upload_limit() { - MTRACE("monero_daemon_rpc::reset_upload_limit()"); - auto res = set_bandwidth_limits(-1, 0); - if (res->m_up != boost::none) return res->m_up.get(); - throw std::runtime_error("Could not set download limit"); -} - -std::vector> monero_daemon_rpc::get_peers() { - auto res = m_rpc->send_json_request("get_connections"); - check_response_status(res); - std::vector> peers; - monero_peer::from_property_tree(res, peers); - return peers; -} - -std::vector> monero_daemon_rpc::get_known_peers() { - auto res = m_rpc->send_path_request("get_peer_list"); - check_response_status(res); - std::vector> peers; - monero_peer::from_property_tree(res, peers); - return peers; -} - -void monero_daemon_rpc::set_outgoing_peer_limit(int limit) { - MTRACE("monero_daemon_rpc::set_outgoing_peer_limit()"); - if (limit < 0) throw std::runtime_error("Outgoing peer limit must be >= 0"); - auto params = std::make_shared(); - params->m_out_peers = limit; - auto res = m_rpc->send_path_request("out_peers", params); - check_response_status(res); -} - -void monero_daemon_rpc::set_incoming_peer_limit(int limit) { - MTRACE("monero_daemon_rpc::set_incoming_peer_limit()"); - if (limit < 0) throw std::runtime_error("Incoming peer limit must be >= 0"); - auto params = std::make_shared(); - params->m_in_peers = limit; - auto res = m_rpc->send_path_request("in_peers", params); - check_response_status(res); -} - -std::vector> monero_daemon_rpc::get_peer_bans() { - MTRACE("monero_daemon_rpc::get_peer_bans()"); - auto res = m_rpc->send_json_request("get_bans"); - check_response_status(res); - std::vector> bans; - monero_ban::from_property_tree(res, bans); - return bans; -} - -void monero_daemon_rpc::set_peer_bans(const std::vector>& bans) { - MTRACE("monero_daemon_rpc::set_peer_bans()"); - auto params = std::make_shared(bans); - auto res = m_rpc->send_json_request("set_bans", params); - check_response_status(res); -} - -void monero_daemon_rpc::start_mining(const std::string &address, int num_threads, bool is_background, bool ignore_battery) { - MTRACE("monero_daemon_rpc::start_mining()"); - if (address.empty()) throw std::runtime_error("Must provide address to mine to"); - if (num_threads <= 0) throw std::runtime_error("Number of threads must be an integer greater than 0"); - auto params = std::make_shared(address, num_threads, is_background, ignore_battery); - auto res = m_rpc->send_path_request("start_mining", params); - check_response_status(res); -} - -void monero_daemon_rpc::stop_mining() { - MTRACE("monero_daemon_rpc::stop_mining()"); - auto res = m_rpc->send_path_request("stop_mining"); - check_response_status(res); -} - -std::shared_ptr monero_daemon_rpc::get_mining_status() { - MTRACE("monero_daemon_rpc::get_mining_status()"); - auto res = m_rpc->send_path_request("mining_status"); - check_response_status(res); - auto result = std::make_shared(); - monero_mining_status::from_property_tree(res, result); - return result; -} - -void monero_daemon_rpc::submit_blocks(const std::vector& block_blobs) { - MTRACE("monero_daemon_rpc::submit_blocks()"); - if (block_blobs.empty()) throw std::runtime_error("Must provide an array of mined block blobs to submit"); - auto params = std::make_shared(block_blobs); - auto res = m_rpc->send_json_request("submit_block", params); - check_response_status(res); -} - -std::shared_ptr monero_daemon_rpc::prune_blockchain(bool check) { - MTRACE("monero_daemon_rpc::prune_blockchain()"); - auto params = std::make_shared(check); - auto res = m_rpc->send_json_request("prune_blockchain", params); - check_response_status(res); - std::shared_ptr result = std::make_shared(); - monero_prune_result::from_property_tree(res, result); - return result; -} - -std::shared_ptr monero_daemon_rpc::check_for_update() { - MTRACE("monero_daemon_rpc::check_for_update()"); - auto params = std::make_shared("check"); - auto res = m_rpc->send_path_request("update", params); - check_response_status(res); - auto result = std::make_shared(); - monero_daemon_update_check_result::from_property_tree(res, result); - return result; -} - -std::shared_ptr monero_daemon_rpc::download_update(const std::string& path) { - MTRACE("monero_daemon_rpc::download_update()"); - auto params = std::make_shared("download", path); - auto res = m_rpc->send_path_request("update", params); - check_response_status(res); - auto result = std::make_shared(); - monero_daemon_update_download_result::from_property_tree(res, result); - return result; -} - -void monero_daemon_rpc::stop() { - MTRACE("monero_daemon_rpc::stop()"); - auto res = m_rpc->send_path_request("stop_daemon"); - check_response_status(res); -} - -std::shared_ptr monero_daemon_rpc::wait_for_next_block_header() { - MTRACE("monero_daemon_rpc::wait_for_next_block_header()"); - - // use mutex and condition variable with predicate to wait for block - boost::mutex temp; - boost::condition_variable cv; - bool ready = false; - - // create listener which notifies condition variable when block is added - block_notifier block_listener(&temp, &cv, &ready); - - // register the listener - add_listener(block_listener); - - // wait until condition variable is notified - boost::mutex::scoped_lock lock(temp); - cv.wait(lock, [&]() { return ready; }); - - // unregister the listener - remove_listener(block_listener); - - // return last height - return block_listener.m_last_header; -} - -std::shared_ptr monero_daemon_rpc::get_bandwidth_limits() { - MTRACE("monero_daemon_rpc::get_bandwidth_limits()"); - auto res = m_rpc->send_path_request("get_limit"); - check_response_status(res); - auto limits = std::make_shared(); - monero_bandwidth_limits::from_property_tree(res, limits); - return limits; -} - -std::shared_ptr monero_daemon_rpc::set_bandwidth_limits(int up, int down) { - MTRACE("monero_daemon_rpc::set_bandwidth_limits()"); - auto limits = std::make_shared(up, down); - auto res = m_rpc->send_path_request("set_limit", limits); - check_response_status(res); - monero_bandwidth_limits::from_property_tree(res, limits); - return limits; -} - -void monero_daemon_rpc::refresh_listening() { - boost::lock_guard lock(m_listeners_mutex); - if (!m_poller && m_listeners.size() > 0) { - m_poller = std::make_shared(this); - } - if (m_poller) m_poller->set_is_polling(m_listeners.size() > 0); -} - -void monero_daemon_rpc::check_response_status(const boost::property_tree::ptree& node) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("status")) { - std::string status = it->second.data(); - - // TODO monero-project empty string status is returned for download update response when an update is available - if (status == std::string("OK") || status == std::string("")) { - return; - } - else throw monero_rpc_error(status); - } - } - - throw std::runtime_error("Could not get JSON RPC response status"); -} - -monero_daemon_rpc::~monero_daemon_rpc() { - MTRACE("~monero_daemon_rpc()"); - remove_listeners(); -} diff --git a/src/cpp/daemon/py_monero_daemon_rpc.h b/src/cpp/daemon/py_monero_daemon_rpc.h deleted file mode 100644 index 95a0701..0000000 --- a/src/cpp/daemon/py_monero_daemon_rpc.h +++ /dev/null @@ -1,157 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ -#pragma once - -#include "py_monero_daemon.h" - -class monero_daemon_poller; - -/** - * Implements a Monero daemon using monerod-rpc. - */ -class monero_daemon_rpc : public monero_daemon { -public: - - /** - * Destruct the daemon. - */ - ~monero_daemon_rpc() override; - monero_daemon_rpc(const std::shared_ptr& rpc); - monero_daemon_rpc(const std::string& uri, const std::string& username = "", const std::string& password = "", const std::string& proxy_uri = "", const std::string& zmq_uri = "", uint64_t timeout = 20000); - - /** - * Supported daemon methods. - */ - std::set get_listeners() override; - void add_listener(monero_daemon_listener &listener) override; - void remove_listener(monero_daemon_listener &listener) override; - void remove_listeners() override; - std::shared_ptr get_rpc_connection() const; - bool is_connected(); - monero::monero_version get_version() override; - bool is_trusted() override; - uint64_t get_height() override; - std::string get_block_hash(uint64_t height) override; - std::shared_ptr get_block_template(const std::string& wallet_address, const boost::optional& reserve_size = boost::none) override; - std::shared_ptr get_last_block_header() override; - std::shared_ptr get_block_header_by_hash(const std::string& hash) override; - std::shared_ptr get_block_header_by_height(uint64_t height) override; - std::vector> get_block_headers_by_range(uint64_t start_height, uint64_t end_height) override; - std::shared_ptr get_block_by_hash(const std::string& hash) override; - std::vector> get_blocks_by_hash(const std::vector& block_hashes, uint64_t start_height, bool prune) override; - std::shared_ptr get_block_by_height(uint64_t height) override; - std::vector> get_blocks_by_height(const std::vector& heights) override; - std::vector> get_blocks_by_range(boost::optional start_height, boost::optional end_height) override; - std::vector> get_blocks_by_range_chunked(boost::optional start_height, boost::optional end_height, boost::optional max_chunk_size) override; - std::vector get_block_hashes(const std::vector& block_hashes, uint64_t start_height) override; - std::vector> get_txs(const std::vector& tx_hashes, bool prune = false) override; - std::vector get_tx_hexes(const std::vector& tx_hashes, bool prune = false) override; - std::shared_ptr get_miner_tx_sum(uint64_t height, uint64_t num_blocks) override; - std::shared_ptr get_fee_estimate(uint64_t grace_blocks = 0) override; - std::shared_ptr submit_tx_hex(const std::string& tx_hex, bool do_not_relay = false) override; - void relay_txs_by_hash(const std::vector& tx_hashes) override; - std::shared_ptr get_tx_pool_stats() override; - std::vector> get_tx_pool() override; - std::vector get_tx_pool_hashes() override; - void flush_tx_pool(const std::vector &hashes) override; - void flush_tx_pool() override; - void flush_tx_pool(const std::string &hash) override; - std::vector get_key_image_spent_statuses(const std::vector& key_images) override; - std::vector> get_outputs(const std::vector& outputs) override; - std::vector> get_output_histogram(const std::vector& amounts, const boost::optional& min_count, const boost::optional& max_count, const boost::optional& is_unlocked, const boost::optional& recent_cutoff) override; - std::vector> get_output_distribution(const std::vector& amounts, const boost::optional& is_cumulative = boost::none, const boost::optional& start_height = boost::none, const boost::optional& end_height = boost::none) override; - std::shared_ptr get_info() override; - std::shared_ptr get_sync_info() override; - std::shared_ptr get_hard_fork_info() override; - std::vector> get_alt_chains() override; - std::vector get_alt_block_hashes() override; - int get_download_limit() override; - int set_download_limit(int limit) override; - int reset_download_limit() override; - int get_upload_limit() override; - int set_upload_limit(int limit) override; - int reset_upload_limit() override; - std::vector> get_peers() override; - std::vector> get_known_peers() override; - void set_outgoing_peer_limit(int limit) override; - void set_incoming_peer_limit(int limit) override; - std::vector> get_peer_bans() override; - void set_peer_bans(const std::vector>& bans) override; - void start_mining(const std::string &address, int num_threads, bool is_background, bool ignore_battery) override; - void stop_mining() override; - std::shared_ptr get_mining_status() override; - void submit_blocks(const std::vector& block_blobs) override; - std::shared_ptr prune_blockchain(bool check) override; - std::shared_ptr check_for_update() override; - std::shared_ptr download_update(const std::string& path = "") override; - void stop() override; - std::shared_ptr wait_for_next_block_header() override; - -// --------------------------------- PRIVATE -------------------------------- - -private: - friend class monero_daemon_poller; - mutable boost::recursive_mutex m_listeners_mutex; - std::set m_listeners; - std::shared_ptr m_rpc; - std::shared_ptr m_poller; - std::unordered_map> m_cached_headers; - - std::vector> get_max_blocks(boost::optional start_height, boost::optional max_height, boost::optional chunk_size); - std::shared_ptr get_block_header_by_height_cached(uint64_t height, uint64_t max_height); - std::shared_ptr get_bandwidth_limits(); - std::shared_ptr set_bandwidth_limits(int up, int down); - void refresh_listening(); - static void check_response_status(const boost::property_tree::ptree& node); -}; diff --git a/src/cpp/daemon/py_monero_daemon_rpc_model.cpp b/src/cpp/daemon/py_monero_daemon_rpc_model.cpp deleted file mode 100644 index 021b6cd..0000000 --- a/src/cpp/daemon/py_monero_daemon_rpc_model.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ -#include "py_monero_daemon_rpc_model.h" -#include "utils/monero_utils.h" - -// --------------------------- MONERO DOWNLOAD UPDATE PARAMS --------------------------- - -monero_download_update_params::monero_download_update_params(const std::string& command, const std::string& path): m_command(command) { - if (!path.empty()) m_path = path; -} - -rapidjson::Value monero_download_update_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_command != boost::none) monero_utils::add_json_member("command", m_command.get(), allocator, root, value_str); - if (m_path != boost::none) monero_utils::add_json_member("path", m_path.get(), allocator, root, value_str); - - // return root - return root; -} - -// --------------------------- MONERO BANDWITH LIMITS PARAMS --------------------------- - -void monero_bandwidth_limits::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& limits) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("limit_up")) limits->m_up = it->second.get_value(); - else if (key == std::string("limit_down")) limits->m_down = it->second.get_value(); - } -} - -rapidjson::Value monero_bandwidth_limits::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_up != boost::none) monero_utils::add_json_member("limit_up", m_up.get(), allocator, root, value_num); - if (m_down != boost::none) monero_utils::add_json_member("limit_down", m_down.get(), allocator, root, value_num); - - // return root - return root; -} - -// --------------------------- MONERO SUBMIT TX PARAMS --------------------------- - -rapidjson::Value monero_submit_tx_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_tx_hex != boost::none) monero_utils::add_json_member("tx_as_hex", m_tx_hex.get(), allocator, root, value_str); - - // set bool values - if (m_do_not_relay != boost::none) monero_utils::add_json_member("do_not_relay", m_do_not_relay.get(), allocator, root); - - // set sub-arrays - if (!m_tx_hashes.empty()) root.AddMember("txids", monero_utils::to_rapidjson_val(allocator, m_tx_hashes), allocator); - - // return root - return root; -} - -// --------------------------- MONERO PEER LIMITS PARAMS --------------------------- - -rapidjson::Value monero_peer_limits_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_in_peers != boost::none) monero_utils::add_json_member("in_peers", m_in_peers.get(), allocator, root, value_num); - if (m_out_peers != boost::none) monero_utils::add_json_member("out_peers", m_out_peers.get(), allocator, root, value_num); - - // return root - return root; -} - -// --------------------------- MONERO GET TXS PARAMS --------------------------- - -rapidjson::Value monero_get_txs_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set bool values - if (m_prune != boost::none) monero_utils::add_json_member("prune", m_prune.get(), allocator, root); - if (m_decode_as_json != boost::none) monero_utils::add_json_member("decode_as_json", m_decode_as_json.get(), allocator, root); - - // set sub-arrays - if (!m_tx_hashes.empty()) root.AddMember("txs_hashes", monero_utils::to_rapidjson_val(allocator, m_tx_hashes), allocator); - - // return root - return root; -} - -// --------------------------- MONERO IS KEY IMAGE SPENT PARAMS --------------------------- - -rapidjson::Value monero_is_key_image_spent_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set sub-arrays - if (!m_key_images.empty()) root.AddMember("key_images", monero_utils::to_rapidjson_val(allocator, m_key_images), allocator); - - // return root - return root; -} - -// --------------------------- MONERO START MINING PARAMS --------------------------- - -rapidjson::Value monero_start_mining_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_miner_address != boost::none) monero_utils::add_json_member("miner_address", m_miner_address.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_num_threads != boost::none) monero_utils::add_json_member("threads_count", m_num_threads.get(), allocator, root, value_num); - - // set bool values - if (m_is_background != boost::none) monero_utils::add_json_member("do_background_mining", m_is_background.get(), allocator, root); - if (m_ignore_battery != boost::none) monero_utils::add_json_member("ignore_battery", m_ignore_battery.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO PRUNE BLOCKCHAIN PARAMS --------------------------- - -rapidjson::Value monero_prune_blockchain_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set bool values - if (m_check != boost::none) monero_utils::add_json_member("check", m_check.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO SUBMIT BLOCKS PARAMS --------------------------- - -rapidjson::Value monero_submit_blocks_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - return monero_utils::to_rapidjson_val(allocator, m_block_blobs); -} - -// --------------------------- MONERO GET BLOCK PARAMS --------------------------- - -rapidjson::Value monero_get_block_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - rapidjson::Value value_num(rapidjson::kNumberType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_hash != boost::none) monero_utils::add_json_member("hash", m_hash.get(), allocator, root, value_str); - if (m_wallet_address != boost::none) monero_utils::add_json_member("wallet_address", m_wallet_address.get(), allocator, root, value_str); - - // set num values - if (m_height != boost::none) monero_utils::add_json_member("height", m_height.get(), allocator, root, value_num); - if (m_start_height != boost::none) monero_utils::add_json_member("start_height", m_start_height.get(), allocator, root, value_num); - if (m_end_height != boost::none) monero_utils::add_json_member("end_height", m_end_height.get(), allocator, root, value_num); - if (m_reserve_size != boost::none) monero_utils::add_json_member("reserve_size", m_reserve_size.get(), allocator, root, value_num); - - // set bool values - if (m_fill_pow_hash != boost::none) monero_utils::add_json_member("fill_pow_hash", m_fill_pow_hash.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO GET BLOCK HASH PARAMS --------------------------- - -rapidjson::Value monero_get_block_hash_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - std::vector params; - if (m_height != boost::none) params.push_back(m_height.get()); - return monero_utils::to_rapidjson_val(allocator, params); -} - -// --------------------------- MONERO GET MINER TX SUM PARAMS --------------------------- - -rapidjson::Value monero_get_miner_tx_sum_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set num values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_height != boost::none) monero_utils::add_json_member("height", m_height.get(), allocator, root, value_num); - if (m_count != boost::none) monero_utils::add_json_member("count", m_count.get(), allocator, root, value_num); - - // return root - return root; -} - -// --------------------------- MONERO GET FEE ESTIMATE PARAMS --------------------------- - -rapidjson::Value monero_get_fee_estimate_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set num values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_grace_blocks != boost::none) monero_utils::add_json_member("grace_blocks", m_grace_blocks.get(), allocator, root, value_num); - - // return root - return root; -} - -// --------------------------- MONERO SET BANS PARAMS --------------------------- - -rapidjson::Value monero_set_bans_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set sub-arrays - if (!m_bans.empty()) root.AddMember("bans", monero_utils::to_rapidjson_val(allocator, m_bans), allocator); - - // return root - return root; -} - -// --------------------------- MONERO GET OUTPUT HISTOGRAM PARAMS --------------------------- - -rapidjson::Value monero_get_output_histogram_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set num values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_min_count != boost::none) monero_utils::add_json_member("min_count", m_min_count.get(), allocator, root, value_num); - if (m_max_count != boost::none) monero_utils::add_json_member("max_count", m_max_count.get(), allocator, root, value_num); - if (m_recent_cutoff != boost::none) monero_utils::add_json_member("recent_cutoff", m_recent_cutoff.get(), allocator, root, value_num); - - // set bool values - if (m_is_unlocked != boost::none) monero_utils::add_json_member("is_unlocked", m_is_unlocked.get(), allocator, root); - - // set sub-array values - if (!m_amounts.empty()) root.AddMember("amounts", monero_utils::to_rapidjson_val(allocator, m_amounts), allocator); - - // return root - return root; -} - -// --------------------------- MONERO GET OUTPUT DISTRIBUTION PARAMS --------------------------- - -rapidjson::Value monero_get_output_distribution_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set num values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_from_height != boost::none) monero_utils::add_json_member("from_height", m_from_height.get(), allocator, root, value_num); - if (m_to_height != boost::none) monero_utils::add_json_member("to_height", m_to_height.get(), allocator, root, value_num); - - // set bool values - if (m_cumulative != boost::none) monero_utils::add_json_member("cumulative", m_cumulative.get(), allocator, root); - if (m_binary != boost::none) monero_utils::add_json_member("binary", m_binary.get(), allocator, root); - - // set sub-array values - if (!m_amounts.empty()) root.AddMember("amounts", monero_utils::to_rapidjson_val(allocator, m_amounts), allocator); - - // return root - return root; -} - - -// --------------------------- MONERO GET BLOCK RESULT --------------------------- - -void monero_get_block_result::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& result) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("count")) result->m_count = it->second.get_value(); - else if (key == std::string("height")) result->m_height = it->second.get_value(); - else if (key == std::string("untrusted")) result->m_untrusted = it->second.get_value(); - } -} - -void monero_get_block_result::from_property_tree(const boost::property_tree::ptree& node, std::vector& block_hashes) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("blks_hashes")) { - auto node2 = it->second; - for(auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - block_hashes.push_back(it2->second.data()); - } - } - } -} diff --git a/src/cpp/daemon/py_monero_daemon_rpc_model.h b/src/cpp/daemon/py_monero_daemon_rpc_model.h deleted file mode 100644 index fefc503..0000000 --- a/src/cpp/daemon/py_monero_daemon_rpc_model.h +++ /dev/null @@ -1,234 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ -#pragma once - -#include "py_monero_daemon_model.h" - -// ------------------------------ RPC Params --------------------------------- - -struct monero_download_update_params : public monero::serializable_struct { -public: - boost::optional m_command; - boost::optional m_path; - - monero_download_update_params(const std::string& command = "download", const std::string& path = ""); - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_submit_tx_params : public monero::serializable_struct { -public: - boost::optional m_tx_hex; - boost::optional m_do_not_relay; - std::vector m_tx_hashes; - - monero_submit_tx_params(const std::vector& tx_hashes): m_tx_hashes(tx_hashes) { } - monero_submit_tx_params(const std::string& tx_hex, bool do_not_relay): m_tx_hex(tx_hex), m_do_not_relay(do_not_relay) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_peer_limits_params : public monero::serializable_struct { -public: - boost::optional m_in_peers; - boost::optional m_out_peers; - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_get_txs_params : public monero::serializable_struct { -public: - std::vector m_tx_hashes; - boost::optional m_decode_as_json; - boost::optional m_prune; - - monero_get_txs_params(const std::vector &tx_hashes, bool prune, bool decode_as_json = true): m_tx_hashes(tx_hashes), m_prune(prune), m_decode_as_json(decode_as_json) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_is_key_image_spent_params : public monero::serializable_struct { -public: - std::vector m_key_images; - - monero_is_key_image_spent_params(const std::vector& key_images): m_key_images(key_images) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -// ------------------------------ JSON-RPC Params --------------------------------- - -struct monero_start_mining_params : public monero::serializable_struct { -public: - boost::optional m_miner_address; - boost::optional m_num_threads; - boost::optional m_is_background; - boost::optional m_ignore_battery; - - monero_start_mining_params(const std::string& address, int num_threads, bool is_background, bool ignore_battery): m_miner_address(address), m_num_threads(num_threads), m_is_background(is_background), m_ignore_battery(ignore_battery) { } - monero_start_mining_params(int num_threads, bool is_background, bool ignore_battery): m_num_threads(num_threads), m_is_background(is_background), m_ignore_battery(ignore_battery) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_prune_blockchain_params : public monero::serializable_struct { -public: - boost::optional m_check; - - monero_prune_blockchain_params(bool check = true): m_check(check) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_submit_blocks_params : public monero::serializable_struct { -public: - std::vector m_block_blobs; - - monero_submit_blocks_params(const std::vector& block_blobs): m_block_blobs(block_blobs) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_get_block_params : public monero::serializable_struct { -public: - boost::optional m_height; - boost::optional m_hash; - boost::optional m_fill_pow_hash; - boost::optional m_start_height; - boost::optional m_end_height; - boost::optional m_wallet_address; - boost::optional m_reserve_size; - - monero_get_block_params(uint64_t height, bool fill_pow_hash = false): m_height(height), m_fill_pow_hash(fill_pow_hash) { } - monero_get_block_params(const std::string& hash, bool fill_pow_hash = false): m_hash(hash), m_fill_pow_hash(fill_pow_hash) { } - monero_get_block_params(uint64_t start_height, uint64_t end_height): m_start_height(start_height), m_end_height(end_height) { } - monero_get_block_params(const std::string& wallet_address, const boost::optional& reserve_size): m_wallet_address(wallet_address), m_reserve_size(reserve_size) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_get_block_hash_params : public monero::serializable_struct { -public: - boost::optional m_height; - - monero_get_block_hash_params(uint64_t height): m_height(height) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_get_miner_tx_sum_params : public monero::serializable_struct { -public: - boost::optional m_height; - boost::optional m_count; - - monero_get_miner_tx_sum_params(uint64_t height, uint64_t count): m_height(height), m_count(count) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_get_fee_estimate_params : public monero::serializable_struct { -public: - boost::optional m_grace_blocks; - - monero_get_fee_estimate_params(uint64_t grace_blocks = 0): m_grace_blocks(grace_blocks) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_set_bans_params : public monero::serializable_struct { -public: - std::vector> m_bans; - - monero_set_bans_params(const std::vector>& bans): m_bans(bans) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_get_output_histogram_params : public monero::serializable_struct { -public: - std::vector m_amounts; - boost::optional m_min_count; - boost::optional m_max_count; - boost::optional m_is_unlocked; - boost::optional m_recent_cutoff; - - monero_get_output_histogram_params(const std::vector& amounts, const boost::optional& min_count, const boost::optional& max_count, const boost::optional& is_unlocked, const boost::optional& recent_cutoff) : m_amounts(amounts), m_min_count(min_count), m_max_count(max_count), m_is_unlocked(is_unlocked), m_recent_cutoff(recent_cutoff) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_get_output_distribution_params : public monero::serializable_struct { -public: - std::vector m_amounts; - boost::optional m_cumulative; - boost::optional m_binary; - boost::optional m_from_height; - boost::optional m_to_height; - - monero_get_output_distribution_params(const std::vector& amounts, const boost::optional& cumulative, const boost::optional& from_height, const boost::optional& to_height) : m_amounts(amounts), m_cumulative(cumulative), m_from_height(from_height), m_to_height(to_height), m_binary(false) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -// ------------------------------ JSON-RPC Response --------------------------------- - -struct monero_get_block_result { -public: - boost::optional m_count; - boost::optional m_height; - boost::optional m_untrusted; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& result); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector& block_hashes); -}; diff --git a/src/cpp/py_monero.cpp b/src/cpp/py_monero.cpp index a3d4646..135e03c 100644 --- a/src/cpp/py_monero.cpp +++ b/src/cpp/py_monero.cpp @@ -51,8 +51,10 @@ * * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers */ -#include "daemon/py_monero_daemon_rpc.h" -#include "wallet/py_monero_wallet_rpc.h" +#include "daemon/py_monero_daemon.h" +#include "daemon/monero_daemon_rpc.h" +#include "wallet/py_monero_wallet.h" +#include "wallet/monero_wallet_rpc.h" #include "wallet/monero_wallet_keys.h" #include "wallet/monero_wallet_full.h" #include "utils/py_monero_utils.h" @@ -75,11 +77,11 @@ using VectorUint32 = std::vector; using VectorUint64 = std::vector; using VectorString = std::vector; -using VectorMoneroOutgoingTransfer = std::vector>; -using VectorMoneroIncomingTransfer = std::vector>; -using VectorMoneroTx = std::vector>; -using VectorMoneroTxWallet = std::vector>; -using VectorMoneroSubaddress = std::vector; +using VectorMoneroOutgoingTransfer = std::vector>; +using VectorMoneroIncomingTransfer = std::vector>; +using VectorMoneroTx = std::vector>; +using VectorMoneroTxWallet = std::vector>; +using VectorMoneroSubaddress = std::vector; using VectorMoneroDestination = std::vector>; @@ -92,52 +94,52 @@ PYBIND11_MAKE_OPAQUE(VectorUint64); PYBIND11_MODULE(monero, m) { m.doc() = ""; - auto py_serializable_struct = py::class_>(m, "SerializableStruct"); - auto py_monero_rpc_payment_info =py::class_>(m, "MoneroRpcPaymentInfo"); - auto py_monero_rpc_connection = py::class_>(m, "MoneroRpcConnection"); - - auto py_monero_ssl_options = py::class_>(m, "SslOptions"); - auto py_monero_version = py::class_>(m, "MoneroVersion"); - auto py_monero_block_header = py::class_>(m, "MoneroBlockHeader"); - auto py_monero_block = py::class_>(m, "MoneroBlock"); - auto py_monero_tx = py::class_>(m, "MoneroTx"); - auto py_monero_key_image = py::class_>(m, "MoneroKeyImage"); - auto py_monero_output = py::class_>(m, "MoneroOutput"); - auto py_monero_wallet_config = py::class_>(m, "MoneroWalletConfig"); - auto py_monero_subaddress = py::class_>(m, "MoneroSubaddress"); - auto py_monero_sync_result = py::class_>(m, "MoneroSyncResult"); - auto py_monero_account = py::class_>(m, "MoneroAccount"); - auto py_monero_account_tag = py::class_>(m, "MoneroAccountTag"); - auto py_monero_destination = py::class_>(m, "MoneroDestination"); - auto py_monero_transfer = py::class_>(m, "MoneroTransfer"); - auto py_monero_incoming_transfer = py::class_>(m, "MoneroIncomingTransfer"); - auto py_monero_outgoing_transfer = py::class_>(m, "MoneroOutgoingTransfer"); - auto py_monero_transfer_query = py::class_>(m, "MoneroTransferQuery"); - auto py_monero_output_wallet = py::class_>(m, "MoneroOutputWallet"); - auto py_monero_output_query = py::class_>(m, "MoneroOutputQuery"); - auto py_monero_tx_wallet = py::class_>(m, "MoneroTxWallet"); - auto py_monero_tx_query = py::class_>(m, "MoneroTxQuery"); - auto py_monero_tx_set = py::class_>(m, "MoneroTxSet"); - auto py_monero_integrated_address = py::class_>(m, "MoneroIntegratedAddress"); - auto py_monero_decoded_address = py::class_>(m, "MoneroDecodedAddress"); - auto py_monero_tx_config = py::class_>(m, "MoneroTxConfig"); - auto py_monero_key_image_import_result = py::class_>(m, "MoneroKeyImageImportResult"); - auto py_monero_message_signature_result = py::class_>(m, "MoneroMessageSignatureResult"); - auto py_monero_check = py::class_>(m, "MoneroCheck"); - auto py_monero_check_tx = py::class_>(m, "MoneroCheckTx"); - auto py_monero_check_reserve = py::class_>(m, "MoneroCheckReserve"); - auto py_monero_multisig_info = py::class_>(m, "MoneroMultisigInfo"); - auto py_monero_multisig_init_result = py::class_>(m, "MoneroMultisigInitResult"); - auto py_monero_multisig_sign_result = py::class_>(m, "MoneroMultisigSignResult"); - auto py_monero_address_book_entry = py::class_>(m, "MoneroAddressBookEntry"); - auto py_monero_wallet_listener = py::class_>(m, "MoneroWalletListener"); + auto py_serializable_struct = py::class_>(m, "SerializableStruct"); + auto py_monero_rpc_payment_info =py::class_>(m, "MoneroRpcPaymentInfo"); + auto py_monero_rpc_connection = py::class_>(m, "MoneroRpcConnection"); + + auto py_monero_ssl_options = py::class_>(m, "SslOptions"); + auto py_monero_version = py::class_>(m, "MoneroVersion"); + auto py_monero_block_header = py::class_>(m, "MoneroBlockHeader"); + auto py_monero_block = py::class_>(m, "MoneroBlock"); + auto py_monero_tx = py::class_>(m, "MoneroTx"); + auto py_monero_key_image = py::class_>(m, "MoneroKeyImage"); + auto py_monero_output = py::class_>(m, "MoneroOutput"); + auto py_monero_wallet_config = py::class_>(m, "MoneroWalletConfig"); + auto py_monero_subaddress = py::class_>(m, "MoneroSubaddress"); + auto py_monero_sync_result = py::class_>(m, "MoneroSyncResult"); + auto py_monero_account = py::class_>(m, "MoneroAccount"); + auto py_monero_account_tag = py::class_>(m, "MoneroAccountTag"); + auto py_monero_destination = py::class_>(m, "MoneroDestination"); + auto py_monero_transfer = py::class_>(m, "MoneroTransfer"); + auto py_monero_incoming_transfer = py::class_>(m, "MoneroIncomingTransfer"); + auto py_monero_outgoing_transfer = py::class_>(m, "MoneroOutgoingTransfer"); + auto py_monero_transfer_query = py::class_>(m, "MoneroTransferQuery"); + auto py_monero_output_wallet = py::class_>(m, "MoneroOutputWallet"); + auto py_monero_output_query = py::class_>(m, "MoneroOutputQuery"); + auto py_monero_tx_wallet = py::class_>(m, "MoneroTxWallet"); + auto py_monero_tx_query = py::class_>(m, "MoneroTxQuery"); + auto py_monero_tx_set = py::class_>(m, "MoneroTxSet"); + auto py_monero_integrated_address = py::class_>(m, "MoneroIntegratedAddress"); + auto py_monero_decoded_address = py::class_>(m, "MoneroDecodedAddress"); + auto py_monero_tx_config = py::class_>(m, "MoneroTxConfig"); + auto py_monero_key_image_import_result = py::class_>(m, "MoneroKeyImageImportResult"); + auto py_monero_message_signature_result = py::class_>(m, "MoneroMessageSignatureResult"); + auto py_monero_check = py::class_>(m, "MoneroCheck"); + auto py_monero_check_tx = py::class_>(m, "MoneroCheckTx"); + auto py_monero_check_reserve = py::class_>(m, "MoneroCheckReserve"); + auto py_monero_multisig_info = py::class_>(m, "MoneroMultisigInfo"); + auto py_monero_multisig_init_result = py::class_>(m, "MoneroMultisigInitResult"); + auto py_monero_multisig_sign_result = py::class_>(m, "MoneroMultisigSignResult"); + auto py_monero_address_book_entry = py::class_>(m, "MoneroAddressBookEntry"); + auto py_monero_wallet_listener = py::class_>(m, "MoneroWalletListener"); auto py_monero_daemon_listener = py::class_>(m, "MoneroDaemonListener"); auto py_monero_daemon = py::class_>(m, "MoneroDaemon"); auto py_monero_daemon_rpc = py::class_>(m, "MoneroDaemonRpc"); - auto py_monero_wallet = py::class_>(m, "MoneroWallet"); - auto py_monero_wallet_keys = py::class_>(m, "MoneroWalletKeys"); - auto py_monero_wallet_full = py::class_>(m, "MoneroWalletFull"); - auto py_monero_wallet_rpc = py::class_>(m, "MoneroWalletRpc"); + auto py_monero_wallet = py::class_>(m, "MoneroWallet"); + auto py_monero_wallet_keys = py::class_>(m, "MoneroWalletKeys"); + auto py_monero_wallet_full = py::class_>(m, "MoneroWalletFull"); + auto py_monero_wallet_rpc = py::class_>(m, "MoneroWalletRpc"); auto py_monero_utils = py::class_(m, "MoneroUtils"); auto py_tx_height_comparator = py::class_>(m, "TxHeightComparator"); @@ -172,13 +174,13 @@ PYBIND11_MODULE(monero, m) { .def("copy", [](const std::vector>& v) { return std::vector>(v); }); - py::bind_vector>>(m, "VectorMoneroBlock") - .def("copy", [](const std::vector>& v) { - return std::vector>(v); + py::bind_vector>>(m, "VectorMoneroBlock") + .def("copy", [](const std::vector>& v) { + return std::vector>(v); }); - py::bind_vector>>(m, "VectorMoneroBlockHeader") - .def("copy", [](const std::vector>& v) { - return std::vector>(v); + py::bind_vector>>(m, "VectorMoneroBlockHeader") + .def("copy", [](const std::vector>& v) { + return std::vector>(v); }); py::bind_vector(m, "VectorMoneroTx") .def("sort", [](VectorMoneroTx &v) { @@ -194,17 +196,17 @@ PYBIND11_MODULE(monero, m) { .def("copy", [](const VectorMoneroTxWallet& v) { return VectorMoneroTxWallet(v); }); - py::bind_vector>>(m, "VectorMoneroOutput") - .def("copy", [](const std::vector>& v) { - return std::vector>(v); + py::bind_vector>>(m, "VectorMoneroOutput") + .def("copy", [](const std::vector>& v) { + return std::vector>(v); }); - py::bind_vector>>(m, "VectorMoneroOutputWallet") - .def("copy", [](const std::vector>& v) { - return std::vector>(v); + py::bind_vector>>(m, "VectorMoneroOutputWallet") + .def("copy", [](const std::vector>& v) { + return std::vector>(v); }); - py::bind_vector>>(m, "VectorMoneroTransfer") - .def("copy", [](const std::vector>& v) { - return std::vector>(v); + py::bind_vector>>(m, "VectorMoneroTransfer") + .def("copy", [](const std::vector>& v) { + return std::vector>(v); }); py::bind_vector(m, "VectorMoneroIncomingTransfer") .def("sort", [](VectorMoneroIncomingTransfer &v) { @@ -233,17 +235,17 @@ PYBIND11_MODULE(monero, m) { py::implicitly_convertible>(); py::implicitly_convertible>>(); py::implicitly_convertible>>(); - py::implicitly_convertible>>(); - py::implicitly_convertible>>(); + py::implicitly_convertible>>(); + py::implicitly_convertible>>(); py::implicitly_convertible(); py::implicitly_convertible(); - py::implicitly_convertible>>(); - py::implicitly_convertible>>(); - py::implicitly_convertible>>(); + py::implicitly_convertible>>(); + py::implicitly_convertible>>(); + py::implicitly_convertible>>(); py::implicitly_convertible(); - py::implicitly_convertible>>(); - py::implicitly_convertible>(); - py::implicitly_convertible>>(); + py::implicitly_convertible>>(); + py::implicitly_convertible>(); + py::implicitly_convertible>>(); // bind maps py::bind_map>(m, "UInt64Map"); @@ -271,10 +273,10 @@ PYBIND11_MODULE(monero, m) { }); // enum monero_network_type - py::enum_(m, "MoneroNetworkType") - .value("MAINNET", monero::monero_network_type::MAINNET) - .value("TESTNET", monero::monero_network_type::TESTNET) - .value("STAGENET", monero::monero_network_type::STAGENET); + py::enum_(m, "MoneroNetworkType") + .value("MAINNET", monero_network_type::MAINNET) + .value("TESTNET", monero_network_type::TESTNET) + .value("STAGENET", monero_network_type::STAGENET); // enum monero_connection_type py::enum_(m, "MoneroConnectionType") @@ -297,20 +299,20 @@ PYBIND11_MODULE(monero, m) { .value("SUBADDRESS", monero_address_type::SUBADDRESS); // enum monero_tx_priority - py::enum_(m, "MoneroTxPriority") - .value("DEFAULT", monero::monero_tx_priority::DEFAULT) - .value("UNIMPORTANT", monero::monero_tx_priority::UNIMPORTANT) - .value("NORMAL", monero::monero_tx_priority::NORMAL) - .value("ELEVATED", monero::monero_tx_priority::ELEVATED); + py::enum_(m, "MoneroTxPriority") + .value("DEFAULT", monero_tx_priority::DEFAULT) + .value("UNIMPORTANT", monero_tx_priority::UNIMPORTANT) + .value("NORMAL", monero_tx_priority::NORMAL) + .value("ELEVATED", monero_tx_priority::ELEVATED); // enum monero_message_signature_type - py::enum_(m, "MoneroMessageSignatureType") - .value("SIGN_WITH_SPEND_KEY", monero::monero_message_signature_type::SIGN_WITH_SPEND_KEY) - .value("SIGN_WITH_VIEW_KEY", monero::monero_message_signature_type::SIGN_WITH_VIEW_KEY); + py::enum_(m, "MoneroMessageSignatureType") + .value("SIGN_WITH_SPEND_KEY", monero_message_signature_type::SIGN_WITH_SPEND_KEY) + .value("SIGN_WITH_VIEW_KEY", monero_message_signature_type::SIGN_WITH_VIEW_KEY); // serializable_struct py_serializable_struct - .def("serialize", [](monero::serializable_struct& self) { + .def("serialize", [](serializable_struct& self) { MONERO_CATCH_AND_RETHROW(self.serialize()); }); @@ -330,7 +332,7 @@ PYBIND11_MODULE(monero, m) { .def_readwrite("ssl_allow_any_cert", &ssl_options::m_ssl_allow_any_cert); // monero_fee_estimate - py::class_>(m, "MoneroFeeEstimate") + py::class_>(m, "MoneroFeeEstimate") .def(py::init<>()) .def_readwrite("fee", &monero_fee_estimate::m_fee) .def_readwrite("fees", &monero_fee_estimate::m_fees) @@ -343,34 +345,34 @@ PYBIND11_MODULE(monero, m) { // monero_version py_monero_version .def(py::init<>()) - .def_readwrite("number", &monero::monero_version::m_number) - .def_readwrite("is_release", &monero::monero_version::m_is_release); + .def_readwrite("number", &monero_version::m_number) + .def_readwrite("is_release", &monero_version::m_is_release); // monero_rpc_connection py_monero_rpc_connection .def(py::init(), py::arg("uri") = "", py::arg("username") = "", py::arg("password") = "", py::arg("proxy_uri") = "", py::arg("zmq_uri") = "", py::arg("priority") = 0, py::arg("timeout") = 20000) - .def(py::init(), py::arg("rpc")) - .def_static("before", [](const std::shared_ptr& c1, const std::shared_ptr& c2, const std::shared_ptr& current_connection) { - MONERO_CATCH_AND_RETHROW(PyMoneroRpcConnection::before(c1, c2, current_connection)); + .def(py::init(), py::arg("rpc")) + .def_static("before", [](const std::shared_ptr& c1, const std::shared_ptr& c2, const std::shared_ptr& current_connection) { + MONERO_CATCH_AND_RETHROW(monero_rpc_connection::before(c1, c2, current_connection)); }, py::arg("c1"), py::arg("c2"), py::arg("current_connection")) .def_static("compare", [](int p1, int p2) { - MONERO_CATCH_AND_RETHROW(PyMoneroRpcConnection::compare(p1, p2)); + MONERO_CATCH_AND_RETHROW(monero_rpc_connection::compare(p1, p2)); }, py::arg("p1"), py::arg("p2")) .def_property("uri", - [](const PyMoneroRpcConnection& self) { return self.m_uri; }, - [](PyMoneroRpcConnection& self, const boost::optional& val) { + [](const monero_rpc_connection& self) { return self.m_uri; }, + [](monero_rpc_connection& self, const boost::optional& val) { // normalize uri if (val != boost::none && !val->empty()) { self.m_uri = val; } else self.m_uri = boost::none; }) - .def_readonly("username", &PyMoneroRpcConnection::m_username) - .def_readonly("password", &PyMoneroRpcConnection::m_password) + .def_readonly("username", &monero_rpc_connection::m_username) + .def_readonly("password", &monero_rpc_connection::m_password) .def_property_readonly("response_time", - [](const PyMoneroRpcConnection& self) { return self.m_response_time; }) + [](const monero_rpc_connection& self) { return self.m_response_time; }) .def_property("proxy_uri", - [](const PyMoneroRpcConnection& self) { return self.m_proxy_uri; }, - [](PyMoneroRpcConnection& self, const boost::optional& val) { + [](const monero_rpc_connection& self) { return self.m_proxy_uri; }, + [](monero_rpc_connection& self, const boost::optional& val) { // normalize proxy uri if (val != boost::none && !val->empty()) { self.m_proxy_uri = val; @@ -378,104 +380,120 @@ PYBIND11_MODULE(monero, m) { self.reset(); }) .def_property("zmq_uri", - [](const PyMoneroRpcConnection& self) { return self.m_zmq_uri; }, - [](PyMoneroRpcConnection& self, const boost::optional& val) { + [](const monero_rpc_connection& self) { return self.m_zmq_uri; }, + [](monero_rpc_connection& self, const boost::optional& val) { // normalize zmq uri if (val != boost::none && !val->empty()) { self.m_zmq_uri = val; } else self.m_zmq_uri = boost::none; }) .def_property("priority", - [](const PyMoneroRpcConnection& self) { return self.m_priority; }, - [](PyMoneroRpcConnection& self, int val) { self.m_priority = val; }) + [](const monero_rpc_connection& self) { return self.m_priority; }, + [](monero_rpc_connection& self, int val) { self.m_priority = val; }) .def_property("timeout", - [](const PyMoneroRpcConnection& self) { return self.m_timeout; }, - [](PyMoneroRpcConnection& self, uint64_t val) { self.m_timeout = val; }) - .def("set_attribute", [](PyMoneroRpcConnection& self, const std::string& key, const std::string& value) { + [](const monero_rpc_connection& self) { return self.m_timeout; }, + [](monero_rpc_connection& self, uint64_t val) { self.m_timeout = val; }) + .def("set_attribute", [](monero_rpc_connection& self, const std::string& key, const std::string& value) { MONERO_CATCH_AND_RETHROW(self.set_attribute(key, value)); }, py::arg("key"), py::arg("value")) - .def("get_attribute", [](const PyMoneroRpcConnection& self, const std::string& key) { + .def("get_attribute", [](const monero_rpc_connection& self, const std::string& key) { MONERO_CATCH_AND_RETHROW(self.get_attribute(key)); }, py::arg("key")) - .def("set_credentials", [](PyMoneroRpcConnection& self, const std::string& username, const std::string& password) { + .def("set_credentials", [](monero_rpc_connection& self, const std::string& username, const std::string& password) { MONERO_CATCH_AND_RETHROW(self.set_credentials(username, password)); }, py::arg("username"), py::arg("password"), py::call_guard()) - .def("is_onion", [](const PyMoneroRpcConnection& self) { + .def("is_onion", [](const monero_rpc_connection& self) { MONERO_CATCH_AND_RETHROW(self.is_onion()); }) - .def("is_i2p", [](const PyMoneroRpcConnection& self) { + .def("is_i2p", [](const monero_rpc_connection& self) { MONERO_CATCH_AND_RETHROW(self.is_i2p()); }) - .def("is_online", [](const PyMoneroRpcConnection& self) { + .def("is_online", [](const monero_rpc_connection& self) { MONERO_CATCH_AND_RETHROW(self.is_online()); }) - .def("is_authenticated", [](const PyMoneroRpcConnection& self) { + .def("is_authenticated", [](const monero_rpc_connection& self) { MONERO_CATCH_AND_RETHROW(self.is_authenticated()); }) - .def("is_connected", [](const PyMoneroRpcConnection& self) { + .def("is_connected", [](const monero_rpc_connection& self) { MONERO_CATCH_AND_RETHROW(self.is_connected()); }) - .def("check_connection", [](PyMoneroRpcConnection& self, int timeout_ms) { + .def("check_connection", [](monero_rpc_connection& self, int timeout_ms) { MONERO_CATCH_AND_RETHROW(self.check_connection(timeout_ms)); }, py::arg("timeout_ms") = 20000, py::call_guard()) - .def("send_json_request", [](PyMoneroRpcConnection& self, const std::string &method, const boost::optional& parameters) { - MONERO_CATCH_AND_RETHROW(self.send_json_request(method, parameters)); + .def("send_json_request", [](monero_rpc_connection& self, const std::string &method, const boost::optional& parameters) { + monero_rpc_request request(method, std::make_shared(parameters)); + auto response = self.send_json_request(request); + boost::optional res; + if (response.m_result != boost::none) res = PyGenUtils::ptree_to_pyobject(*response.m_result); + return res; }, py::arg("method"), py::arg("parameters") = py::none()) - .def("send_path_request", [](PyMoneroRpcConnection& self, const std::string &method, const boost::optional& parameters) { - MONERO_CATCH_AND_RETHROW(self.send_path_request(method, parameters)); + .def("send_path_request", [](monero_rpc_connection& self, const std::string &method, const boost::optional& parameters) { + monero_rpc_request request(method, std::make_shared(parameters)); + auto response = self.send_path_request(request); + boost::optional res; + if (response.m_response != boost::none) res = PyGenUtils::ptree_to_pyobject(*response.m_response); + return res; }, py::arg("method"), py::arg("parameters") = py::none()) - .def("send_binary_request", [](PyMoneroRpcConnection& self, const std::string &method, const boost::optional& parameters) { - MONERO_CATCH_AND_RETHROW(self.send_binary_request(method, parameters)); + .def("send_binary_request", [](monero_rpc_connection& self, const std::string &method, const boost::optional& parameters) { + monero_rpc_request request(method, std::make_shared(parameters), false); + auto response = self.send_binary_request(request); + boost::optional result; + + if (response.m_binary != boost::none && !response.m_binary->empty()) { + result = py::bytes(response.m_binary.get()); + } + // convert binary string to py::bytes + return result; }, py::arg("method"), py::arg("parameters") = py::none()); // monero_block_header py_monero_block_header .def(py::init<>()) - .def("__str__", &monero::monero_block_header::serialize) - .def_readwrite("hash", &monero::monero_block_header::m_hash) - .def_readwrite("height", &monero::monero_block_header::m_height) - .def_readwrite("timestamp", &monero::monero_block_header::m_timestamp) - .def_readwrite("size", &monero::monero_block_header::m_size) - .def_readwrite("weight", &monero::monero_block_header::m_weight) - .def_readwrite("long_term_weight", &monero::monero_block_header::m_long_term_weight) - .def_readwrite("depth", &monero::monero_block_header::m_depth) - .def_readwrite("difficulty", &monero::monero_block_header::m_difficulty) - .def_readwrite("cumulative_difficulty", &monero::monero_block_header::m_cumulative_difficulty) - .def_readwrite("major_version", &monero::monero_block_header::m_major_version) - .def_readwrite("minor_version", &monero::monero_block_header::m_minor_version) - .def_readwrite("nonce", &monero::monero_block_header::m_nonce) - .def_readwrite("miner_tx_hash", &monero::monero_block_header::m_miner_tx_hash) - .def_readwrite("num_txs", &monero::monero_block_header::m_num_txs) - .def_readwrite("orphan_status", &monero::monero_block_header::m_orphan_status) - .def_readwrite("prev_hash", &monero::monero_block_header::m_prev_hash) - .def_readwrite("reward", &monero::monero_block_header::m_reward) - .def_readwrite("pow_hash", &monero::monero_block_header::m_pow_hash) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def("__str__", &monero_block_header::serialize) + .def_readwrite("hash", &monero_block_header::m_hash) + .def_readwrite("height", &monero_block_header::m_height) + .def_readwrite("timestamp", &monero_block_header::m_timestamp) + .def_readwrite("size", &monero_block_header::m_size) + .def_readwrite("weight", &monero_block_header::m_weight) + .def_readwrite("long_term_weight", &monero_block_header::m_long_term_weight) + .def_readwrite("depth", &monero_block_header::m_depth) + .def_readwrite("difficulty", &monero_block_header::m_difficulty) + .def_readwrite("cumulative_difficulty", &monero_block_header::m_cumulative_difficulty) + .def_readwrite("major_version", &monero_block_header::m_major_version) + .def_readwrite("minor_version", &monero_block_header::m_minor_version) + .def_readwrite("nonce", &monero_block_header::m_nonce) + .def_readwrite("miner_tx_hash", &monero_block_header::m_miner_tx_hash) + .def_readwrite("num_txs", &monero_block_header::m_num_txs) + .def_readwrite("orphan_status", &monero_block_header::m_orphan_status) + .def_readwrite("prev_hash", &monero_block_header::m_prev_hash) + .def_readwrite("reward", &monero_block_header::m_reward) + .def_readwrite("pow_hash", &monero_block_header::m_pow_hash) + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }) - .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { + .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { MONERO_CATCH_AND_RETHROW(self->merge(self, other)); }, py::arg("other")); // monero_block (needs: monero_tx) py_monero_block .def(py::init<>()) - .def("__str__", &monero::monero_block::serialize) - .def_readwrite("hex", &monero::monero_block::m_hex) - .def_readwrite("miner_tx", &monero::monero_block::m_miner_tx) - .def_readwrite("txs", &monero::monero_block::m_txs) - .def_readwrite("tx_hashes", &monero::monero_block::m_tx_hashes) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def("__str__", &monero_block::serialize) + .def_readwrite("hex", &monero_block::m_hex) + .def_readwrite("miner_tx", &monero_block::m_miner_tx) + .def_readwrite("txs", &monero_block::m_txs) + .def_readwrite("tx_hashes", &monero_block::m_tx_hashes) + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }) - .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { + .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { MONERO_CATCH_AND_RETHROW(self->merge(self, other)); }, py::arg("other")); // monero_block_template - py::class_>(m, "MoneroBlockTemplate") + py::class_>(m, "MoneroBlockTemplate") .def(py::init<>()) .def_readwrite("block_template_blob", &monero_block_template::m_block_template_blob) .def_readwrite("block_hashing_blob", &monero_block_template::m_block_hashing_blob) @@ -489,7 +507,7 @@ PYBIND11_MODULE(monero, m) { .def_readwrite("next_seed_hash", &monero_block_template::m_next_seed_hash); // monero_connection_span - py::class_>(m, "MoneroConnectionSpan") + py::class_>(m, "MoneroConnectionSpan") .def(py::init<>()) .def_readwrite("connection_id", &monero_connection_span::m_connection_id) .def_readwrite("num_blocks", &monero_connection_span::m_num_blocks) @@ -500,7 +518,7 @@ PYBIND11_MODULE(monero, m) { .def_readwrite("start_height", &monero_connection_span::m_start_height); // monero_peer - py::class_>(m, "MoneroPeer") + py::class_>(m, "MoneroPeer") .def(py::init<>()) .def_readwrite("id", &monero_peer::m_id) .def_readwrite("address", &monero_peer::m_address) @@ -530,7 +548,7 @@ PYBIND11_MODULE(monero, m) { .def_readwrite("connection_type", &monero_peer::m_connection_type); // monero_alt_chain - py::class_>(m, "MoneroAltChain") + py::class_>(m, "MoneroAltChain") .def(py::init<>()) .def_readwrite("block_hashes", &monero_alt_chain::m_block_hashes) .def_readwrite("difficulty", &monero_alt_chain::m_difficulty) @@ -539,7 +557,7 @@ PYBIND11_MODULE(monero, m) { .def_readwrite("main_chain_parent_block_hash", &monero_alt_chain::m_main_chain_parent_block_hash); // monero_ban - py::class_>(m, "MoneroBan") + py::class_>(m, "MoneroBan") .def(py::init<>()) .def_readwrite("host", &monero_ban::m_host) .def_readwrite("ip", &monero_ban::m_ip) @@ -547,7 +565,7 @@ PYBIND11_MODULE(monero, m) { .def_readwrite("seconds", &monero_ban::m_seconds); // monero_output_distribution_entry - py::class_>(m, "MoneroOutputDistributionEntry") + py::class_>(m, "MoneroOutputDistributionEntry") .def(py::init<>()) .def_readwrite("amount", &monero_output_distribution_entry::m_amount) .def_readwrite("base", &monero_output_distribution_entry::m_base) @@ -555,7 +573,7 @@ PYBIND11_MODULE(monero, m) { .def_readwrite("start_height", &monero_output_distribution_entry::m_start_height); // monero_output_histogram_entry - py::class_>(m, "MoneroOutputHistogramEntry") + py::class_>(m, "MoneroOutputHistogramEntry") .def(py::init<>()) .def_readwrite("amount", &monero_output_histogram_entry::m_amount) .def_readwrite("num_instances", &monero_output_histogram_entry::m_num_instances) @@ -575,7 +593,7 @@ PYBIND11_MODULE(monero, m) { .def_readwrite("voting", &monero_hard_fork_info::m_voting); // monero_prune_result - py::class_>(m, "MoneroPruneResult") + py::class_>(m, "MoneroPruneResult") .def(py::init<>()) .def_readwrite("is_pruned", &monero_prune_result::m_is_pruned) .def_readwrite("pruning_seed", &monero_prune_result::m_pruning_seed); @@ -626,7 +644,7 @@ PYBIND11_MODULE(monero, m) { .def_readwrite("is_restricted", &monero_daemon_info::m_is_restricted); // monero_daemon_update_check_result - py::class_>(m, "MoneroDaemonUpdateCheckResult") + py::class_>(m, "MoneroDaemonUpdateCheckResult") .def(py::init<>()) .def_readwrite("is_update_available", &monero_daemon_update_check_result::m_is_update_available) .def_readwrite("version", &monero_daemon_update_check_result::m_version) @@ -658,7 +676,7 @@ PYBIND11_MODULE(monero, m) { .def_readwrite("is_nonzero_unlock_time", &monero_submit_tx_result::m_is_nonzero_unlock_time); // monero_tx_pool_stats - py::class_>(m, "MoneroTxPoolStats") + py::class_>(m, "MoneroTxPoolStats") .def(py::init<>()) .def_readwrite("num_txs", &monero_tx_pool_stats::m_num_txs) .def_readwrite("num_not_relayed", &monero_tx_pool_stats::m_num_not_relayed) @@ -675,7 +693,7 @@ PYBIND11_MODULE(monero, m) { .def_readwrite("histo", &monero_tx_pool_stats::m_histo, py::return_value_policy::reference_internal); // monero_mining_status - py::class_>(m, "MoneroMiningStatus") + py::class_>(m, "MoneroMiningStatus") .def(py::init<>()) .def_readwrite("is_active", &monero_mining_status::m_is_active) .def_readwrite("is_background", &monero_mining_status::m_is_background) @@ -684,7 +702,7 @@ PYBIND11_MODULE(monero, m) { .def_readwrite("num_threads", &monero_mining_status::m_num_threads); // monero_miner_tx_sum - py::class_>(m, "MoneroMinerTxSum") + py::class_>(m, "MoneroMinerTxSum") .def(py::init<>()) .def_readwrite("emission_sum", &monero_miner_tx_sum::m_emission_sum) .def_readwrite("fee_sum", &monero_miner_tx_sum::m_fee_sum); @@ -692,56 +710,56 @@ PYBIND11_MODULE(monero, m) { // monero_tx py_monero_tx .def(py::init<>()) - .def_property_readonly_static("DEFAULT_PAYMENT_ID", [](py::object /* self */) { return monero::monero_tx::DEFAULT_PAYMENT_ID; }) - .def_readwrite("block", &monero::monero_tx::m_block) - .def_readwrite("hash", &monero::monero_tx::m_hash) - .def_readwrite("version", &monero::monero_tx::m_version) - .def_readwrite("is_miner_tx", &monero::monero_tx::m_is_miner_tx) - .def_readwrite("payment_id", &monero::monero_tx::m_payment_id) - .def_readwrite("fee", &monero::monero_tx::m_fee) - .def_readwrite("ring_size", &monero::monero_tx::m_ring_size) - .def_readwrite("relay", &monero::monero_tx::m_relay) - .def_readwrite("is_relayed", &monero::monero_tx::m_is_relayed) - .def_readwrite("is_confirmed", &monero::monero_tx::m_is_confirmed) - .def_readwrite("in_tx_pool", &monero::monero_tx::m_in_tx_pool) - .def_readwrite("num_confirmations", &monero::monero_tx::m_num_confirmations) - .def_readwrite("unlock_time", &monero::monero_tx::m_unlock_time) - .def_readwrite("last_relayed_timestamp", &monero::monero_tx::m_last_relayed_timestamp) - .def_readwrite("received_timestamp", &monero::monero_tx::m_received_timestamp) - .def_readwrite("is_double_spend_seen", &monero::monero_tx::m_is_double_spend_seen) - .def_readwrite("key", &monero::monero_tx::m_key) - .def_readwrite("full_hex", &monero::monero_tx::m_full_hex) - .def_readwrite("pruned_hex", &monero::monero_tx::m_pruned_hex) - .def_readwrite("prunable_hex", &monero::monero_tx::m_prunable_hex) - .def_readwrite("prunable_hash", &monero::monero_tx::m_prunable_hash) - .def_readwrite("size", &monero::monero_tx::m_size) - .def_readwrite("weight", &monero::monero_tx::m_weight) - .def_readwrite("inputs", &monero::monero_tx::m_inputs) - .def_readwrite("outputs", &monero::monero_tx::m_outputs) - .def_readwrite("output_indices", &monero::monero_tx::m_output_indices) - .def_readwrite("metadata", &monero::monero_tx::m_metadata) - .def_readwrite("common_tx_sets", &monero::monero_tx::m_common_tx_sets) - .def_readwrite("extra", &monero::monero_tx::m_extra) - .def_readwrite("rct_signatures", &monero::monero_tx::m_rct_signatures) - .def_readwrite("rct_sig_prunable", &monero::monero_tx::m_rct_sig_prunable) - .def_readwrite("is_kept_by_block", &monero::monero_tx::m_is_kept_by_block) - .def_readwrite("is_failed", &monero::monero_tx::m_is_failed) - .def_readwrite("last_failed_height", &monero::monero_tx::m_last_failed_height) - .def_readwrite("last_failed_hash", &monero::monero_tx::m_last_failed_hash) - .def_readwrite("max_used_block_height", &monero::monero_tx::m_max_used_block_height) - .def_readwrite("max_used_block_hash", &monero::monero_tx::m_max_used_block_hash) - .def_readwrite("signatures", &monero::monero_tx::m_signatures) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def_property_readonly_static("DEFAULT_PAYMENT_ID", [](py::object /* self */) { return monero_tx::DEFAULT_PAYMENT_ID; }) + .def_readwrite("block", &monero_tx::m_block) + .def_readwrite("hash", &monero_tx::m_hash) + .def_readwrite("version", &monero_tx::m_version) + .def_readwrite("is_miner_tx", &monero_tx::m_is_miner_tx) + .def_readwrite("payment_id", &monero_tx::m_payment_id) + .def_readwrite("fee", &monero_tx::m_fee) + .def_readwrite("ring_size", &monero_tx::m_ring_size) + .def_readwrite("relay", &monero_tx::m_relay) + .def_readwrite("is_relayed", &monero_tx::m_is_relayed) + .def_readwrite("is_confirmed", &monero_tx::m_is_confirmed) + .def_readwrite("in_tx_pool", &monero_tx::m_in_tx_pool) + .def_readwrite("num_confirmations", &monero_tx::m_num_confirmations) + .def_readwrite("unlock_time", &monero_tx::m_unlock_time) + .def_readwrite("last_relayed_timestamp", &monero_tx::m_last_relayed_timestamp) + .def_readwrite("received_timestamp", &monero_tx::m_received_timestamp) + .def_readwrite("is_double_spend_seen", &monero_tx::m_is_double_spend_seen) + .def_readwrite("key", &monero_tx::m_key) + .def_readwrite("full_hex", &monero_tx::m_full_hex) + .def_readwrite("pruned_hex", &monero_tx::m_pruned_hex) + .def_readwrite("prunable_hex", &monero_tx::m_prunable_hex) + .def_readwrite("prunable_hash", &monero_tx::m_prunable_hash) + .def_readwrite("size", &monero_tx::m_size) + .def_readwrite("weight", &monero_tx::m_weight) + .def_readwrite("inputs", &monero_tx::m_inputs) + .def_readwrite("outputs", &monero_tx::m_outputs) + .def_readwrite("output_indices", &monero_tx::m_output_indices) + .def_readwrite("metadata", &monero_tx::m_metadata) + .def_readwrite("common_tx_sets", &monero_tx::m_common_tx_sets) + .def_readwrite("extra", &monero_tx::m_extra) + .def_readwrite("rct_signatures", &monero_tx::m_rct_signatures) + .def_readwrite("rct_sig_prunable", &monero_tx::m_rct_sig_prunable) + .def_readwrite("is_kept_by_block", &monero_tx::m_is_kept_by_block) + .def_readwrite("is_failed", &monero_tx::m_is_failed) + .def_readwrite("last_failed_height", &monero_tx::m_last_failed_height) + .def_readwrite("last_failed_hash", &monero_tx::m_last_failed_hash) + .def_readwrite("max_used_block_height", &monero_tx::m_max_used_block_height) + .def_readwrite("max_used_block_hash", &monero_tx::m_max_used_block_hash) + .def_readwrite("signatures", &monero_tx::m_signatures) + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }) - .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { + .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { MONERO_CATCH_AND_RETHROW(self->merge(self, other)); }, py::arg("other")) - .def("get_height", [](monero::monero_tx& self) { + .def("get_height", [](monero_tx& self) { MONERO_CATCH_AND_RETHROW(self.get_height()); }) - .def("__lt__", [](const std::shared_ptr& a, const std::shared_ptr& b){ + .def("__lt__", [](const std::shared_ptr& a, const std::shared_ptr& b){ monero_tx_height_comparator comp; return comp(a, b); }); @@ -750,90 +768,91 @@ PYBIND11_MODULE(monero, m) { py_monero_key_image .def(py::init<>()) .def_static("deserialize_key_images", [](const std::string& key_images_json) { - MONERO_CATCH_AND_RETHROW(monero::monero_key_image::deserialize_key_images(key_images_json)); + MONERO_CATCH_AND_RETHROW(monero_key_image::deserialize_key_images(key_images_json)); }, py::arg("key_images_json")) - .def_readwrite("hex", &monero::monero_key_image::m_hex) - .def_readwrite("signature", &monero::monero_key_image::m_signature) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def_readwrite("hex", &monero_key_image::m_hex) + .def_readwrite("signature", &monero_key_image::m_signature) + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }) - .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { + .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { MONERO_CATCH_AND_RETHROW(self->merge(self, other)); }, py::arg("other")); // monero_output py_monero_output .def(py::init<>()) - .def_readwrite("tx", &monero::monero_output::m_tx) - .def_readwrite("key_image", &monero::monero_output::m_key_image) - .def_readwrite("amount", &monero::monero_output::m_amount) - .def_readwrite("index", &monero::monero_output::m_index) - .def_readwrite("stealth_public_key", &monero::monero_output::m_stealth_public_key) - .def_readwrite("ring_output_indices", &monero::monero_output::m_ring_output_indices) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def_readwrite("tx", &monero_output::m_tx) + .def_readwrite("key_image", &monero_output::m_key_image) + .def_readwrite("amount", &monero_output::m_amount) + .def_readwrite("index", &monero_output::m_index) + .def_readwrite("stealth_public_key", &monero_output::m_stealth_public_key) + .def_readwrite("ring_output_indices", &monero_output::m_ring_output_indices) + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }) - .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { + .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { MONERO_CATCH_AND_RETHROW(self->merge(self, other)); }, py::arg("other")); // monero_wallet_config py_monero_wallet_config .def(py::init<>()) - .def(py::init(), py::arg("config"), py::keep_alive<1, 2>()) + .def(py::init(), py::arg("config"), py::keep_alive<1, 2>()) .def_static("deserialize", [](const std::string& config_json) { - MONERO_CATCH_AND_RETHROW(monero::monero_wallet_config::deserialize(config_json)); + MONERO_CATCH_AND_RETHROW(monero_wallet_config::deserialize(config_json)); }, py::arg("config_json")) - .def_readwrite("path", &monero::monero_wallet_config::m_path) - .def_readwrite("password", &monero::monero_wallet_config::m_password) - .def_readwrite("network_type", &monero::monero_wallet_config::m_network_type) - .def_readwrite("server", &monero::monero_wallet_config::m_server) - .def_readwrite("seed", &monero::monero_wallet_config::m_seed) - .def_readwrite("seed_offset", &monero::monero_wallet_config::m_seed_offset) - .def_readwrite("primary_address", &monero::monero_wallet_config::m_primary_address) - .def_readwrite("private_view_key", &monero::monero_wallet_config::m_private_view_key) - .def_readwrite("private_spend_key", &monero::monero_wallet_config::m_private_spend_key) - .def_readwrite("save_current", &monero::monero_wallet_config::m_save_current) - .def_readwrite("language", &monero::monero_wallet_config::m_language) - .def_readwrite("restore_height", &monero::monero_wallet_config::m_restore_height) - .def_readwrite("account_lookahead", &monero::monero_wallet_config::m_account_lookahead) - .def_readwrite("subaddress_lookahead", &monero::monero_wallet_config::m_subaddress_lookahead) - .def_readwrite("is_multisig", &monero::monero_wallet_config::m_is_multisig) - .def("copy", [](monero::monero_wallet_config& self) { + .def_readwrite("path", &monero_wallet_config::m_path) + .def_readwrite("password", &monero_wallet_config::m_password) + .def_readwrite("network_type", &monero_wallet_config::m_network_type) + .def_readwrite("server", &monero_wallet_config::m_server) + .def_readwrite("seed", &monero_wallet_config::m_seed) + .def_readwrite("seed_offset", &monero_wallet_config::m_seed_offset) + .def_readwrite("primary_address", &monero_wallet_config::m_primary_address) + .def_readwrite("private_view_key", &monero_wallet_config::m_private_view_key) + .def_readwrite("private_spend_key", &monero_wallet_config::m_private_spend_key) + .def_readwrite("save_current", &monero_wallet_config::m_save_current) + .def_readwrite("language", &monero_wallet_config::m_language) + .def_readwrite("restore_height", &monero_wallet_config::m_restore_height) + .def_readwrite("account_lookahead", &monero_wallet_config::m_account_lookahead) + .def_readwrite("subaddress_lookahead", &monero_wallet_config::m_subaddress_lookahead) + .def_readwrite("is_multisig", &monero_wallet_config::m_is_multisig) + .def_readwrite("regtest", &monero_wallet_config::m_regtest) + .def("copy", [](monero_wallet_config& self) { MONERO_CATCH_AND_RETHROW(self.copy()); }); // monero_subaddress py_monero_subaddress .def(py::init<>()) - .def_readwrite("account_index", &monero::monero_subaddress::m_account_index) - .def_readwrite("index", &monero::monero_subaddress::m_index) - .def_readwrite("address", &monero::monero_subaddress::m_address) - .def_readwrite("label", &monero::monero_subaddress::m_label) - .def_readwrite("balance", &monero::monero_subaddress::m_balance) - .def_readwrite("unlocked_balance", &monero::monero_subaddress::m_unlocked_balance) - .def_readwrite("num_unspent_outputs", &monero::monero_subaddress::m_num_unspent_outputs) - .def_readwrite("is_used", &monero::monero_subaddress::m_is_used) - .def_readwrite("num_blocks_to_unlock", &monero::monero_subaddress::m_num_blocks_to_unlock); + .def_readwrite("account_index", &monero_subaddress::m_account_index) + .def_readwrite("index", &monero_subaddress::m_index) + .def_readwrite("address", &monero_subaddress::m_address) + .def_readwrite("label", &monero_subaddress::m_label) + .def_readwrite("balance", &monero_subaddress::m_balance) + .def_readwrite("unlocked_balance", &monero_subaddress::m_unlocked_balance) + .def_readwrite("num_unspent_outputs", &monero_subaddress::m_num_unspent_outputs) + .def_readwrite("is_used", &monero_subaddress::m_is_used) + .def_readwrite("num_blocks_to_unlock", &monero_subaddress::m_num_blocks_to_unlock); // monero_sync_result py_monero_sync_result .def(py::init<>()) .def(py::init(), py::arg("num_blocks_fetched"), py::arg("received_money")) - .def_readwrite("num_blocks_fetched", &monero::monero_sync_result::m_num_blocks_fetched) - .def_readwrite("received_money", &monero::monero_sync_result::m_received_money); + .def_readwrite("num_blocks_fetched", &monero_sync_result::m_num_blocks_fetched) + .def_readwrite("received_money", &monero_sync_result::m_received_money); // monero_account py_monero_account .def(py::init<>()) - .def_readwrite("index", &monero::monero_account::m_index) - .def_readwrite("primary_address", &monero::monero_account::m_primary_address) - .def_readwrite("balance", &monero::monero_account::m_balance) - .def_readwrite("unlocked_balance", &monero::monero_account::m_unlocked_balance) - .def_readwrite("tag", &monero::monero_account::m_tag) - .def_readwrite("subaddresses", &monero::monero_account::m_subaddresses); + .def_readwrite("index", &monero_account::m_index) + .def_readwrite("primary_address", &monero_account::m_primary_address) + .def_readwrite("balance", &monero_account::m_balance) + .def_readwrite("unlocked_balance", &monero_account::m_unlocked_balance) + .def_readwrite("tag", &monero_account::m_tag) + .def_readwrite("subaddresses", &monero_account::m_subaddresses); // monero_account_tag py_monero_account_tag @@ -849,29 +868,29 @@ PYBIND11_MODULE(monero, m) { .def(py::init<>()) .def(py::init(), py::arg("address")) .def(py::init(), py::arg("address"), py::arg("amount")) - .def_readwrite("address", &monero::monero_destination::m_address) - .def_readwrite("amount", &monero::monero_destination::m_amount) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def_readwrite("address", &monero_destination::m_address) + .def_readwrite("amount", &monero_destination::m_amount) + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }); // monero_transfer py_monero_transfer .def(py::init<>()) - .def_readwrite("tx", &monero::monero_transfer::m_tx) - .def_readwrite("account_index", &monero::monero_transfer::m_account_index) - .def_readwrite("amount", &monero::monero_transfer::m_amount) - .def("is_incoming", [](monero::monero_transfer& self) { + .def_readwrite("tx", &monero_transfer::m_tx) + .def_readwrite("account_index", &monero_transfer::m_account_index) + .def_readwrite("amount", &monero_transfer::m_amount) + .def("is_incoming", [](monero_transfer& self) { MONERO_CATCH_AND_RETHROW(self.is_incoming()); }) - .def("is_outgoing", [](monero::monero_transfer& self) { + .def("is_outgoing", [](monero_transfer& self) { MONERO_CATCH_AND_RETHROW(self.is_outgoing()); }) - .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { + .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { MONERO_CATCH_AND_RETHROW(self->merge(self, other)); }, py::arg("other")) - .def("copy", [](const std::shared_ptr& self) { + .def("copy", [](const std::shared_ptr& self) { auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }); @@ -879,17 +898,17 @@ PYBIND11_MODULE(monero, m) { // monero_incoming_transfer py_monero_incoming_transfer .def(py::init<>()) - .def_readwrite("address", &monero::monero_incoming_transfer::m_address) - .def_readwrite("subaddress_index", &monero::monero_incoming_transfer::m_subaddress_index) - .def_readwrite("num_suggested_confirmations", &monero::monero_incoming_transfer::m_num_suggested_confirmations) - .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { + .def_readwrite("address", &monero_incoming_transfer::m_address) + .def_readwrite("subaddress_index", &monero_incoming_transfer::m_subaddress_index) + .def_readwrite("num_suggested_confirmations", &monero_incoming_transfer::m_num_suggested_confirmations) + .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { MONERO_CATCH_AND_RETHROW(self->merge(self, other)); }, py::arg("other")) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }) - .def("__lt__", [](const monero::monero_incoming_transfer& a, const monero::monero_incoming_transfer& b){ + .def("__lt__", [](const monero_incoming_transfer& a, const monero_incoming_transfer& b){ monero_incoming_transfer_comparator comp; return comp(a, b); }); @@ -897,14 +916,14 @@ PYBIND11_MODULE(monero, m) { // monero_outgoing_transfer py_monero_outgoing_transfer .def(py::init<>()) - .def_readwrite("subaddress_indices", &monero::monero_outgoing_transfer::m_subaddress_indices) - .def_readwrite("addresses", &monero::monero_outgoing_transfer::m_addresses) - .def_readwrite("destinations", &monero::monero_outgoing_transfer::m_destinations) - .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { + .def_readwrite("subaddress_indices", &monero_outgoing_transfer::m_subaddress_indices) + .def_readwrite("addresses", &monero_outgoing_transfer::m_addresses) + .def_readwrite("destinations", &monero_outgoing_transfer::m_destinations) + .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { MONERO_CATCH_AND_RETHROW(self->merge(self, other)); }, py::arg("other")) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }); @@ -912,24 +931,24 @@ PYBIND11_MODULE(monero, m) { py_monero_transfer_query .def(py::init<>()) .def_static("deserialize_from_block", [](const std::string& transfer_query_json) { - MONERO_CATCH_AND_RETHROW(monero::monero_transfer_query::deserialize_from_block(transfer_query_json)); + MONERO_CATCH_AND_RETHROW(monero_transfer_query::deserialize_from_block(transfer_query_json)); }, py::arg("transfer_query_json")) - .def_readwrite("incoming", &monero::monero_transfer_query::m_is_incoming) + .def_readwrite("incoming", &monero_transfer_query::m_is_incoming) .def_property("outgoing", - [](const monero::monero_transfer_query& self) { return self.is_outgoing(); }, - [](monero::monero_transfer_query& self, const boost::optional& val) { + [](const monero_transfer_query& self) { return self.is_outgoing(); }, + [](monero_transfer_query& self, const boost::optional& val) { if (val == boost::none) self.m_is_incoming = boost::none; else self.m_is_incoming = !val.get(); }) - .def_readwrite("address", &monero::monero_transfer_query::m_address) - .def_readwrite("addresses", &monero::monero_transfer_query::m_addresses) - .def_readwrite("subaddress_index", &monero::monero_transfer_query::m_subaddress_index) - .def_readwrite("subaddress_indices", &monero::monero_transfer_query::m_subaddress_indices) - .def_readwrite("destinations", &monero::monero_transfer_query::m_destinations) - .def_readwrite("has_destinations", &monero::monero_transfer_query::m_has_destinations) + .def_readwrite("address", &monero_transfer_query::m_address) + .def_readwrite("addresses", &monero_transfer_query::m_addresses) + .def_readwrite("subaddress_index", &monero_transfer_query::m_subaddress_index) + .def_readwrite("subaddress_indices", &monero_transfer_query::m_subaddress_indices) + .def_readwrite("destinations", &monero_transfer_query::m_destinations) + .def_readwrite("has_destinations", &monero_transfer_query::m_has_destinations) .def_property("tx_query", - [](const monero::monero_transfer_query& self) { return self.m_tx_query; }, - [](std::shared_ptr& self, const std::shared_ptr& val) { + [](const monero_transfer_query& self) { return self.m_tx_query; }, + [](std::shared_ptr& self, const std::shared_ptr& val) { const auto old_query = self->m_tx_query; self->m_tx_query = val; if (val != nullptr) { @@ -941,29 +960,29 @@ PYBIND11_MODULE(monero, m) { old_query.get()->m_transfer_query = boost::none; } }) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }) - .def("meets_criteria", [](monero::monero_transfer_query& self, monero_transfer* transfer, bool query_parent) { + .def("meets_criteria", [](monero_transfer_query& self, monero_transfer* transfer, bool query_parent) { MONERO_CATCH_AND_RETHROW(self.meets_criteria(transfer, query_parent)); }, py::arg("transfer"), py::arg("query_parent") = true); // monero_output_wallet py_monero_output_wallet .def(py::init<>()) - .def_readwrite("account_index", &monero::monero_output_wallet::m_account_index) - .def_readwrite("subaddress_index", &monero::monero_output_wallet::m_subaddress_index) - .def_readwrite("is_spent", &monero::monero_output_wallet::m_is_spent) - .def_readwrite("is_frozen", &monero::monero_output_wallet::m_is_frozen) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def_readwrite("account_index", &monero_output_wallet::m_account_index) + .def_readwrite("subaddress_index", &monero_output_wallet::m_subaddress_index) + .def_readwrite("is_spent", &monero_output_wallet::m_is_spent) + .def_readwrite("is_frozen", &monero_output_wallet::m_is_frozen) + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }) - .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { + .def("merge", [](const std::shared_ptr& self, const std::shared_ptr& other) { MONERO_CATCH_AND_RETHROW(self->merge(self, other)); }, py::arg("other")) - .def("__lt__", [](const monero::monero_output_wallet& a, const monero::monero_output_wallet& b){ + .def("__lt__", [](const monero_output_wallet& a, const monero_output_wallet& b){ monero_output_comparator comp; return comp(a, b); }); @@ -972,13 +991,13 @@ PYBIND11_MODULE(monero, m) { py_monero_output_query .def(py::init<>()) .def_static("deserialize_from_block", [](const std::string& output_query_json) { - MONERO_CATCH_AND_RETHROW(monero::monero_output_query::deserialize_from_block(output_query_json)); + MONERO_CATCH_AND_RETHROW(monero_output_query::deserialize_from_block(output_query_json)); }, py::arg("output_query_json")) - .def_readwrite("subaddress_indices", &monero::monero_output_query::m_subaddress_indices) - .def_readwrite("min_amount", &monero::monero_output_query::m_min_amount) - .def_readwrite("max_amount", &monero::monero_output_query::m_max_amount) - .def_readonly("tx_query", &monero::monero_output_query::m_tx_query) - .def("set_tx_query", [](const std::shared_ptr& self, const std::shared_ptr& val, bool output_query) { + .def_readwrite("subaddress_indices", &monero_output_query::m_subaddress_indices) + .def_readwrite("min_amount", &monero_output_query::m_min_amount) + .def_readwrite("max_amount", &monero_output_query::m_max_amount) + .def_readonly("tx_query", &monero_output_query::m_tx_query) + .def("set_tx_query", [](const std::shared_ptr& self, const std::shared_ptr& val, bool output_query) { const auto old_query = self->m_tx_query; if (val != nullptr) { self->m_tx_query = val; @@ -992,31 +1011,31 @@ PYBIND11_MODULE(monero, m) { else old_query.get()->m_input_query = boost::none; } }, py::arg("tx_query"), py::arg("output_query")) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }) - .def("meets_criteria", [](monero::monero_output_query& self, monero_output_wallet* output, bool query_parent) { + .def("meets_criteria", [](monero_output_query& self, monero_output_wallet* output, bool query_parent) { MONERO_CATCH_AND_RETHROW(self.meets_criteria(output, query_parent)); }, py::arg("output"), py::arg("query_parent") = true); // monero_tx_wallet py_monero_tx_wallet .def(py::init<>()) - .def_readwrite("tx_set", &monero::monero_tx_wallet::m_tx_set) - .def_readwrite("is_incoming", &monero::monero_tx_wallet::m_is_incoming) - .def_readwrite("is_outgoing", &monero::monero_tx_wallet::m_is_outgoing) - .def_readwrite("incoming_transfers", &monero::monero_tx_wallet::m_incoming_transfers) - .def_readwrite("outgoing_transfer", &monero::monero_tx_wallet::m_outgoing_transfer) - .def_readwrite("note", &monero::monero_tx_wallet::m_note) - .def_readwrite("is_locked", &monero::monero_tx_wallet::m_is_locked) - .def_readwrite("input_sum", &monero::monero_tx_wallet::m_input_sum) - .def_readwrite("output_sum", &monero::monero_tx_wallet::m_output_sum) - .def_readwrite("change_address", &monero::monero_tx_wallet::m_change_address) - .def_readwrite("change_amount", &monero::monero_tx_wallet::m_change_amount) - .def_readwrite("num_dummy_outputs", &monero::monero_tx_wallet::m_num_dummy_outputs) - .def_readwrite("extra_hex", &monero::monero_tx_wallet::m_extra_hex) - .def("get_incoming_amount", [](monero::monero_tx_wallet& self) { + .def_readwrite("tx_set", &monero_tx_wallet::m_tx_set) + .def_readwrite("is_incoming", &monero_tx_wallet::m_is_incoming) + .def_readwrite("is_outgoing", &monero_tx_wallet::m_is_outgoing) + .def_readwrite("incoming_transfers", &monero_tx_wallet::m_incoming_transfers) + .def_readwrite("outgoing_transfer", &monero_tx_wallet::m_outgoing_transfer) + .def_readwrite("note", &monero_tx_wallet::m_note) + .def_readwrite("is_locked", &monero_tx_wallet::m_is_locked) + .def_readwrite("input_sum", &monero_tx_wallet::m_input_sum) + .def_readwrite("output_sum", &monero_tx_wallet::m_output_sum) + .def_readwrite("change_address", &monero_tx_wallet::m_change_address) + .def_readwrite("change_amount", &monero_tx_wallet::m_change_amount) + .def_readwrite("num_dummy_outputs", &monero_tx_wallet::m_num_dummy_outputs) + .def_readwrite("extra_hex", &monero_tx_wallet::m_extra_hex) + .def("get_incoming_amount", [](monero_tx_wallet& self) { uint64_t amount = 0; for (const auto& transfer : self.m_incoming_transfers) { if (transfer->m_amount != boost::none) @@ -1024,45 +1043,45 @@ PYBIND11_MODULE(monero, m) { } return amount; }) - .def("get_outgoing_amount", [](monero::monero_tx_wallet& self) { + .def("get_outgoing_amount", [](monero_tx_wallet& self) { uint64_t amount = 0; if (self.m_outgoing_transfer != boost::none && self.m_outgoing_transfer.value()->m_amount != boost::none) amount = self.m_outgoing_transfer.value()->m_amount.get(); return amount; }) - .def("get_transfers", [](monero::monero_tx_wallet& self) { + .def("get_transfers", [](monero_tx_wallet& self) { MONERO_CATCH_AND_RETHROW(self.get_transfers()); }) - .def("get_transfers", [](monero::monero_tx_wallet& self, const monero_transfer_query& query) { + .def("get_transfers", [](monero_tx_wallet& self, const monero_transfer_query& query) { MONERO_CATCH_AND_RETHROW(self.get_transfers(query)); }, py::arg("query")) - .def("filter_transfers", [](monero::monero_tx_wallet& self, const monero_transfer_query& query) { + .def("filter_transfers", [](monero_tx_wallet& self, const monero_transfer_query& query) { MONERO_CATCH_AND_RETHROW(self.filter_transfers(query)); }, py::arg("query")) - .def("get_inputs_wallet", [](monero::monero_tx_wallet& self, const boost::optional& query) { - std::vector> inputs; + .def("get_inputs_wallet", [](monero_tx_wallet& self, const boost::optional& query) { + std::vector> inputs; for(const auto& i : self.m_inputs) { - auto input = std::dynamic_pointer_cast(i); + auto input = std::dynamic_pointer_cast(i); if (!input) continue; if (query == boost::none || query.value().meets_criteria(input.get())) inputs.push_back(input); } return inputs; }, py::arg("query") = py::none()) - .def("get_outputs_wallet", [](monero::monero_tx_wallet& self) { + .def("get_outputs_wallet", [](monero_tx_wallet& self) { MONERO_CATCH_AND_RETHROW(self.get_outputs_wallet()); }) - .def("get_outputs_wallet", [](monero::monero_tx_wallet& self, const monero_output_query& query) { + .def("get_outputs_wallet", [](monero_tx_wallet& self, const monero_output_query& query) { MONERO_CATCH_AND_RETHROW(self.get_outputs_wallet(query)); }, py::arg("query")) - .def("filter_outputs_wallet", [](monero::monero_tx_wallet& self, const monero_output_query& query) { + .def("filter_outputs_wallet", [](monero_tx_wallet& self, const monero_output_query& query) { MONERO_CATCH_AND_RETHROW(self.filter_outputs_wallet(query)); }, py::arg("query")) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }) - .def("merge", [](const std::shared_ptr &self, const std::shared_ptr& tgt) { + .def("merge", [](const std::shared_ptr &self, const std::shared_ptr& tgt) { MONERO_CATCH_AND_RETHROW(self->merge(self, tgt)); }, py::arg("tgt")); @@ -1070,37 +1089,37 @@ PYBIND11_MODULE(monero, m) { py_monero_tx_query .def(py::init<>()) .def_static("deserialize_from_block", [](const std::string& tx_query_json) { - MONERO_CATCH_AND_RETHROW(monero::monero_tx_query::deserialize_from_block(tx_query_json)); + MONERO_CATCH_AND_RETHROW(monero_tx_query::deserialize_from_block(tx_query_json)); }, py::arg("tx_query_json")) - .def_readwrite("is_outgoing", &monero::monero_tx_query::m_is_outgoing) - .def_readwrite("is_incoming", &monero::monero_tx_query::m_is_incoming) - .def_readwrite("hashes", &monero::monero_tx_query::m_hashes) - .def_readwrite("has_payment_id", &monero::monero_tx_query::m_has_payment_id) - .def_readwrite("payment_ids", &monero::monero_tx_query::m_payment_ids) - .def_readwrite("height", &monero::monero_tx_query::m_height) - .def_readwrite("min_height", &monero::monero_tx_query::m_min_height) - .def_readwrite("max_height", &monero::monero_tx_query::m_max_height) - .def_readwrite("include_outputs", &monero::monero_tx_query::m_include_outputs) + .def_readwrite("is_outgoing", &monero_tx_query::m_is_outgoing) + .def_readwrite("is_incoming", &monero_tx_query::m_is_incoming) + .def_readwrite("hashes", &monero_tx_query::m_hashes) + .def_readwrite("has_payment_id", &monero_tx_query::m_has_payment_id) + .def_readwrite("payment_ids", &monero_tx_query::m_payment_ids) + .def_readwrite("height", &monero_tx_query::m_height) + .def_readwrite("min_height", &monero_tx_query::m_min_height) + .def_readwrite("max_height", &monero_tx_query::m_max_height) + .def_readwrite("include_outputs", &monero_tx_query::m_include_outputs) .def_property("transfer_query", - [](const monero::monero_tx_query& self) { return self.m_transfer_query; }, - [](std::shared_ptr& self, const boost::optional>& val) { - set_query(self, self->m_transfer_query, val); + [](const monero_tx_query& self) { return self.m_transfer_query; }, + [](std::shared_ptr& self, const boost::optional>& val) { + PyMoneroUtils::set_query(self, self->m_transfer_query, val); }) .def_property("input_query", - [](const monero::monero_tx_query& self) { return self.m_input_query; }, - [](std::shared_ptr& self, const boost::optional>& val) { - set_query(self, self->m_input_query, val); + [](const monero_tx_query& self) { return self.m_input_query; }, + [](std::shared_ptr& self, const boost::optional>& val) { + PyMoneroUtils::set_query(self, self->m_input_query, val); }) .def_property("output_query", - [](const monero::monero_tx_query& self) { return self.m_output_query; }, - [](std::shared_ptr& self, const boost::optional>& val) { - set_query(self, self->m_output_query, val); + [](const monero_tx_query& self) { return self.m_output_query; }, + [](std::shared_ptr& self, const boost::optional>& val) { + PyMoneroUtils::set_query(self, self->m_output_query, val); }) - .def("copy", [](const std::shared_ptr& self) { - auto tgt = std::make_shared(); + .def("copy", [](const std::shared_ptr& self) { + auto tgt = std::make_shared(); MONERO_CATCH_AND_RETHROW(self->copy(self, tgt)); }) - .def("meets_criteria", [](monero::monero_tx_query& self, monero_tx_wallet* tx, bool query_children) { + .def("meets_criteria", [](monero_tx_query& self, monero_tx_wallet* tx, bool query_children) { MONERO_CATCH_AND_RETHROW(self.meets_criteria(tx, query_children)); }, py::arg("tx"), py::arg("query_children") = false); @@ -1108,23 +1127,23 @@ PYBIND11_MODULE(monero, m) { py_monero_tx_set .def(py::init<>()) .def_static("deserialize", [](const std::string& tx_set_json) { - MONERO_CATCH_AND_RETHROW(monero::monero_tx_set::deserialize(tx_set_json)); + MONERO_CATCH_AND_RETHROW(monero_tx_set::deserialize(tx_set_json)); }, py::arg("tx_set_json")) - .def_readwrite("txs", &monero::monero_tx_set::m_txs) - .def_readwrite("signed_tx_hex", &monero::monero_tx_set::m_signed_tx_hex) - .def_readwrite("unsigned_tx_hex", &monero::monero_tx_set::m_unsigned_tx_hex) - .def_readwrite("multisig_tx_hex", &monero::monero_tx_set::m_multisig_tx_hex); + .def_readwrite("txs", &monero_tx_set::m_txs) + .def_readwrite("signed_tx_hex", &monero_tx_set::m_signed_tx_hex) + .def_readwrite("unsigned_tx_hex", &monero_tx_set::m_unsigned_tx_hex) + .def_readwrite("multisig_tx_hex", &monero_tx_set::m_multisig_tx_hex); // monero_integrated_address py_monero_integrated_address .def(py::init<>()) - .def_readwrite("standard_address", &monero::monero_integrated_address::m_standard_address) - .def_readwrite("payment_id", &monero::monero_integrated_address::m_payment_id) - .def_readwrite("integrated_address", &monero::monero_integrated_address::m_integrated_address); + .def_readwrite("standard_address", &monero_integrated_address::m_standard_address) + .def_readwrite("payment_id", &monero_integrated_address::m_payment_id) + .def_readwrite("integrated_address", &monero_integrated_address::m_integrated_address); // monero_decoded_address py_monero_decoded_address - .def(py::init(), py::arg("address"), py::arg("address_type"), py::arg("network_type")) + .def(py::init(), py::arg("address"), py::arg("address_type"), py::arg("network_type")) .def_readwrite("address", &monero_decoded_address::m_address) .def_readwrite("address_type", &monero_decoded_address::m_address_type) .def_readwrite("network_type", &monero_decoded_address::m_network_type); @@ -1132,122 +1151,122 @@ PYBIND11_MODULE(monero, m) { // monero_tx_config py_monero_tx_config .def(py::init<>()) - .def(py::init(), py::arg("config")) + .def(py::init(), py::arg("config")) .def_static("deserialize", [](const std::string& config_json) { - MONERO_CATCH_AND_RETHROW(monero::monero_tx_config::deserialize(config_json)); + MONERO_CATCH_AND_RETHROW(monero_tx_config::deserialize(config_json)); }, py::arg("config_json")) - .def_readwrite("address", &monero::monero_tx_config::m_address) - .def_readwrite("amount", &monero::monero_tx_config::m_amount) - .def_readwrite("destinations", &monero::monero_tx_config::m_destinations) - .def_readwrite("subtract_fee_from", &monero::monero_tx_config::m_subtract_fee_from) - .def_readwrite("payment_id", &monero::monero_tx_config::m_payment_id) - .def_readwrite("priority", &monero::monero_tx_config::m_priority) - .def_readwrite("ring_size", &monero::monero_tx_config::m_ring_size) - .def_readwrite("fee", &monero::monero_tx_config::m_fee) - .def_readwrite("account_index", &monero::monero_tx_config::m_account_index) - .def_readwrite("subaddress_indices", &monero::monero_tx_config::m_subaddress_indices) - .def_readwrite("can_split", &monero::monero_tx_config::m_can_split) - .def_readwrite("relay", &monero::monero_tx_config::m_relay) - .def_readwrite("note", &monero::monero_tx_config::m_note) - .def_readwrite("recipient_name", &monero::monero_tx_config::m_recipient_name) - .def_readwrite("below_amount", &monero::monero_tx_config::m_below_amount) - .def_readwrite("sweep_each_subaddress", &monero::monero_tx_config::m_sweep_each_subaddress) - .def_readwrite("key_image", &monero::monero_tx_config::m_key_image) - .def("set_address", [](monero::monero_tx_config& self, const std::string& address) { + .def_readwrite("address", &monero_tx_config::m_address) + .def_readwrite("amount", &monero_tx_config::m_amount) + .def_readwrite("destinations", &monero_tx_config::m_destinations) + .def_readwrite("subtract_fee_from", &monero_tx_config::m_subtract_fee_from) + .def_readwrite("payment_id", &monero_tx_config::m_payment_id) + .def_readwrite("priority", &monero_tx_config::m_priority) + .def_readwrite("ring_size", &monero_tx_config::m_ring_size) + .def_readwrite("fee", &monero_tx_config::m_fee) + .def_readwrite("account_index", &monero_tx_config::m_account_index) + .def_readwrite("subaddress_indices", &monero_tx_config::m_subaddress_indices) + .def_readwrite("can_split", &monero_tx_config::m_can_split) + .def_readwrite("relay", &monero_tx_config::m_relay) + .def_readwrite("note", &monero_tx_config::m_note) + .def_readwrite("recipient_name", &monero_tx_config::m_recipient_name) + .def_readwrite("below_amount", &monero_tx_config::m_below_amount) + .def_readwrite("sweep_each_subaddress", &monero_tx_config::m_sweep_each_subaddress) + .def_readwrite("key_image", &monero_tx_config::m_key_image) + .def("set_address", [](monero_tx_config& self, const std::string& address) { if (self.m_destinations.size() > 1) throw monero_error("Cannot set address because MoneroTxConfig already has multiple destinations"); if (self.m_destinations.empty()) { - auto dest = std::make_shared(); + auto dest = std::make_shared(); dest->m_address = address; self.m_destinations.push_back(dest); } else self.m_destinations[0]->m_address = address; }) - .def("copy", [](monero::monero_tx_config& self) { + .def("copy", [](monero_tx_config& self) { MONERO_CATCH_AND_RETHROW(self.copy()); }) - .def("get_normalized_destinations", [](monero::monero_tx_config& self) { + .def("get_normalized_destinations", [](monero_tx_config& self) { MONERO_CATCH_AND_RETHROW(self.get_normalized_destinations()); }); // monero_key_image_import_result py_monero_key_image_import_result .def(py::init<>()) - .def_readwrite("height", &monero::monero_key_image_import_result::m_height) - .def_readwrite("spent_amount", &monero::monero_key_image_import_result::m_spent_amount) - .def_readwrite("unspent_amount", &monero::monero_key_image_import_result::m_unspent_amount); + .def_readwrite("height", &monero_key_image_import_result::m_height) + .def_readwrite("spent_amount", &monero_key_image_import_result::m_spent_amount) + .def_readwrite("unspent_amount", &monero_key_image_import_result::m_unspent_amount); // monero_message_signature_result py_monero_message_signature_result .def(py::init<>()) - .def_readwrite("is_good", &monero::monero_message_signature_result::m_is_good) - .def_readwrite("version", &monero::monero_message_signature_result::m_version) - .def_readwrite("is_old", &monero::monero_message_signature_result::m_is_old) - .def_readwrite("signature_type", &monero::monero_message_signature_result::m_signature_type); + .def_readwrite("is_good", &monero_message_signature_result::m_is_good) + .def_readwrite("version", &monero_message_signature_result::m_version) + .def_readwrite("is_old", &monero_message_signature_result::m_is_old) + .def_readwrite("signature_type", &monero_message_signature_result::m_signature_type); // monero_check py_monero_check .def(py::init<>()) - .def_readwrite("is_good", &monero::monero_check::m_is_good); + .def_readwrite("is_good", &monero_check::m_is_good); // monero_check_tx py_monero_check_tx .def(py::init<>()) - .def_readwrite("in_tx_pool", &monero::monero_check_tx::m_in_tx_pool) - .def_readwrite("num_confirmations", &monero::monero_check_tx::m_num_confirmations) - .def_readwrite("received_amount", &monero::monero_check_tx::m_received_amount); + .def_readwrite("in_tx_pool", &monero_check_tx::m_in_tx_pool) + .def_readwrite("num_confirmations", &monero_check_tx::m_num_confirmations) + .def_readwrite("received_amount", &monero_check_tx::m_received_amount); // monero_check_reserve py_monero_check_reserve .def(py::init<>()) - .def_readwrite("total_amount", &monero::monero_check_reserve::m_total_amount) - .def_readwrite("unconfirmed_spent_amount", &monero::monero_check_reserve::m_unconfirmed_spent_amount); + .def_readwrite("total_amount", &monero_check_reserve::m_total_amount) + .def_readwrite("unconfirmed_spent_amount", &monero_check_reserve::m_unconfirmed_spent_amount); // monero_multisig_info py_monero_multisig_info .def(py::init<>()) - .def_readwrite("is_multisig", &monero::monero_multisig_info::m_is_multisig) - .def_readwrite("is_ready", &monero::monero_multisig_info::m_is_ready) - .def_readwrite("threshold", &monero::monero_multisig_info::m_threshold) - .def_readwrite("num_participants", &monero::monero_multisig_info::m_num_participants); + .def_readwrite("is_multisig", &monero_multisig_info::m_is_multisig) + .def_readwrite("is_ready", &monero_multisig_info::m_is_ready) + .def_readwrite("threshold", &monero_multisig_info::m_threshold) + .def_readwrite("num_participants", &monero_multisig_info::m_num_participants); // monero_multisig_init_result py_monero_multisig_init_result .def(py::init<>()) - .def_readwrite("address", &monero::monero_multisig_init_result::m_address) - .def_readwrite("multisig_hex", &monero::monero_multisig_init_result::m_multisig_hex); + .def_readwrite("address", &monero_multisig_init_result::m_address) + .def_readwrite("multisig_hex", &monero_multisig_init_result::m_multisig_hex); // monero_multisig_sign_result py_monero_multisig_sign_result .def(py::init<>()) - .def_readwrite("signed_multisig_tx_hex", &monero::monero_multisig_sign_result::m_signed_multisig_tx_hex) - .def_readwrite("tx_hashes", &monero::monero_multisig_sign_result::m_tx_hashes); + .def_readwrite("signed_multisig_tx_hex", &monero_multisig_sign_result::m_signed_multisig_tx_hex) + .def_readwrite("tx_hashes", &monero_multisig_sign_result::m_tx_hashes); // monero_address_book_entry py_monero_address_book_entry .def(py::init<>()) .def(py::init(), py::arg("index"), py::arg("address"), py::arg("description")) .def(py::init(), py::arg("index"), py::arg("address"), py::arg("description"), py::arg("payment_id")) - .def_readwrite("index", &monero::monero_address_book_entry::m_index) - .def_readwrite("address", &monero::monero_address_book_entry::m_address) - .def_readwrite("description", &monero::monero_address_book_entry::m_description) - .def_readwrite("payment_id", &monero::monero_address_book_entry::m_payment_id); + .def_readwrite("index", &monero_address_book_entry::m_index) + .def_readwrite("address", &monero_address_book_entry::m_address) + .def_readwrite("description", &monero_address_book_entry::m_description) + .def_readwrite("payment_id", &monero_address_book_entry::m_payment_id); // monero_wallet_listener py_monero_wallet_listener .def(py::init<>()) - .def("on_sync_progress", [](monero::monero_wallet_listener& self, uint64_t height, uint64_t start_height, uint64_t end_height, double percent_done, const std::string& message) { + .def("on_sync_progress", [](monero_wallet_listener& self, uint64_t height, uint64_t start_height, uint64_t end_height, double percent_done, const std::string& message) { MONERO_CATCH_AND_RETHROW(self.on_sync_progress(height, start_height, end_height, percent_done, message)); }, py::arg("height"), py::arg("start_height"), py::arg("end_height"), py::arg("percent_done"), py::arg("message")) - .def("on_new_block", [](monero::monero_wallet_listener& self, uint64_t height) { + .def("on_new_block", [](monero_wallet_listener& self, uint64_t height) { MONERO_CATCH_AND_RETHROW(self.on_new_block(height)); }, py::arg("height")) - .def("on_balances_changed", [](monero::monero_wallet_listener& self, uint64_t new_balance, uint64_t new_unlocked_balance) { + .def("on_balances_changed", [](monero_wallet_listener& self, uint64_t new_balance, uint64_t new_unlocked_balance) { MONERO_CATCH_AND_RETHROW(self.on_balances_changed(new_balance, new_unlocked_balance)); }, py::arg("new_balance"), py::arg("new_unlocked_balance")) - .def("on_output_received", [](monero::monero_wallet_listener& self, const monero_output_wallet& output) { + .def("on_output_received", [](monero_wallet_listener& self, const monero_output_wallet& output) { MONERO_CATCH_AND_RETHROW(self.on_output_received(output)); }, py::arg("output")) - .def("on_output_spent", [](monero::monero_wallet_listener& self, const monero_output_wallet& output) { + .def("on_output_spent", [](monero_wallet_listener& self, const monero_output_wallet& output) { MONERO_CATCH_AND_RETHROW(self.on_output_spent(output)); }, py::arg("output")); @@ -1255,7 +1274,7 @@ PYBIND11_MODULE(monero, m) { py_monero_daemon_listener .def(py::init<>()) .def_readwrite("last_header", &monero_daemon_listener::m_last_header) - .def("on_block_header", [](monero_daemon_listener& self, const std::shared_ptr& header) { + .def("on_block_header", [](monero_daemon_listener& self, const std::shared_ptr& header) { MONERO_CATCH_AND_RETHROW(self.on_block_header(header)); }, py::arg("header")); @@ -1373,7 +1392,7 @@ PYBIND11_MODULE(monero, m) { .def("get_key_image_spent_statuses", [](monero_daemon& self, const std::vector& key_images) { MONERO_CATCH_AND_RETHROW(self.get_key_image_spent_statuses(key_images)); }, py::arg("key_images"), py::call_guard()) - .def("get_outputs", [](monero_daemon& self, const std::vector& outputs) { + .def("get_outputs", [](monero_daemon& self, const std::vector& outputs) { MONERO_CATCH_AND_RETHROW(self.get_outputs(outputs)); }, py::arg("outputs"), py::call_guard()) .def("get_output_histogram", [](monero_daemon& self, const std::vector& amounts, const boost::optional& min_count, const boost::optional& max_count, const boost::optional& is_unlocked, const boost::optional& recent_cutoff) { @@ -1469,7 +1488,7 @@ PYBIND11_MODULE(monero, m) { // monero_daemon_rpc py_monero_daemon_rpc - .def(py::init&>(), py::arg("rpc"), py::call_guard()) + .def(py::init&>(), py::arg("rpc"), py::call_guard()) .def(py::init(), py::arg("uri"), py::arg("username") = "", py::arg("password") = "", py::arg("proxy_uri") = "", py::arg("zmq_uri") = "", py::arg("timeout") = 20000, py::call_guard()) .def("get_rpc_connection", [](const monero_daemon_rpc& self) { MONERO_CATCH_AND_RETHROW(self.get_rpc_connection()); @@ -1485,7 +1504,7 @@ PYBIND11_MODULE(monero, m) { .def("is_view_only", [](PyMoneroWallet& self) { MONERO_CATCH_AND_RETHROW(self.is_view_only()); }, py::call_guard()) - .def("set_daemon_connection", [](PyMoneroWallet& self, const boost::optional& connection) { + .def("set_daemon_connection", [](PyMoneroWallet& self, const boost::optional>& connection) { MONERO_CATCH_AND_RETHROW(self.set_daemon_connection(connection)); }, py::arg("connection"), py::call_guard()) .def("set_daemon_connection", [](PyMoneroWallet& self, const std::string& uri, const std::string& username, const std::string& password, const std::string& proxy) { @@ -1563,10 +1582,10 @@ PYBIND11_MODULE(monero, m) { .def("get_height_by_date", [](PyMoneroWallet& self, uint16_t year, uint8_t month, uint8_t day) { MONERO_CATCH_AND_RETHROW(self.get_height_by_date(year, month, day)); }, py::arg("year"), py::arg("month"), py::arg("day"), py::call_guard()) - .def("add_listener", [](PyMoneroWallet& self, monero::monero_wallet_listener& listener) { + .def("add_listener", [](PyMoneroWallet& self, monero_wallet_listener& listener) { MONERO_CATCH_AND_RETHROW(self.add_listener(listener)); }, py::arg("listener"), py::call_guard()) - .def("remove_listener", [](PyMoneroWallet& self, monero::monero_wallet_listener& listener) { + .def("remove_listener", [](PyMoneroWallet& self, monero_wallet_listener& listener) { MONERO_CATCH_AND_RETHROW(self.remove_listener(listener)); }, py::arg("listener"), py::call_guard()) .def("get_listeners", [](PyMoneroWallet& self) { @@ -1575,13 +1594,13 @@ PYBIND11_MODULE(monero, m) { .def("sync", [](PyMoneroWallet& self) { MONERO_CATCH_AND_RETHROW(self.sync()); }, py::call_guard()) - .def("sync", [](PyMoneroWallet& self, monero::monero_wallet_listener& listener) { + .def("sync", [](PyMoneroWallet& self, monero_wallet_listener& listener) { MONERO_CATCH_AND_RETHROW(self.sync(listener)); }, py::arg("listener"), py::call_guard()) .def("sync", [](PyMoneroWallet& self, uint64_t start_height) { MONERO_CATCH_AND_RETHROW(self.sync(start_height)); }, py::arg("start_height"), py::call_guard()) - .def("sync", [](PyMoneroWallet& self, uint64_t start_height, monero::monero_wallet_listener& listener) { + .def("sync", [](PyMoneroWallet& self, uint64_t start_height, monero_wallet_listener& listener) { MONERO_CATCH_AND_RETHROW(self.sync(start_height, listener)); }, py::arg("start_height"), py::arg("listener"), py::call_guard()) .def("start_syncing", [](PyMoneroWallet& self, uint64_t sync_period_in_ms) { @@ -1666,7 +1685,7 @@ PYBIND11_MODULE(monero, m) { MONERO_CATCH_AND_RETHROW(self.set_subaddress_label(account_idx, subaddress_idx, label)); }, py::arg("account_idx"), py::arg("subaddress_idx"), py::arg("label") = "", py::call_guard()) .def("get_tx", [](PyMoneroWallet& self, const std::string& tx_hash) { - std::shared_ptr result = nullptr; + std::shared_ptr result = nullptr; monero_tx_query query; query.m_hashes.push_back(tx_hash); auto txs = self.get_txs(query); @@ -1678,35 +1697,35 @@ PYBIND11_MODULE(monero, m) { .def("get_txs", [](PyMoneroWallet& self) { MONERO_CATCH_AND_RETHROW(self.get_txs()); }, py::call_guard()) - .def("get_txs", [](PyMoneroWallet& self, const monero::monero_tx_query& query) { + .def("get_txs", [](PyMoneroWallet& self, const monero_tx_query& query) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::get_and_sort_txs(self, query)); }, py::arg("query"), py::call_guard()) .def("get_txs", [](PyMoneroWallet& self, const std::vector& tx_hashes) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::get_and_sort_txs(self, tx_hashes)); }, py::arg("tx_hashes"), py::call_guard()) - .def("get_transfers", [](PyMoneroWallet& self, const monero::monero_transfer_query& query) { + .def("get_transfers", [](PyMoneroWallet& self, const monero_transfer_query& query) { MONERO_CATCH_AND_RETHROW(self.get_transfers(query)); }, py::arg("query"), py::call_guard()) .def("get_transfers", [](PyMoneroWallet& self) { - monero::monero_transfer_query query; + monero_transfer_query query; MONERO_CATCH_AND_RETHROW(self.get_transfers(query)); }, py::call_guard()) .def("get_transfers", [](PyMoneroWallet& self, uint32_t account_index) { - monero::monero_transfer_query query; + monero_transfer_query query; query.m_account_index = account_index; MONERO_CATCH_AND_RETHROW(self.get_transfers(query)); }, py::arg("account_index"), py::call_guard()) .def("get_transfers", [](PyMoneroWallet& self, uint32_t account_index, uint32_t subaddress_index) { - monero::monero_transfer_query query; + monero_transfer_query query; query.m_account_index = account_index; query.m_subaddress_index = subaddress_index; MONERO_CATCH_AND_RETHROW(self.get_transfers(query)); }, py::arg("account_index"), py::arg("subaddress_index"), py::call_guard()) - .def("get_outputs", [](PyMoneroWallet& self, const monero::monero_output_query& query) { + .def("get_outputs", [](PyMoneroWallet& self, const monero_output_query& query) { MONERO_CATCH_AND_RETHROW(self.get_outputs(query)); }, py::arg("query"), py::call_guard()) .def("get_outputs", [](PyMoneroWallet& self) { - monero::monero_output_query query; + monero_output_query query; MONERO_CATCH_AND_RETHROW(self.get_outputs(query)); }, py::call_guard()) .def("export_outputs", [](PyMoneroWallet& self, bool all) { @@ -1736,16 +1755,16 @@ PYBIND11_MODULE(monero, m) { .def("get_default_fee_priority", [](PyMoneroWallet& self) { MONERO_CATCH_AND_RETHROW(self.get_default_fee_priority()); }, py::call_guard()) - .def("create_tx", [](PyMoneroWallet& self, const monero::monero_tx_config& config) { + .def("create_tx", [](PyMoneroWallet& self, const monero_tx_config& config) { MONERO_CATCH_AND_RETHROW(self.create_tx(config)); }, py::arg("config"), py::call_guard()) - .def("create_txs", [](PyMoneroWallet& self, const monero::monero_tx_config& config) { + .def("create_txs", [](PyMoneroWallet& self, const monero_tx_config& config) { MONERO_CATCH_AND_RETHROW(self.create_txs(config)); }, py::arg("config"), py::call_guard()) - .def("sweep_unlocked", [](PyMoneroWallet& self, const monero::monero_tx_config& config) { + .def("sweep_unlocked", [](PyMoneroWallet& self, const monero_tx_config& config) { MONERO_CATCH_AND_RETHROW(self.sweep_unlocked(config)); }, py::arg("config"), py::call_guard()) - .def("sweep_output", [](PyMoneroWallet& self, const monero::monero_tx_config& config) { + .def("sweep_output", [](PyMoneroWallet& self, const monero_tx_config& config) { MONERO_CATCH_AND_RETHROW(self.sweep_output(config)); }, py::arg("config"), py::call_guard()) .def("sweep_dust", [](PyMoneroWallet& self, bool relay) { @@ -1754,7 +1773,7 @@ PYBIND11_MODULE(monero, m) { .def("relay_tx", [](PyMoneroWallet& self, const std::string& tx_metadata) { MONERO_CATCH_AND_RETHROW(self.relay_tx(tx_metadata)); }, py::arg("tx_metadata"), py::call_guard()) - .def("relay_tx", [](PyMoneroWallet& self, const monero::monero_tx_wallet& tx) { + .def("relay_tx", [](PyMoneroWallet& self, const monero_tx_wallet& tx) { MONERO_CATCH_AND_RETHROW(self.relay_tx(tx)); }, py::arg("tx"), py::call_guard()) .def("relay_txs", [](PyMoneroWallet& self, const std::vector>& txs) { @@ -1763,16 +1782,16 @@ PYBIND11_MODULE(monero, m) { .def("relay_txs", [](PyMoneroWallet& self, const std::vector& tx_metadatas) { MONERO_CATCH_AND_RETHROW(self.relay_txs(tx_metadatas)); }, py::arg("tx_metadatas"), py::call_guard()) - .def("describe_tx_set", [](PyMoneroWallet& self, const monero::monero_tx_set& tx_set) { + .def("describe_tx_set", [](PyMoneroWallet& self, const monero_tx_set& tx_set) { MONERO_CATCH_AND_RETHROW(self.describe_tx_set(tx_set)); }, py::arg("tx_set"), py::call_guard()) .def("describe_unsigned_tx_set", [](PyMoneroWallet& self, const std::string& unsigned_tx_hex) { - monero::monero_tx_set tx_set; + monero_tx_set tx_set; tx_set.m_unsigned_tx_hex = unsigned_tx_hex; MONERO_CATCH_AND_RETHROW(self.describe_tx_set(tx_set)); }, py::arg("unsigned_tx_hex"), py::call_guard()) .def("describe_multisig_tx_set", [](PyMoneroWallet& self, const std::string& multisig_tx_hex) { - monero::monero_tx_set tx_set; + monero_tx_set tx_set; tx_set.m_multisig_tx_hex = multisig_tx_hex; MONERO_CATCH_AND_RETHROW(self.describe_tx_set(tx_set)); }, py::arg("multisig_tx_hex"), py::call_guard()) @@ -1790,7 +1809,7 @@ PYBIND11_MODULE(monero, m) { return self.verify_message(msg, address, signature); } catch (...) { // TODO wallet full can differentiate incorrect from invalid address, but rpc returns -2 for both, so returning bad result for consistency - return monero::monero_message_signature_result(); + return monero_message_signature_result(); } }, py::arg("msg"), py::arg("address"), py::arg("signature"), py::call_guard()) .def("get_tx_key", [](PyMoneroWallet& self, const std::string& tx_hash) { @@ -1848,22 +1867,22 @@ PYBIND11_MODULE(monero, m) { .def("delete_address_book_entry", [](PyMoneroWallet& self, uint64_t index) { MONERO_CATCH_AND_RETHROW(self.delete_address_book_entry(index)); }, py::arg("index"), py::call_guard()) - .def("tag_accounts", [](monero::monero_wallet& self, const std::string& tag, const std::vector& account_indices) { + .def("tag_accounts", [](monero_wallet& self, const std::string& tag, const std::vector& account_indices) { throw monero_error("MoneroWallet.tag_accounts(): not supported"); }, py::arg("tag"), py::arg("account_indices"), py::call_guard()) - .def("untag_accounts", [](monero::monero_wallet& self, const std::vector& account_indices) { + .def("untag_accounts", [](monero_wallet& self, const std::vector& account_indices) { throw monero_error("MoneroWallet.untag_accounts(): not supported"); }, py::arg("account_indices"), py::call_guard()) - .def("get_account_tags", [](monero::monero_wallet& self) { + .def("get_account_tags", [](monero_wallet& self) { throw monero_error("MoneroWallet.get_account_tags(): not supported"); }, py::call_guard()) - .def("set_account_tag_label", [](monero::monero_wallet& self, const std::string& tag, const std::string& label) { + .def("set_account_tag_label", [](monero_wallet& self, const std::string& tag, const std::string& label) { throw monero_error("MoneroWallet.set_account_tag_label(): not supported"); }, py::arg("tag"), py::arg("label"), py::call_guard()) .def("set_account_label", [](PyMoneroWallet& self, uint32_t account_idx, const std::string& label) { MONERO_CATCH_AND_RETHROW(self.set_subaddress_label(account_idx, 0, label)); }, py::arg("account_idx"), py::arg("label"), py::call_guard()) - .def("get_payment_uri", [](PyMoneroWallet& self, const monero::monero_tx_config& config) { + .def("get_payment_uri", [](PyMoneroWallet& self, const monero_tx_config& config) { MONERO_CATCH_AND_RETHROW(self.get_payment_uri(config)); }, py::arg("config"), py::call_guard()) .def("parse_payment_uri", [](PyMoneroWallet& self, const std::string& uri) { @@ -1929,52 +1948,49 @@ PYBIND11_MODULE(monero, m) { .def("save", [](PyMoneroWallet& self) { MONERO_CATCH_AND_RETHROW(self.save()); }, py::call_guard()) - .def("close", [](monero::monero_wallet& self, bool save) { + .def("close", [](monero_wallet& self, bool save) { MONERO_CATCH_AND_RETHROW(self.close(save)); }, py::arg("save") = false, py::call_guard()); // monero_wallet_keys py_monero_wallet_keys - .def_static("create_wallet_random", [](const monero::monero_wallet_config& config) { - MONERO_CATCH_AND_RETHROW(monero::monero_wallet_keys::create_wallet_random(config)); + .def_static("create_wallet_random", [](const monero_wallet_config& config) { + MONERO_CATCH_AND_RETHROW(monero_wallet_keys::create_wallet_random(config)); }, py::arg("config"), py::call_guard()) - .def_static("create_wallet_from_seed", [](const monero::monero_wallet_config& config) { - MONERO_CATCH_AND_RETHROW(monero::monero_wallet_keys::create_wallet_from_seed(config)); + .def_static("create_wallet_from_seed", [](const monero_wallet_config& config) { + MONERO_CATCH_AND_RETHROW(monero_wallet_keys::create_wallet_from_seed(config)); }, py::arg("config"), py::call_guard()) - .def_static("create_wallet_from_keys", [](const monero::monero_wallet_config& config) { - MONERO_CATCH_AND_RETHROW(monero::monero_wallet_keys::create_wallet_from_keys(config)); + .def_static("create_wallet_from_keys", [](const monero_wallet_config& config) { + MONERO_CATCH_AND_RETHROW(monero_wallet_keys::create_wallet_from_keys(config)); }, py::arg("config"), py::call_guard()) .def_static("get_seed_languages", []() { - MONERO_CATCH_AND_RETHROW(monero::monero_wallet_keys::get_seed_languages()); + MONERO_CATCH_AND_RETHROW(monero_wallet_keys::get_seed_languages()); }, py::call_guard()) - .def("tag_accounts", [](monero::monero_wallet_keys& self, const std::string& tag, const std::vector& account_indices) { + .def("tag_accounts", [](monero_wallet_keys& self, const std::string& tag, const std::vector& account_indices) { throw monero_error("MoneroWalletKeys.tag_accounts(): not supported"); }, py::arg("tag"), py::arg("account_indices"), py::call_guard()) - .def("untag_accounts", [](monero::monero_wallet_keys& self, const std::vector& account_indices) { + .def("untag_accounts", [](monero_wallet_keys& self, const std::vector& account_indices) { throw monero_error("MoneroWalletKeys.untag_accounts(): not supported"); }, py::arg("account_indices"), py::call_guard()) - .def("get_account_tags", [](monero::monero_wallet_keys& self) { + .def("get_account_tags", [](monero_wallet_keys& self) { throw monero_error("MoneroWalletKeys.get_account_tags(): not supported"); }, py::call_guard()) - .def("set_account_tag_label", [](monero::monero_wallet_keys& self, const std::string& tag, const std::string& label) { + .def("set_account_tag_label", [](monero_wallet_keys& self, const std::string& tag, const std::string& label) { throw monero_error("MoneroWalletKeys.set_account_tag_label(): not supported"); }, py::arg("tag"), py::arg("label"), py::call_guard()); // monero_wallet_full py_monero_wallet_full .def_static("wallet_exists", [](const std::string& path) { - MONERO_CATCH_AND_RETHROW(monero::monero_wallet_full::wallet_exists(path)); + MONERO_CATCH_AND_RETHROW(monero_wallet_full::wallet_exists(path)); }, py::arg("path"), py::call_guard()) - .def_static("open_wallet", [](const std::string& path, const std::string& password, monero::monero_network_type nettype) { - MONERO_CATCH_AND_RETHROW(monero::monero_wallet_full::open_wallet(path, password, nettype)); - }, py::arg("path"), py::arg("password"), py::arg("nettype"), py::call_guard()) - .def_static("open_wallet_data", [](const std::string& password, monero::monero_network_type nettype, const std::string& keys_data, const std::string& cache_data) { - MONERO_CATCH_AND_RETHROW(monero::monero_wallet_full::open_wallet_data(password, nettype, keys_data, cache_data, monero::monero_rpc_connection())); - }, py::arg("password"), py::arg("nettype"), py::arg("keys_data"), py::arg("cache_data"), py::call_guard()) - .def_static("open_wallet_data", [](const std::string& password, monero::monero_network_type nettype, const std::string& keys_data, const std::string& cache_data, const monero_rpc_connection& daemon_connection) { - MONERO_CATCH_AND_RETHROW(monero::monero_wallet_full::open_wallet_data(password, nettype, keys_data, cache_data, daemon_connection)); - }, py::arg("password"), py::arg("nettype"), py::arg("keys_data"), py::arg("cache_data"), py::arg("daemon_connection"), py::call_guard()) - .def_static("create_wallet", [](const monero::monero_wallet_config& config) { + .def_static("open_wallet", [](const std::string& path, const std::string& password, monero_network_type nettype, bool regtest) { + MONERO_CATCH_AND_RETHROW(monero_wallet_full::open_wallet(path, password, nettype, regtest)); + }, py::arg("path"), py::arg("password"), py::arg("nettype"), py::arg("regtest") = false, py::call_guard()) + .def_static("open_wallet_data", [](const std::string& password, monero_network_type nettype, const std::string& keys_data, const std::string& cache_data, const std::shared_ptr& daemon_connection, bool regtest) { + MONERO_CATCH_AND_RETHROW(monero_wallet_full::open_wallet_data(password, nettype, keys_data, cache_data, daemon_connection, nullptr, regtest)); + }, py::arg("password"), py::arg("nettype"), py::arg("keys_data"), py::arg("cache_data"), py::arg("daemon_connection") = std::make_shared(), py::arg("regtest") = false, py::call_guard()) + .def_static("create_wallet", [](const monero_wallet_config& config) { try { return monero_wallet_full::create_wallet(config); } catch(const std::exception& ex) { @@ -1985,35 +2001,35 @@ PYBIND11_MODULE(monero, m) { } }, py::arg("config"), py::call_guard()) .def_static("get_seed_languages", []() { - MONERO_CATCH_AND_RETHROW(monero::monero_wallet_full::get_seed_languages()); + MONERO_CATCH_AND_RETHROW(monero_wallet_full::get_seed_languages()); }, py::call_guard()) - .def("get_keys_file_buffer", [](monero::monero_wallet_full& self, std::string& password, bool view_only) { + .def("get_keys_file_buffer", [](monero_wallet_full& self, std::string& password, bool view_only) { MONERO_CATCH_AND_RETHROW(self.get_keys_file_buffer(password, view_only)); }, py::arg("password"), py::arg("view_only"), py::call_guard()) - .def("get_cache_file_buffer", [](monero::monero_wallet_full& self) { + .def("get_cache_file_buffer", [](monero_wallet_full& self) { MONERO_CATCH_AND_RETHROW(self.get_cache_file_buffer()); }, py::call_guard()) - .def("tag_accounts", [](monero::monero_wallet_full& self, const std::string& tag, const std::vector& account_indices) { + .def("tag_accounts", [](monero_wallet_full& self, const std::string& tag, const std::vector& account_indices) { throw monero_error("MoneroWalletFull.tag_accounts(): not implemented"); }, py::arg("tag"), py::arg("account_indices"), py::call_guard()) - .def("untag_accounts", [](monero::monero_wallet_full& self, const std::vector& account_indices) { + .def("untag_accounts", [](monero_wallet_full& self, const std::vector& account_indices) { throw monero_error("MoneroWalletFull.untag_accounts(): not implemented"); }, py::arg("account_indices"), py::call_guard()) - .def("get_account_tags", [](monero::monero_wallet_full& self) { + .def("get_account_tags", [](monero_wallet_full& self) { throw monero_error("MoneroWalletFull.get_account_tags(): not implemented"); }, py::call_guard()) - .def("set_account_tag_label", [](monero::monero_wallet_full& self, const std::string& tag, const std::string& label) { + .def("set_account_tag_label", [](monero_wallet_full& self, const std::string& tag, const std::string& label) { throw monero_error("MoneroWalletFull.set_account_tag_label(): not implemented"); }, py::arg("tag"), py::arg("label"), py::call_guard()); // monero_wallet_rpc py_monero_wallet_rpc - .def(py::init&>(), py::arg("rpc_connection"), py::call_guard()) + .def(py::init&>(), py::arg("rpc_connection"), py::call_guard()) .def(py::init(), py::arg("uri") = "", py::arg("username") = "", py::arg("password") = "", py::arg("proxy_uri") = "", py::arg("zmq_uri") = "", py::arg("timeout") = 20000, py::call_guard()) - .def("create_wallet", [](monero_wallet_rpc& self, const std::shared_ptr& config) { + .def("create_wallet", [](monero_wallet_rpc& self, const std::shared_ptr& config) { MONERO_CATCH_AND_RETHROW(self.create_wallet(config)); }, py::arg("config"), py::call_guard()) - .def("open_wallet", [](monero_wallet_rpc& self, const std::shared_ptr& config) { + .def("open_wallet", [](monero_wallet_rpc& self, const std::shared_ptr& config) { MONERO_CATCH_AND_RETHROW(self.open_wallet(config)); }, py::arg("config"), py::call_guard()) .def("open_wallet", [](monero_wallet_rpc& self, const std::string& name, const std::string& password) { @@ -2029,13 +2045,13 @@ PYBIND11_MODULE(monero, m) { MONERO_CATCH_AND_RETHROW(self.get_rpc_connection()); }, py::call_guard()) // this because of function hiding - .def("set_daemon_connection", [](PyMoneroWallet& self, const boost::optional& connection) { + .def("set_daemon_connection", [](PyMoneroWallet& self, const boost::optional>& connection) { MONERO_CATCH_AND_RETHROW(self.set_daemon_connection(connection)); }, py::arg("connection"), py::call_guard()) .def("set_daemon_connection", [](PyMoneroWallet& self, const std::string& uri, const std::string& username, const std::string& password, const std::string& proxy) { MONERO_CATCH_AND_RETHROW(self.set_daemon_connection(uri, username, password, proxy)); }, py::arg("uri"), py::arg("username") = "", py::arg("password") = "", py::arg("proxy") = "", py::call_guard()) - .def("set_daemon_connection", [](monero_wallet_rpc& self, const boost::optional& connection, bool is_trusted, const boost::optional& ssl_options) { + .def("set_daemon_connection", [](monero_wallet_rpc& self, const boost::optional>& connection, bool is_trusted, const boost::optional& ssl_options) { MONERO_CATCH_AND_RETHROW(self.set_daemon_connection(connection, is_trusted, ssl_options)); }, py::arg("connection"), py::arg("is_trusted"), py::arg("ssl_options"), py::call_guard()) .def("stop", [](monero_wallet_rpc& self) { @@ -2060,19 +2076,19 @@ PYBIND11_MODULE(monero, m) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::get_version()); }) .def_static("get_ring_size", []() { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::get_ring_size()); + return monero_utils::RING_SIZE; }) .def_static("set_log_level", [](int loglevel) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::set_log_level(loglevel)); + MONERO_CATCH_AND_RETHROW(monero_utils::set_log_level(loglevel)); }, py::arg("loglevel")) .def_static("configure_logging", [](const std::string& path, bool console) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::configure_logging(path, console)); + MONERO_CATCH_AND_RETHROW(monero_utils::configure_logging(path, console)); }, py::arg("path"), py::arg("console")) .def_static("get_integrated_address", [](monero_network_type network_type, const std::string& standard_address, const std::string& payment_id) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::get_integrated_address(network_type, standard_address, payment_id)); + MONERO_CATCH_AND_RETHROW(monero_utils::get_integrated_address(network_type, standard_address, payment_id)); }, py::arg("network_type"), py::arg("standard_address"), py::arg("payment_id") = "") .def_static("is_valid_address", [](const std::string& address, monero_network_type network_type) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::is_valid_address(address, network_type)); + return monero_utils::is_valid_address(address, network_type); }, py::arg("address"), py::arg("network_type")) .def_static("is_valid_public_view_key", [](const std::string& public_view_key) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::is_valid_public_view_key(public_view_key)); @@ -2081,10 +2097,10 @@ PYBIND11_MODULE(monero, m) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::is_valid_public_spend_key(public_spend_key)); }, py::arg("public_spend_key")) .def_static("is_valid_private_view_key", [](const std::string& private_view_key) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::is_valid_private_view_key(private_view_key)); + return monero_utils::is_valid_private_view_key(private_view_key); }, py::arg("private_view_key")) .def_static("is_valid_private_spend_key", [](const std::string& private_spend_key) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::is_valid_private_spend_key(private_spend_key)); + MONERO_CATCH_AND_RETHROW(monero_utils::is_valid_private_spend_key(private_spend_key)); }, py::arg("private_spend_key")) .def_static("is_valid_payment_id", [](const std::string& payment_id) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::is_valid_payment_id(payment_id)); @@ -2093,7 +2109,7 @@ PYBIND11_MODULE(monero, m) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::is_valid_mnemonic(mnemonic)); }, py::arg("mnemonic")) .def_static("validate_address", [](const std::string& address, monero_network_type network_type) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::validate_address(address, network_type)); + MONERO_CATCH_AND_RETHROW(monero_utils::validate_address(address, network_type)); }, py::arg("address"), py::arg("network_type")) .def_static("validate_public_view_key", [](const std::string& public_view_key) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::validate_public_view_key(public_view_key)); @@ -2102,10 +2118,10 @@ PYBIND11_MODULE(monero, m) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::validate_public_spend_key(public_spend_key)); }, py::arg("public_spend_key")) .def_static("validate_private_view_key", [](const std::string& private_view_key) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::validate_private_view_key(private_view_key)); + MONERO_CATCH_AND_RETHROW(monero_utils::validate_private_view_key(private_view_key)); }, py::arg("private_view_key")) .def_static("validate_private_spend_key", [](const std::string& private_spend_key) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::validate_private_spend_key(private_spend_key)); + MONERO_CATCH_AND_RETHROW(monero_utils::validate_private_spend_key(private_spend_key)); }, py::arg("private_spend_key")) .def_static("validate_payment_id", [](const std::string& payment_id) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::validate_payment_id(payment_id)); @@ -2114,20 +2130,20 @@ PYBIND11_MODULE(monero, m) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::validate_mnemonic(mnemonic)); }, py::arg("mnemonic")) .def_static("is_valid_language", [](const std::string& language) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::is_valid_language(language)); + return monero_utils::is_valid_language(language); }, py::arg("language")) - .def_static("get_blocks_from_txs", [](const std::vector>& txs) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::get_blocks_from_txs(txs)); + .def_static("get_blocks_from_txs", [](const std::vector>& txs) { + MONERO_CATCH_AND_RETHROW(monero_utils::get_blocks_from_txs(txs)); }, py::arg("txs")) - .def_static("get_blocks_from_transfers", [](const std::vector>& transfers) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::get_blocks_from_transfers(transfers)); + .def_static("get_blocks_from_transfers", [](const std::vector>& transfers) { + MONERO_CATCH_AND_RETHROW(monero_utils::get_blocks_from_transfers(transfers)); }, py::arg("transfers")) - .def_static("get_blocks_from_outputs", [](const std::vector>& outputs) { - MONERO_CATCH_AND_RETHROW(PyMoneroUtils::get_blocks_from_outputs(outputs)); + .def_static("get_blocks_from_outputs", [](const std::vector>& outputs) { + MONERO_CATCH_AND_RETHROW(monero_utils::get_blocks_from_outputs(outputs)); }, py::arg("outputs")) - .def_static("get_payment_uri", [](const monero::monero_tx_config &config, monero_network_type network_type) { + .def_static("get_payment_uri", [](const monero_tx_config &config, monero_network_type network_type) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::get_payment_uri(config, network_type)); - }, py::arg("config"), py::arg("network_type") = monero::monero_network_type::MAINNET) + }, py::arg("config"), py::arg("network_type") = monero_network_type::MAINNET) .def_static("xmr_to_atomic_units", [](double amount_xmr) { MONERO_CATCH_AND_RETHROW(PyMoneroUtils::xmr_to_atomic_units(amount_xmr)); }, py::arg("amount_xmr")) @@ -2154,19 +2170,19 @@ PYBIND11_MODULE(monero, m) { }, py::arg("bin")); py_tx_height_comparator - .def_static("compare", [](const std::shared_ptr& tx1, const std::shared_ptr& tx2) { + .def_static("compare", [](const std::shared_ptr& tx1, const std::shared_ptr& tx2) { monero_tx_height_comparator tx_comp; MONERO_CATCH_AND_RETHROW(tx_comp(tx1, tx2)); }, py::arg("tx1"), py::arg("tx2")); py_incoming_transfer_comparator - .def_static("compare", [](const monero::monero_incoming_transfer& t1, const monero::monero_incoming_transfer& t2){ + .def_static("compare", [](const monero_incoming_transfer& t1, const monero_incoming_transfer& t2){ monero_incoming_transfer_comparator tr_comp; MONERO_CATCH_AND_RETHROW(tr_comp(t1, t2)); }, py::arg("transfer1"), py::arg("transfer2")); py_output_comparator - .def_static("compare", [](const monero::monero_output_wallet& o1, const monero::monero_output_wallet& o2) { + .def_static("compare", [](const monero_output_wallet& o1, const monero_output_wallet& o2) { monero_output_comparator out_comp; MONERO_CATCH_AND_RETHROW(out_comp(o1, o2)); }, py::arg("output1"), py::arg("output2")); diff --git a/src/cpp/utils/py_monero_utils.cpp b/src/cpp/utils/py_monero_utils.cpp index b79e054..dbb61d9 100644 --- a/src/cpp/utils/py_monero_utils.cpp +++ b/src/cpp/utils/py_monero_utils.cpp @@ -52,26 +52,10 @@ * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers */ #include -#include "py_monero_utils.h" #include "cryptonote_basic/cryptonote_format_utils.h" +#include "py_monero_utils.h" -int PyMoneroUtils::get_ring_size() { - return monero_utils::RING_SIZE; -} - -void PyMoneroUtils::set_log_level(int level) { - monero_utils::set_log_level(level); -} - -void PyMoneroUtils::configure_logging(const std::string& path, bool console) { - monero_utils::configure_logging(path, console); -} - -bool PyMoneroUtils::is_valid_address(const std::string& address, monero_network_type network_type) { - return monero_utils::is_valid_address(address, network_type); -} - bool PyMoneroUtils::is_valid_public_view_key(const std::string& public_view_key) { return is_hex_64(public_view_key); } @@ -80,14 +64,6 @@ bool PyMoneroUtils::is_valid_public_spend_key(const std::string& public_spend_ke return is_hex_64(public_spend_key); } -bool PyMoneroUtils::is_valid_private_view_key(const std::string& private_view_key) { - return monero_utils::is_valid_private_view_key(private_view_key); -} - -bool PyMoneroUtils::is_valid_private_spend_key(const std::string& private_spend_key) { - return monero_utils::is_valid_private_spend_key(private_spend_key); -} - bool PyMoneroUtils::is_valid_payment_id(const std::string& payment_id) { return payment_id.size() == 16 || payment_id.size() == 64; } @@ -102,10 +78,6 @@ bool PyMoneroUtils::is_valid_mnemonic(const std::string& mnemonic) { } } -void PyMoneroUtils::validate_address(const std::string& address, monero_network_type network_type) { - monero_utils::validate_address(address, network_type); -} - void PyMoneroUtils::validate_public_view_key(const std::string& public_view_key) { if(!is_hex_64(public_view_key)) throw std::runtime_error("Invalid public view key"); } @@ -114,14 +86,6 @@ void PyMoneroUtils::validate_public_spend_key(const std::string& public_spend_ke if(!is_hex_64(public_spend_key)) throw std::runtime_error("Invalid public view key"); } -void PyMoneroUtils::validate_private_view_key(const std::string& private_view_key) { - monero_utils::validate_private_view_key(private_view_key); -} - -void PyMoneroUtils::validate_private_spend_key(const std::string& private_spend_key) { - monero_utils::validate_private_spend_key(private_spend_key); -} - void PyMoneroUtils::validate_payment_id(const std::string& payment_id) { if (!is_valid_payment_id(payment_id)) throw std::runtime_error("Invalid payment id"); } @@ -231,22 +195,6 @@ void PyMoneroUtils::binary_blocks_to_property_tree(const std::string &bin, boost node.put_child("txs", all_txs); } -bool PyMoneroUtils::is_valid_language(const std::string& language) { - return monero_utils::is_valid_language(language); -} - -std::vector> PyMoneroUtils::get_blocks_from_txs(std::vector> txs) { - return monero_utils::get_blocks_from_txs(txs); -} - -std::vector> PyMoneroUtils::get_blocks_from_transfers(std::vector> transfers) { - return monero_utils::get_blocks_from_transfers(transfers); -} - -std::vector> PyMoneroUtils::get_blocks_from_outputs(std::vector> outputs) { - return monero_utils::get_blocks_from_outputs(outputs); -} - std::string PyMoneroUtils::get_payment_uri(const monero_tx_config& config, monero_network_type network_type) { // validate config std::vector> destinations = config.get_normalized_destinations(); @@ -309,14 +257,10 @@ std::string PyMoneroUtils::make_uri(const std::string &address, const std::strin return uri; } -monero_integrated_address PyMoneroUtils::get_integrated_address(monero_network_type network_type, const std::string& standard_address, const std::string& payment_id) { - return monero_utils::get_integrated_address(network_type, standard_address, payment_id); -} - -void PyMoneroUtils::sort_txs_wallet(std::vector>& txs, const std::vector& hashes) { +void PyMoneroUtils::sort_txs_wallet(std::vector>& txs, const std::vector& hashes) { bool empty = hashes.empty(); std::vector tx_hashes; - std::unordered_map> tx_map; + std::unordered_map> tx_map; for (const auto& tx : txs) { std::string tx_hash = tx->m_hash.get(); @@ -324,7 +268,7 @@ void PyMoneroUtils::sort_txs_wallet(std::vector> sorted_txs; + std::vector> sorted_txs; sorted_txs.reserve(hashes.size()); const auto& v_hashes = empty ? tx_hashes : hashes; @@ -339,13 +283,13 @@ void PyMoneroUtils::sort_txs_wallet(std::vector> PyMoneroUtils::get_and_sort_txs(const monero::monero_wallet& wallet, const monero::monero_tx_query& tx_query) { +std::vector> PyMoneroUtils::get_and_sort_txs(const monero_wallet& wallet, const monero_tx_query& tx_query) { auto txs = wallet.get_txs(tx_query); sort_txs_wallet(txs, tx_query.m_hashes); return txs; } -std::vector> PyMoneroUtils::get_and_sort_txs(const monero::monero_wallet& wallet, const std::vector& tx_hashes) { +std::vector> PyMoneroUtils::get_and_sort_txs(const monero_wallet& wallet, const std::vector& tx_hashes) { monero_tx_query tx_query; tx_query.m_hashes = tx_hashes; return get_and_sort_txs(wallet, tx_query); diff --git a/src/cpp/utils/py_monero_utils.h b/src/cpp/utils/py_monero_utils.h index 873d485..47e5036 100644 --- a/src/cpp/utils/py_monero_utils.h +++ b/src/cpp/utils/py_monero_utils.h @@ -65,22 +65,13 @@ class PyMoneroUtils { PyMoneroUtils() {}; static std::string get_version() { return std::string("0.0.1"); }; - static int get_ring_size(); - static void set_log_level(int level); - static void configure_logging(const std::string& path, bool console); static monero_integrated_address get_integrated_address(monero_network_type network_type, const std::string& standard_address, const std::string& payment_id = ""); - static bool is_valid_address(const std::string& address, monero_network_type network_type); static bool is_valid_public_view_key(const std::string& public_view_key); static bool is_valid_public_spend_key(const std::string& public_spend_key); - static bool is_valid_private_view_key(const std::string& private_view_key); - static bool is_valid_private_spend_key(const std::string& private_spend_key); static bool is_valid_payment_id(const std::string& payment_id); static bool is_valid_mnemonic(const std::string& mnemonic); - static void validate_address(const std::string& address, monero_network_type network_type); static void validate_public_view_key(const std::string& public_view_key); static void validate_public_spend_key(const std::string& public_spend_key); - static void validate_private_view_key(const std::string& private_view_key); - static void validate_private_spend_key(const std::string& private_spend_key); static void validate_payment_id(const std::string& payment_id); static void validate_mnemonic(const std::string& mnemonic); @@ -91,19 +82,35 @@ class PyMoneroUtils { static std::string binary_blocks_to_json(const std::string &bin); static void binary_blocks_to_property_tree(const std::string &bin, boost::property_tree::ptree &node); static bool is_valid_language(const std::string& language); - static std::vector> get_blocks_from_txs(std::vector> txs); - static std::vector> get_blocks_from_transfers(std::vector> transfers); - static std::vector> get_blocks_from_outputs(std::vector> outputs); static std::string get_payment_uri(const monero_tx_config& config, monero_network_type network_type); static uint64_t xmr_to_atomic_units(double amount_xmr); static double atomic_units_to_xmr(uint64_t amount_atomic_units); - static void sort_txs_wallet(std::vector>& txs, const std::vector& hashes); - static std::vector> get_and_sort_txs(const monero::monero_wallet& wallet, const std::vector& tx_hashes); - static std::vector> get_and_sort_txs(const monero::monero_wallet& wallet, const monero::monero_tx_query& tx_query); + static void sort_txs_wallet(std::vector>& txs, const std::vector& hashes); + static std::vector> get_and_sort_txs(const monero_wallet& wallet, const std::vector& tx_hashes); + static std::vector> get_and_sort_txs(const monero_wallet& wallet, const monero_tx_query& tx_query); + + template + static void set_query(std::shared_ptr& self, boost::optional>& field, const boost::optional>& val) { + const auto old = field; + field = val; + + // set new reference + if (field != boost::none) { + field.get()->m_tx_query = self; + } + + // cleanup old + if (old != boost::none) { + if (val != boost::none && val.get() == old.get()) { + return; + } + old.get()->m_tx_query = boost::none; + } + } private: static bool is_hex_64(const std::string& value); - static std::string make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, monero::monero_network_type network_type); + static std::string make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, monero_network_type network_type); }; diff --git a/src/cpp/wallet/py_monero_wallet.cpp b/src/cpp/wallet/py_monero_wallet.cpp deleted file mode 100644 index 58c736a..0000000 --- a/src/cpp/wallet/py_monero_wallet.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ -#include "py_monero_wallet.h" - - -void PyMoneroWallet::announce_new_block(uint64_t height) { - for (const auto &listener : m_listeners) { - try { - listener->on_new_block(height); - } catch (const std::exception &e) { - MERROR(e.what()); - } - } -} - -void PyMoneroWallet::announce_balances_changed(uint64_t balance, uint64_t unlocked_balance) { - for (const auto &listener : m_listeners) { - try { - listener->on_balances_changed(balance, unlocked_balance); - } catch (const std::exception &e) { - MERROR(e.what()); - } - } -} - -void PyMoneroWallet::announce_output_spent(const std::shared_ptr &output) { - for (const auto &listener : m_listeners) { - try { - listener->on_output_spent(*output); - } catch (const std::exception &e) { - MERROR(e.what()); - } - } -} - -void PyMoneroWallet::announce_output_received(const std::shared_ptr &output) { - for (const auto &listener : m_listeners) { - try { - listener->on_output_received(*output); - } catch (const std::exception &e) { - MERROR(e.what()); - } - } -} diff --git a/src/cpp/wallet/py_monero_wallet.h b/src/cpp/wallet/py_monero_wallet.h index cf3baa6..46a2ed9 100644 --- a/src/cpp/wallet/py_monero_wallet.h +++ b/src/cpp/wallet/py_monero_wallet.h @@ -55,11 +55,17 @@ #include #include -#include "py_monero_wallet_model.h" +#include "common/py_monero_common.h" #include "wallet/monero_wallet.h" -// TODO sorting is really needed? -std::vector> get_and_sort_txs(const monero::monero_wallet& wallet, const monero::monero_tx_query& tx_query); +struct PyMoneroTransfer : public monero_transfer { +public: + using monero_transfer::monero_transfer; + + boost::optional is_incoming() const override { + PYBIND11_OVERRIDE_PURE(boost::optional, monero_transfer, is_incoming); + } +}; class PyMoneroWalletListener : public monero_wallet_listener { public: @@ -85,42 +91,21 @@ class PyMoneroWalletListener : public monero_wallet_listener { } }; -PYBIND11_MAKE_OPAQUE(std::vector); -PYBIND11_MAKE_OPAQUE(std::vector>); -PYBIND11_MAKE_OPAQUE(std::vector>); -PYBIND11_MAKE_OPAQUE(std::vector>); -PYBIND11_MAKE_OPAQUE(std::vector>); -PYBIND11_MAKE_OPAQUE(std::vector>); -PYBIND11_MAKE_OPAQUE(std::vector>); -PYBIND11_MAKE_OPAQUE(std::vector>); -PYBIND11_MAKE_OPAQUE(std::vector>); -PYBIND11_MAKE_OPAQUE(std::vector>); -PYBIND11_MAKE_OPAQUE(std::vector); + +PYBIND11_MAKE_OPAQUE(std::vector>); +PYBIND11_MAKE_OPAQUE(std::vector>); +PYBIND11_MAKE_OPAQUE(std::vector>); +PYBIND11_MAKE_OPAQUE(std::vector>); +PYBIND11_MAKE_OPAQUE(std::vector>); +PYBIND11_MAKE_OPAQUE(std::vector); PYBIND11_MAKE_OPAQUE(std::vector>); PYBIND11_MAKE_OPAQUE(std::vector>); -class PyMoneroWallet : public monero::monero_wallet { +class PyMoneroWallet : public monero_wallet { public: PyMoneroWallet() { } virtual ~PyMoneroWallet() = default; - virtual void tag_accounts(const std::string& tag, const std::vector& account_indices) { - throw std::runtime_error("MoneroWallet.tag_accounts(): not implemented"); - } - - virtual void untag_accounts(const std::vector& account_indices) { - throw std::runtime_error("MoneroWallet.untag_accounts(): not implemented"); - } - - // TODO define method in monero-cpp wallet interface - virtual std::vector> get_account_tags() { - throw std::runtime_error("MoneroWallet.get_account_tags(): not implemented"); - } - - virtual void set_account_tag_label(const std::string& tag, const std::string& label) { - throw std::runtime_error("MoneroWallet.set_account_tags(): not implemented"); - } - bool is_view_only() const override { PYBIND11_OVERRIDE(bool, monero_wallet, is_view_only); } @@ -129,12 +114,12 @@ class PyMoneroWallet : public monero::monero_wallet { PYBIND11_OVERRIDE(void, monero_wallet, set_daemon_connection, uri, username, password, proxy); } - void set_daemon_connection(const boost::optional& connection) override { + void set_daemon_connection(const boost::optional>& connection) override { PYBIND11_OVERRIDE(void, monero_wallet, set_daemon_connection, connection); } - boost::optional get_daemon_connection() const override { - PYBIND11_OVERRIDE(boost::optional, monero_wallet, get_daemon_connection); + boost::optional> get_daemon_connection() const override { + PYBIND11_OVERRIDE(boost::optional>, monero_wallet, get_daemon_connection); } bool is_connected_to_daemon() const override { @@ -230,15 +215,15 @@ class PyMoneroWallet : public monero::monero_wallet { } void add_listener(monero_wallet_listener& listener) override { - m_listeners.insert(&listener); + PYBIND11_OVERRIDE(void, monero_wallet, add_listener, listener); } void remove_listener(monero_wallet_listener& listener) override { - m_listeners.erase(&listener); + PYBIND11_OVERRIDE(void, monero_wallet, remove_listener, listener); } std::set get_listeners() override { - return m_listeners; + PYBIND11_OVERRIDE(std::set, monero_wallet, get_listeners); } monero_sync_result sync() override { @@ -601,13 +586,4 @@ class PyMoneroWallet : public monero::monero_wallet { PYBIND11_OVERRIDE(void, monero_wallet, close, save); } - virtual void announce_new_block(uint64_t height); - virtual void announce_balances_changed(uint64_t balance, uint64_t unlocked_balance); - virtual void announce_output_spent(const std::shared_ptr &output); - virtual void announce_output_received(const std::shared_ptr &output); - virtual bool is_closed() const { return m_is_closed; } - -protected: - bool m_is_closed = false; - std::set m_listeners; }; diff --git a/src/cpp/wallet/py_monero_wallet_model.cpp b/src/cpp/wallet/py_monero_wallet_model.cpp deleted file mode 100644 index 24fa3d3..0000000 --- a/src/cpp/wallet/py_monero_wallet_model.cpp +++ /dev/null @@ -1,1219 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ -#include "py_monero_wallet_model.h" -#include "utils/monero_utils.h" - -// ------------------------------ Custom Data Model --------------------------------- - -PyMoneroKeyImage::PyMoneroKeyImage(const monero::monero_key_image &key_image) { - m_hex = key_image.m_hex; - m_signature = key_image.m_signature; -} - -rapidjson::Value PyMoneroKeyImage::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_hex != boost::none) monero_utils::add_json_member("key_image", m_hex.get(), allocator, root, value_str); - if (m_signature != boost::none) monero_utils::add_json_member("signature", m_signature.get(), allocator, root, value_str); - - // return root - return root; -} - -bool PyMoneroOutputQuery::is_contextual(const monero::monero_output_query &query) { - if (query.m_tx_query == boost::none) return false; - if (query.m_tx_query.get()->m_is_incoming != boost::none) return true; // requires context of all transfers - if (query.m_tx_query.get()->m_is_outgoing != boost::none) return true; - if (query.m_tx_query.get()->m_transfer_query != boost::none) return true; // requires context of transfers - return false; -} - -bool PyMoneroTransferQuery::is_contextual(const monero::monero_transfer_query &query) { - if (query.m_tx_query == boost::none) return false; - // requires context of all transfers - if (query.m_tx_query.get()->m_is_incoming != boost::none) return true; - if (query.m_tx_query.get()->m_is_outgoing != boost::none) return true; - // requires context of inputs - if (query.m_tx_query.get()->m_input_query != boost::none) return true; - // requires context of inputs - if (query.m_tx_query.get()->m_output_query != boost::none) return true; - return false; -} - -std::shared_ptr PyMoneroTxQuery::decontextualize(const std::shared_ptr &query) { - query->m_is_incoming = boost::none; - query->m_is_outgoing = boost::none; - query->m_transfer_query = boost::none; - query->m_input_query = boost::none; - query->m_output_query = boost::none; - return query; -} - -bool PyMoneroTxWallet::decode_rpc_type(const std::string &rpc_type, const std::shared_ptr &tx) { - bool is_outgoing = false; - if (rpc_type == std::string("in")) { - tx->m_is_confirmed = true; - tx->m_in_tx_pool = false; - tx->m_is_relayed = true; - tx->m_relay = true; - tx->m_is_failed = false; - tx->m_is_miner_tx = false; - } else if (rpc_type == std::string("out")) { - is_outgoing = true; - tx->m_is_confirmed = true; - tx->m_in_tx_pool = false; - tx->m_is_relayed = true; - tx->m_relay = true; - tx->m_is_failed = false; - tx->m_is_miner_tx = false; - } else if (rpc_type == std::string("pool")) { - tx->m_is_confirmed = false; - tx->m_in_tx_pool = true; - tx->m_is_relayed = true; - tx->m_relay = true; - tx->m_is_failed = false; - tx->m_is_miner_tx = false; // TODO: but could it be? - } else if (rpc_type == std::string("pending")) { - is_outgoing = true; - tx->m_is_confirmed = false; - tx->m_in_tx_pool = true; - tx->m_is_relayed = true; - tx->m_relay = true; - tx->m_is_failed = false; - tx->m_is_miner_tx = false; - } else if (rpc_type == std::string("block")) { - tx->m_is_confirmed = true; - tx->m_in_tx_pool = false; - tx->m_is_relayed = true; - tx->m_relay = true; - tx->m_is_failed = false; - tx->m_is_miner_tx = true; - } else if (rpc_type == std::string("failed")) { - is_outgoing = true; - tx->m_is_confirmed = false; - tx->m_in_tx_pool = false; - tx->m_is_relayed = false; - tx->m_relay = true; - tx->m_is_failed = true; - tx->m_is_miner_tx = false; - } else { - throw std::runtime_error(std::string("Unrecognized transfer type: ") + rpc_type); - } - return is_outgoing; -} - -void PyMoneroTxWallet::init_sent(const monero::monero_tx_config &config, std::shared_ptr &tx, bool copy_destinations) { - bool relay = bool_equals_2(true, config.m_relay); - tx->m_is_outgoing = true; - tx->m_is_confirmed = false; - tx->m_num_confirmations = 0; - tx->m_in_tx_pool = relay; - tx->m_relay = relay; - tx->m_is_relayed = relay; - tx->m_is_miner_tx = false; - tx->m_is_failed = false; - tx->m_is_locked = true; - tx->m_ring_size = monero_utils::RING_SIZE; - - auto outgoing_transfer = std::make_shared(); - outgoing_transfer->m_tx = tx; - - if (config.m_subaddress_indices.size() == 1) { - // we know src subaddress indices iff request specifies 1 - outgoing_transfer->m_subaddress_indices = config.m_subaddress_indices; - } - - if (copy_destinations) { - auto conf_dests = config.get_normalized_destinations(); - for(const auto &conf_dest : conf_dests) { - auto dest = std::make_shared(); - conf_dest->copy(conf_dest, dest); - outgoing_transfer->m_destinations.push_back(dest); - } - } - - tx->m_outgoing_transfer = outgoing_transfer; - tx->m_payment_id = config.m_payment_id; - if (tx->m_unlock_time == boost::none) tx->m_unlock_time = 0; - if (bool_equals_2(true, tx->m_relay)) { - if (tx->m_last_relayed_timestamp == boost::none) { - // set last relayed timestamp to current time iff relayed - // TODO (monero-wallet-rpc): provide timestamp on response; unconfirmed timestamps vary - tx->m_last_relayed_timestamp = static_cast(time(NULL)); - } - if (tx->m_is_double_spend_seen == boost::none) tx->m_is_double_spend_seen = false; - } -} - -void PyMoneroTxWallet::from_property_tree_with_transfer(const boost::property_tree::ptree& node, const std::shared_ptr& tx, boost::optional &is_outgoing, const monero_tx_config &config) { - std::shared_ptr header = nullptr; - std::shared_ptr outgoing_transfer = nullptr; - std::shared_ptr incoming_transfer = nullptr; - - bool key_found = false; - - for (auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("type")) { - is_outgoing = decode_rpc_type(it->second.data(), tx); - key_found = true; - } - } - - for (auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("txid") || key == std::string("tx_hash")) tx->m_hash = it->second.data(); - else if (key == std::string("fee")) tx->m_fee = it->second.get_value(); - else if (key == std::string("note") && !it->second.data().empty()) tx->m_note = it->second.data(); - else if (key == std::string("tx_key") && !it->second.data().empty()) tx->m_key = it->second.data(); - else if (key == std::string("tx_size")) tx->m_size = it->second.get_value(); - else if (key == std::string("unlock_time")) tx->m_unlock_time = it->second.get_value(); - else if (key == std::string("weight")) tx->m_weight = it->second.get_value(); - else if (key == std::string("locked")) tx->m_is_locked = it->second.get_value(); - else if (key == std::string("tx_blob") && !it->second.data().empty()) tx->m_full_hex = it->second.data(); - else if (key == std::string("tx_metadata") && !it->second.data().empty()) tx->m_metadata = it->second.data(); - else if (key == std::string("double_spend_seen")) tx->m_is_double_spend_seen = it->second.get_value(); - else if (key == std::string("block_height") || key == std::string("height")) { - if (bool_equals_2(true, tx->m_is_confirmed)) { - if (header == nullptr) header = std::make_shared(); - header->m_height = it->second.get_value(); - } - } - else if (key == std::string("timestamp")) { - if (bool_equals_2(true, tx->m_is_confirmed)) { - if (header == nullptr) header = std::make_shared(); - header->m_timestamp = it->second.get_value(); - } - } - else if (key == std::string("confirmations")) tx->m_num_confirmations = it->second.get_value(); - else if (key == std::string("suggested_confirmations_threshold")) { - if (*is_outgoing) { - if (outgoing_transfer == nullptr) - outgoing_transfer = std::make_shared(); - outgoing_transfer->m_tx = tx; - } - else { - if (incoming_transfer == nullptr) - incoming_transfer = std::make_shared(); - incoming_transfer->m_tx = tx; - incoming_transfer->m_num_suggested_confirmations = it->second.get_value(); - } - } - else if (key == std::string("amount")) { - if (*is_outgoing) { - if (outgoing_transfer == nullptr) { - outgoing_transfer = std::make_shared(); - outgoing_transfer->m_tx = tx; - } - outgoing_transfer->m_amount = it->second.get_value(); - } - else { - if (incoming_transfer == nullptr) incoming_transfer = std::make_shared(); - incoming_transfer->m_tx = tx; - incoming_transfer->m_amount = it->second.get_value(); - } - } - else if (key == std::string("address")) { - if (!*is_outgoing) { - if (incoming_transfer == nullptr) incoming_transfer = std::make_shared(); - incoming_transfer->m_tx = tx; - incoming_transfer->m_address = it->second.data(); - } - } - else if (key == std::string("payment_id")) { - std::string payment_id = it->second.data(); - if (payment_id != std::string("") && payment_id != monero::monero_tx_wallet::DEFAULT_PAYMENT_ID) { - tx->m_payment_id = payment_id; - } - } - else if (key == std::string("subaddr_indices")) { - if (*is_outgoing) { - if (outgoing_transfer == nullptr) { - outgoing_transfer = std::make_shared(); - outgoing_transfer->m_tx = tx; - } - } - else { - if (incoming_transfer == nullptr) incoming_transfer = std::make_shared(); - incoming_transfer->m_tx = tx; - } - - auto node2 = it->second; - bool first_major = true; - bool first_minor = true; - - for(auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto node3 = it2->second; - - for(auto it3 = node3.begin(); it3 != node3.end(); ++it3) { - std::string index_key = it3->first; - - if (index_key == std::string("major") && first_major) { - if (*is_outgoing) outgoing_transfer->m_account_index = it3->second.get_value(); - else incoming_transfer->m_account_index = it3->second.get_value(); - first_major = false; - } - else if (index_key == std::string("minor")) { - if (*is_outgoing) { - outgoing_transfer->m_subaddress_indices.push_back(it3->second.get_value()); - } - else if (first_minor) { - incoming_transfer->m_subaddress_index = it3->second.get_value(); - first_minor = false; - } - } - } - } - } - else if (key == std::string("destinations") || key == std::string("recipients")) { - if (!*is_outgoing) throw std::runtime_error("Expected outgoing transaction"); - if (outgoing_transfer == nullptr) { - outgoing_transfer = std::make_shared(); - outgoing_transfer->m_tx = tx; - } - auto node2 = it->second; - outgoing_transfer->m_destinations.clear(); - - for(auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto node3 = it2->second; - auto dest = std::make_shared(); - - for(auto it3 = node3.begin(); it3 != node3.end(); ++it3) { - std::string _key = it3->first; - - if (_key == std::string("address")) dest->m_address = it3->second.data(); - else if (_key == std::string("amount")) dest->m_amount = it3->second.get_value(); - else throw std::runtime_error(std::string("Unrecognized transaction destination field: ") + _key); - } - - outgoing_transfer->m_destinations.push_back(dest); - } - } - else if (key == std::string("amount_in")) tx->m_input_sum = it->second.get_value(); - else if (key == std::string("amount_out")) tx->m_output_sum = it->second.get_value(); - else if (key == std::string("change_address") && !it->second.data().empty()) tx->m_change_address = it->second.data(); - else if (key == std::string("change_amount")) tx->m_change_amount = it->second.get_value(); - else if (key == std::string("dummy_outputs")) tx->m_num_dummy_outputs = it->second.get_value(); - else if (key == std::string("extra")) tx->m_extra_hex = it->second.data(); - else if (key == std::string("ring_size")) tx->m_ring_size = it->second.get_value(); - else if (key == std::string("spent_key_images")) { - auto node2 = it->second; - - for(auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - std::string _key = it2->first; - - if (_key == std::string("key_images")) { - auto node3 = it2->second; - if (tx->m_inputs.size() > 0) throw std::runtime_error("inputs should be empty"); - - for(auto it3 = node3.begin(); it3 != node3.end(); ++it3) { - auto output = std::make_shared(); - auto key_image = std::make_shared(); - - key_image->m_hex = it3->second.data(); - output->m_key_image = key_image; - output->m_tx = tx; - tx->m_inputs.push_back(output); - } - } - } - } - else if (key == std::string("amounts_by_dest")) { - if (!*is_outgoing) throw std::runtime_error("Expected outgoing transaction"); - if (outgoing_transfer == nullptr) { - outgoing_transfer = std::make_shared(); - outgoing_transfer->m_tx = tx; - } - auto node2 = it->second; - std::vector amounts_by_dest; - - for(auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - std::string _key = it2->first; - - if (_key == std::string("amounts")) { - auto node3 = it2->second; - - for(auto it3 = node3.begin(); it3 != node3.end(); ++it3) { - amounts_by_dest.push_back(it3->second.get_value()); - } - } - } - - auto destinations = config.get_normalized_destinations(); - size_t num_destinations = destinations.size(); - if (num_destinations != amounts_by_dest.size()) throw std::runtime_error("Expected destinations size equal to amounts by dest size"); - outgoing_transfer->m_destinations.clear(); - for(uint64_t i = 0; i < num_destinations; i++) { - auto dest = std::make_shared(); - dest->m_address = destinations[i]->m_address; - dest->m_amount = amounts_by_dest[i]; - outgoing_transfer->m_destinations.push_back(dest); - } - } - } - - if (!key_found && is_outgoing == boost::none) throw std::runtime_error("Must indicate if tx is outgoing (true) xor incoming (false) since unknown"); - // link block and tx - if (header != nullptr) { - auto block = std::make_shared(); - header->copy(header, block); - block->m_txs.push_back(tx); - tx->m_block = block; - } - - if (*is_outgoing && outgoing_transfer != nullptr) { - if (tx->m_is_confirmed == boost::none) tx->m_is_confirmed = false; - if (bool_equals_2(false, outgoing_transfer->m_tx->m_is_confirmed)) tx->m_num_confirmations = 0; - tx->m_is_outgoing = true; - - if (tx->m_outgoing_transfer != boost::none) { - // overwrite to avoid reconcile error TODO: remove after >18.3.1 when amounts_by_dest supported - if (!outgoing_transfer->m_destinations.empty()) { - tx->m_outgoing_transfer.get()->m_destinations.clear(); - } - tx->m_outgoing_transfer.get()->merge(tx->m_outgoing_transfer.get(), outgoing_transfer); - } - else tx->m_outgoing_transfer = outgoing_transfer; - } - else if (is_outgoing != boost::none && *is_outgoing == false && incoming_transfer != nullptr) { - if (tx->m_is_confirmed == boost::none) tx->m_is_confirmed = false; - if (bool_equals_2(false, incoming_transfer->m_tx->m_is_confirmed)) tx->m_num_confirmations = 0; - tx->m_is_incoming = true; - tx->m_incoming_transfers.push_back(incoming_transfer); - } - -} - -void PyMoneroTxWallet::from_property_tree_with_transfer(const boost::property_tree::ptree& node, const std::shared_ptr& tx, boost::optional &is_outgoing) { - monero::monero_tx_config config; - from_property_tree_with_transfer(node, tx, is_outgoing, config); -} - -void PyMoneroTxWallet::from_property_tree_with_transfer(const boost::property_tree::ptree& node, const std::shared_ptr& tx) { - boost::optional is_outgoing; - from_property_tree_with_transfer(node, tx, is_outgoing); -} - -void PyMoneroTxWallet::from_property_tree_with_output(const boost::property_tree::ptree& node, const std::shared_ptr& tx) { - tx->m_is_confirmed = true; - tx->m_is_relayed = true; - tx->m_is_failed = false; - tx->m_in_tx_pool = false; - - auto output = std::make_shared(); - output->m_tx = tx; - - for(auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("amount")) output->m_amount = it->second.get_value(); - else if (key == std::string("spent")) output->m_is_spent = it->second.get_value(); - else if (key == std::string("key_image") && !it->second.data().empty()) { - auto key_image = std::make_shared(); - key_image->m_hex = it->second.data(); - output->m_key_image = key_image; - } - else if (key == std::string("global_index")) output->m_index = it->second.get_value(); - else if (key == std::string("tx_hash")) tx->m_hash = it->second.data(); - else if (key == std::string("unlocked")) tx->m_is_locked = !it->second.get_value(); - else if (key == std::string("frozen")) output->m_is_frozen = it->second.get_value(); - else if (key == std::string("pubkey")) output->m_stealth_public_key = it->second.data(); - else if (key == std::string("subaddr_index")) { - for(auto indices_it = it->second.begin(); indices_it != it->second.end(); ++indices_it) { - std::string indices_key = indices_it->first; - if (indices_key == std::string("major")) output->m_account_index = indices_it->second.get_value(); - if (indices_key == std::string("minor")) output->m_subaddress_index = indices_it->second.get_value(); - } - } - else if (key == std::string("block_height")) { - auto block = std::make_shared(); - block->m_height = it->second.get_value(); - block->m_txs.push_back(tx); - tx->m_block = block; - } - } - - tx->m_outputs.push_back(output); -} - -void PyMoneroTxWallet::from_property_tree_with_output_and_merge(const boost::property_tree::ptree& node, std::unordered_map>& tx_map, std::unordered_map>& block_map) { - for(auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("transfers")) { - for(auto rpc_output_it = it->second.begin(); rpc_output_it != it->second.end(); ++rpc_output_it) { - auto tx = std::make_shared(); - from_property_tree_with_output(rpc_output_it->second, tx); - merge_tx(tx, tx_map, block_map); - } - } - } -} - -void PyMoneroTxWallet::from_property_tree_with_transfer_and_merge(const boost::property_tree::ptree& node, std::unordered_map>& tx_map, std::unordered_map>& block_map) { - for (auto it = node.begin(); it != node.end(); ++it) { - for (auto it2 = it->second.begin(); it2 != it->second.end(); ++it2) { - auto tx = std::make_shared(); - PyMoneroTxWallet::from_property_tree_with_transfer(it2->second, tx); - - if (tx->m_is_confirmed != boost::none && *tx->m_is_confirmed == true) { - if (tx->m_block == boost::none) throw std::runtime_error("Confirmed tx has no block"); - auto& block_txs = tx->m_block.get()->m_txs; - if (std::find(block_txs.begin(), block_txs.end(), tx) == block_txs.end()) { - throw std::runtime_error("Tx not found in its block"); - } - } - - // replace transfer amount with destination sum - // TODO monero-wallet-rpc: confirmed tx from/to same account has amount 0 but cached transfers - if (tx->m_outgoing_transfer != boost::none && bool_equals_2(true, tx->m_is_relayed) && !bool_equals_2(true, tx->m_is_failed) && - !tx->m_outgoing_transfer.get()->m_destinations.empty() && tx->m_outgoing_transfer.get()->m_amount.get() == 0) { - auto outgoing_transfer = tx->m_outgoing_transfer.get(); - uint64_t transfer_total = 0; - for(const auto& destination : outgoing_transfer->m_destinations) { - transfer_total += destination->m_amount.get(); - } - outgoing_transfer->m_amount = transfer_total; - } - - // merge tx - merge_tx(tx, tx_map, block_map); - } - } -} - -/** - * Merges a transaction into a unique set of transactions. - * - * @param tx is the transaction to merge into the existing txs - * @param tx_map maps tx hashes to txs - * @param block_map maps block heights to blocks - */ -void PyMoneroTxWallet::merge_tx(const std::shared_ptr& tx, std::unordered_map>& tx_map, std::unordered_map>& block_map) { - if (tx->m_hash == boost::none) throw std::runtime_error("Tx hash is not initialized"); - - // merge tx - std::unordered_map>::const_iterator tx_iter = tx_map.find(*tx->m_hash); - if (tx_iter == tx_map.end()) { - tx_map[*tx->m_hash] = tx; // cache new tx - } else { - std::shared_ptr& a_tx = tx_map[*tx->m_hash]; - a_tx->merge(a_tx, tx); // merge with existing tx - } - - // merge tx's block if confirmed - if (tx->get_height() != boost::none) { - std::unordered_map>::const_iterator block_iter = block_map.find(tx->get_height().get()); - if (block_iter == block_map.end()) { - block_map[tx->get_height().get()] = tx->m_block.get(); // cache new block - } else { - std::shared_ptr& a_block = block_map[tx->get_height().get()]; - a_block->merge(a_block, tx->m_block.get()); // merge with existing block - } - } -} - -void PyMoneroTxSet::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& set) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("multisig_txset") && !it->second.data().empty()) set->m_multisig_tx_hex = it->second.data(); - else if (key == std::string("unsigned_txset") && !it->second.data().empty()) set->m_unsigned_tx_hex = it->second.data(); - else if (key == std::string("signed_txset") && !it->second.data().empty()) set->m_signed_tx_hex = it->second.data(); - } -} - -void PyMoneroTxSet::from_tx(const boost::property_tree::ptree& node, const std::shared_ptr& set, const std::shared_ptr &tx, bool is_outgoing, const monero_tx_config &config) { - from_property_tree(node, set); - boost::optional outgoing = is_outgoing; - PyMoneroTxWallet::from_property_tree_with_transfer(node, tx, outgoing, config); - tx->m_tx_set = set; - set->m_txs.push_back(tx); -} - -void PyMoneroTxSet::from_sent_txs(const boost::property_tree::ptree& node, const std::shared_ptr& set) { - std::vector> txs; - from_sent_txs(node, set, txs, boost::none); -} - -void PyMoneroTxSet::from_sent_txs(const boost::property_tree::ptree& node, const std::shared_ptr& set, std::vector> &txs, const boost::optional &conf) { - from_property_tree(node, set); - int num_txs = 0; - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("fee_list") && num_txs == 0) { - auto fee_list_node = it->second; - for (auto it2 = fee_list_node.begin(); it2 != fee_list_node.end(); ++it2) { - num_txs++; - } - } - else if (key == std::string("tx_hash_list") && num_txs == 0) { - auto tx_hash_list_node = it->second; - for (auto it2 = tx_hash_list_node.begin(); it2 != tx_hash_list_node.end(); ++it2) { - num_txs++; - } - } - } - - if (num_txs == 0) { - if (txs.size() > 0) throw std::runtime_error("txs should be empty"); - return; - } - - if (txs.size() > 0) set->m_txs = txs; - else { - for(int i = 0; i < num_txs; i++) { - auto tx = std::make_shared(); - txs.push_back(tx); - } - } - - for(const auto &tx : txs) { - tx->m_tx_set = set; - tx->m_is_outgoing = true; - } - - set->m_txs = txs; - - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("tx_hash_list")) { - auto node2 = it->second; - int i = 0; - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto tx = txs[i]; - tx->m_hash = it2->second.data(); - i++; - } - } - else if (key == std::string("tx_key_list")) { - auto node2 = it->second; - int i = 0; - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto tx = txs[i]; - tx->m_key = it2->second.data(); - i++; - } - } - else if (key == std::string("tx_blob_list")) { - auto node2 = it->second; - int i = 0; - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto tx = txs[i]; - tx->m_full_hex = it2->second.data(); - i++; - } - } - else if (key == std::string("tx_metadata_list")) { - auto node2 = it->second; - int i = 0; - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto tx = txs[i]; - tx->m_metadata = it2->second.data(); - i++; - } - } - else if (key == std::string("fee_list")) { - auto node2 = it->second; - int i = 0; - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto tx = txs[i]; - tx->m_fee = it2->second.get_value(); - i++; - } - } - else if (key == std::string("amount_list")) { - auto node2 = it->second; - int i = 0; - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto tx = txs[i]; - if (tx->m_outgoing_transfer == boost::none) { - auto outgoing_transfer = std::make_shared(); - outgoing_transfer->m_tx = tx; - tx->m_outgoing_transfer = outgoing_transfer; - } - tx->m_outgoing_transfer.get()->m_amount = it2->second.get_value(); - i++; - } - } - else if (key == std::string("weight_list")) { - auto node2 = it->second; - int i = 0; - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto tx = txs[i]; - tx->m_weight = it2->second.get_value(); - i++; - } - } - else if (key == std::string("spent_key_images_list")) { - auto node2 = it->second; - int i = 0; - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto tx = txs[i]; - if (tx->m_inputs.size() > 0) throw std::runtime_error("Expected no inputs in sent tx"); - - auto node3 = it2->second; - for (auto it3 = node3.begin(); it3 != node3.end(); ++it3) { - std::string _key = it3->first; - - if (_key == std::string("key_images")) { - auto node4 = it3->second; - - for (auto it4 = node4.begin(); it4 != node4.end(); ++it4) { - auto output = std::make_shared(); - output->m_key_image = std::make_shared(); - output->m_key_image.get()->m_hex = it4->second.data(); - output->m_tx = tx; - tx->m_inputs.push_back(output); - } - } - } - - i++; - } - } - else if (key == std::string("amounts_by_dest_list")) { - auto node2 = it->second; - int i = 0; - int destination_idx = 0; - - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto tx = txs[i]; - auto node3 = it2->second; - for (auto it3 = node3.begin(); it3 != node3.end(); ++it3) { - std::string _key = it3->first; - - if (_key == std::string("amounts")) { - std::vector amounts_by_dest; - auto node4 = it3->second; - - for(auto it4 = node4.begin(); it4 != node4.end(); ++it4) { - amounts_by_dest.push_back(it4->second.get_value()); - } - - if (tx->m_outgoing_transfer == boost::none) { - auto outgoing_transfer = std::make_shared(); - outgoing_transfer->m_tx = tx; - tx->m_outgoing_transfer = outgoing_transfer; - } - - tx->m_outgoing_transfer.get()->m_destinations.clear(); - - for(const auto& amount : amounts_by_dest) { - if (conf == boost::none) throw std::runtime_error("Expected tx configuration"); - auto config = conf.get(); - if (config.m_destinations.size() == 1) { - // sweeping can create multiple withone address - auto dest = std::make_shared(); - dest->m_address = config.m_destinations[0]->m_address; - dest->m_amount = amount; - tx->m_outgoing_transfer.get()->m_destinations.push_back(dest); - } - else { - auto dest = std::make_shared(); - dest->m_address = config.get_normalized_destinations()[destination_idx]->m_address; - dest->m_amount = amount; - tx->m_outgoing_transfer.get()->m_destinations.push_back(dest); - destination_idx++; - } - } - } - } - - i++; - } - } - } -} - -void PyMoneroTxSet::from_describe_transfer(const boost::property_tree::ptree& node, const std::shared_ptr& set) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("desc")) { - auto node2 = it->second; - - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto tx = std::make_shared(); - boost::optional outgoing = true; - PyMoneroTxWallet::from_property_tree_with_transfer(it2->second, tx, outgoing); - tx->m_tx_set = set; - set->m_txs.push_back(tx); - } - } - } -} - -void PyMoneroKeyImage::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& key_image) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("key_image")) key_image->m_hex = it->second.data(); - else if (key == std::string("signature")) key_image->m_signature = it->second.data(); - } -} - -void PyMoneroKeyImage::from_property_tree(const boost::property_tree::ptree& node, std::vector>& key_images) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("signed_key_images")) { - auto key_images_node = it->second; - - for (auto it2 = key_images_node.begin(); it2 != key_images_node.end(); ++it2) { - auto key_image = std::make_shared(); - from_property_tree(it2->second, key_image); - key_images.push_back(key_image); - } - } - } -} - -void PyMoneroKeyImageImportResult::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& result) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("height")) result->m_height = it->second.get_value(); - else if (key == std::string("spent")) result->m_spent_amount = it->second.get_value(); - else if (key == std::string("unspent")) result->m_unspent_amount = it->second.get_value(); - } -} - -void PyMoneroMultisigInfo::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& info) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("multisig")) info->m_is_multisig = it->second.get_value(); - else if (key == std::string("ready")) info->m_is_ready = it->second.get_value(); - else if (key == std::string("threshold")) info->m_threshold = it->second.get_value(); - else if (key == std::string("total")) info->m_num_participants = it->second.get_value(); - } -} - -void PyMoneroMultisigInitResult::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& info) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("address")) info->m_address = it->second.data(); - else if (key == std::string("multisig_info")) info->m_multisig_hex = it->second.data(); - } -} - -void PyMoneroMultisigSignResult::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& res) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("tx_data_hex")) res->m_signed_multisig_tx_hex = it->second.data(); - else if (key == std::string("tx_hash_list")) { - auto node2 = it->second; - for (boost::property_tree::ptree::const_iterator it2 = node2.begin(); it2 != node.end(); ++it2) { - res->m_tx_hashes.push_back(it2->second.data()); - } - } - } -} - -void PyMoneroSubaddress::from_rpc_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& subaddress) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("account_index")) subaddress->m_account_index = it->second.get_value(); - else if (key == std::string("address_index")) subaddress->m_index = it->second.get_value(); - else if (key == std::string("address")) subaddress->m_address = it->second.data(); - else if (key == std::string("balance")) subaddress->m_balance = it->second.get_value(); - else if (key == std::string("unlocked_balance")) subaddress->m_unlocked_balance = it->second.get_value(); - else if (key == std::string("label") && !it->second.data().empty()) subaddress->m_label = it->second.data(); - else if (key == std::string("used")) subaddress->m_is_used = it->second.get_value(); - else if (key == std::string("num_unspent_outputs")) subaddress->m_num_unspent_outputs = it->second.get_value(); - else if (key == std::string("blocks_to_unlock")) subaddress->m_num_blocks_to_unlock = it->second.get_value(); - } -} - -void PyMoneroSubaddress::from_rpc_property_tree(const boost::property_tree::ptree& node, std::vector>& subaddresses) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - bool rpc_subaddresses = key == std::string("addresses"); - - if (key == std::string("per_subaddress") || rpc_subaddresses) { - auto per_subaddress_node = it->second; - - for (auto it2 = per_subaddress_node.begin(); it2 != per_subaddress_node.end(); ++it2) { - auto sub = std::make_shared(); - if (rpc_subaddresses) from_rpc_property_tree(it2->second, sub); - else from_property_tree(it2->second, sub); - subaddresses.push_back(sub); - } - } - } -} - -void PyMoneroSubaddress::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& subaddress) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("major")) subaddress->m_account_index = it->second.get_value(); - else if (key == std::string("minor")) subaddress->m_index = it->second.get_value(); - else if (key == std::string("index")) { - auto node2 = it->second; - from_property_tree(node2, subaddress); - } - } -} - -void PyMoneroIntegratedAddress::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& subaddress) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("integrated_address")) subaddress->m_integrated_address = it->second.data(); - else if (key == std::string("standard_address")) subaddress->m_standard_address = it->second.data(); - else if (key == std::string("payment_id")) subaddress->m_payment_id = it->second.data(); - } -} - -void PyMoneroAccount::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& account) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("account_index")) account->m_index = it->second.get_value(); - else if (key == std::string("balance")) account->m_balance = it->second.get_value(); - else if (key == std::string("unlocked_balance")) account->m_unlocked_balance = it->second.get_value(); - else if (key == std::string("base_address")) account->m_primary_address = it->second.data(); - else if (key == std::string("tag")) account->m_tag = it->second.data(); - else if (key == std::string("label")) { - // label belongs to first subaddress - } - } - if (account->m_tag != boost::none && account->m_tag->empty()) account->m_tag = boost::none; -} - -void PyMoneroAccount::from_property_tree(const boost::property_tree::ptree& node, std::vector>& accounts) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("subaddress_accounts")) { - auto accounts_node = it->second; - - for (auto it2 = accounts_node.begin(); it2 != accounts_node.end(); ++it2) { - auto account = std::make_shared(); - from_property_tree(it2->second, account); - accounts.push_back(account); - } - } - } -} - -void PyMoneroAccount::from_property_tree(const boost::property_tree::ptree& node, std::vector& accounts) { - std::vector> accounts_ptr; - from_property_tree(node, accounts_ptr); - - for (const auto &account : accounts_ptr) { - accounts.push_back(*account); - } -} - -void PyMoneroAddressBookEntry::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& entry) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("index")) entry->m_index = it->second.get_value(); - else if (key == std::string("address")) entry->m_address = it->second.data(); - else if (key == std::string("description")) entry->m_description = it->second.data(); - else if (key == std::string("payment_id")) entry->m_payment_id = it->second.data(); - } -} - -void PyMoneroAddressBookEntry::from_property_tree(const boost::property_tree::ptree& node, std::vector>& entries) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("entries")) { - auto entries_node = it->second; - - for (auto it2 = entries_node.begin(); it2 != entries_node.end(); ++it2) { - auto entry = std::make_shared(); - from_property_tree(it2->second, entry); - entries.push_back(entry); - } - } - } -} - -void PyMoneroCheckReserve::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& check) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("good")) check->m_is_good = it->second.get_value(); - else if (key == std::string("total")) check->m_total_amount = it->second.get_value(); - else if (key == std::string("spent")) check->m_unconfirmed_spent_amount = it->second.get_value(); - } - - if (!bool_equals_2(true, check->m_is_good)) { - // normalize invalid check reserve - check->m_total_amount = boost::none; - check->m_unconfirmed_spent_amount = boost::none; - } -} - -void PyMoneroCheckTxProof::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& check) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("good")) check->m_is_good = it->second.get_value(); - if (key == std::string("in_pool")) check->m_in_tx_pool = it->second.get_value(); - else if (key == std::string("confirmations")) check->m_num_confirmations = it->second.get_value(); - else if (key == std::string("received")) check->m_received_amount = it->second.get_value(); - } - - if (!bool_equals_2(true, check->m_is_good)) { - // normalize invalid tx proof - check->m_in_tx_pool = boost::none; - check->m_num_confirmations = boost::none; - check->m_received_amount = boost::none; - } -} - -void PyMoneroMessageSignatureResult::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr result) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("good")) result->m_is_good = it->second.get_value(); - else if (key == std::string("old")) result->m_is_old = it->second.get_value(); - else if (key == std::string("signature_type")) { - std::string sig_type = it->second.data(); - if (sig_type == std::string("view")) { - result->m_signature_type = monero::monero_message_signature_type::SIGN_WITH_VIEW_KEY; - } - else { - result->m_signature_type = monero::monero_message_signature_type::SIGN_WITH_SPEND_KEY; - } - } - else if (key == std::string("version")) result->m_version = it->second.get_value(); - } -} - -// ------------------------------ Extended Data Model --------------------------------- - -bool monero_tx_height_comparator::operator()(const std::shared_ptr& tx1, const std::shared_ptr& tx2) const { - auto h1 = tx1->get_height(); - auto h2 = tx2->get_height(); - - if (h1 == boost::none && h2 == boost::none) { - // both unconfirmed - return false; - } - else if (h1 == boost::none) { - // tx1 is unconfirmed - return false; - } - else if (h2 == boost::none) { - // tx2 is unconfirmed - return true; - } - - if (*h1 != *h2) { - return *h1 < *h2; - } - - // txs are in the same block so retain their original order - const auto& txs = tx1->m_block.get()->m_txs; - auto it1 = std::find(txs.begin(), txs.end(), tx1); - auto it2 = std::find(txs.begin(), txs.end(), tx2); - - return std::distance(txs.begin(), it1) < std::distance(txs.begin(), it2); -} - -bool monero_incoming_transfer_comparator::operator()(const std::shared_ptr& t1, const std::shared_ptr& t2) const { - return (*this)(*t1, *t2); -} - -bool monero_incoming_transfer_comparator::operator()(const monero::monero_incoming_transfer& t1, const monero::monero_incoming_transfer& t2) const { - monero_tx_height_comparator tx_comp; - - // compare by height - if (tx_comp(t1.m_tx, t2.m_tx)) return true; - if (tx_comp(t2.m_tx, t1.m_tx)) return false; - - // compare by account and subaddress index - if (t1.m_account_index.value() != t2.m_account_index.value()) { - return t1.m_account_index.value() < t2.m_account_index.value(); - } - - return t1.m_subaddress_index.value() < t2.m_subaddress_index.value(); -} - -bool monero_output_comparator::operator()(const monero::monero_output_wallet& o1, const monero::monero_output_wallet& o2) const { - monero_tx_height_comparator tx_comp; - - if (tx_comp(o1.m_tx, o2.m_tx)) return true; - if (tx_comp(o2.m_tx, o1.m_tx)) return false; - - if (o1.m_account_index.value() != o2.m_account_index.value()) { - return o1.m_account_index.value() < o2.m_account_index.value(); - } - - if (o1.m_subaddress_index.value() != o2.m_subaddress_index.value()) { - return o1.m_subaddress_index.value() < o2.m_subaddress_index.value(); - } - - if (o1.m_index.value() != o2.m_index.value()) { - return o1.m_index.value() < o2.m_index.value(); - } - - return o1.m_key_image.get()->m_hex.value() < o2.m_key_image.get()->m_hex.value(); -} - -// --------------------------- MONERO DECODED ADDRESS --------------------------- - -monero_decoded_address::monero_decoded_address(const std::string& address, monero_address_type address_type, monero::monero_network_type network_type): - m_address(address), - m_address_type(address_type), - m_network_type(network_type) { -} - -rapidjson::Value monero_decoded_address::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - monero_utils::add_json_member("address", m_address, allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - monero_utils::add_json_member("addressType", (uint8_t)m_address_type, allocator, root, value_num); - monero_utils::add_json_member("networkType", (uint8_t)m_network_type, allocator, root, value_num); - - // return root - return root; -} - -// --------------------------- MONERO ACCOUNT TAG --------------------------- - -void monero_account_tag::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& account_tag) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("tag")) account_tag->m_tag = it->second.data(); - else if (key == std::string("label") && !it->second.data().empty()) account_tag->m_label = it->second.data(); - } -} - -void monero_account_tag::from_property_tree(const boost::property_tree::ptree& node, std::vector>& account_tags) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("account_tags")) { - auto account_tags_node = it->second; - - for (auto it2 = account_tags_node.begin(); it2 != account_tags_node.end(); ++it2) { - auto account_tag = std::make_shared(); - from_property_tree(it2->second, account_tag); - account_tags.push_back(account_tag); - } - } - } -} - -rapidjson::Value monero_account_tag::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_tag != boost::none) monero_utils::add_json_member("tag", m_tag.get(), allocator, root, value_str); - if (m_label != boost::none) monero_utils::add_json_member("label", m_label.get(), allocator, root, value_str); - if (!m_account_indices.empty()) root.AddMember("accountIndices", monero_utils::to_rapidjson_val(allocator, m_account_indices), allocator); - - // return root - return root; -} - -/** - * ---------------- DUPLICATED MONERO-CPP WALLET FULL CODE --------------------- - */ - -bool bool_equals_2(bool val, const boost::optional& opt_val) { - return opt_val == boost::none ? false : val == *opt_val; -} - -/** - * Returns true iff tx1's height is known to be less than tx2's height for sorting. - */ -bool tx_height_less_than(const std::shared_ptr& tx1, const std::shared_ptr& tx2) { - if (tx1->m_block != boost::none && tx2->m_block != boost::none) return tx1->get_height() < tx2->get_height(); - else if (tx1->m_block == boost::none) return false; - else return true; -} - -/** - * Returns true iff transfer1 is ordered before transfer2 by ascending account and subaddress indices. - */ -bool incoming_transfer_before(const std::shared_ptr& transfer1, const std::shared_ptr& transfer2) { - - // compare by height - if (tx_height_less_than(transfer1->m_tx, transfer2->m_tx)) return true; - - // compare by account and subaddress index - if (transfer1->m_account_index.get() < transfer2->m_account_index.get()) return true; - else if (transfer1->m_account_index.get() == transfer2->m_account_index.get()) return transfer1->m_subaddress_index.get() < transfer2->m_subaddress_index.get(); - else return false; -} - -/** - * Returns true iff wallet vout1 is ordered before vout2 by ascending account and subaddress indices then index. - */ -bool vout_before(const std::shared_ptr& o1, const std::shared_ptr& o2) { - if (o1 == o2) return false; // ignore equal references - std::shared_ptr ow1 = std::static_pointer_cast(o1); - std::shared_ptr ow2 = std::static_pointer_cast(o2); - - // compare by height - if (tx_height_less_than(ow1->m_tx, ow2->m_tx)) return true; - - // compare by account index, subaddress index, output index, then key image hex - if (ow1->m_account_index.get() < ow2->m_account_index.get()) return true; - if (ow1->m_account_index.get() == ow2->m_account_index.get()) { - if (ow1->m_subaddress_index.get() < ow2->m_subaddress_index.get()) return true; - if (ow1->m_subaddress_index.get() == ow2->m_subaddress_index.get()) { - if (ow1->m_index.get() < ow2->m_index.get()) return true; - if (ow1->m_index.get() == ow2->m_index.get()) throw std::runtime_error("Should never sort outputs with duplicate indices"); - } - } - return false; -} diff --git a/src/cpp/wallet/py_monero_wallet_model.h b/src/cpp/wallet/py_monero_wallet_model.h deleted file mode 100644 index 150389f..0000000 --- a/src/cpp/wallet/py_monero_wallet_model.h +++ /dev/null @@ -1,278 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ -#pragma once - -#include "daemon/py_monero_daemon_model.h" -#include "wallet/monero_wallet_model.h" - -// ------------------------------ Custom Data Model --------------------------------- - -struct PyMoneroTxQuery : public monero::monero_tx_query { -public: - - static std::shared_ptr decontextualize(const std::shared_ptr &query); -}; - -struct PyMoneroOutputQuery : public monero::monero_output_query { -public: - - static bool is_contextual(const monero::monero_output_query &query); -}; - -struct PyMoneroTransferQuery : public monero::monero_transfer_query { -public: - - static bool is_contextual(const monero::monero_transfer_query &query); -}; - -struct PyMoneroTxWallet : public monero::monero_tx_wallet { -public: - - static bool decode_rpc_type(const std::string &rpc_type, const std::shared_ptr &tx); - static void init_sent(const monero::monero_tx_config &config, std::shared_ptr &tx, bool copy_destinations); - static void from_property_tree_with_transfer(const boost::property_tree::ptree& node, const std::shared_ptr& tx, boost::optional &is_outgoing, const monero_tx_config &config); - static void from_property_tree_with_transfer(const boost::property_tree::ptree& node, const std::shared_ptr& tx, boost::optional &is_outgoing); - static void from_property_tree_with_transfer(const boost::property_tree::ptree& node, const std::shared_ptr& tx); - static void from_property_tree_with_transfer_and_merge(const boost::property_tree::ptree& node, std::unordered_map>& tx_map, std::unordered_map>& block_map); - static void from_property_tree_with_output(const boost::property_tree::ptree& node, const std::shared_ptr& tx); - static void from_property_tree_with_output_and_merge(const boost::property_tree::ptree& node, std::unordered_map>& tx_map, std::unordered_map>& block_map); - static void merge_tx(const std::shared_ptr& tx, std::unordered_map>& tx_map, std::unordered_map>& block_map); -}; - -struct PyMoneroTxSet : public monero::monero_tx_set { -public: - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& set); - static void from_tx(const boost::property_tree::ptree& node, const std::shared_ptr& set, const std::shared_ptr &tx, bool is_outgoing, const monero_tx_config &config); - static void from_sent_txs(const boost::property_tree::ptree& node, const std::shared_ptr& set); - static void from_sent_txs(const boost::property_tree::ptree& node, const std::shared_ptr& set, std::vector> &txs, const boost::optional &conf); - static void from_describe_transfer(const boost::property_tree::ptree& node, const std::shared_ptr& set); -}; - -struct PyMoneroKeyImage : public monero::monero_key_image { -public: - - PyMoneroKeyImage(const monero::monero_key_image &key_image); - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& key_image); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector>& key_images); -}; - -struct PyMoneroKeyImageImportResult : public monero::monero_key_image_import_result { -public: - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& result); -}; - -struct PyMoneroMultisigInfo : public monero::monero_multisig_info { -public: - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& info); -}; - -struct PyMoneroMultisigInitResult : public monero::monero_multisig_init_result { -public: - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& info); -}; - -struct PyMoneroMultisigSignResult : public monero::monero_multisig_sign_result { -public: - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& res); -}; - -struct PyMoneroTransfer : public monero_transfer { -public: - using monero_transfer::monero_transfer; - - boost::optional is_incoming() const override { - PYBIND11_OVERRIDE_PURE(boost::optional, monero_transfer, is_incoming); - } -}; - -struct PyMoneroSubaddress : public monero::monero_subaddress { -public: - - static void from_rpc_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& subaddress); - static void from_rpc_property_tree(const boost::property_tree::ptree& node, std::vector>& subaddresses); - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& subaddress); -}; - -struct PyMoneroIntegratedAddress : public monero::monero_integrated_address { -public: - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& subaddress); -}; - -struct PyMoneroAccount : public monero::monero_account { -public: - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& account); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector>& accounts); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector& accounts); -}; - -struct PyMoneroAddressBookEntry : public monero::monero_address_book_entry { -public: - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& entry); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector>& entries); -}; - -struct PyMoneroCheckReserve : public monero::monero_check_reserve { -public: - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& check); -}; - -struct PyMoneroCheckTxProof : public monero::monero_check_tx { -public: - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& check); -}; - -struct PyMoneroMessageSignatureResult : public monero::monero_message_signature_result { -public: - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr result); -}; - -// ------------------------------ Extended Data Model --------------------------------- - -enum monero_address_type : uint8_t { - PRIMARY_ADDRESS = 0, - INTEGRATED_ADDRESS, - SUBADDRESS -}; - -// Compares two transactions by their height -struct monero_tx_height_comparator { - bool operator()(const std::shared_ptr& tx1, const std::shared_ptr& tx2) const; -}; - -// Compares two transfers by ascending account and subaddress indices -struct monero_incoming_transfer_comparator { - bool operator()(const std::shared_ptr& t1, const std::shared_ptr& t2) const; - bool operator()(const monero::monero_incoming_transfer& t1, const monero::monero_incoming_transfer& t2) const; -}; - -// Compares two outputs by ascending account and subaddress indices -struct monero_output_comparator { - bool operator()(const monero::monero_output_wallet& o1, const monero::monero_output_wallet& o2) const; -}; - -struct monero_decoded_address : public monero::serializable_struct { -public: - std::string m_address; - monero_address_type m_address_type; - monero::monero_network_type m_network_type; - - monero_decoded_address(const std::string& address, monero_address_type address_type, monero::monero_network_type network_type); - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_account_tag : public monero::serializable_struct { -public: - boost::optional m_tag; - boost::optional m_label; - std::vector m_account_indices; - - monero_account_tag() { } - monero_account_tag(const std::string& tag, const std::string& label): m_tag(tag), m_label(label) { } - monero_account_tag(const std::string& tag, const std::string& label, const std::vector& account_indices): m_tag(tag), m_label(label), m_account_indices(account_indices) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& account_tag); - static void from_property_tree(const boost::property_tree::ptree& node, std::vector>& account_tags); -}; - -struct monero_wallet_balance { -public: - uint64_t m_balance; - uint64_t m_unlocked_balance; - - monero_wallet_balance(uint64_t balance = 0, uint64_t unlocked_balance = 0): m_balance(balance), m_unlocked_balance(unlocked_balance) { } -}; - -// ------------------------------ Utilities --------------------------------- - -// TODO expose bool_equals_2 from monero-cpp -bool bool_equals_2(bool val, const boost::optional& opt_val); -bool tx_height_less_than(const std::shared_ptr& tx1, const std::shared_ptr& tx2); -bool incoming_transfer_before(const std::shared_ptr& transfer1, const std::shared_ptr& transfer2); -bool vout_before(const std::shared_ptr& o1, const std::shared_ptr& o2); - -template -void set_query(std::shared_ptr& self, boost::optional>& field, const boost::optional>& val) { - - const auto old = field; - field = val; - - // set new reference - if (field != boost::none) { - field.get()->m_tx_query = self; - } - - // cleanup old - if (old != boost::none) { - if (val != boost::none && val.get() == old.get()) { - return; - } - old.get()->m_tx_query = boost::none; - } -} diff --git a/src/cpp/wallet/py_monero_wallet_rpc.cpp b/src/cpp/wallet/py_monero_wallet_rpc.cpp deleted file mode 100644 index a8ecb1b..0000000 --- a/src/cpp/wallet/py_monero_wallet_rpc.cpp +++ /dev/null @@ -1,2183 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ -#include "py_monero_wallet_rpc.h" -#include "py_monero_wallet_rpc_model.h" -#include "utils/monero_utils.h" - - -/** - * Polls wallet and sends notifications in order to notify external wallet listeners. - */ -class monero_wallet_poller: public thread_poller { -public: - - explicit monero_wallet_poller(monero_wallet_rpc *wallet): m_num_polling(0) { - m_wallet = wallet; - init_common("monero_wallet_rpc"); - }; - - void poll() override { - // skip if next poll is queued - if (m_num_polling > 1) return; - m_num_polling++; - - // synchronize polls - boost::lock_guard lock(m_mutex); - try { - // skip if wallet is closed - if (m_wallet->is_closed()) { - m_num_polling--; - return; - } - - // take initial snapshot - if (m_prev_balances == boost::none) { - m_prev_height = m_wallet->get_height(); - monero::monero_tx_query tx_query; - tx_query.m_is_locked = true; - m_prev_locked_txs = m_wallet->get_txs(tx_query); - m_prev_balances = m_wallet->get_balances(boost::none, boost::none); - m_num_polling--; - return; - } - - // announce height changes - uint64_t height = m_wallet->get_height(); - if (m_prev_height.get() != height) { - for (uint64_t i = m_prev_height.get(); i < height; i++) { - on_new_block(i); - } - - m_prev_height = height; - } - - // get locked txs for comparison to previous - uint64_t min_height = 0; // only monitor recent txs - if (height > 70) min_height = height - 70; - monero::monero_tx_query tx_query; - tx_query.m_is_locked = true; - tx_query.m_min_height = min_height; - tx_query.m_include_outputs = true; - - auto locked_txs = m_wallet->get_txs(tx_query); - - // collect hashes of txs no longer locked - std::vector no_longer_locked_hashes; - for (const auto &prev_locked_tx : m_prev_locked_txs) { - if (get_tx(locked_txs, prev_locked_tx->m_hash.get()) == nullptr) { - no_longer_locked_hashes.push_back(prev_locked_tx->m_hash.get()); - } - } - - // save locked txs for next comparison - m_prev_locked_txs = locked_txs; - std::vector> unlocked_txs; - - if (!no_longer_locked_hashes.empty()) { - // fetch txs which are no longer locked - monero_tx_query tx_query; - tx_query.m_is_locked = false; - tx_query.m_min_height = min_height; - tx_query.m_hashes = no_longer_locked_hashes; - tx_query.m_include_outputs = true; - unlocked_txs = m_wallet->get_txs(tx_query); - } - - // announce new unconfirmed and confirmed txs - for (const auto &locked_tx : locked_txs) { - bool announced = false; - const std::string& tx_hash = locked_tx->m_hash.get(); - if (bool_equals_2(true, locked_tx->m_is_confirmed)) { - if (std::find(m_prev_confirmed_notifications.begin(), m_prev_confirmed_notifications.end(), tx_hash) == m_prev_confirmed_notifications.end()) { - m_prev_confirmed_notifications.push_back(tx_hash); - announced = true; - } - } - else { - if (std::find(m_prev_unconfirmed_notifications.begin(), m_prev_unconfirmed_notifications.end(), tx_hash) == m_prev_unconfirmed_notifications.end()) { - m_prev_unconfirmed_notifications.push_back(tx_hash); - announced = true; - } - } - - if (announced) notify_outputs(locked_tx); - } - - // announce new unlocked outputs - for (const auto &unlocked_tx : unlocked_txs) { - std::string tx_hash = unlocked_tx->m_hash.get(); - // stop tracking tx notifications - m_prev_confirmed_notifications.erase(std::remove_if(m_prev_confirmed_notifications.begin(), m_prev_confirmed_notifications.end(), [&tx_hash](const std::string& iter){ return iter == tx_hash; }), m_prev_confirmed_notifications.end()); - m_prev_unconfirmed_notifications.erase(std::remove_if(m_prev_unconfirmed_notifications.begin(), m_prev_unconfirmed_notifications.end(), [&tx_hash](const std::string& iter){ return iter == tx_hash; }), m_prev_unconfirmed_notifications.end()); - notify_outputs(unlocked_tx); - } - - // announce balance changes - check_for_changed_balances(); - - m_num_polling--; - } - catch (const std::exception &e) { - m_num_polling--; - if (m_is_polling) { - MERROR("Failed to background poll wallet " << m_wallet->get_path() << ": " << e.what()); - } - } - } - -private: - monero_wallet_rpc *m_wallet; - std::atomic m_num_polling; - - std::vector m_prev_unconfirmed_notifications; - std::vector m_prev_confirmed_notifications; - boost::optional> m_prev_balances; - boost::optional m_prev_height; - std::vector> m_prev_locked_txs; - - std::shared_ptr get_tx(const std::vector>& txs, const std::string& tx_hash){ - for (const auto& tx : txs) { - if (tx->m_hash == tx_hash) return tx; - } - - return nullptr; - } - - void on_new_block(uint64_t height) { - m_wallet->announce_new_block(height); - } - - void notify_outputs(const std::shared_ptr &tx) { - // notify spent outputs - // TODO (monero-project): monero-wallet-rpc does not allow scrape of tx inputs so providing one input with outgoing amount - if (tx->m_outgoing_transfer != boost::none) { - auto outgoing_transfer = tx->m_outgoing_transfer.get(); - if (!tx->m_inputs.empty()) throw std::runtime_error("Tx inputs should be empty"); - auto output = std::make_shared(); - output->m_amount = outgoing_transfer->m_amount.get() + tx->m_fee.get(); - output->m_account_index = outgoing_transfer->m_account_index; - output->m_tx = tx; - // initialize if transfer sourced from single subaddress - if (outgoing_transfer->m_subaddress_indices.size() == 1) { - output->m_subaddress_index = outgoing_transfer->m_subaddress_indices[0]; - } - tx->m_inputs.clear(); - tx->m_inputs.push_back(output); - m_wallet->announce_output_spent(output); - } - - // notify received outputs - if (tx->m_incoming_transfers.size() > 0) { - if (!tx->m_outputs.empty()) { - // TODO (monero-project): outputs only returned for confirmed txs - for(const auto &output : tx->get_outputs_wallet()) { - m_wallet->announce_output_received(output); - } - } - else { - // TODO (monero-project): monero-wallet-rpc does not allow scrape of unconfirmed received outputs so using incoming transfer values - tx->m_outputs.clear(); - for (const auto &transfer : tx->m_incoming_transfers) { - auto output = std::make_shared(); - output->m_account_index = transfer->m_account_index; - output->m_subaddress_index = transfer->m_subaddress_index; - output->m_amount = transfer->m_amount.get(); - output->m_tx = tx; - tx->m_outputs.push_back(output); - } - - for (const auto &output : tx->get_outputs_wallet()) { - m_wallet->announce_output_received(output); - } - } - } - } - - bool check_for_changed_balances() { - auto balances = m_wallet->get_balances(boost::none, boost::none); - if (balances->m_balance != m_prev_balances.get()->m_balance || balances->m_unlocked_balance != m_prev_balances.get()->m_unlocked_balance) { - m_prev_balances = balances; - m_wallet->announce_balances_changed(balances->m_balance, balances->m_unlocked_balance); - return true; - } - return false; - } -}; - -monero_wallet_rpc::monero_wallet_rpc(const std::shared_ptr& rpc_connection): m_rpc(rpc_connection) { - if (!m_rpc->is_online() && m_rpc->m_uri != boost::none) m_rpc->check_connection(); -} - -monero_wallet_rpc::monero_wallet_rpc(const std::string& uri, const std::string& username, const std::string& password, const std::string& proxy_uri, const std::string& zmq_uri, uint64_t timeout): m_rpc(std::make_shared(uri, username, password, proxy_uri, zmq_uri, 0, timeout)) { - if (m_rpc->m_uri != boost::none) m_rpc->check_connection(); -} - -monero_wallet_rpc::~monero_wallet_rpc() { - MTRACE("~monero_wallet_rpc()"); - clear(); -} - -void monero_wallet_rpc::add_listener(monero_wallet_listener& listener) { - PyMoneroWallet::add_listener(listener); - refresh_listening(); -} - -void monero_wallet_rpc::remove_listener(monero_wallet_listener& listener) { - PyMoneroWallet::remove_listener(listener); - refresh_listening(); -} - -monero_wallet_rpc* monero_wallet_rpc::open_wallet(const std::shared_ptr &config) { - MTRACE("monero_wallet_rpc::open_wallet(...)"); - if (config == nullptr) throw std::runtime_error("Must provide configuration of wallet to open"); - if (config->m_path == boost::none || config->m_path->empty()) throw std::runtime_error("Filename is not initialized"); - std::string path = config->m_path.get(); - std::string password = std::string(""); - if (config->m_password != boost::none) password = config->m_password.get(); - - auto params = std::make_shared(path, password); - m_rpc->send_json_request("open_wallet", params); - clear(); - - if (config->m_server != boost::none) { - set_daemon_connection(config->m_server); - } - - return this; -} - -monero_wallet_rpc* monero_wallet_rpc::open_wallet(const std::string& name, const std::string& password) { - MTRACE("monero_wallet_rpc::open_wallet(" << name << ", ***"); - auto config = std::make_shared(); - config->m_path = name; - config->m_password = password; - return open_wallet(config); -} - -void handle_create_wallet_error(const monero_rpc_error& ex, const std::string& path) { - std::string msg = ex.what(); - std::transform(msg.begin(), msg.end(), msg.begin(), [](unsigned char c){ return std::tolower(c); }); - if (msg.find("already exists") != std::string::npos) throw monero_rpc_error(ex.code, std::string("Wallet already exists: ") + path); - if (msg == std::string("electrum-style word list failed verification")) throw monero_rpc_error(ex.code, std::string("Invalid mnemonic")); - throw ex; -} - -monero_wallet_rpc* monero_wallet_rpc::create_wallet(const std::shared_ptr &config) { - MTRACE("monero_wallet_rpc::create_wallet(...)"); - - if (config == nullptr) throw std::runtime_error("Must specify config to create wallet"); - if (config->m_network_type != boost::none) throw std::runtime_error("Cannot specify network type when creating RPC wallet"); - if (config->m_seed != boost::none && (config->m_primary_address != boost::none || config->m_private_view_key != boost::none || config->m_private_spend_key != boost::none)) { - throw std::runtime_error("Wallet can be initialized with a seed or keys but not both"); - } - if (config->m_account_lookahead != boost::none || config->m_subaddress_lookahead != boost::none) throw std::runtime_error("monero-wallet-rpc does not support creating wallets with subaddress lookahead over rpc"); - - if (config->m_seed != boost::none) create_wallet_from_seed(config); - else if (config->m_private_spend_key != boost::none || config->m_primary_address != boost::none) create_wallet_from_keys(config); - else create_wallet_random(config); - - if (config->m_server != boost::none) { - set_daemon_connection(config->m_server); - } - - return this; -} - -std::vector monero_wallet_rpc::get_seed_languages() const { - auto node = m_rpc->send_json_request("get_languages"); - std::vector languages; - - for (auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("languages")) { - auto languages_node = it->second; - - for (auto it2 = languages_node.begin(); it2 != languages_node.end(); ++it2) { - languages.push_back(it2->second.data()); - } - } - } - - return languages; -} - -void monero_wallet_rpc::stop() { - MTRACE("monero_wallet_rpc::stop()"); - m_rpc->send_json_request("stop_wallet"); -} - -bool monero_wallet_rpc::is_view_only() const { - try { - std::string key = "mnemonic"; - query_key(key); - return false; - } - catch (const monero_rpc_error& e) { - if (e.code == -29) return true; - if (e.code == -1) return false; - throw; - } -} - -boost::optional monero_wallet_rpc::get_daemon_connection() const { - MTRACE("monero_wallet_rpc::get_daemon_connection()"); - if (m_daemon_connection == nullptr) return boost::none; - return boost::optional(*m_daemon_connection); -} - -void monero_wallet_rpc::set_daemon_connection(const std::string& uri, const std::string& username, const std::string& password, const std::string& proxy_uri) { - MTRACE("monero_wallet_rpc::set_daemon_connection(" << uri << ", " << username << ", " << "***" << ", " << proxy_uri << ")"); - - if (uri.empty()) { - set_daemon_connection(boost::none); - return; - } - boost::optional rpc = PyMoneroRpcConnection(uri, username, password, proxy_uri); - set_daemon_connection(rpc); -} - -void monero_wallet_rpc::set_daemon_connection(const boost::optional& connection, bool is_trusted, const boost::optional& ssl_options) { - auto params = std::make_shared(); - if (connection == boost::none) { - params->m_address = "placeholder"; - params->m_username = ""; - params->m_password = ""; - } - else { - params->m_address = connection->m_uri; - params->m_username = connection->m_username; - params->m_password = connection->m_password; - } - - params->m_trusted = is_trusted; - params->m_ssl_support = "autodetect"; - params->m_ssl_options = ssl_options; - - m_rpc->send_json_request("set_daemon", params); - - if (connection == boost::none || connection->m_uri == boost::none || connection->m_uri->empty()) { - m_daemon_connection = nullptr; - } - else { - m_daemon_connection = std::make_shared(connection.get()); - } -} - -void monero_wallet_rpc::set_daemon_connection(const boost::optional& connection) { - set_daemon_connection(connection, false, boost::none); -} - -bool monero_wallet_rpc::is_connected_to_daemon() const { - try { - check_reserve_proof(get_primary_address(), "", ""); - return false; - } - catch (const monero_rpc_error& e) { - if (e.code == -13) throw; // no wallet file - return e.message.find("Failed to connect to daemon") == std::string::npos; - } -} - -monero::monero_version monero_wallet_rpc::get_version() const { - auto res = m_rpc->send_json_request("get_version"); - std::shared_ptr info = std::make_shared(); - PyMoneroVersion::from_property_tree(res, info); - return *info; -} - -std::string monero_wallet_rpc::get_path() const { - return m_path; -} - -std::string monero_wallet_rpc::get_seed() const { - std::string key = "mnemonic"; - return query_key(key); -} - -std::string monero_wallet_rpc::get_seed_language() const { - throw std::runtime_error("MoneroWalletRpc::get_seed_language() not supported"); -} - -std::string monero_wallet_rpc::get_public_view_key() const { - MTRACE("monero_wallet_rpc::get_public_view_key()"); - std::string key = "public_view_key"; - return query_key(key); -} - -std::string monero_wallet_rpc::get_private_view_key() const { - MTRACE("monero_wallet_rpc::get_private_view_key()"); - std::string key = "view_key"; - return query_key(key); -} - -std::string monero_wallet_rpc::get_public_spend_key() const { - MTRACE("monero_wallet_rpc::get_public_spend_key()"); - std::string key = "public_spend_key"; - return query_key(key); -} - -std::string monero_wallet_rpc::get_private_spend_key() const { - MTRACE("monero_wallet_rpc::get_private_spend_key()"); - std::string key = "spend_key"; - return query_key(key); -} - -std::string monero_wallet_rpc::get_address(const uint32_t account_idx, const uint32_t subaddress_idx) const { - auto it = m_address_cache.find(account_idx); - if (it == m_address_cache.end()) { - // cache's all addresses at this account - std::vector empty_indices; - get_subaddresses(account_idx, empty_indices, true); - // uses cache - return get_address(account_idx, subaddress_idx); - } - - auto subaddress_map = it->second; - auto it2 = subaddress_map.find(subaddress_idx); - - if (it2 == subaddress_map.end()) { - // cache's all addresses at this account - std::vector empty_indices; - get_subaddresses(account_idx, empty_indices, true); - auto it3 = m_address_cache.find(account_idx); - auto it4 = it3->second.find(subaddress_idx); - if (it4 == it3->second.end()) return std::string(""); - return it4->second; - } - - return it2->second; -} - -monero_subaddress monero_wallet_rpc::get_address_index(const std::string& address) const { - MTRACE("monero_wallet_rpc:.get_address_index(" << address << ")"); - - auto params = std::make_shared(address); - auto res = m_rpc->send_json_request("get_address_index", params); - auto tmplt = std::make_shared(); - PyMoneroSubaddress::from_property_tree(res, tmplt); - return *tmplt; -} - -monero_integrated_address monero_wallet_rpc::get_integrated_address(const std::string& standard_address, const std::string& payment_id) const { - MTRACE("monero_wallet_rpc::get_integrated_address(" << standard_address << ", " << payment_id << ")"); - - auto params = std::make_shared(standard_address, payment_id); - auto res = m_rpc->send_json_request("make_integrated_address", params); - auto tmplt = std::make_shared(); - PyMoneroIntegratedAddress::from_property_tree(res, tmplt); - return decode_integrated_address(tmplt->m_integrated_address); -} - -monero_integrated_address monero_wallet_rpc::decode_integrated_address(const std::string& integrated_address) const { - MTRACE("monero_wallet_rpc::decode_integrated_address(" << integrated_address << ")"); - - auto params = std::make_shared(integrated_address); - auto res = m_rpc->send_json_request("split_integrated_address", params); - auto tmplt = std::make_shared(); - PyMoneroIntegratedAddress::from_property_tree(res, tmplt); - tmplt->m_integrated_address = integrated_address; - return *tmplt; -} - -uint64_t monero_wallet_rpc::get_height() const { - auto res = m_rpc->send_json_request("get_height"); - return monero_wallet_get_height_response::from_property_tree(res); -} - -uint64_t monero_wallet_rpc::get_daemon_height() const { - throw std::runtime_error("monero-wallet-rpc does not support getting the chain height"); -} - -uint64_t monero_wallet_rpc::get_height_by_date(uint16_t year, uint8_t month, uint8_t day) const { - throw std::runtime_error("monero-wallet-rpc does not support getting a height by date"); -} - -monero_sync_result monero_wallet_rpc::refresh(const std::shared_ptr& params) { - boost::lock_guard lock(m_sync_mutex); - try { - auto node = m_rpc->send_json_request("refresh", params); - poll(); - monero_sync_result sync_result(0, false); - - for (auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("blocks_fetched")) sync_result.m_num_blocks_fetched = it->second.get_value(); - else if (key == std::string("received_money")) sync_result.m_received_money = it->second.get_value(); - } - - return sync_result; - } catch (const monero_rpc_error& ex) { - if (ex.message == std::string("no connection to daemon")) throw monero_error("Wallet is not connected to daemon"); - throw; - } -} - -monero_sync_result monero_wallet_rpc::sync() { - MTRACE("monero_wallet_rpc::sync()"); - auto params = std::make_shared(); - return refresh(params); -} - -monero_sync_result monero_wallet_rpc::sync(monero_wallet_listener& listener) { - throw std::runtime_error("Monero Wallet RPC does not support reporting sync progress"); -} - -monero_sync_result monero_wallet_rpc::sync(uint64_t start_height, monero_wallet_listener& listener) { - throw std::runtime_error("Monero Wallet RPC does not support reporting sync progress"); -} - -monero_sync_result monero_wallet_rpc::sync(uint64_t start_height) { - MTRACE("monero_wallet_rpc::sync(" << start_height << ")"); - auto params = std::make_shared(start_height); - return refresh(params); -} - -void monero_wallet_rpc::start_syncing(uint64_t sync_period_in_ms) { - // convert ms to seconds for rpc parameter - uint64_t sync_period_in_seconds = sync_period_in_ms / 1000; - - // send rpc request - auto params = std::make_shared(true, sync_period_in_seconds); - m_rpc->send_json_request("auto_refresh", params); - - // update sync period for poller - m_sync_period_in_ms = sync_period_in_ms; - if (m_poller != nullptr) m_poller->set_period_in_ms(m_sync_period_in_ms.get()); - - // poll if listening - poll(); -} - -void monero_wallet_rpc::stop_syncing() { - auto params = std::make_shared(false); - m_rpc->send_json_request("auto_refresh", params); -} - -void monero_wallet_rpc::scan_txs(const std::vector& tx_hashes) { - MTRACE("monero_wallet_rpc::scan_txs()"); - if (tx_hashes.empty()) throw std::runtime_error("No tx hashes given to scan"); - auto params = std::make_shared(tx_hashes); - m_rpc->send_json_request("scan_tx", params); - poll(); -} - -void monero_wallet_rpc::rescan_spent() { - MTRACE("monero_wallet_rpc::rescan_spent()"); - m_rpc->send_json_request("rescan_spent"); -} - -void monero_wallet_rpc::rescan_blockchain() { - MTRACE("monero_wallet_rpc::rescan_blockchain()"); - m_rpc->send_json_request("rescan_blockchain"); -} - -uint64_t monero_wallet_rpc::get_balance() const { - auto wallet_balance = get_balances(boost::none, boost::none); - return wallet_balance->m_balance; -} - -uint64_t monero_wallet_rpc::get_balance(uint32_t account_index) const { - auto wallet_balance = get_balances(account_index, boost::none); - return wallet_balance->m_balance; -} - -uint64_t monero_wallet_rpc::get_balance(uint32_t account_idx, uint32_t subaddress_idx) const { - auto wallet_balance = get_balances(account_idx, subaddress_idx); - return wallet_balance->m_balance; -} - -uint64_t monero_wallet_rpc::get_unlocked_balance() const { - auto wallet_balance = get_balances(boost::none, boost::none); - return wallet_balance->m_unlocked_balance; -} - -uint64_t monero_wallet_rpc::get_unlocked_balance(uint32_t account_index) const { - auto wallet_balance = get_balances(account_index, boost::none); - return wallet_balance->m_unlocked_balance; -} - -uint64_t monero_wallet_rpc::get_unlocked_balance(uint32_t account_idx, uint32_t subaddress_idx) const { - auto wallet_balance = get_balances(account_idx, subaddress_idx); - return wallet_balance->m_unlocked_balance; -} - -monero_account monero_wallet_rpc::get_account(const uint32_t account_idx, bool include_subaddresses) const { - return get_account(account_idx, include_subaddresses, false); -} - -monero_account monero_wallet_rpc::get_account(const uint32_t account_idx, bool include_subaddresses, bool skip_balances) const { - MTRACE("monero_wallet_rpc::get_account(" << account_idx << ", " << include_subaddresses << ")"); - - for(auto& account : monero::monero_wallet::get_accounts()) { - if (account.m_index.get() == account_idx) { - if (include_subaddresses) { - std::vector empty_indices; - account.m_subaddresses = get_subaddresses(account_idx, empty_indices, skip_balances); - } - return account; - } - } - throw std::runtime_error("Account with index " + std::to_string(account_idx) + " does not exist"); -} - -std::vector monero_wallet_rpc::get_accounts(bool include_subaddresses, const std::string& tag) const { - return get_accounts(include_subaddresses, tag, false); -} - -std::vector monero_wallet_rpc::get_accounts(bool include_subaddresses, const std::string& tag, bool skip_balances) const { - MTRACE("monero_wallet_rpc::get_accounts(" << include_subaddresses << ", " << tag << ")"); - - auto params = std::make_shared(tag); - auto node = m_rpc->send_json_request("get_accounts", params); - std::vector accounts; - PyMoneroAccount::from_property_tree(node, accounts); - if (include_subaddresses) { - - for (auto &account : accounts) { - std::vector empty_indices; - account.m_subaddresses = get_subaddresses(account.m_index.get(), empty_indices, true); - - if (!skip_balances) { - for (auto &subaddress : account.m_subaddresses) { - subaddress.m_balance = 0; - subaddress.m_unlocked_balance = 0; - subaddress.m_num_unspent_outputs = 0; - subaddress.m_num_blocks_to_unlock = 0; - } - } - } - - if (!skip_balances) { - auto params2 = std::make_shared(true); - auto node2 = m_rpc->send_json_request("get_balance", params2); - auto bal_res = std::make_shared(); - monero_get_balance_response::from_property_tree(node2, bal_res); - for (const auto &subaddress : bal_res->m_per_subaddress) { - // merge info - auto account = &accounts[subaddress->m_account_index.get()]; - if (account->m_index != subaddress->m_account_index) throw std::runtime_error("RPC accounts are out of order"); - auto tgt_subaddress = &account->m_subaddresses[subaddress->m_index.get()]; - if (tgt_subaddress->m_index != subaddress->m_index) throw std::runtime_error("RPC subaddresses are out of order"); - - if (subaddress->m_balance != boost::none) tgt_subaddress->m_balance = subaddress->m_balance; - if (subaddress->m_unlocked_balance != boost::none) tgt_subaddress->m_unlocked_balance = subaddress->m_unlocked_balance; - if (subaddress->m_num_unspent_outputs != boost::none) tgt_subaddress->m_num_unspent_outputs = subaddress->m_num_unspent_outputs; - if (subaddress->m_num_blocks_to_unlock != boost::none) tgt_subaddress->m_num_blocks_to_unlock = subaddress->m_num_blocks_to_unlock; - } - } - } - - return accounts; -} - -monero_account monero_wallet_rpc::create_account(const std::string& label) { - MTRACE("monero_wallet_rpc::create_account(" << label << ")"); - - auto params = std::make_shared(); - params->m_label = label; - auto node = m_rpc->send_json_request("create_account", params); - monero_account res; - res.m_balance = 0; - res.m_unlocked_balance = 0; - bool found_index = false; - bool address_found = false; - - for (auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("account_index")) { - found_index = true; - res.m_index = it->second.get_value(); - } - else if (key == std::string("address")) { - address_found = true; - res.m_primary_address = it->second.data(); - } - } - - if (!found_index || !address_found) throw std::runtime_error("Could not create account"); - - return res; -} - -std::vector monero_wallet_rpc::get_subaddresses(const uint32_t account_idx, const std::vector& subaddress_indices, bool skip_balances) const { - MTRACE("monero_wallet_rpc::get_subaddresses(" << account_idx << ", ...)"); - MTRACE("monero_wallet_rpc::get_subaddresses(): Subaddress indices size: " << subaddress_indices.size()); - - // fetch subaddresses - auto params = std::make_shared(account_idx, subaddress_indices); - auto node = m_rpc->send_json_request("get_address", params); - std::vector subaddresses; - std::vector> subaddresses_ptr; - PyMoneroSubaddress::from_rpc_property_tree(node, subaddresses_ptr); - - for(const auto& subaddress_ptr : subaddresses_ptr) { - subaddress_ptr->m_account_index = account_idx; - subaddresses.push_back(*subaddress_ptr); - } - - // initialize subaddresses - - // fetch and initialize subaddress balances - if (!skip_balances) { - // these fields are not initialized if subaddress is unused and therefore not returned from `get_balance` - for (auto &subaddress : subaddresses) { - subaddress.m_balance = 0; - subaddress.m_unlocked_balance = 0; - subaddress.m_num_unspent_outputs = 0; - subaddress.m_num_blocks_to_unlock = 0; - } - - // fetch and initialize balances - auto node2 = m_rpc->send_json_request("get_balance", params); - std::vector> subaddresses2; - PyMoneroSubaddress::from_rpc_property_tree(node2, subaddresses2); - - for (auto &tgt_subaddress: subaddresses) { - for (const auto &rpc_subaddress : subaddresses2) { - if (rpc_subaddress->m_index != tgt_subaddress.m_index) continue; // skip to subaddress with same index - if (rpc_subaddress->m_balance != boost::none) tgt_subaddress.m_balance = rpc_subaddress->m_balance; - if (rpc_subaddress->m_unlocked_balance != boost::none) tgt_subaddress.m_unlocked_balance = rpc_subaddress->m_unlocked_balance; - if (rpc_subaddress->m_num_unspent_outputs != boost::none) tgt_subaddress.m_num_unspent_outputs = rpc_subaddress->m_num_unspent_outputs; - if (rpc_subaddress->m_num_blocks_to_unlock != boost::none) tgt_subaddress.m_num_blocks_to_unlock = rpc_subaddress->m_num_blocks_to_unlock; - } - } - } - - // cache addresses - auto it = m_address_cache.find(account_idx); - if (it == m_address_cache.end()) { - m_address_cache[account_idx] = std::unordered_map(); - } - - for (const auto& subaddress : subaddresses) { - m_address_cache[account_idx][subaddress.m_index.get()] = subaddress.m_address.get(); - } - - // return results - return subaddresses; -} - -std::vector monero_wallet_rpc::get_subaddresses(uint32_t account_idx, const std::vector& subaddress_indices) const { - return get_subaddresses(account_idx, subaddress_indices, false); -} - -std::vector monero_wallet_rpc::get_subaddresses(const uint32_t account_idx) const { - std::vector empty_indices; - return get_subaddresses(account_idx, empty_indices); -} - -monero_subaddress monero_wallet_rpc::get_subaddress(const uint32_t account_idx, const uint32_t subaddress_idx) const { - - std::vector subaddress_indices; - subaddress_indices.push_back(subaddress_idx); - auto subaddresses = get_subaddresses(account_idx, subaddress_indices); - if (subaddresses.empty()) throw std::runtime_error("Subaddress is not initialized"); - if (subaddresses.size() != 1) throw std::runtime_error("Only 1 subaddress should be returned"); - return subaddresses[0]; -} - -monero_subaddress monero_wallet_rpc::create_subaddress(uint32_t account_idx, const std::string& label) { - MTRACE("monero_wallet_rpc::create_subaddress(" << account_idx << ", " << label << ")"); - - auto params = std::make_shared(account_idx, label); - auto node = m_rpc->send_json_request("create_address", params); - monero_subaddress sub; - sub.m_account_index = account_idx; - if (!label.empty()) sub.m_label = label; - sub.m_balance = 0; - sub.m_unlocked_balance = 0; - sub.m_num_unspent_outputs = 0; - sub.m_is_used = false; - sub.m_num_blocks_to_unlock = 0; - - for(auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("address_index")) sub.m_index = it->second.get_value(); - else if (key == std::string("address")) sub.m_address = it->second.data(); - } - - return sub; -} - -void monero_wallet_rpc::set_subaddress_label(uint32_t account_idx, uint32_t subaddress_idx, const std::string& label) { - MTRACE("monero_wallet_rpc::set_subaddress_label(" << account_idx << ", " << subaddress_idx << ", " << label << ")"); - - auto params = std::make_shared(account_idx, subaddress_idx, label); - m_rpc->send_json_request("label_address", params); -} - -std::string monero_wallet_rpc::export_outputs(bool all) const { - auto params = std::make_shared(all); - auto node = m_rpc->send_json_request("export_outputs", params); - - for (auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("outputs_data_hex")) return it->second.data(); - } - - throw std::runtime_error("Could not get outputs hex"); -} - -int monero_wallet_rpc::import_outputs(const std::string& outputs_hex) { - auto params = std::make_shared(outputs_hex); - auto node = m_rpc->send_json_request("import_outputs", params); - int num_imported = 0; - - for (auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("num_imported")) { - num_imported = it->second.get_value(); - break; - } - } - - return num_imported; -} - -std::vector> monero_wallet_rpc::export_key_images(bool all) const { - MTRACE("monero_wallet_rpc::export_key_images()"); - - auto params = std::make_shared(all); - auto node = m_rpc->send_json_request("export_key_images", params); - std::vector> key_images; - PyMoneroKeyImage::from_property_tree(node, key_images); - return key_images; -} - -std::shared_ptr monero_wallet_rpc::import_key_images(const std::vector>& key_images) { - MTRACE("monero_wallet_rpc::import_key_images()"); - - auto params = std::make_shared(key_images); - auto node = m_rpc->send_json_request("import_key_images", params); - auto import_result = std::make_shared(); - PyMoneroKeyImageImportResult::from_property_tree(node, import_result); - return import_result; -} - -void monero_wallet_rpc::freeze_output(const std::string& key_image) { - auto params = std::make_shared(key_image); - m_rpc->send_json_request("freeze", params); -} - -void monero_wallet_rpc::thaw_output(const std::string& key_image) { - auto params = std::make_shared(key_image); - m_rpc->send_json_request("thaw", params); -} - -bool monero_wallet_rpc::is_output_frozen(const std::string& key_image) { - auto params = std::make_shared(key_image); - auto node = m_rpc->send_json_request("frozen", params); - - for(auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("frozen")) return it->second.get_value(); - } - - throw std::runtime_error("Could not get output"); -} - -monero_tx_priority monero_wallet_rpc::get_default_fee_priority() const { - auto node = m_rpc->send_json_request("get_default_fee_priority"); - - for(auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("priority")) { - int priority = it->second.get_value(); - - if (priority == 0) return monero_tx_priority::DEFAULT; - else if (priority == 1) return monero_tx_priority::UNIMPORTANT; - else if (priority == 2) return monero_tx_priority::NORMAL; - else if (priority == 3) return monero_tx_priority::ELEVATED; - } - } - - throw std::runtime_error("Could not get default fee priority"); -} - -std::vector> monero_wallet_rpc::create_txs(const monero_tx_config& conf) { - MTRACE("monero_wallet_rpc::create_txs"); - - // validate, copy, and normalize request - monero_tx_config config = conf; - if (config.m_address == boost::none && config.m_destinations.empty()) throw std::runtime_error("Destinations cannot be empty"); - if (config.m_sweep_each_subaddress != boost::none) throw std::runtime_error("Sweep each subaddress not supported"); - if (config.m_below_amount != boost::none) throw std::runtime_error("Below amount not supported"); - - if (config.m_can_split == boost::none) { - config = config.copy(); - config.m_can_split = true; - } - if (bool_equals_2(true, config.m_relay) && is_multisig()) throw std::runtime_error("Cannot relay multisig transaction until co-signed"); - - // determine account and subaddresses to send from - if (config.m_account_index == boost::none) throw std::runtime_error("Must specify the account index to send from"); - auto account_idx = config.m_account_index.get(); - - // cannot apply subtractFeeFrom with `transfer_split` call - if (bool_equals_2(true, config.m_can_split) && config.m_subtract_fee_from.size() > 0) { - throw std::runtime_error("subtractfeefrom transfers cannot be split over multiple transactions yet"); - } - - // build request parameters - auto params = std::make_shared(config); - std::string request_path = "transfer"; - if (bool_equals_2(true, config.m_can_split)) request_path = "transfer_split"; - - boost::property_tree::ptree node; - try { - node = m_rpc->send_json_request(request_path, params); - } catch (const monero_rpc_error& ex) { - std::string message = ex.what(); - if (message.find("WALLET_RPC_ERROR_CODE_WRONG_ADDRESS") != std::string::npos) throw monero_error("Invalid destination address"); - throw; - } - - // pre-initialize txs iff present. multisig and view-only wallets will have tx set without transactions - std::vector> txs; - int num_txs = 0; - bool can_split = bool_equals_2(true, config.m_can_split); - for(auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (can_split && key == std::string("fee_list")) { - auto fee_list_node = it->second; - for(auto it2 = fee_list_node.begin(); it2 != fee_list_node.end(); ++it2) { - num_txs++; - } - } - else if (!can_split && key == std::string("fee")) { - num_txs = 1; - } - } - - bool copy_destinations = num_txs == 1; - for (int i = 0; i < num_txs; i++) { - auto tx = std::make_shared(); - PyMoneroTxWallet::init_sent(config, tx, copy_destinations); - tx->m_outgoing_transfer.get()->m_account_index = account_idx; - - if (config.m_subaddress_indices.size() == 1) { - tx->m_outgoing_transfer.get()->m_subaddress_indices = config.m_subaddress_indices; - } - - txs.push_back(tx); - } - - // notify of changes - if (bool_equals_2(true, config.m_relay)) poll(); - - // initialize tx set from rpc response with pre-initialized txs - auto tx_set = std::make_shared(); - if (can_split) { - PyMoneroTxSet::from_sent_txs(node, tx_set, txs, config); - } - else if (txs.empty()) { - auto __tx = std::make_shared(); - PyMoneroTxSet::from_tx(node, tx_set, __tx, true, config); - } - else { - PyMoneroTxSet::from_tx(node, tx_set, txs[0], true, config); - } - - return tx_set->m_txs; -} - -std::vector> monero_wallet_rpc::sweep_unlocked(const monero_tx_config& config) { - // validate config - std::vector> destinations = config.get_normalized_destinations(); - if (destinations.size() != 1) throw std::runtime_error("Must specify exactly one destination to sweep to"); - if (destinations[0]->m_address == boost::none) throw std::runtime_error("Must specify destination address to sweep to"); - if (destinations[0]->m_amount != boost::none) throw std::runtime_error("Cannot specify amount to sweep"); - if (config.m_account_index == boost::none && config.m_subaddress_indices.size() != 0) throw std::runtime_error("Must specify account index if subaddress indices are specified"); - - // determine account and subaddress indices to sweep; default to all with unlocked balance if not specified - std::map> indices; - if (config.m_account_index != boost::none) { - if (config.m_subaddress_indices.size() != 0) { - indices[config.m_account_index.get()] = config.m_subaddress_indices; - } else { - std::vector subaddress_indices; - for (const monero_subaddress& subaddress : monero_wallet::get_subaddresses(config.m_account_index.get())) { - // TODO wallet rpc sweep_all now supports req.subaddr_indices_all - if (subaddress.m_unlocked_balance.get() > 0) subaddress_indices.push_back(subaddress.m_index.get()); - } - indices[config.m_account_index.get()] = subaddress_indices; - } - } else { - std::vector accounts = monero_wallet::get_accounts(true); - for (const monero_account& account : accounts) { - if (account.m_unlocked_balance.get() > 0) { - std::vector subaddress_indices; - for (const monero_subaddress& subaddress : account.m_subaddresses) { - if (subaddress.m_unlocked_balance.get() > 0) subaddress_indices.push_back(subaddress.m_index.get()); - } - indices[account.m_index.get()] = subaddress_indices; - } - } - } - - // sweep from each account and collect resulting txs - std::vector> txs; - for (std::pair> subaddress_indices_pair : indices) { - - // copy and modify the original config - monero_tx_config copy = config.copy(); - copy.m_account_index = subaddress_indices_pair.first; - copy.m_sweep_each_subaddress = false; - - // sweep all subaddresses together // TODO monero-project: can this reveal outputs belong to the same wallet? - if (copy.m_sweep_each_subaddress == boost::none || copy.m_sweep_each_subaddress.get() != true) { - copy.m_subaddress_indices = subaddress_indices_pair.second; - std::vector> account_txs = sweep_account(copy); - txs.insert(std::end(txs), std::begin(account_txs), std::end(account_txs)); - } - - // otherwise sweep each subaddress individually - else { - for (uint32_t subaddress_index : subaddress_indices_pair.second) { - std::vector subaddress_indices; - subaddress_indices.push_back(subaddress_index); - copy.m_subaddress_indices = subaddress_indices; - std::vector> account_txs = sweep_account(copy); - txs.insert(std::end(txs), std::begin(account_txs), std::end(account_txs)); - } - } - } - - // notify listeners of spent funds - if (config.m_relay != boost::none && config.m_relay.get()) poll(); - return txs; -} - -std::shared_ptr monero_wallet_rpc::sweep_output(const monero_tx_config& config) { - MTRACE("monero_wallet_rpc::sweep_output()"); - - // validate request - std::vector> destinations = config.get_normalized_destinations(); - if (config.m_sweep_each_subaddress != boost::none) throw std::runtime_error("Cannot sweep each subaddress when sweeping single output"); - if (config.m_below_amount != boost::none) throw std::runtime_error("Cannot specifiy below_amount when sweeping single output"); - if (config.m_can_split != boost::none) throw std::runtime_error("Splitting is not applicable when sweeping output"); - if (destinations.size() != 1) throw std::runtime_error("Must provide exactly one destination address to sweep output to"); - if (destinations[0]->m_address == boost::none) throw std::runtime_error("Must specify destination address to sweep to"); - if (destinations[0]->m_amount != boost::none) throw std::runtime_error("Cannot specify amount to sweep"); - - auto params = std::make_shared(config); - auto node = m_rpc->send_json_request("sweep_single", params); - if (bool_equals_2(true, config.m_relay)) poll(); - auto set = std::make_shared(); - auto tx = std::make_shared(); - PyMoneroTxWallet::init_sent(config, tx, true); - PyMoneroTxSet::from_tx(node, set, tx, true, config); - return tx; -} - -std::vector> monero_wallet_rpc::sweep_dust(bool relay) { - MTRACE("monero_wallet_rpc::sweep_dust()"); - - auto params = std::make_shared(relay); - auto node = m_rpc->send_json_request("sweep_dust", params); - if (relay) poll(); - auto set = std::make_shared(); - PyMoneroTxSet::from_sent_txs(node, set); - return set->m_txs; -} - -std::vector monero_wallet_rpc::relay_txs(const std::vector& tx_metadatas) { - MTRACE("monero_wallet_rpc::relay_txs()"); - - if (tx_metadatas.empty()) throw std::runtime_error("Must provide an array of tx metadata to relay"); - - std::vector tx_hashes; - - for (const auto &tx_metadata : tx_metadatas) { - auto params = std::make_shared(tx_metadata); - auto node = m_rpc->send_json_request("relay_tx", params); - - for (auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("tx_hash")) tx_hashes.push_back(it->second.data()); - } - } - - return tx_hashes; -} - -monero_tx_set monero_wallet_rpc::describe_tx_set(const monero_tx_set& tx_set) { - auto params = std::make_shared(); - params->m_multisig_txset = tx_set.m_multisig_tx_hex; - params->m_unsigned_txset = tx_set.m_unsigned_tx_hex; - auto node = m_rpc->send_json_request("describe_transfer", params); - auto set = std::make_shared(); - PyMoneroTxSet::from_describe_transfer(node, set); - return *set; -} - -monero_tx_set monero_wallet_rpc::sign_txs(const std::string& unsigned_tx_hex) { - auto params = std::make_shared(unsigned_tx_hex); - auto node = m_rpc->send_json_request("sign_transfer", params); - auto set = std::make_shared(); - PyMoneroTxSet::from_sent_txs(node, set); - return *set; -} - -std::vector monero_wallet_rpc::submit_txs(const std::string& signed_tx_hex) { - auto params = std::make_shared(); - params->m_signed_tx_hex = signed_tx_hex; - auto node = m_rpc->send_json_request("submit_transfer", params); - poll(); - std::vector hashes; - - for (auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("tx_hash_list")) { - auto hashes_node = it->second; - - for (auto it2 = hashes_node.begin(); it2 != hashes_node.end(); ++it2) { - hashes.push_back(it2->second.data()); - } - } - } - - return hashes; -} - -std::string monero_wallet_rpc::sign_message(const std::string& msg, monero_message_signature_type signature_type, uint32_t account_idx, uint32_t subaddress_idx) const { - auto params = std::make_shared(msg, signature_type, account_idx, subaddress_idx); - auto node = m_rpc->send_json_request("sign", params); - return monero_signature::from_property_tree(node); -} - -monero_message_signature_result monero_wallet_rpc::verify_message(const std::string& msg, const std::string& address, const std::string& signature) const { - auto params = std::make_shared(msg, address, signature); - auto sig_result = std::make_shared(); - sig_result->m_is_good = false; - try { - auto node = m_rpc->send_json_request("verify", params); - PyMoneroMessageSignatureResult::from_property_tree(node, sig_result); - } catch (const monero_rpc_error& ex) { - if (ex.code != -2) throw; - } - - return *sig_result; -} - -void normalize_wallet_error(const monero_rpc_error& ex) { - // normalize error message - if (ex.code == -1 && std::string(ex.what()).find("basic_string") != std::string::npos) { - throw monero_rpc_error(-1, "Must provide signature to check tx proof"); - } else if (ex.code == -8 && ex.what() == std::string("TX ID has invalid format")) { - throw monero_rpc_error(-8, "TX hash has invalid format"); - } - throw; -} - -std::string monero_wallet_rpc::get_tx_key(const std::string& tx_hash) const { - MTRACE("monero_wallet_rpc::get_tx_key()"); - - try { - auto params = std::make_shared(tx_hash); - auto node = m_rpc->send_json_request("get_tx_key", params); - - for (auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("tx_key")) { - return it->second.data(); - } - } - } catch (const monero_rpc_error& ex) { - normalize_wallet_error(ex); - } - - throw std::runtime_error("Could not get tx key"); -} - -std::shared_ptr monero_wallet_rpc::check_tx_key(const std::string& tx_hash, const std::string& tx_key, const std::string& address) const { - MTRACE("monero_wallet_rpc::check_tx_key()"); - - auto check = std::make_shared(); - try { - auto params = std::make_shared(tx_hash, tx_key, address); - auto node = m_rpc->send_json_request("check_tx_key", params); - check->m_is_good = true; - PyMoneroCheckTxProof::from_property_tree(node, check); - } catch (const monero_rpc_error& ex) { - normalize_wallet_error(ex); - } - - return check; -} - -std::string monero_wallet_rpc::get_tx_proof(const std::string& tx_hash, const std::string& address, const std::string& message) const { - std::string tx_proof; - try { - auto params = std::make_shared(tx_hash, message); - params->m_address = address; - auto node = m_rpc->send_json_request("get_tx_proof", params); - tx_proof = monero_signature::from_property_tree(node); - } catch (const monero_rpc_error& ex) { - normalize_wallet_error(ex); - } - - return tx_proof; -} - -std::shared_ptr monero_wallet_rpc::check_tx_proof(const std::string& tx_hash, const std::string& address, const std::string& message, const std::string& signature) const { - MTRACE("monero_wallet_rpc::check_tx_proof()"); - - auto check = std::make_shared(); - try { - auto params = std::make_shared(tx_hash, address, message, signature); - auto node = m_rpc->send_json_request("check_tx_proof", params); - PyMoneroCheckTxProof::from_property_tree(node, check); - } catch (const monero_rpc_error& ex) { - normalize_wallet_error(ex); - } - - return check; -} - -std::string monero_wallet_rpc::get_spend_proof(const std::string& tx_hash, const std::string& message) const { - MTRACE("monero_wallet_rpc::get_spend_proof()"); - - std::string spend_proof; - try { - auto params = std::make_shared(tx_hash, message); - auto node = m_rpc->send_json_request("get_spend_proof", params); - spend_proof = monero_signature::from_property_tree(node); - } catch (const monero_rpc_error& ex) { - normalize_wallet_error(ex); - } - - return spend_proof; -} - -bool monero_wallet_rpc::check_spend_proof(const std::string& tx_hash, const std::string& message, const std::string& signature) const { - MTRACE("monero_wallet_rpc::check_spend_proof()"); - - auto proof = std::make_shared(); - try { - auto params = std::make_shared(tx_hash, message); - params->m_signature = signature; - auto node = m_rpc->send_json_request("check_spend_proof", params); - PyMoneroCheckReserve::from_property_tree(node, proof); - } catch (const monero_rpc_error& ex) { - normalize_wallet_error(ex); - } - - return proof->m_is_good; -} - -std::string monero_wallet_rpc::get_reserve_proof_wallet(const std::string& message) const { - MTRACE("monero_wallet_rpc::get_reserve_proof_wallet()"); - auto params = std::make_shared(message); - auto node = m_rpc->send_json_request("get_reserve_proof", params); - return monero_signature::from_property_tree(node); -} - -std::string monero_wallet_rpc::get_reserve_proof_account(uint32_t account_idx, uint64_t amount, const std::string& message) const { - MTRACE("monero_wallet_rpc::get_reserve_proof_account()"); - auto params = std::make_shared(account_idx, amount, message); - auto node = m_rpc->send_json_request("get_reserve_proof", params); - return monero_signature::from_property_tree(node); -} - -std::shared_ptr monero_wallet_rpc::check_reserve_proof(const std::string& address, const std::string& message, const std::string& signature) const { - MTRACE("monero_wallet_rpc::check_reserve_proof()"); - auto params = std::make_shared(address, message, signature); - auto node = m_rpc->send_json_request("check_reserve_proof", params); - auto proof = std::make_shared(); - PyMoneroCheckReserve::from_property_tree(node, proof); - return proof; -} - -std::string monero_wallet_rpc::get_tx_note(const std::string& tx_hash) const { - MTRACE("monero_wallet_rpc::get_tx_note()"); - std::vector tx_hashes; - tx_hashes.push_back(tx_hash); - auto notes = get_tx_notes(tx_hashes); - if (notes.size() != 1) throw std::runtime_error("Expected one tx note"); - return notes[0]; -} - -std::vector monero_wallet_rpc::get_tx_notes(const std::vector& tx_hashes) const { - MTRACE("monero_wallet_rpc::get_tx_notes()"); - auto params = std::make_shared(tx_hashes); - auto node = m_rpc->send_json_request("get_tx_notes", params); - std::vector notes; - - for (auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("notes")) { - auto notes_node = it->second; - - for (auto it2 = notes_node.begin(); it2 != notes_node.end(); ++it2) { - notes.push_back(it2->second.data()); - } - } - } - - return notes; -} - -void monero_wallet_rpc::set_tx_note(const std::string& tx_hash, const std::string& note) { - MTRACE("monero_wallet_rpc::set_tx_note()"); - std::vector tx_hashes; - std::vector notes; - tx_hashes.push_back(tx_hash); - notes.push_back(note); - - set_tx_notes(tx_hashes, notes); -} - -void monero_wallet_rpc::set_tx_notes(const std::vector& tx_hashes, const std::vector& notes) { - MTRACE("monero_wallet_rpc::set_tx_notes()"); - auto params = std::make_shared(tx_hashes, notes); - m_rpc->send_json_request("set_tx_notes", params); -} - -std::vector monero_wallet_rpc::get_address_book_entries(const std::vector& indices) const { - MTRACE("monero_wallet_rpc::get_address_book_entries()"); - auto params = std::make_shared(indices); - auto node = m_rpc->send_json_request("get_address_book", params); - std::vector> entries_ptr; - PyMoneroAddressBookEntry::from_property_tree(node, entries_ptr); - std::vector entries; - - for (const auto &entry : entries_ptr) { - entries.push_back(*entry); - } - - return entries; -} - -uint64_t monero_wallet_rpc::add_address_book_entry(const std::string& address, const std::string& description) { - MTRACE("monero_wallet_rpc::add_address_book_entry()"); - auto params = std::make_shared(address, description); - auto node = m_rpc->send_json_request("add_address_book", params); - - for (auto it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - - if (key == std::string("index")) { - return it->second.get_value(); - } - } - - throw std::runtime_error("Invalid response from wallet rpc"); -} - -void monero_wallet_rpc::edit_address_book_entry(uint64_t index, bool set_address, const std::string& address, bool set_description, const std::string& description) { - MTRACE("monero_wallet_rpc::edit_address_book_entry()"); - auto params = std::make_shared(index, set_address, address, set_description, description); - m_rpc->send_json_request("edit_address_book", params); -} - -void monero_wallet_rpc::delete_address_book_entry(uint64_t index) { - auto params = std::make_shared(index); - m_rpc->send_json_request("delete_address_book", params); -} - -void monero_wallet_rpc::tag_accounts(const std::string& tag, const std::vector& account_indices) { - auto params = std::make_shared(tag, account_indices); - m_rpc->send_json_request("tag_accounts", params); -} - -void monero_wallet_rpc::untag_accounts(const std::vector& account_indices) { - auto params = std::make_shared(account_indices); - m_rpc->send_json_request("untag_accounts", params); -} - -std::vector> monero_wallet_rpc::get_account_tags() { - auto res = m_rpc->send_json_request("get_account_tags"); - std::vector> account_tags; - monero_account_tag::from_property_tree(res, account_tags); - return account_tags; -} - -void monero_wallet_rpc::set_account_tag_label(const std::string& tag, const std::string& label) { - auto params = std::make_shared(tag, label); - m_rpc->send_json_request("set_account_tag_description", params); -} - -std::string monero_wallet_rpc::get_payment_uri(const monero_tx_config& config) const { - MTRACE("monero_wallet_rpc::get_payment_uri()"); - auto params = std::make_shared(config); - auto res = m_rpc->send_json_request("make_uri", params); - return monero_payment_uri_params::from_property_tree(res); -} - -std::shared_ptr monero_wallet_rpc::parse_payment_uri(const std::string& uri) const { - MTRACE("monero_wallet_rpc::parse_payment_uri(" << uri << ")"); - auto params = std::make_shared(uri); - auto res = m_rpc->send_json_request("parse_uri", params); - auto uri_response = std::make_shared(); - monero_payment_uri_params::from_property_tree(res, uri_response); - return uri_response->to_tx_config(); -} - -void monero_wallet_rpc::set_attribute(const std::string& key, const std::string& val) { - auto params = std::make_shared(key, val); - m_rpc->send_json_request("set_attribute", params); -} - -bool monero_wallet_rpc::get_attribute(const std::string& key, std::string& value) const { - try { - auto params = std::make_shared(key); - auto res = m_rpc->send_json_request("get_attribute", params); - key_value::from_property_tree(res, params); - if (params->m_value == boost::none) return false; - value = params->m_value.get(); - return true; - } - catch (const monero_rpc_error& ex) { - if (ex.code == -45) { // attribute not found - value = std::string(""); - return true; - } - } - - return false; -} - -void monero_wallet_rpc::start_mining(boost::optional num_threads, boost::optional background_mining, boost::optional ignore_battery) { - MTRACE("monero_wallet_rpc::start_mining()"); - auto params = std::make_shared(num_threads.value_or(0), background_mining.value_or(false), ignore_battery.value_or(false)); - m_rpc->send_json_request("start_mining", params); -} - -void monero_wallet_rpc::stop_mining() { - MTRACE("monero_wallet_rpc::stop_mining()"); - m_rpc->send_json_request("stop_mining"); -} - -bool monero_wallet_rpc::is_multisig_import_needed() const { - auto res = m_rpc->send_json_request("get_balance"); - auto balance = std::make_shared(); - monero_get_balance_response::from_property_tree(res, balance); - return bool_equals_2(true, balance->m_multisig_import_needed); -} - -monero_multisig_info monero_wallet_rpc::get_multisig_info() const { - auto res = m_rpc->send_json_request("is_multisig"); - auto info = std::make_shared(); - PyMoneroMultisigInfo::from_property_tree(res, info); - return *info; -} - -std::string monero_wallet_rpc::prepare_multisig() { - auto params = std::make_shared(); - auto res = m_rpc->send_json_request("prepare_multisig", params); - clear_address_cache(); - auto response = std::make_shared(); - monero_multisig_response::from_property_tree(res, response); - if (response->m_multisig_info == boost::none) throw std::runtime_error("Failed to prepare multisig"); - return response->m_multisig_info.get(); -} - -std::string monero_wallet_rpc::make_multisig(const std::vector& multisig_hexes, int threshold, const std::string& password) { - auto params = std::make_shared(multisig_hexes, threshold, password); - auto res = m_rpc->send_json_request("make_multisig", params); - clear_address_cache(); - auto response = std::make_shared(); - monero_multisig_response::from_property_tree(res, response); - if (response->m_multisig_info == boost::none) throw std::runtime_error("Failed to make multisig"); - return response->m_multisig_info.get(); -} - -monero_multisig_init_result monero_wallet_rpc::exchange_multisig_keys(const std::vector& multisig_hexes, const std::string& password) { - auto params = std::make_shared(multisig_hexes, password); - auto res = m_rpc->send_json_request("exchange_multisig_keys", params); - clear_address_cache(); - auto multisig_init = std::make_shared(); - PyMoneroMultisigInitResult::from_property_tree(res, multisig_init); - return *multisig_init; -} - -std::string monero_wallet_rpc::export_multisig_hex() { - auto res = m_rpc->send_json_request("export_multisig_info"); - auto response = std::make_shared(); - monero_multisig_response::from_property_tree(res, response); - if (response->m_multisig_info == boost::none) throw std::runtime_error("Failed to export multisig"); - return response->m_multisig_info.get(); -} - -int monero_wallet_rpc::import_multisig_hex(const std::vector& multisig_hexes) { - auto params = std::make_shared(multisig_hexes); - auto res = m_rpc->send_json_request("import_multisig_info", params); - auto response = std::make_shared(); - monero_multisig_response::from_property_tree(res, response); - if (response->m_num_outputs == boost::none) throw std::runtime_error("Failed to export multisig"); - return response->m_num_outputs.get(); -} - -monero_multisig_sign_result monero_wallet_rpc::sign_multisig_tx_hex(const std::string& multisig_tx_hex) { - auto params = std::make_shared(multisig_tx_hex); - auto res = m_rpc->send_json_request("sign_multisig", params); - auto multisig_result = std::make_shared(); - PyMoneroMultisigSignResult::from_property_tree(res, multisig_result); - return *multisig_result; -} - -std::vector monero_wallet_rpc::submit_multisig_tx_hex(const std::string& signed_multisig_tx_hex) { - auto params = std::make_shared(signed_multisig_tx_hex); - auto res = m_rpc->send_json_request("submit_multisig", params); - auto response = std::make_shared(); - monero_multisig_response::from_property_tree(res, response); - return response->m_tx_hashes; -} - -void monero_wallet_rpc::change_password(const std::string& old_password, const std::string& new_password) { - MTRACE("monero_wallet_rpc::change_password(" << "***" << ", ***)"); - auto params = std::make_shared(old_password, new_password); - m_rpc->send_json_request("change_wallet_password", params); -} - -void monero_wallet_rpc::save() { - MTRACE("monero_wallet_rpc::save()"); - m_rpc->send_json_request("store"); -} - -bool monero_wallet_rpc::is_closed() const { - try { - get_primary_address(); - } catch (const monero_rpc_error& ex) { - return ex.code == -8 && ex.what() == std::string("No wallet file"); - } - - return false; -} - -void monero_wallet_rpc::close(bool save) { - MTRACE("monero_wallet_rpc::close()"); - clear(); - auto params = std::make_shared(save); - m_rpc->send_json_request("close_wallet", params); -} - -std::shared_ptr monero_wallet_rpc::get_balances(boost::optional account_idx, boost::optional subaddress_idx) const { - auto balance = std::make_shared(); - - if (account_idx == boost::none) { - if (subaddress_idx != boost::none) throw std::runtime_error("Must provide account index with subaddress index"); - - auto accounts = monero::monero_wallet::get_accounts(); - - for(const auto &account : accounts) { - balance->m_balance += account.m_balance.get(); - balance->m_unlocked_balance += account.m_unlocked_balance.get(); - } - - return balance; - } - else { - auto params = std::make_shared(account_idx.get(), subaddress_idx); - auto res = m_rpc->send_json_request("get_balance", params); - auto bal_res = std::make_shared(); - monero_get_balance_response::from_property_tree(res, bal_res); - - if (subaddress_idx == boost::none) { - balance->m_balance = bal_res->m_balance.get(); - balance->m_unlocked_balance = bal_res->m_unlocked_balance.get(); - return balance; - } - else if (bal_res->m_per_subaddress.size() > 0) { - auto sub = bal_res->m_per_subaddress[0]; - balance->m_balance = sub->m_balance.get(); - balance->m_unlocked_balance = sub->m_unlocked_balance.get(); - } - } - - return balance; -} - -monero_wallet_rpc* monero_wallet_rpc::create_wallet_random(const std::shared_ptr &conf) { - // validate and normalize config - auto config = conf->copy(); - if (config.m_seed_offset != boost::none) throw std::runtime_error("Cannot specify seed offset when creating random wallet"); - if (config.m_restore_height != boost::none) throw std::runtime_error("Cannot specify restore height when creating random wallet"); - if (config.m_save_current != boost::none && config.m_save_current == false) throw std::runtime_error("Current wallet is saved automatically when creating random wallet"); - if (config.m_path == boost::none || config.m_path->empty()) throw std::runtime_error("Wallet name is not initialized"); - if (config.m_language == boost::none || config.m_language->empty()) config.m_language = "English"; - - // send request - std::string filename = config.m_path.get(); - std::string password = config.m_password.get(); - std::string language = config.m_language.get(); - - auto params = std::make_shared(filename, password, language); - try { m_rpc->send_json_request("create_wallet", params); } - catch (const monero_rpc_error& ex) { handle_create_wallet_error(ex, filename); } - clear(); - m_path = config.m_path.get(); - return this; -} - -monero_wallet_rpc* monero_wallet_rpc::create_wallet_from_seed(const std::shared_ptr &conf) { - auto config = conf->copy(); - if (config.m_language == boost::none || config.m_language->empty()) config.m_language = "English"; - auto filename = config.m_path.get(); - auto password = config.m_password; - auto seed = config.m_seed; - auto seed_offset = config.m_seed_offset; - auto restore_height = config.m_restore_height; - auto language = config.m_language; - bool autosave_current = false; - bool enable_multisig_experimental = false; - if (config.m_save_current != boost::none) autosave_current = config.m_save_current.get(); - if (config.m_is_multisig != boost::none) enable_multisig_experimental = config.m_is_multisig.get(); - auto params = std::make_shared(filename, password, seed, seed_offset, restore_height, language, autosave_current, enable_multisig_experimental); - try { m_rpc->send_json_request("restore_deterministic_wallet", params); } - catch (const monero_rpc_error& ex) { handle_create_wallet_error(ex, filename); } - clear(); - m_path = config.m_path.get(); - return this; -} - -monero_wallet_rpc* monero_wallet_rpc::create_wallet_from_keys(const std::shared_ptr &config) { - if (config->m_seed_offset != boost::none) throw std::runtime_error("Cannot specify seed offset when creating wallet from keys"); - if (config->m_restore_height == boost::none) config->m_restore_height = 0; - std::string filename = config->m_path.get(); - std::string password = config->m_password.get(); - std::string address = config->m_primary_address.get(); - std::string view_key = ""; - std::string spend_key = ""; - if (config->m_private_view_key != boost::none) view_key = config->m_private_view_key.get(); - if (config->m_private_spend_key != boost::none) spend_key = config->m_private_spend_key.get(); - uint64_t restore_height = config->m_restore_height.get(); - bool autosave_current = false; - if (config->m_save_current != boost::none) autosave_current = config->m_save_current.get(); - auto params = std::make_shared(filename, password, address, view_key, spend_key, restore_height, autosave_current); - try { m_rpc->send_json_request("generate_from_keys", params); } - catch (const monero_rpc_error& ex) { handle_create_wallet_error(ex, filename); } - clear(); - m_path = config->m_path.get(); - return this; -} - -std::string monero_wallet_rpc::query_key(const std::string& key_type) const { - auto params = std::make_shared(key_type); - auto node = m_rpc->send_json_request("query_key", params); - auto kv = std::make_shared(); - key_value::from_property_tree(node, kv); - if (kv->m_key == boost::none) throw std::runtime_error(std::string("Cloud not query key: ") + key_type); - return *kv->m_key; -} - -std::vector> monero_wallet_rpc::sweep_account(const monero_tx_config &conf) { - auto config = conf.copy(); - // validate config - if (config.m_account_index == boost::none) throw std::runtime_error("Must specify an account index to sweep from"); - std::vector> destinations = config.get_normalized_destinations(); - if (destinations.size() != 1) throw std::runtime_error("Must provide exactly one destination address to sweep output to"); - if (destinations[0]->m_address == boost::none) throw std::runtime_error("Must specify destination address to sweep to"); - if (destinations[0]->m_amount != boost::none) throw std::runtime_error("Cannot specify destination amount to sweep"); - if (config.m_key_image != boost::none) throw std::runtime_error("Cannot define key image in sweep_account(); use sweep_output() to sweep an output by its key image"); - if (bool_equals_2(true, config.m_sweep_each_subaddress)) throw std::runtime_error("Cannot sweep each subaddress with RPC `sweep_all`"); - if (config.m_subtract_fee_from.size() > 0) throw std::runtime_error("Sweep transactions do not support subtracting fees from destinations"); - - // sweep from all subaddresses if not otherwise defined - if (config.m_subaddress_indices.empty()) { - uint32_t account_idx = config.m_account_index.get(); - auto subaddresses = get_subaddresses(account_idx); - for (const auto &subaddress : subaddresses) { - config.m_subaddress_indices.push_back(subaddress.m_index.get()); - } - } - if (config.m_subaddress_indices.size() == 0) throw std::runtime_error("No subaddresses to sweep from"); - bool relay = config.m_relay == true; - auto params = std::make_shared(config); - params->m_get_tx_key = boost::none; - params->m_get_tx_keys = true; - auto node = m_rpc->send_json_request("sweep_all", params); - if (bool_equals_2(true, config.m_relay)) poll(); - std::vector> txs; - auto set = std::make_shared(); - PyMoneroTxSet::from_sent_txs(node, set, txs, config); - - for (auto &tx : set->m_txs) { - tx->m_is_locked = true; - tx->m_is_confirmed = false; - tx->m_num_confirmations = 0; - tx->m_relay = relay; - tx->m_in_tx_pool = relay; - tx->m_is_relayed = relay; - tx->m_is_miner_tx = false; - tx->m_is_failed = false; - tx->m_ring_size = monero_utils::RING_SIZE; - if (tx->m_outgoing_transfer == boost::none) throw std::runtime_error("Tx outgoing transfer is none"); - auto transfer = tx->m_outgoing_transfer.get(); - transfer->m_account_index = config.m_account_index; - if (config.m_subaddress_indices.size() == 1) { - transfer->m_subaddress_indices = config.m_subaddress_indices; - } - auto destination = std::make_shared(); - destination->m_address = destinations[0]->m_address; - destination->m_amount = transfer->m_amount; - transfer->m_destinations.clear(); - transfer->m_destinations.push_back(destination); - tx->m_payment_id = config.m_payment_id; - if (tx->m_unlock_time == boost::none) tx->m_unlock_time = 0; - if (relay) { - if (tx->m_last_relayed_timestamp == boost::none) { - // TODO (monero-wallet-rpc): provide timestamp on response; unconfirmed timestamps vary - tx->m_last_relayed_timestamp = static_cast(time(NULL)); - } - if (tx->m_is_double_spend_seen == boost::none) tx->m_is_double_spend_seen = false; - } - } - - return set->m_txs; -} - -void monero_wallet_rpc::clear_address_cache() { - m_address_cache.clear(); -} - -void monero_wallet_rpc::refresh_listening() { - if (m_poller == nullptr && !m_listeners.empty()) { - m_poller = std::make_unique(this); - if (m_sync_period_in_ms != boost::none) m_poller->set_period_in_ms(m_sync_period_in_ms.get()); - } - if (m_poller != nullptr) { - m_poller->set_is_polling(!m_listeners.empty()); - } -} - -void monero_wallet_rpc::poll() { - if (m_poller != nullptr && m_poller->is_polling()) { - m_poller->poll(); - } -} - -void monero_wallet_rpc::clear() { - m_listeners.clear(); - refresh_listening(); - clear_address_cache(); - m_path = ""; -} - -std::vector> monero_wallet_rpc::get_txs() const { - return get_txs(monero_tx_query()); -} - -std::vector> monero_wallet_rpc::get_txs(const monero_tx_query& query) const { - MTRACE("monero_wallet_rpc::get_txs(query)"); - - // copy query - std::shared_ptr query_sp = std::make_shared(query); // convert to shared pointer - std::shared_ptr _query = query_sp->copy(query_sp, std::make_shared()); // deep copy - - // temporarily disable transfer and output queries in order to collect all tx context - boost::optional> transfer_query = _query->m_transfer_query; - boost::optional> input_query = _query->m_input_query; - boost::optional> output_query = _query->m_output_query; - _query->m_transfer_query = boost::none; - _query->m_input_query = boost::none; - _query->m_output_query = boost::none; - - // fetch all transfers that meet tx query - std::shared_ptr temp_transfer_query = std::make_shared(); - temp_transfer_query->m_tx_query = PyMoneroTxQuery::decontextualize(_query->copy(_query, std::make_shared())); - temp_transfer_query->m_tx_query.get()->m_transfer_query = temp_transfer_query; - std::vector> transfers = get_transfers_aux(*temp_transfer_query); - monero_utils::free(temp_transfer_query->m_tx_query.get()); - - // collect unique txs from transfers while retaining order - std::vector> txs = std::vector>(); - std::unordered_set> txsSet; - for (const std::shared_ptr& transfer : transfers) { - if (txsSet.find(transfer->m_tx) == txsSet.end()) { - txs.push_back(transfer->m_tx); - txsSet.insert(transfer->m_tx); - } - } - - // cache types into maps for merging and lookup - std::unordered_map> tx_map; - std::unordered_map> block_map; - for (const std::shared_ptr& tx : txs) { - PyMoneroTxWallet::merge_tx(tx, tx_map, block_map); - } - - // fetch and merge outputs if requested - if ((_query->m_include_outputs != boost::none && *_query->m_include_outputs) || output_query != boost::none) { - std::shared_ptr temp_output_query = std::make_shared(); - temp_output_query->m_tx_query = PyMoneroTxQuery::decontextualize(_query->copy(_query, std::make_shared())); - temp_output_query->m_tx_query.get()->m_output_query = temp_output_query; - std::vector> outputs = get_outputs_aux(*temp_output_query); - monero_utils::free(temp_output_query->m_tx_query.get()); - - // merge output txs one time while retaining order - std::unordered_set> output_txs; - for (const std::shared_ptr& output : outputs) { - std::shared_ptr tx = std::static_pointer_cast(output->m_tx); - if (output_txs.find(tx) == output_txs.end()) { - PyMoneroTxWallet::merge_tx(tx, tx_map, block_map); - output_txs.insert(tx); - } - } - } - - // restore transfer and output queries - _query->m_transfer_query = transfer_query; - _query->m_input_query = input_query; - _query->m_output_query = output_query; - - // filter txs that don't meet transfer query - std::vector> queried_txs; - std::vector>::iterator tx_iter = txs.begin(); - while (tx_iter != txs.end()) { - std::shared_ptr tx = *tx_iter; - if (_query->meets_criteria(tx.get())) { - queried_txs.push_back(tx); - ++tx_iter; - } else { - tx_map.erase(tx->m_hash.get()); - tx_iter = txs.erase(tx_iter); - if (tx->m_block != boost::none) tx->m_block.get()->m_txs.erase(std::remove(tx->m_block.get()->m_txs.begin(), tx->m_block.get()->m_txs.end(), tx), tx->m_block.get()->m_txs.end()); // TODO, no way to use tx_iter? - } - } - txs = queried_txs; - - // special case: re-fetch txs if inconsistency caused by needing to make multiple wallet calls - // TODO monero-project: offer wallet.get_txs(...) - for (const std::shared_ptr& tx : txs) { - if ((*tx->m_is_confirmed && tx->m_block == boost::none) || (!*tx->m_is_confirmed && tx->m_block != boost::none)) { - MWARNING("Inconsistency detected building txs from multiple wallet2 calls, re-fetching"); - monero_utils::free(txs); - txs.clear(); - txs = get_txs(*_query); - monero_utils::free(_query); - return txs; - } - } - - // if tx hashes requested, order txs - if (!_query->m_hashes.empty()) { - txs.clear(); - for (const std::string& tx_hash : _query->m_hashes) { - std::unordered_map>::const_iterator tx_iter = tx_map.find(tx_hash); - if (tx_iter != tx_map.end()) txs.push_back(tx_iter->second); - } - } - - // free query and return - monero_utils::free(_query); - return txs; -} - -std::vector> monero_wallet_rpc::get_transfers(const monero_transfer_query& query) const { - // get transfers directly if query does not require tx context (e.g. other transfers, outputs) - if (!PyMoneroTransferQuery::is_contextual(query)) return get_transfers_aux(query); - - // otherwise get txs with full models to fulfill query - std::vector> transfers; - for (const std::shared_ptr& tx : get_txs(*(query.m_tx_query.get()))) { - for (const std::shared_ptr& transfer : tx->filter_transfers(query)) { // collect queried transfers, erase if excluded - transfers.push_back(transfer); - } - } - return transfers; -} - -std::vector> monero_wallet_rpc::get_outputs(const monero_output_query& query) const { - // get outputs directly if query does not require tx context (e.g. other outputs, transfers) - if (!PyMoneroOutputQuery::is_contextual(query)) return get_outputs_aux(query); - - // otherwise get txs with full models to fulfill query - std::vector> outputs; - for (const std::shared_ptr& tx : get_txs(*(query.m_tx_query.get()))) { - for (const std::shared_ptr& output : tx->filter_outputs_wallet(query)) { // collect queried outputs, erase if excluded - outputs.push_back(output); - } - } - return outputs; -} - -std::map> monero_wallet_rpc::get_account_indices(bool get_subaddr_indices) const { - std::map> indices; - for (const auto& account : monero::monero_wallet::get_accounts()) { - uint32_t account_idx = account.m_index.get(); - if (get_subaddr_indices) { - indices[account_idx] = get_subaddress_indices(account_idx); - } - else indices[account_idx] = std::vector(); - } - return indices; -} - -std::vector monero_wallet_rpc::get_subaddress_indices(uint32_t account_idx) const { - // fetch subaddresses - auto params = std::make_shared(account_idx); - auto node = m_rpc->send_json_request("get_address", params); - std::vector subadress_indices; - std::vector> subaddresses; - PyMoneroSubaddress::from_rpc_property_tree(node, subaddresses); - for (const auto& subaddress : subaddresses) { - subadress_indices.push_back(subaddress->m_index.get()); - } - return subadress_indices; -} - -std::vector> monero_wallet_rpc::get_transfers_aux(const monero_transfer_query& query) const { - MTRACE("monero_wallet_rpc::get_transfers_aux(query)"); - - // copy and normalize query - std::shared_ptr _query; - if (query.m_tx_query == boost::none) { - std::shared_ptr query_ptr = std::make_shared(query); // convert to shared pointer for copy // TODO: does this copy unecessarily? copy constructor is not defined - _query = query_ptr->copy(query_ptr, std::make_shared()); - _query->m_tx_query = std::make_shared(); - _query->m_tx_query.get()->m_transfer_query = _query; - } else { - std::shared_ptr tx_query = query.m_tx_query.get()->copy(query.m_tx_query.get(), std::make_shared()); - _query = tx_query->m_transfer_query.get(); - } - std::shared_ptr tx_query = _query->m_tx_query.get(); - - boost::optional account_index = boost::none; - if (_query->m_account_index != boost::none) account_index = *_query->m_account_index; - std::set subaddress_indices; - for (int i = 0; i < _query->m_subaddress_indices.size(); i++) { - subaddress_indices.insert(_query->m_subaddress_indices[i]); - } - - // translate from monero_tx_query to in, out, pending, pool, failed terminology used by monero-wallet-rpc - bool can_be_confirmed = !bool_equals_2(false, tx_query->m_is_confirmed) && !bool_equals_2(true, tx_query->m_in_tx_pool) && !bool_equals_2(true, tx_query->m_is_failed) && !bool_equals_2(false, tx_query->m_is_relayed); - bool can_be_in_tx_pool = !bool_equals_2(true, tx_query->m_is_confirmed) && !bool_equals_2(false, tx_query->m_in_tx_pool) && !bool_equals_2(true, tx_query->m_is_failed) && tx_query->get_height() == boost::none && tx_query->m_min_height == boost::none && !bool_equals_2(false, tx_query->m_is_locked); - bool can_be_incoming = !bool_equals_2(false, _query->m_is_incoming) && !bool_equals_2(true, _query->is_outgoing()) && !bool_equals_2(true, _query->m_has_destinations); - bool can_be_outgoing = !bool_equals_2(false, _query->is_outgoing()) && !bool_equals_2(true, _query->m_is_incoming); - bool is_in = can_be_incoming && can_be_confirmed; - bool is_out = can_be_outgoing && can_be_confirmed; - bool is_pending = can_be_outgoing && can_be_in_tx_pool; - bool is_pool = can_be_incoming && can_be_in_tx_pool; - bool is_failed = !bool_equals_2(false, tx_query->m_is_failed) && !bool_equals_2(true, tx_query->m_is_confirmed) && !bool_equals_2(true, tx_query->m_in_tx_pool) && !bool_equals_2(false, tx_query->m_is_locked); - - // check if fetching pool txs contradicted by configuration - if (tx_query->m_in_tx_pool != boost::none && tx_query->m_in_tx_pool.get() && !can_be_in_tx_pool) { - monero_utils::free(tx_query); - throw std::runtime_error("Cannot fetch pool transactions because it contradicts configuration"); - } - - // cache unique txs and blocks - std::unordered_map> tx_map; - std::unordered_map> block_map; - - auto params = std::make_shared(); - params->m_in = is_in; - params->m_out = is_out; - params->m_pool = is_pool; - params->m_pending = is_pending; - params->m_failed = is_failed; - params->m_max_height = tx_query->m_max_height; - - if (tx_query->m_min_height != boost::none) { - uint64_t min_height = tx_query->m_min_height.get(); - // TODO monero-project: wallet2::get_payments() min_height is exclusive, so manually offset to match intended range (issues #5751, #5598) - if (min_height > 0) params->m_min_height = min_height - 1; - else params->m_min_height = min_height; - } - - if (_query->m_account_index == boost::none) { - if (_query->m_subaddress_index != boost::none || !_query->m_subaddress_indices.empty()) throw std::runtime_error("Filter specifies a subaddress index but not an account index"); - params->m_all_accounts = true; - } else { - params->m_account_index = _query->m_account_index; - - // set subaddress indices param - params->m_subaddr_indices = _query->m_subaddress_indices; - if (_query->m_subaddress_index != boost::none && std::find(_query->m_subaddress_indices.end(), _query->m_subaddress_indices.end(), _query->m_subaddress_index.get()) != _query->m_subaddress_indices.end()) { - params->m_subaddr_indices.push_back(_query->m_subaddress_index.get()); - } - } - - // build txs using `get_transfers` - auto node = m_rpc->send_json_request("get_transfers", params); - - PyMoneroTxWallet::from_property_tree_with_transfer_and_merge(node, tx_map, block_map); - - // sort txs by block height - std::vector> txs; - for (std::unordered_map>::const_iterator tx_iter = tx_map.begin(); tx_iter != tx_map.end(); ++tx_iter) { - txs.push_back(tx_iter->second); - } - sort(txs.begin(), txs.end(), tx_height_less_than); - - // filter transfers - std::vector> transfers; - for (const std::shared_ptr& tx : txs) { - - // tx is not incoming/outgoing unless already set - if (tx->m_is_incoming == boost::none) tx->m_is_incoming = false; - if (tx->m_is_outgoing == boost::none) tx->m_is_outgoing = false; - - // sort incoming transfers - sort(tx->m_incoming_transfers.begin(), tx->m_incoming_transfers.end(), incoming_transfer_before); - - // collect queried transfers, erase if excluded - for (const std::shared_ptr& transfer : tx->filter_transfers(*_query)) transfers.push_back(transfer); - - // remove excluded txs from block - if (tx->m_block != boost::none && tx->m_outgoing_transfer == boost::none && tx->m_incoming_transfers.empty()) { - tx->m_block.get()->m_txs.erase(std::remove(tx->m_block.get()->m_txs.begin(), tx->m_block.get()->m_txs.end(), tx), tx->m_block.get()->m_txs.end()); // TODO, no way to use const_iterator? - } - } - MTRACE("monero_wallet_rpc::get_transfers() returning " << transfers.size() << " transfers"); - - // free query and return transfers - monero_utils::free(tx_query); - return transfers; -} - -std::vector> monero_wallet_rpc::get_outputs_aux(const monero_output_query& query) const { - MTRACE("monero_wallet_rpc::get_outputs_aux(query)"); - - // copy and normalize query - std::shared_ptr _query; - if (query.m_tx_query == boost::none) { - std::shared_ptr query_ptr = std::make_shared(query); // convert to shared pointer for copy - _query = query_ptr->copy(query_ptr, std::make_shared()); - } else { - std::shared_ptr tx_query = query.m_tx_query.get()->copy(query.m_tx_query.get(), std::make_shared()); - if (query.m_tx_query.get()->m_output_query != boost::none && query.m_tx_query.get()->m_output_query.get().get() == &query) { - _query = tx_query->m_output_query.get(); - } else { - if (query.m_tx_query.get()->m_output_query != boost::none) throw std::runtime_error("Output query's tx query must be a circular reference or null"); - std::shared_ptr query_ptr = std::make_shared(query); // convert query to shared pointer for copy - _query = query_ptr->copy(query_ptr, std::make_shared()); - _query->m_tx_query = tx_query; - } - } - if (_query->m_tx_query == boost::none) _query->m_tx_query = std::make_shared(); - std::shared_ptr tx_query = _query->m_tx_query.get(); - - // determine account and subaddress indices to be queried - std::map> indices; - if (_query->m_account_index != boost::none) { - std::vector subaddress_indices; - if (_query->m_subaddress_index != boost::none) { - subaddress_indices.push_back(_query->m_subaddress_index.get()); - } - for (const auto& subaddress_idx : _query->m_subaddress_indices) { - subaddress_indices.push_back(subaddress_idx); - } - // null will fetch from all subaddresses - indices[_query->m_account_index.get()] = subaddress_indices; - } - else { - if (_query->m_subaddress_index != boost::none) throw std::runtime_error("Request specifies a subaddress index but not an account index"); - if (!_query->m_subaddress_indices.empty()) throw std::runtime_error("Request specifies subaddress indices but not an account index"); - // fetch all account indices without subaddresses - indices = get_account_indices(false); - } - - // cache unique txs and blocks - std::unordered_map> tx_map; - std::unordered_map> block_map; - - // collect txs with outputs for each indicated account using `incoming_transfers` rpc call - std::string transfer_type = "all"; - if (_query->m_is_spent != boost::none) { - if (_query->m_is_spent.value() == true) transfer_type = "unavailable"; - else transfer_type = "available"; - } - - auto params = std::make_shared(transfer_type); - - for(const auto& kv : indices) { - uint32_t account_idx = kv.first; - params->m_account_index = account_idx; - params->m_subaddr_indices = kv.second; - // send request - auto node = m_rpc->send_json_request("incoming_transfers", params); - - // convert response to txs with outputs and merge - PyMoneroTxWallet::from_property_tree_with_output_and_merge(node, tx_map, block_map); - } - - // sort txs by block height - std::vector> txs ; - for (std::unordered_map>::const_iterator tx_iter = tx_map.begin(); tx_iter != tx_map.end(); ++tx_iter) { - txs.push_back(tx_iter->second); - } - sort(txs.begin(), txs.end(), tx_height_less_than); - - // filter and return outputs - std::vector> outputs; - for (const std::shared_ptr& tx : txs) { - - // sort outputs - sort(tx->m_outputs.begin(), tx->m_outputs.end(), vout_before); - - // collect queried outputs, erase if excluded - for (const std::shared_ptr& output : tx->filter_outputs_wallet(*_query)) outputs.push_back(output); - - // remove txs without outputs - if (tx->m_outputs.empty() && tx->m_block != boost::none) tx->m_block.get()->m_txs.erase(std::remove(tx->m_block.get()->m_txs.begin(), tx->m_block.get()->m_txs.end(), tx), tx->m_block.get()->m_txs.end()); // TODO, no way to use const_iterator? - } - - // free query and return outputs - monero_utils::free(tx_query); - return outputs; -} \ No newline at end of file diff --git a/src/cpp/wallet/py_monero_wallet_rpc.h b/src/cpp/wallet/py_monero_wallet_rpc.h deleted file mode 100644 index 136914b..0000000 --- a/src/cpp/wallet/py_monero_wallet_rpc.h +++ /dev/null @@ -1,263 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ -#pragma once - -#include "py_monero_wallet.h" - -// forward declaration of internal wallet poller -class monero_wallet_poller; - -/** - * Implements a Monero wallet using monero-wallet-rpc. - */ -class monero_wallet_rpc : public PyMoneroWallet { -public: - - /** - * Destruct the wallet. - */ - ~monero_wallet_rpc(); - monero_wallet_rpc(const std::shared_ptr& rpc_connection); - monero_wallet_rpc(const std::string& uri = "", const std::string& username = "", const std::string& password = "", const std::string& proxy_uri = "", const std::string& zmq_uri = "", uint64_t timeout = 20000); - - /** - * Open an existing wallet from rpc server. - * - * @param config is the wallet configuration - * @return a pointer to the wallet instance - */ - monero_wallet_rpc* open_wallet(const std::shared_ptr &config); - - /** - * Open an existing wallet from rpc server. - * - * @param name is the wallet's name to open - * @param password is the password of the wallet file to open - * @return a pointer to the wallet instance - */ - monero_wallet_rpc* open_wallet(const std::string& name, const std::string& password); - - /** - * Create a new wallet with the given configuration. - * - * @param config is the wallet configuration - * @return a pointer to the wallet instance - */ - monero_wallet_rpc* create_wallet(const std::shared_ptr &config); - - /** - * Get the wallet's RPC connection. - * - * @return the wallet's rpc connection - */ - std::shared_ptr get_rpc_connection() const { return m_rpc; } - - /** - * Get a list of available languages for the wallet's seed. - * - * @return the available languages for the wallet's seed - */ - std::vector get_seed_languages() const; - - /** - * Save and close the current wallet and stop the RPC server. - */ - void stop(); - - /** - * Supported wallet methods. - */ - void add_listener(monero_wallet_listener& listener) override; - void remove_listener(monero_wallet_listener& listener) override; - bool is_view_only() const override; - boost::optional get_daemon_connection() const override; - void set_daemon_connection(const boost::optional& connection, bool is_trusted, const boost::optional& ssl_options); - void set_daemon_connection(const boost::optional& connection) override; - void set_daemon_connection(const std::string& uri, const std::string& username = "", const std::string& password = "", const std::string& proxy_uri = "") override; - bool is_connected_to_daemon() const override; - monero::monero_version get_version() const override; - std::string get_path() const override; - std::string get_seed() const override; - std::string get_seed_language() const override; - std::string get_public_view_key() const override; - std::string get_private_view_key() const override; - std::string get_public_spend_key() const override; - std::string get_private_spend_key() const override; - std::string get_address(const uint32_t account_idx, const uint32_t subaddress_idx) const override; - monero_subaddress get_address_index(const std::string& address) const override; - monero_integrated_address get_integrated_address(const std::string& standard_address = "", const std::string& payment_id = "") const override; - monero_integrated_address decode_integrated_address(const std::string& integrated_address) const override; - uint64_t get_height() const override; - uint64_t get_daemon_height() const override; - uint64_t get_height_by_date(uint16_t year, uint8_t month, uint8_t day) const override; - monero_sync_result sync() override; - monero_sync_result sync(monero_wallet_listener& listener) override; - monero_sync_result sync(uint64_t start_height, monero_wallet_listener& listener) override; - monero_sync_result sync(uint64_t start_height) override; - void start_syncing(uint64_t sync_period_in_ms = 10000) override; - void stop_syncing() override; - void scan_txs(const std::vector& tx_hashes) override; - void rescan_spent() override; - void rescan_blockchain() override; - uint64_t get_balance() const override; - uint64_t get_balance(uint32_t account_index) const override; - uint64_t get_balance(uint32_t account_idx, uint32_t subaddress_idx) const override; - uint64_t get_unlocked_balance() const override; - uint64_t get_unlocked_balance(uint32_t account_index) const override; - uint64_t get_unlocked_balance(uint32_t account_idx, uint32_t subaddress_idx) const override; - monero_account get_account(const uint32_t account_idx, bool include_subaddresses) const override; - monero_account get_account(const uint32_t account_idx, bool include_subaddresses, bool skip_balances) const; - std::vector get_accounts(bool include_subaddresses, const std::string& tag) const override; - std::vector get_accounts(bool include_subaddresses, const std::string& tag, bool skip_balances) const; - monero_account create_account(const std::string& label = "") override; - std::vector get_subaddresses(const uint32_t account_idx, const std::vector& subaddress_indices, bool skip_balances) const; - std::vector get_subaddresses(uint32_t account_idx, const std::vector& subaddress_indices) const override; - std::vector get_subaddresses(const uint32_t account_idx) const override; - monero_subaddress get_subaddress(const uint32_t account_idx, const uint32_t subaddress_idx) const override; - monero_subaddress create_subaddress(uint32_t account_idx, const std::string& label = "") override; - void set_subaddress_label(uint32_t account_idx, uint32_t subaddress_idx, const std::string& label = "") override; - std::vector> get_txs() const override; - std::vector> get_txs(const monero_tx_query& query) const override; - std::vector> get_transfers(const monero_transfer_query& query) const override; - std::vector> get_outputs(const monero_output_query& query) const override; - std::string export_outputs(bool all = false) const override; - int import_outputs(const std::string& outputs_hex) override; - std::vector> export_key_images(bool all = false) const override; - std::shared_ptr import_key_images(const std::vector>& key_images) override; - void freeze_output(const std::string& key_image) override; - void thaw_output(const std::string& key_image) override; - bool is_output_frozen(const std::string& key_image) override; - monero_tx_priority get_default_fee_priority() const override; - std::vector> create_txs(const monero_tx_config& conf) override; - std::shared_ptr sweep_output(const monero_tx_config& config) override; - std::vector> sweep_dust(bool relay = false) override; - std::vector> sweep_unlocked(const monero_tx_config& config) override; - std::vector relay_txs(const std::vector& tx_metadatas) override; - monero_tx_set describe_tx_set(const monero_tx_set& tx_set) override; - monero_tx_set sign_txs(const std::string& unsigned_tx_hex) override; - std::vector submit_txs(const std::string& signed_tx_hex) override; - std::string sign_message(const std::string& msg, monero_message_signature_type signature_type, uint32_t account_idx = 0, uint32_t subaddress_idx = 0) const override; - monero_message_signature_result verify_message(const std::string& msg, const std::string& address, const std::string& signature) const override; - std::string get_tx_key(const std::string& tx_hash) const override; - std::shared_ptr check_tx_key(const std::string& tx_hash, const std::string& tx_key, const std::string& address) const override; - std::string get_tx_proof(const std::string& tx_hash, const std::string& address, const std::string& message) const override; - std::shared_ptr check_tx_proof(const std::string& tx_hash, const std::string& address, const std::string& message, const std::string& signature) const override; - std::string get_spend_proof(const std::string& tx_hash, const std::string& message) const override; - bool check_spend_proof(const std::string& tx_hash, const std::string& message, const std::string& signature) const override; - std::string get_reserve_proof_wallet(const std::string& message) const override; - std::string get_reserve_proof_account(uint32_t account_idx, uint64_t amount, const std::string& message) const override; - std::shared_ptr check_reserve_proof(const std::string& address, const std::string& message, const std::string& signature) const override; - std::string get_tx_note(const std::string& tx_hash) const override; - std::vector get_tx_notes(const std::vector& tx_hashes) const override; - void set_tx_note(const std::string& tx_hashes, const std::string& notes) override; - void set_tx_notes(const std::vector& tx_hashes, const std::vector& notes) override; - std::vector get_address_book_entries(const std::vector& indices) const override; - uint64_t add_address_book_entry(const std::string& address, const std::string& description) override; - void edit_address_book_entry(uint64_t index, bool set_address, const std::string& address, bool set_description, const std::string& description) override; - void delete_address_book_entry(uint64_t index) override; - void tag_accounts(const std::string& tag, const std::vector& account_indices) override; - void untag_accounts(const std::vector& account_indices) override; - std::vector> get_account_tags() override; - void set_account_tag_label(const std::string& tag, const std::string& label) override; - std::string get_payment_uri(const monero_tx_config& config) const override; - std::shared_ptr parse_payment_uri(const std::string& uri) const override; - void set_attribute(const std::string& key, const std::string& val) override; - bool get_attribute(const std::string& key, std::string& value) const override; - void start_mining(boost::optional num_threads, boost::optional background_mining, boost::optional ignore_battery) override; - void stop_mining() override; - bool is_multisig_import_needed() const override; - monero_multisig_info get_multisig_info() const override; - std::string prepare_multisig() override; - std::string make_multisig(const std::vector& multisig_hexes, int threshold, const std::string& password) override; - monero_multisig_init_result exchange_multisig_keys(const std::vector& multisig_hexes, const std::string& password) override; - std::string export_multisig_hex() override; - int import_multisig_hex(const std::vector& multisig_hexes) override; - monero_multisig_sign_result sign_multisig_tx_hex(const std::string& multisig_tx_hex) override; - std::vector submit_multisig_tx_hex(const std::string& signed_multisig_tx_hex) override; - void change_password(const std::string& old_password, const std::string& new_password) override; - void save() override; - bool is_closed() const override; - void close(bool save = false) override; - std::shared_ptr get_balances(boost::optional account_idx, boost::optional subaddress_idx) const; - -// --------------------------------- PRIVATE -------------------------------- - -private: - friend class monero_wallet_poller; - boost::optional m_sync_period_in_ms; - std::string m_path = ""; - std::shared_ptr m_rpc; - std::shared_ptr m_daemon_connection; - std::unique_ptr m_poller; - - mutable boost::recursive_mutex m_sync_mutex; - mutable std::unordered_map> m_address_cache; - - monero_wallet_rpc* create_wallet_random(const std::shared_ptr &config); - monero_wallet_rpc* create_wallet_from_seed(const std::shared_ptr &config); - monero_wallet_rpc* create_wallet_from_keys(const std::shared_ptr &config); - - monero_sync_result refresh(const std::shared_ptr& params); - - std::map> get_account_indices(bool get_subaddress_indices) const; - std::vector get_subaddress_indices(uint32_t account_idx) const; - std::vector> get_outputs_aux(const monero_output_query& query) const; - std::vector> get_transfers_aux(const monero_transfer_query& query) const; - std::string query_key(const std::string& key_type) const; - std::vector> sweep_account(const monero_tx_config &conf); - void clear_address_cache(); - void refresh_listening(); - void poll(); - void clear(); -}; diff --git a/src/cpp/wallet/py_monero_wallet_rpc_model.cpp b/src/cpp/wallet/py_monero_wallet_rpc_model.cpp deleted file mode 100644 index f9e0ece..0000000 --- a/src/cpp/wallet/py_monero_wallet_rpc_model.cpp +++ /dev/null @@ -1,794 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ - -#include "py_monero_wallet_rpc_model.h" -#include "utils/monero_utils.h" - -// --------------------------- MONERO GET PAYMENT URI --------------------------- - -monero_payment_uri_params::monero_payment_uri_params(const monero_tx_config& config): - m_recipient_name(config.m_recipient_name), - m_tx_description(config.m_note), - m_payment_id(config.m_payment_id) { - - if (config.m_destinations.empty()) { - m_address = config.m_address; - m_amount = config.m_amount; - } else { - const auto& dest = config.m_destinations[0]; - m_address = dest->m_address; - m_amount = dest->m_amount; - } -} - -std::string monero_payment_uri_params::from_property_tree(const boost::property_tree::ptree& node) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("uri")) return it->second.data(); - } - throw std::runtime_error("Invalid make uri response"); -} - -void monero_payment_uri_params::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& response) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("uri")) { - monero_payment_uri_params::from_property_tree(it->second, response); - return; - } - if (key == std::string("address") && !it->second.data().empty()) response->m_address = it->second.data(); - else if (key == std::string("amount")) response->m_amount = it->second.get_value(); - else if (key == std::string("payment_id") && !it->second.data().empty()) response->m_payment_id = it->second.data(); - else if (key == std::string("recipient_name") && !it->second.data().empty()) response->m_recipient_name = it->second.data(); - else if (key == std::string("tx_description") && !it->second.data().empty()) response->m_tx_description = it->second.data(); - } -} - -std::shared_ptr monero_payment_uri_params::to_tx_config() const { - auto tx_config = std::make_shared(); - tx_config->m_payment_id = m_payment_id; - tx_config->m_recipient_name = m_recipient_name; - tx_config->m_note = m_tx_description; - auto dest = std::make_shared(); - dest->m_amount = m_amount; - dest->m_address = m_address; - tx_config->m_destinations.push_back(dest); - return tx_config; -} - -rapidjson::Value monero_payment_uri_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); - if (m_payment_id != boost::none) monero_utils::add_json_member("payment_id", m_payment_id.get(), allocator, root, value_str); - if (m_recipient_name != boost::none) monero_utils::add_json_member("recipient_name", m_recipient_name.get(), allocator, root, value_str); - if (m_tx_description != boost::none) monero_utils::add_json_member("tx_description", m_tx_description.get(), allocator, root, value_str); - if (m_uri != boost::none) monero_utils::add_json_member("uri", m_uri.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_amount != boost::none) monero_utils::add_json_member("amount", m_amount.get(), allocator, root, value_num); - - // return root - return root; -} - -// --------------------------- MONERO SIGNATURE --------------------------- - -std::string monero_signature::from_property_tree(const boost::property_tree::ptree& node) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("signature")) return it->second.data(); - } - - throw std::runtime_error("Invalid reserve proof response"); -} - -// --------------------------- MONERO GET BALANCE PARAMS --------------------------- - -monero_get_balance_params::monero_get_balance_params(uint32_t account_idx, boost::optional address_idx, bool all_accounts, bool strict): - m_account_idx(account_idx), - m_all_accounts(all_accounts), - m_strict(strict) { - if (address_idx != boost::none) m_address_indices.push_back(address_idx.get()); -} - -rapidjson::Value monero_get_balance_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_account_idx != boost::none) monero_utils::add_json_member("account_index", m_account_idx.get(), allocator, root, value_num); - - // set bool values - if (m_all_accounts != boost::none) monero_utils::add_json_member("all_accounts", m_all_accounts.get(), allocator, root); - if (m_strict != boost::none) monero_utils::add_json_member("strict", m_strict.get(), allocator, root); - - // set sub-arrays - if (!m_address_indices.empty()) root.AddMember("address_indices", monero_utils::to_rapidjson_val(allocator, m_address_indices), allocator); - - // return root - return root; -} - -// --------------------------- MONERO IMPORT EXPORT KEY IMAGES PARAMS --------------------------- - -monero_wallet_data_params::monero_wallet_data_params(const std::vector> &key_images) { - for(const auto &key_image : key_images) { - m_key_images.push_back(std::make_shared(*key_image)); - } -} - -rapidjson::Value monero_wallet_data_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_outputs_hex != boost::none) monero_utils::add_json_member("outputs_data_hex", m_outputs_hex.get(), allocator, root, value_str); - - // set bool values - if (m_all != boost::none) monero_utils::add_json_member("all", m_all.get(), allocator, root); - - // set sub-arrays - if (m_all == boost::none && m_key_images.size() > 0) root.AddMember("signed_key_images", monero_utils::to_rapidjson_val(allocator, m_key_images), allocator); - - // return root - return root; -} - -// --------------------------- MONERO SWEEP PARAMS --------------------------- - -monero_sweep_params::monero_sweep_params(const monero_tx_config& config): - m_address(config.m_address), - m_account_index(config.m_account_index), - m_subaddr_indices(config.m_subaddress_indices), - m_key_image(config.m_key_image), - m_relay(config.m_relay), - m_priority(config.m_priority), - m_payment_id(config.m_payment_id), - m_below_amount(config.m_below_amount), - m_get_tx_key(true), - m_get_tx_hex(true), - m_get_tx_metadata(true) { -} - -rapidjson::Value monero_sweep_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); - if (m_key_image != boost::none) monero_utils::add_json_member("key_image", m_key_image.get(), allocator, root, value_str); - if (m_payment_id != boost::none) monero_utils::add_json_member("payment_id", m_payment_id.get(), allocator, root, value_str); - - // set number values - rapidjson::Value val_num(rapidjson::kNumberType); - if (m_account_index != boost::none) monero_utils::add_json_member("account_index", m_account_index.get(), allocator, root, val_num); - if (m_priority != boost::none) monero_utils::add_json_member("priority", m_priority.get(), allocator, root, val_num); - if (m_below_amount != boost::none) monero_utils::add_json_member("below_amount", m_below_amount.get(), allocator, root, val_num); - - // set bool values - if (m_get_tx_key != boost::none) monero_utils::add_json_member("get_tx_key", m_get_tx_key.get(), allocator, root); - if (m_get_tx_keys != boost::none) monero_utils::add_json_member("get_tx_keys", m_get_tx_keys.get(), allocator, root); - if (m_get_tx_hex != boost::none) monero_utils::add_json_member("get_tx_hex", m_get_tx_hex.get(), allocator, root); - if (m_get_tx_metadata != boost::none) monero_utils::add_json_member("get_tx_metadata", m_get_tx_metadata.get(), allocator, root); - bool relay = bool_equals_2(true, m_relay); - monero_utils::add_json_member("do_not_relay", !relay, allocator, root); - - // set sub-arrays - if (m_subaddr_indices.size() > 0) root.AddMember("subaddr_indices", monero_utils::to_rapidjson_val(allocator, m_subaddr_indices), allocator); - - // return root - return root; -} - -// --------------------------- MONERO TRANSFER PARAMS --------------------------- - -monero_transfer_params::monero_transfer_params(const monero::monero_tx_config &config) { - for (const auto& sub_idx : config.m_subaddress_indices) { - m_subaddress_indices.push_back(sub_idx); - } - - if (config.m_address != boost::none) { - auto dest = std::make_shared(); - dest->m_address = config.m_address; - dest->m_amount = config.m_amount; - m_destinations.push_back(dest); - } - - for (const auto &dest : config.m_destinations) { - if (dest->m_address == boost::none) throw std::runtime_error("Destination address is not defined"); - if (dest->m_amount == boost::none) throw std::runtime_error("Destination amount is not defined"); - if (config.m_address != boost::none && *dest->m_address == *config.m_address) continue; - m_destinations.push_back(dest); - } - - m_subtract_fee_from_outputs = config.m_subtract_fee_from; - m_account_index = config.m_account_index; - m_payment_id = config.m_payment_id; - if (bool_equals_2(true, config.m_relay)) { - m_do_not_relay = false; - } - else { - m_do_not_relay = true; - } - if (config.m_priority == monero_tx_priority::DEFAULT) { - m_priority = 0; - } - else if (config.m_priority == monero_tx_priority::UNIMPORTANT) { - m_priority = 1; - } - else if (config.m_priority == monero_tx_priority::NORMAL) { - m_priority = 2; - } - else if (config.m_priority == monero_tx_priority::ELEVATED) { - m_priority = 3; - } - m_get_tx_hex = true; - m_get_tx_metadata = true; - if (bool_equals_2(true, config.m_can_split)) m_get_tx_keys = true; - else m_get_tx_key = true; -} - -rapidjson::Value monero_transfer_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_payment_id != boost::none) monero_utils::add_json_member("payment_id", m_payment_id.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_account_index != boost::none) monero_utils::add_json_member("account_index", m_account_index.get(), allocator, root, value_num); - if (m_priority != boost::none) monero_utils::add_json_member("priority", m_priority.get(), allocator, root, value_num); - - // set bool values - if (m_do_not_relay != boost::none) monero_utils::add_json_member("do_not_relay", m_do_not_relay.get(), allocator, root); - if (m_get_tx_hex != boost::none) monero_utils::add_json_member("get_tx_hex", m_get_tx_hex.get(), allocator, root); - if (m_get_tx_metadata != boost::none) monero_utils::add_json_member("get_tx_metadata", m_get_tx_metadata.get(), allocator, root); - if (m_get_tx_keys != boost::none) monero_utils::add_json_member("get_tx_keys", m_get_tx_keys.get(), allocator, root); - if (m_get_tx_key != boost::none) monero_utils::add_json_member("get_tx_key", m_get_tx_key.get(), allocator, root); - - // set sub-arrays - if (!m_subtract_fee_from_outputs.empty()) root.AddMember("subtract_fee_from_outputs", monero_utils::to_rapidjson_val(allocator, m_subtract_fee_from_outputs), allocator); - if (!m_subaddress_indices.empty()) root.AddMember("subaddr_indices", monero_utils::to_rapidjson_val(allocator, m_subaddress_indices), allocator); - if (!m_destinations.empty()) root.AddMember("destinations", monero_utils::to_rapidjson_val(allocator, m_destinations), allocator); - - // return root - return root; -} - -// --------------------------- MONERO QUERY KEY PARAMS --------------------------- - -rapidjson::Value monero_query_key_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_key_type != boost::none) monero_utils::add_json_member("key_type", m_key_type.get(), allocator, root, value_str); - - // return root - return root; -} - -// --------------------------- MONERO QUERY OUTPUT PARAMS --------------------------- - -rapidjson::Value monero_query_output_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_key_image != boost::none) monero_utils::add_json_member("key_image", m_key_image.get(), allocator, root, value_str); - - // return root - return root; -} - -// --------------------------- MONERO GET ADDRESS PARAMS --------------------------- - -rapidjson::Value monero_get_address_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_account_index != boost::none) monero_utils::add_json_member("account_index", m_account_index.get(), allocator, root, value_num); - - // set sub-arrays - if (!m_subaddress_indices.empty()) root.AddMember("address_index", monero_utils::to_rapidjson_val(allocator, m_subaddress_indices), allocator); - - // return root - return root; -} - -// --------------------------- MONERO INTEGRATED ADDRESS PARAMS --------------------------- - -rapidjson::Value monero_integrated_address_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_standard_address != boost::none) monero_utils::add_json_member("standard_address", m_standard_address.get(), allocator, root, value_str); - if (m_payment_id != boost::none) monero_utils::add_json_member("payment_id", m_payment_id.get(), allocator, root, value_str); - if (m_integrated_address != boost::none) monero_utils::add_json_member("integrated_address", m_integrated_address.get(), allocator, root, value_str); - - // return root - return root; -} - -// --------------------------- MONERO MULTISIG PARAMS --------------------------- - -rapidjson::Value monero_multisig_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_password != boost::none) monero_utils::add_json_member("password", m_password.get(), allocator, root, value_str); - if (m_multisig_tx_hex != boost::none) monero_utils::add_json_member("tx_data_hex", m_multisig_tx_hex.get(), allocator, root, value_str); - - // set number values - rapidjson::Value val_num(rapidjson::kNumberType); - if (m_threshold != boost::none) monero_utils::add_json_member("threshold", m_threshold.get(), allocator, root, val_num); - - // set bool values - if (m_enable_multisig_experimental != boost::none) monero_utils::add_json_member("enable_multisig_experimental", m_enable_multisig_experimental.get(), allocator, root); - - // set sub-arrays - if (!m_multisig_info.empty()) root.AddMember("multisig_info", monero_utils::to_rapidjson_val(allocator, m_multisig_info), allocator); - if (!m_multisig_hexes.empty()) root.AddMember("info", monero_utils::to_rapidjson_val(allocator, m_multisig_hexes), allocator); - - // return root - return root; -} - -// --------------------------- MONERO CLOSE WALLET PARAMS --------------------------- - -rapidjson::Value monero_close_wallet_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set bool values - if (m_save != boost::none) monero_utils::add_json_member("autosave_current", m_save.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO CHANGE WALLET PASSWORD PARAMS --------------------------- - -rapidjson::Value monero_change_wallet_password_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_old_password != boost::none) monero_utils::add_json_member("old_password", m_old_password.get(), allocator, root, value_str); - if (m_new_password != boost::none) monero_utils::add_json_member("new_password", m_new_password.get(), allocator, root, value_str); - - // return root - return root; -} - -// --------------------------- MONERO SET DAEMON PARAMS --------------------------- - -rapidjson::Value monero_set_daemon_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); - if (m_username != boost::none) monero_utils::add_json_member("username", m_username.get(), allocator, root, value_str); - if (m_password != boost::none) monero_utils::add_json_member("password", m_password.get(), allocator, root, value_str); - if (m_ssl_support != boost::none) monero_utils::add_json_member("ssl_support", m_ssl_support.get(), allocator, root, value_str); - if (m_ssl_options != boost::none && m_ssl_options->m_ssl_private_key_path != boost::none) monero_utils::add_json_member("ssl_private_key_path", m_ssl_options->m_ssl_private_key_path.get(), allocator, root, value_str); - if (m_ssl_options != boost::none && m_ssl_options->m_ssl_certificate_path != boost::none) monero_utils::add_json_member("ssl_certificate_path", m_ssl_options->m_ssl_certificate_path.get(), allocator, root, value_str); - if (m_ssl_options != boost::none && m_ssl_options->m_ssl_ca_file != boost::none) monero_utils::add_json_member("ssl_ca_file", m_ssl_options->m_ssl_ca_file.get(), allocator, root, value_str); - - // set bool values - if (m_trusted != boost::none) monero_utils::add_json_member("trusted", m_trusted.get(), allocator, root); - if (m_ssl_options != boost::none && m_ssl_options->m_ssl_allow_any_cert != boost::none) monero_utils::add_json_member("ssl_allow_any_cert", m_ssl_options->m_ssl_allow_any_cert.get(), allocator, root); - - // set sub-arrays - if (m_ssl_options != boost::none && !m_ssl_options->m_ssl_allowed_fingerprints.empty()) root.AddMember("ssl_allowed_fingerprints", monero_utils::to_rapidjson_val(allocator, m_ssl_options->m_ssl_allowed_fingerprints), allocator); - - // return root - return root; -} - -// --------------------------- MONERO TAG ACCOUNT PARAMS --------------------------- - -rapidjson::Value monero_account_tag_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_tag != boost::none) monero_utils::add_json_member("tag", m_tag.get(), allocator, root, value_str); - if (m_label != boost::none) monero_utils::add_json_member("label", m_label.get(), allocator, root, value_str); - - // set sub-arrays - if (!m_account_indices.empty()) root.AddMember("accounts", monero_utils::to_rapidjson_val(allocator, m_account_indices), allocator); - - // return root - return root; -} - -// --------------------------- MONERO TX NOTES PARAMS --------------------------- - -rapidjson::Value monero_tx_notes_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set sub-arrays - if (!m_tx_hashes.empty()) root.AddMember("txids", monero_utils::to_rapidjson_val(allocator, m_tx_hashes), allocator); - if (!m_notes.empty()) root.AddMember("notes", monero_utils::to_rapidjson_val(allocator, m_notes), allocator); - - // return root - return root; -} - -// --------------------------- MONERO ADDRESS BOOK ENTRY PARAMS --------------------------- - -rapidjson::Value monero_address_book_entry_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); - if (m_description != boost::none) monero_utils::add_json_member("description", m_description.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_index != boost::none) monero_utils::add_json_member("index", m_index.get(), allocator, root, value_num); - - // set bool values - if (m_set_address != boost::none) monero_utils::add_json_member("set_address", m_set_address.get(), allocator, root); - if (m_set_description != boost::none) monero_utils::add_json_member("set_description", m_set_description.get(), allocator, root); - - // set sub-arrays - if (!m_entries.empty()) root.AddMember("entries", monero_utils::to_rapidjson_val(allocator, m_entries), allocator); - - // return root - return root; -} - -// --------------------------- MONERO VERIFY SIGN MESSAGE PARAMS --------------------------- - -rapidjson::Value monero_verify_sign_message_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_data != boost::none) monero_utils::add_json_member("data", m_data.get(), allocator, root, value_str); - if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); - if (m_signature != boost::none) monero_utils::add_json_member("signature", m_signature.get(), allocator, root, value_str); - if (m_signature_type != boost::none) { - if (m_signature_type == monero::monero_message_signature_type::SIGN_WITH_VIEW_KEY) { - monero_utils::add_json_member("signature_type", std::string("view"), allocator, root, value_str); - } - else { - monero_utils::add_json_member("signature_type", std::string("spend"), allocator, root, value_str); - } - } - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_account_index != boost::none) monero_utils::add_json_member("account_index", m_account_index.get(), allocator, root, value_num); - if (m_address_index != boost::none) monero_utils::add_json_member("address_index", m_address_index.get(), allocator, root, value_num); - - // return root - return root; -} - -// --------------------------- MONERO CHECK TX KEY PARAMS --------------------------- - -rapidjson::Value monero_check_tx_key_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_tx_hash != boost::none) monero_utils::add_json_member("txid", m_tx_hash.get(), allocator, root, value_str); - if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); - if (m_tx_key != boost::none) monero_utils::add_json_member("tx_key", m_tx_key.get(), allocator, root, value_str); - - // return root - return root; -} - -// --------------------------- MONERO SIGN DESCRIBE TRANSFER PARAMS --------------------------- - -rapidjson::Value monero_sign_describe_transfer_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_unsigned_txset != boost::none) monero_utils::add_json_member("unsigned_txset", m_unsigned_txset.get(), allocator, root, value_str); - if (m_multisig_txset != boost::none) monero_utils::add_json_member("multisig_txset", m_multisig_txset.get(), allocator, root, value_str); - - // return root - return root; -} - -// --------------------------- MONERO WALLET RELAY TX PARAMS --------------------------- - -rapidjson::Value monero_wallet_relay_tx_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_hex != boost::none) monero_utils::add_json_member("hex", m_hex.get(), allocator, root, value_str); - if (m_signed_tx_hex != boost::none) monero_utils::add_json_member("tx_data_hex", m_signed_tx_hex.get(), allocator, root, value_str); - - // return root - return root; -} - -// --------------------------- MONERO CREATE EDIT SUBADDRESS PARAMS --------------------------- - -rapidjson::Value monero_create_edit_subaddress_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_label != boost::none) monero_utils::add_json_member("label", m_label.get(), allocator, root, value_str); - - // set number values - rapidjson::Value val_num(rapidjson::kNumberType); - if (m_account_index != boost::none && m_subaddress_index != boost::none) { - rapidjson::Value index(rapidjson::kObjectType); - monero_utils::add_json_member("major", m_account_index.get(), allocator, index, val_num); - monero_utils::add_json_member("minor", m_subaddress_index.get(), allocator, index, val_num); - root.AddMember("index", index, allocator); - } - else if (m_account_index != boost::none) monero_utils::add_json_member("account_index", m_account_index.get(), allocator, root, val_num); - - // return root - return root; -} - -// --------------------------- MONERO CREATE OPEN WALLET PARAMS --------------------------- - -rapidjson::Value monero_create_open_wallet_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); - if (m_view_key != boost::none && !m_view_key->empty()) monero_utils::add_json_member("viewkey", m_view_key.get(), allocator, root, value_str); - if (m_spend_key != boost::none && !m_spend_key->empty()) monero_utils::add_json_member("spendkey", m_spend_key.get(), allocator, root, value_str); - if (m_filename != boost::none) monero_utils::add_json_member("filename", m_filename.get(), allocator, root, value_str); - if (m_password != boost::none) monero_utils::add_json_member("password", m_password.get(), allocator, root, value_str); - if (m_language != boost::none) monero_utils::add_json_member("language", m_language.get(), allocator, root, value_str); - if (m_seed != boost::none) monero_utils::add_json_member("seed", m_seed.get(), allocator, root, value_str); - if (m_seed_offset != boost::none) monero_utils::add_json_member("seed_offset", m_seed_offset.get(), allocator, root, value_str); - - // set number values - rapidjson::Value val_num(rapidjson::kNumberType); - if (m_restore_height != boost::none) monero_utils::add_json_member("restore_height", m_restore_height.get(), allocator, root, val_num); - - // set bool values - if (m_autosave_current != boost::none) monero_utils::add_json_member("autosave_current", m_autosave_current.get(), allocator, root); - if (m_enable_multisig_experimental != boost::none) monero_utils::add_json_member("enable_multisig_experimental", m_enable_multisig_experimental.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO RESERVE PROOF PARAMS --------------------------- - -rapidjson::Value monero_reserve_proof_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_message != boost::none) monero_utils::add_json_member("message", m_message.get(), allocator, root, value_str); - if (m_tx_hash != boost::none) monero_utils::add_json_member("txid", m_tx_hash.get(), allocator, root, value_str); - if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); - if (m_signature != boost::none) monero_utils::add_json_member("signature", m_signature.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_account_index != boost::none) monero_utils::add_json_member("account_index", m_account_index.get(), allocator, root, value_num); - if (m_amount != boost::none) monero_utils::add_json_member("amount", m_amount.get(), allocator, root, value_num); - - // set bool values - if (m_all != boost::none) monero_utils::add_json_member("all", m_all.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO REFRESH WALLET PARAMS --------------------------- - -rapidjson::Value monero_wallet_refresh_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_period != boost::none) monero_utils::add_json_member("period", m_period.get(), allocator, root, value_num); - if (m_start_height != boost::none) monero_utils::add_json_member("start_height", m_start_height.get(), allocator, root, value_num); - - // set bool values - if (m_enable != boost::none) monero_utils::add_json_member("enable", m_enable.get(), allocator, root); - - // return root - return root; -} - -// --------------------------- MONERO GET INCOMING TRANSFERS PARAMS --------------------------- - -rapidjson::Value monero_get_incoming_transfers_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_transfer_type != boost::none) monero_utils::add_json_member("transfer_type", m_transfer_type.get(), allocator, root, value_str); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_account_index != boost::none) monero_utils::add_json_member("account_index", m_account_index.get(), allocator, root, value_num); - - // set bool values - if (m_verbose != boost::none) monero_utils::add_json_member("verbose", m_verbose.get(), allocator, root); - - // set sub-arrays - if (!m_subaddr_indices.empty()) root.AddMember("subaddr_indices", monero_utils::to_rapidjson_val(allocator, m_subaddr_indices), allocator); - - // return root - return root; -} - -// --------------------------- MONERO GET TRANSFERS PARAMS --------------------------- - -rapidjson::Value monero_get_transfers_params::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set number values - rapidjson::Value value_num(rapidjson::kNumberType); - - if (m_min_height != boost::none) monero_utils::add_json_member("min_height", m_min_height.get(), allocator, root, value_num); - if (m_max_height != boost::none) monero_utils::add_json_member("max_height", m_max_height.get(), allocator, root, value_num); - if (m_account_index != boost::none) monero_utils::add_json_member("account_index", m_account_index.get(), allocator, root, value_num); - - // set bool values - monero_utils::add_json_member("filter_by_height", m_min_height != boost::none || m_max_height != boost::none, allocator, root); - if (m_in != boost::none) monero_utils::add_json_member("in", m_in.get(), allocator, root); - if (m_out != boost::none) monero_utils::add_json_member("out", m_out.get(), allocator, root); - if (m_pool != boost::none) monero_utils::add_json_member("pool", m_pool.get(), allocator, root); - if (m_pending != boost::none) monero_utils::add_json_member("pending", m_pending.get(), allocator, root); - if (m_failed != boost::none) monero_utils::add_json_member("failed", m_failed.get(), allocator, root); - if (m_all_accounts != boost::none) monero_utils::add_json_member("all_accounts", m_all_accounts.get(), allocator, root); - - // set sub-arrays - if (!m_subaddr_indices.empty()) root.AddMember("subaddr_indices", monero_utils::to_rapidjson_val(allocator, m_subaddr_indices), allocator); - - // return root - return root; -} - -// --------------------------- MONERO GET HEIGHT RESPONSE --------------------------- - -uint64_t monero_wallet_get_height_response::from_property_tree(const boost::property_tree::ptree& node) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("height")) return it->second.get_value(); - } - throw std::runtime_error("Invalid get_height response"); -} - -// --------------------------- MONERO MULTISIG RESPONSE --------------------------- - -void monero_multisig_response::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& response) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("n_outputs")) response->m_num_outputs = it->second.get_value(); - else if (key == std::string("info") || key == std::string("multisig_info") && !it->second.data().empty()) response->m_multisig_info = it->second.data(); - else if (key == std::string("tx_hash_list")) { - const auto& tx_hash_list_node = it->second; - std::vector hashes; - for (auto it2 = tx_hash_list_node.begin(); it2 != tx_hash_list_node.end(); ++it2) { - response->m_tx_hashes.push_back(it2->second.data()); - } - } - } -} - -// --------------------------- MONERO GET BALANCE RESPONSE --------------------------- - -void monero_get_balance_response::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& response) { - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - std::string key = it->first; - if (key == std::string("balance")) response->m_balance = it->second.get_value(); - else if (key == std::string("unlocked_balance")) response->m_unlocked_balance = it->second.get_value(); - else if (key == std::string("multisig_import_needed")) response->m_multisig_import_needed = it->second.get_value(); - else if (key == std::string("time_to_unlock")) response->m_time_to_unlock = it->second.get_value(); - else if (key == std::string("blocks_to_unlock")) response->m_blocks_to_unlock = it->second.get_value(); - else if (key == std::string("per_subaddress")) { - auto node2 = it->second; - - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - auto sub = std::make_shared(); - PyMoneroSubaddress::from_rpc_property_tree(it2->second, sub); - response->m_per_subaddress.push_back(sub); - } - } - } -} diff --git a/src/cpp/wallet/py_monero_wallet_rpc_model.h b/src/cpp/wallet/py_monero_wallet_rpc_model.h deleted file mode 100644 index cabb2a2..0000000 --- a/src/cpp/wallet/py_monero_wallet_rpc_model.h +++ /dev/null @@ -1,464 +0,0 @@ -/** - * Copyright (c) everoddandeven - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Parts of this file are originally copyright (c) 2025-2026 woodser - * - * Parts of this file are originally copyright (c) 2014-2019, The Monero Project - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * All rights reserved. - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - */ -#pragma once - -#include "daemon/py_monero_daemon_rpc_model.h" -#include "py_monero_wallet_model.h" - -// ------------------------------ JSON-RPC Params --------------------------------- - -struct monero_query_key_params : public monero::serializable_struct { -public: - boost::optional m_key_type; - - monero_query_key_params(const std::string& key_type): m_key_type(key_type) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_query_output_params : public monero::serializable_struct { -public: - boost::optional m_key_image; - - monero_query_output_params(const std::string& key_image): m_key_image(key_image) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_get_address_params : public monero::serializable_struct { -public: - boost::optional m_address; - boost::optional m_account_index; - std::vector m_subaddress_indices; - - monero_get_address_params(const std::string& address): m_address(address) { } - monero_get_address_params(uint32_t account_index): m_account_index(account_index) { } - monero_get_address_params(uint32_t account_index, const std::vector& subaddress_indices): m_account_index(account_index), m_subaddress_indices(subaddress_indices) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_integrated_address_params : public monero::serializable_struct { -public: - boost::optional m_integrated_address; - boost::optional m_standard_address; - boost::optional m_payment_id; - - monero_integrated_address_params(const std::string& integrated_address): m_integrated_address(integrated_address) {} - monero_integrated_address_params(const std::string& standard_address, const std::string& payment_id): m_standard_address(standard_address), m_payment_id(payment_id) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_multisig_params : public monero::serializable_struct { -public: - // TODO monero-docs document this parameter - boost::optional m_enable_multisig_experimental; - std::vector m_multisig_info; - std::vector m_multisig_hexes; - boost::optional m_multisig_tx_hex; - boost::optional m_threshold; - boost::optional m_password; - - monero_multisig_params(bool enable_multisig_experimental = true): m_enable_multisig_experimental(enable_multisig_experimental) { } - monero_multisig_params(const std::vector& multisig_hexes, const std::string& password): m_multisig_info(multisig_hexes), m_password(password) { } - monero_multisig_params(const std::vector& multisig_hexes, int threshold, const std::string& password): m_multisig_info(multisig_hexes), m_threshold(threshold), m_password(password) { } - monero_multisig_params(const std::vector& multisig_hexes): m_multisig_hexes(multisig_hexes) { } - monero_multisig_params(const std::string& multisig_tx_hex): m_multisig_tx_hex(multisig_tx_hex) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_payment_uri_params : public monero::serializable_struct { -public: - boost::optional m_uri; - boost::optional m_address; - boost::optional m_amount; - boost::optional m_payment_id; - boost::optional m_recipient_name; - boost::optional m_tx_description; - - monero_payment_uri_params() { } - monero_payment_uri_params(const std::string& uri): m_uri(uri) { } - monero_payment_uri_params(const monero_tx_config& config); - - std::shared_ptr to_tx_config() const; - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& response); - static std::string from_property_tree(const boost::property_tree::ptree& node); -}; - -struct monero_get_balance_params : public monero::serializable_struct { -public: - boost::optional m_account_idx; - std::vector m_address_indices; - boost::optional m_all_accounts; - boost::optional m_strict; - - monero_get_balance_params(bool all_accounts, bool strict = false): m_all_accounts(all_accounts), m_strict(strict) { } - monero_get_balance_params(uint32_t account_idx, const std::vector& address_indices, bool all_accounts = false, bool strict = false): m_account_idx(account_idx), m_address_indices(address_indices), m_all_accounts(all_accounts), m_strict(strict) { } - monero_get_balance_params(uint32_t account_idx, boost::optional address_idx, bool all_accounts = false, bool strict = false); - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_close_wallet_params : public monero::serializable_struct { -public: - boost::optional m_save; - - monero_close_wallet_params(bool save = false): m_save(save) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_change_wallet_password_params : public monero::serializable_struct { -public: - boost::optional m_old_password; - boost::optional m_new_password; - - monero_change_wallet_password_params(const std::string& old_password, const std::string& new_password): m_old_password(old_password), m_new_password(new_password) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_set_daemon_params : public monero::serializable_struct { -public: - boost::optional m_address; - boost::optional m_username; - boost::optional m_password; - boost::optional m_trusted; - boost::optional m_ssl_support; - boost::optional m_ssl_options; - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_account_tag_params : public monero::serializable_struct { -public: - std::vector m_account_indices; - boost::optional m_tag; - boost::optional m_label; - - monero_account_tag_params() {} - monero_account_tag_params(const std::string& tag, const std::string& label = ""): m_tag(tag), m_label(label) { } - monero_account_tag_params(const std::vector& account_indices): m_account_indices(account_indices) { } - monero_account_tag_params(const std::string& tag, const std::vector& account_indices): m_tag(tag), m_account_indices(account_indices) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_tx_notes_params : public monero::serializable_struct { -public: - std::vector m_tx_hashes; - std::vector m_notes; - - monero_tx_notes_params(const std::vector& tx_hashes): m_tx_hashes(tx_hashes) { } - monero_tx_notes_params(const std::vector& tx_hashes, const std::vector& notes): m_tx_hashes(tx_hashes), m_notes(notes) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_address_book_entry_params : public monero::serializable_struct { -public: - boost::optional m_index; // TODO: not boost::optional - boost::optional m_set_address; - boost::optional m_address; - boost::optional m_set_description; - boost::optional m_description; - std::vector m_entries; - - monero_address_book_entry_params(uint64_t index): m_index(index) { } - monero_address_book_entry_params(const std::vector& entries): m_entries(entries) { } - monero_address_book_entry_params(uint64_t index, bool set_address, const std::string& address, bool set_description, const std::string& description): m_index(index), m_set_address(set_address), m_address(address), m_set_description(set_description), m_description(description) { } - monero_address_book_entry_params(const std::string& address, const std::string& description): m_address(address), m_description(description) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_verify_sign_message_params : public monero::serializable_struct { -public: - boost::optional m_data; - boost::optional m_address; - boost::optional m_signature; - boost::optional m_signature_type; - boost::optional m_account_index; - boost::optional m_address_index; - - monero_verify_sign_message_params(const std::string &data, const std::string &address, const std::string& signature): m_data(data), m_address(address), m_signature(signature) { } - monero_verify_sign_message_params(const std::string &data, monero::monero_message_signature_type signature_type, uint32_t account_index, uint32_t address_index): m_data(data), m_signature_type(signature_type), m_account_index(account_index), m_address_index(address_index) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_check_tx_key_params : public monero::serializable_struct { -public: - boost::optional m_tx_hash; - boost::optional m_address; - boost::optional m_tx_key; - - monero_check_tx_key_params(const std::string &tx_hash): m_tx_hash(tx_hash) { } - monero_check_tx_key_params(const std::string &tx_hash, const std::string &tx_key, const std::string &address): m_tx_hash(tx_hash), m_tx_key(tx_key), m_address(address) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_sign_describe_transfer_params : public monero::serializable_struct { -public: - boost::optional m_unsigned_txset; - boost::optional m_multisig_txset; - - monero_sign_describe_transfer_params() { } - monero_sign_describe_transfer_params(const std::string &unsigned_txset) : m_unsigned_txset(unsigned_txset) { } - monero_sign_describe_transfer_params(const std::string &unsigned_txset, const std::string &multisig_txset) : m_unsigned_txset(unsigned_txset), m_multisig_txset(multisig_txset) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_wallet_relay_tx_params : public monero::serializable_struct { -public: - boost::optional m_hex; - boost::optional m_signed_tx_hex; - - monero_wallet_relay_tx_params() {} - monero_wallet_relay_tx_params(const std::string &hex): m_hex(hex) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_sweep_params : public monero::serializable_struct { -public: - boost::optional m_address; - boost::optional m_account_index; - std::vector m_subaddr_indices; - boost::optional m_key_image; - boost::optional m_relay; - boost::optional m_priority; - boost::optional m_payment_id; - boost::optional m_below_amount; - boost::optional m_get_tx_key; - boost::optional m_get_tx_keys; - boost::optional m_get_tx_hex; - boost::optional m_get_tx_metadata; - - monero_sweep_params(bool relay = false): m_relay(relay) { } - monero_sweep_params(const monero_tx_config& config); - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_create_edit_subaddress_params : public monero::serializable_struct { -public: - boost::optional m_label; - boost::optional m_account_index; - boost::optional m_subaddress_index; - - monero_create_edit_subaddress_params(uint32_t account_idx, const std::string& label): m_account_index(account_idx), m_label(label) { } - monero_create_edit_subaddress_params(uint32_t account_idx, uint32_t subaddress_idx, const std::string& label): m_account_index(account_idx), m_subaddress_index(subaddress_idx), m_label(label) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_wallet_data_params : public monero::serializable_struct { -public: - boost::optional m_all; - std::vector> m_key_images; - boost::optional m_outputs_hex; - - monero_wallet_data_params(const std::vector> &key_images); - monero_wallet_data_params(const std::vector> &key_images): m_key_images(key_images) { } - monero_wallet_data_params(bool all): m_all(all) { } - monero_wallet_data_params(const std::string& outputs_hex): m_outputs_hex(outputs_hex) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_create_open_wallet_params : public monero::serializable_struct { -public: - boost::optional m_filename; - boost::optional m_password; - boost::optional m_language; - boost::optional m_seed; - boost::optional m_seed_offset; - boost::optional m_restore_height; - boost::optional m_autosave_current; - boost::optional m_enable_multisig_experimental; - boost::optional m_address; - boost::optional m_view_key; - boost::optional m_spend_key; - - monero_create_open_wallet_params(const boost::optional& filename, const boost::optional &password): m_filename(filename), m_password(password), m_autosave_current(false) { } - monero_create_open_wallet_params(const boost::optional& filename, const boost::optional &password, const boost::optional &language): m_filename(filename), m_password(password), m_language(language), m_autosave_current(false) { } - monero_create_open_wallet_params(const boost::optional& filename, const boost::optional &password, const boost::optional &seed, const boost::optional &seed_offset, const boost::optional &restore_height, const boost::optional &language, const boost::optional &autosave_current, const boost::optional &enable_multisig_experimental): m_filename(filename), m_password(password), m_seed(seed), m_seed_offset(seed_offset), m_restore_height(restore_height), m_language(language), m_autosave_current(autosave_current), m_enable_multisig_experimental(enable_multisig_experimental) { } - monero_create_open_wallet_params(const boost::optional& filename, const boost::optional &password, const boost::optional &address, const boost::optional &view_key, const boost::optional &spend_key, const boost::optional &restore_height, const boost::optional &autosave_current): m_filename(filename), m_password(password), m_address(address), m_view_key(view_key), m_spend_key(spend_key), m_restore_height(restore_height), m_autosave_current(autosave_current) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_reserve_proof_params : public monero::serializable_struct { -public: - boost::optional m_all; - boost::optional m_message; - boost::optional m_tx_hash; - boost::optional m_account_index; - boost::optional m_amount; - boost::optional m_address; - boost::optional m_signature; - - monero_reserve_proof_params(const std::string &message, bool all = true): m_all(all), m_message(message) { } - monero_reserve_proof_params(const std::string &address, const std::string &message, const std::string &signature): m_address(address), m_message(message), m_signature(signature) { } - monero_reserve_proof_params(const std::string &tx_hash, const std::string &address, const std::string &message, const std::string &signature): m_tx_hash(tx_hash), m_address(address), m_message(message), m_signature(signature) { } - monero_reserve_proof_params(const std::string &tx_hash, const std::string &message): m_tx_hash(tx_hash), m_message(message) { } - monero_reserve_proof_params(uint32_t account_index, uint64_t amount, const std::string &message): m_account_index(account_index), m_amount(amount), m_message(message) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_wallet_refresh_params : public monero::serializable_struct { -public: - boost::optional m_enable; - boost::optional m_period; - boost::optional m_start_height; - - monero_wallet_refresh_params() { } - monero_wallet_refresh_params(bool enable): m_enable(enable) { } - monero_wallet_refresh_params(bool enable, uint64_t period): m_enable(enable), m_period(period) { } - monero_wallet_refresh_params(uint64_t start_height): m_start_height(start_height) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_transfer_params : public monero::serializable_struct { -public: - std::vector m_subtract_fee_from_outputs; - boost::optional m_account_index; - std::vector m_subaddress_indices; - boost::optional m_payment_id; - boost::optional m_do_not_relay; - boost::optional m_priority; - boost::optional m_get_tx_hex; - boost::optional m_get_tx_metadata; - boost::optional m_get_tx_keys; - boost::optional m_get_tx_key; - std::vector> m_destinations; - - monero_transfer_params(const monero::monero_tx_config &config); - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_get_transfers_params : public monero::serializable_struct { -public: - boost::optional m_in; - boost::optional m_out; - boost::optional m_pool; - boost::optional m_pending; - boost::optional m_failed; - boost::optional m_min_height; - boost::optional m_max_height; - boost::optional m_all_accounts; - boost::optional m_account_index; - std::vector m_subaddr_indices; - - bool filter_by_height() const { return m_min_height != boost::none || m_max_height != boost::none; } - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_get_incoming_transfers_params : public monero::serializable_struct { -public: - boost::optional m_transfer_type; - boost::optional m_verbose; - boost::optional m_account_index; - std::vector m_subaddr_indices; - - monero_get_incoming_transfers_params(const std::string& transfer_type, bool verbose = true): m_transfer_type(transfer_type), m_verbose(verbose) { } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -struct monero_signature { -public: - - static std::string from_property_tree(const boost::property_tree::ptree& node); -}; - -// ------------------------------ JSON-RPC Response --------------------------------- - -struct monero_wallet_get_height_response { -public: - static uint64_t from_property_tree(const boost::property_tree::ptree& node); -}; - -struct monero_multisig_response { -public: - boost::optional m_num_outputs; - boost::optional m_multisig_info; - std::vector m_tx_hashes; - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& response); -}; - -struct monero_get_balance_response { -public: - boost::optional m_balance; - boost::optional m_unlocked_balance; - boost::optional m_multisig_import_needed; - boost::optional m_time_to_unlock; - boost::optional m_blocks_to_unlock; - std::vector> m_per_subaddress; - - monero_get_balance_response(): m_balance(0), m_unlocked_balance(0) { } - - static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& response); -}; diff --git a/src/python/monero_wallet_config.pyi b/src/python/monero_wallet_config.pyi index 176a3b5..d1f5e64 100644 --- a/src/python/monero_wallet_config.pyi +++ b/src/python/monero_wallet_config.pyi @@ -38,6 +38,8 @@ class MoneroWalletConfig(SerializableStruct): """The wallet RPC connection.""" subaddress_lookahead: int | None """Subaddress index look ahead.""" + regtest: bool | None + """Indicates if wallet is regtest.""" @staticmethod def deserialize(config_json: str) -> MoneroWalletConfig: diff --git a/src/python/monero_wallet_full.pyi b/src/python/monero_wallet_full.pyi index 7535135..cd880dd 100644 --- a/src/python/monero_wallet_full.pyi +++ b/src/python/monero_wallet_full.pyi @@ -1,5 +1,3 @@ -import typing - from .monero_wallet import MoneroWallet from .monero_wallet_config import MoneroWalletConfig from .monero_network_type import MoneroNetworkType @@ -29,34 +27,20 @@ class MoneroWalletFull(MoneroWallet): ... @staticmethod - def open_wallet(path: str, password: str, nettype: MoneroNetworkType) -> MoneroWalletFull: + def open_wallet(path: str, password: str, nettype: MoneroNetworkType, regtest: bool = False) -> MoneroWalletFull: """ Open an existing wallet from disk. :param str path: is the path to the wallet file to open. :param str password: is the password of the wallet file to open. :param MoneroNetworkType nettype: is the wallet's network type. + :param bool regtest: indicates if wallet to open is a regtest wallet (optional). :returns MoneroWalletFull: reference to the wallet instance. """ ... @staticmethod - @typing.overload - def open_wallet_data(password: str, nettype: MoneroNetworkType, keys_data: str, cache_data: str) -> MoneroWalletFull: - """ - Open an in-memory wallet from existing data buffers. - - :param string password: is the password of the wallet file to open. - :param MoneroNetworkType nettype: is the wallet's network type. - :param str keys_data: contains the contents of the ".keys" file. - :param str cache_data: contains the contents of the wallet cache file (no extension). - :returns MoneroWalletFull: reference to the wallet instance. - """ - ... - - @staticmethod - @typing.overload - def open_wallet_data(password: str, nettype: MoneroNetworkType, keys_data: str, cache_data: str, daemon_connection: MoneroRpcConnection) -> MoneroWalletFull: + def open_wallet_data(password: str, nettype: MoneroNetworkType, keys_data: str, cache_data: str, daemon_connection: MoneroRpcConnection = MoneroRpcConnection(), regtest: bool = False) -> MoneroWalletFull: """ Open an in-memory wallet from existing data buffers. @@ -65,6 +49,7 @@ class MoneroWalletFull(MoneroWallet): :param str keys_data: contains the contents of the ".keys" file. :param str cache_data: contains the contents of the wallet cache file (no extension). :param MoneroRpcConnection daemon_connection: is connection information to a daemon (default = an unconnected wallet). + :param bool regtest: indicates if wallet to open is a regtest wallet (optional). :returns MoneroWalletFull: reference to the wallet instance. """ ... diff --git a/tests/test_monero_rpc_connection.py b/tests/test_monero_rpc_connection.py index 6f595b5..b89e852 100644 --- a/tests/test_monero_rpc_connection.py +++ b/tests/test_monero_rpc_connection.py @@ -54,11 +54,10 @@ def test_rpc_connection_serialization(self, node_connection: MoneroRpcConnection # test connection connection = MoneroRpcConnection("test_node:18081", "user", "abc123", "127.0.0.1:9050", "test_node:18084", 1, 1000) connection_str = connection.serialize() - assert '{"uri":"test_node:18081","username":"user","password":"abc123","proxy_uri":"127.0.0.1:9050","zmqUri":"test_node:18084","priority":1,"timeout":1000}' == connection_str + assert '{"uri":"test_node:18081","username":"user","password":"abc123","proxy_uri":"127.0.0.1:9050","zmq_uri":"test_node:18084","priority":1,"timeout":1000}' == connection_str # Can copy a rpc connection @pytest.mark.skipif(Utils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") - @pytest.mark.xfail(reason="TODO move PyMoneroRpcConnection to monero-cpp") def test_connection_copy(self, node_connection: MoneroRpcConnection) -> None: # test copy copy: MoneroRpcConnection = MoneroRpcConnection(node_connection) diff --git a/tests/test_monero_wallet_common.py b/tests/test_monero_wallet_common.py index 3bbe743..23d5943 100644 --- a/tests/test_monero_wallet_common.py +++ b/tests/test_monero_wallet_common.py @@ -1393,7 +1393,7 @@ def test_get_subaddresses_by_indices(self, wallet: MoneroWallet) -> None: fetched_subaddresses = wallet.get_subaddresses(account.index, subaddress_indices) # original subaddresses (minus one removed if applicable) is equal to fetched subaddresses - AssertUtils.assert_subaddresses_equal(subaddresses, fetched_subaddresses) + AssertUtils.assert_list_equals(subaddresses, fetched_subaddresses) # Can get subaddress at a specified account index and subaddress index @pytest.mark.skipif(TestUtils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") @@ -1407,9 +1407,9 @@ def test_get_subaddress_by_index(self, wallet: MoneroWallet) -> None: for subaddress in subaddresses: assert subaddress.index is not None WalletUtils.test_subaddress(subaddress) - AssertUtils.assert_subaddress_equal(subaddress, wallet.get_subaddress(account.index, subaddress.index)) + AssertUtils.assert_equals(subaddress, wallet.get_subaddress(account.index, subaddress.index)) # test plural call with single subaddr number - AssertUtils.assert_subaddress_equal( + AssertUtils.assert_equals( subaddress, wallet.get_subaddresses(account.index, [subaddress.index])[0] ) @@ -1432,7 +1432,7 @@ def test_create_subaddress(self, wallet: MoneroWallet) -> None: WalletUtils.test_subaddress(subaddress) subaddresses_new = wallet.get_subaddresses(account_idx) assert len(subaddresses_new) - 1 == len(subaddresses) - AssertUtils.assert_subaddress_equal(subaddress, subaddresses_new[len(subaddresses_new) - 1]) + AssertUtils.assert_equals(subaddress, subaddresses_new[len(subaddresses_new) - 1]) # create subaddress with label subaddresses = wallet.get_subaddresses(account_idx) @@ -1442,7 +1442,7 @@ def test_create_subaddress(self, wallet: MoneroWallet) -> None: WalletUtils.test_subaddress(subaddress) subaddresses_new = wallet.get_subaddresses(account_idx) assert len(subaddresses) == len(subaddresses_new) - 1 - AssertUtils.assert_subaddress_equal(subaddress, subaddresses_new[len(subaddresses_new) - 1]) + AssertUtils.assert_equals(subaddress, subaddresses_new[len(subaddresses_new) - 1]) account_idx += 1 diff --git a/tests/test_monero_wallet_full.py b/tests/test_monero_wallet_full.py index 950f382..bda1201 100644 --- a/tests/test_monero_wallet_full.py +++ b/tests/test_monero_wallet_full.py @@ -62,6 +62,8 @@ def _create_wallet(self, config: Optional[MoneroWalletConfig], start_syncing: bo if config.restore_height is None and not random: config.restore_height = 0 + config.regtest = config.network_type == MoneroNetworkType.MAINNET and Utils.REGTEST + # create wallet wallet = MoneroWalletFull.create_wallet(config) if not random: diff --git a/tests/test_monero_wallet_interface.py b/tests/test_monero_wallet_interface.py index 6ae5499..6d2dc0c 100644 --- a/tests/test_monero_wallet_interface.py +++ b/tests/test_monero_wallet_interface.py @@ -429,7 +429,6 @@ def test_untag_accounts(self, wallet: MoneroWallet) -> None: def test_get_account_tags(self, wallet: MoneroWallet) -> None: wallet.get_account_tags() - # TODO move definitions to monero-cpp @pytest.mark.not_supported def test_set_account_tag_label(self, wallet: MoneroWallet) -> None: wallet.set_account_tag_label("", "") diff --git a/tests/test_monero_wallet_keys.py b/tests/test_monero_wallet_keys.py index 89462cd..3985267 100644 --- a/tests/test_monero_wallet_keys.py +++ b/tests/test_monero_wallet_keys.py @@ -755,9 +755,9 @@ def test_get_subaddress_by_index(self, wallet: MoneroWallet) -> None: for subaddress in subaddresses: assert subaddress.index is not None WalletUtils.test_subaddress(subaddress, False) - AssertUtils.assert_subaddress_equal(subaddress, self._get_subaddress(wallet, account.index, subaddress.index)) + AssertUtils.assert_equals(subaddress, self._get_subaddress(wallet, account.index, subaddress.index)) # test plural call with single subaddr number - AssertUtils.assert_subaddress_equal( + AssertUtils.assert_equals( subaddress, wallet.get_subaddresses(account.index, [subaddress.index])[0] ) diff --git a/tests/test_monero_wallet_model.py b/tests/test_monero_wallet_model.py index 5c64b4f..dcb822c 100644 --- a/tests/test_monero_wallet_model.py +++ b/tests/test_monero_wallet_model.py @@ -170,7 +170,6 @@ def test_destination(self) -> None: copy: MoneroDestination = dest.copy() AssertUtils.assert_equals(dest, copy) - @pytest.mark.xfail(raises=AssertionError, reason="TODO fix monero-cpp monero_rpc_connection default empty values") def test_wallet_config(self) -> None: config: MoneroWalletConfig = TestUtils.get_wallet_full_config(TestUtils.get_daemon_rpc_connection()) logger.debug(f"Testing wallet config: {config.serialize()}") diff --git a/tests/utils/assert_utils.py b/tests/utils/assert_utils.py index ac2a8ff..9b79b2d 100644 --- a/tests/utils/assert_utils.py +++ b/tests/utils/assert_utils.py @@ -1,16 +1,10 @@ import logging from abc import ABC -from os import getenv -from typing import Any, Optional -from monero import ( - SerializableStruct, MoneroSubaddress, - MoneroRpcConnection -) +from typing import Any +from monero import SerializableStruct, MoneroRpcConnection logger: logging.Logger = logging.getLogger("AssertUtils") -var = getenv("IN_CONTAINER", "true").lower() -IN_CONTAINER: bool = var == "true" or var == "1" class AssertUtils(ABC): @@ -25,11 +19,12 @@ def assert_equals(cls, expr1: Any, expr2: Any, message: str = "assertion failed" :param str message: failure message. """ if isinstance(expr1, MoneroRpcConnection) and isinstance(expr2, MoneroRpcConnection): - # TODO remove this after merge to monero-cpp assert expr1.uri == expr2.uri assert expr1.username == expr2.username assert expr1.password == expr2.password assert expr1.proxy_uri == expr2.proxy_uri + assert expr1.priority == expr2.priority + assert expr1.timeout == expr2.timeout elif isinstance(expr1, SerializableStruct) and isinstance(expr2, SerializableStruct): str1 = expr1.serialize() str2 = expr2.serialize() @@ -39,33 +34,9 @@ def assert_equals(cls, expr1: Any, expr2: Any, message: str = "assertion failed" @classmethod def assert_list_equals(cls, expr1: list[Any], expr2: list[Any], message: str = "lists doesn't equal") -> None: - assert len(expr1) == len(expr2) + size1: int = len(expr1) + size2: int = len(expr2) + assert size1 == size2, f"{size1} = {size2}" for i, elem1 in enumerate(expr1): elem2: Any = expr2[i] cls.assert_equals(elem1, elem2, message) - - @classmethod - def assert_subaddress_equal(cls, subaddress: Optional[MoneroSubaddress], other: Optional[MoneroSubaddress]) -> None: - if subaddress is None and other is None: - return - assert not (subaddress is None or other is None) - assert subaddress.address == other.address - assert subaddress.account_index == other.account_index - assert subaddress.balance == other.balance - assert subaddress.index == other.index - assert subaddress.is_used == other.is_used - assert subaddress.label == other.label - assert subaddress.num_blocks_to_unlock == other.num_blocks_to_unlock - assert subaddress.num_unspent_outputs == other.num_unspent_outputs - assert subaddress.unlocked_balance == other.unlocked_balance - - @classmethod - def assert_subaddresses_equal(cls, subaddresses1: list[MoneroSubaddress], subaddresses2: list[MoneroSubaddress]) -> None: - size1: int = len(subaddresses1) - size2: int = len(subaddresses2) - - if size1 != size2: - raise Exception("Number of subaddresses doesn't match") - - for i, subaddress in enumerate(subaddresses1): - cls.assert_subaddress_equal(subaddress, subaddresses2[i]) diff --git a/tests/utils/test_utils.py b/tests/utils/test_utils.py index 56a403e..2ae15fc 100644 --- a/tests/utils/test_utils.py +++ b/tests/utils/test_utils.py @@ -340,6 +340,7 @@ def get_wallet_full_config(cls, daemon_connection: MoneroRpcConnection) -> Moner config.seed = cls.SEED config.server = daemon_connection config.restore_height = cls.FIRST_RECEIVE_HEIGHT + config.regtest = cls.REGTEST return config @@ -369,7 +370,7 @@ def get_wallet_full(cls) -> MoneroWalletFull: else: logger.debug("Opening full wallet...") cls._WALLET_FULL = MoneroWalletFull.open_wallet( - cls.WALLET_FULL_PATH, cls.WALLET_PASSWORD, cls.NETWORK_TYPE + cls.WALLET_FULL_PATH, cls.WALLET_PASSWORD, cls.NETWORK_TYPE, cls.REGTEST ) logger.debug(f"Opened full wallet at path '{cls.WALLET_FULL_PATH}") cls._WALLET_FULL.set_daemon_connection(cls.get_daemon_rpc_connection()) @@ -424,7 +425,7 @@ def get_mining_wallet(cls) -> MoneroWalletFull: logger.debug("Mining wallet created") else: logger.debug("Opening mining wallet...") - wallet = MoneroWalletFull.open_wallet(cls.MINING_WALLET_FULL_PATH, cls.MINING_WALLET_PASSWORD, cls.NETWORK_TYPE) + wallet = MoneroWalletFull.open_wallet(cls.MINING_WALLET_FULL_PATH, cls.MINING_WALLET_PASSWORD, cls.NETWORK_TYPE, cls.REGTEST) logger.debug("Loaded mining wallet") wallet.set_daemon_connection(cls.get_daemon_rpc_connection()) @@ -570,6 +571,7 @@ def create_wallet_ground_truth( config.seed = seed config.server = daemon_connection config.restore_height = restore_height + config.regtest = cls.REGTEST if start_height is None: start_height = 0 if restore_height is None else restore_height diff --git a/tests/utils/wallet_utils.py b/tests/utils/wallet_utils.py index ed0221c..a5209ba 100644 --- a/tests/utils/wallet_utils.py +++ b/tests/utils/wallet_utils.py @@ -199,7 +199,6 @@ def test_message_signature_result(cls, result: Optional[MoneroMessageSignatureRe assert result.is_old is False assert result.version == 2 else: - # TODO set boost::optional in monero-cpp? assert result.is_good is False assert result.is_old is False #assert result.signature_type is None