From 76a3859bfa7c72223dd54556e7495bab8424729a Mon Sep 17 00:00:00 2001 From: everoddandeven Date: Sat, 21 Mar 2026 19:26:11 +0100 Subject: [PATCH] Wallet and data model fixes * Refactory and data model fixes * Move constructors to cpp files * Remove default implementations * Consolidate rpc connection data model * Other minor fixes --- CMakeLists.txt | 2 - setup.py | 2 - src/cpp/common/py_monero_common.cpp | 185 +++- src/cpp/common/py_monero_common.h | 230 ++--- src/cpp/daemon/py_monero_daemon.h | 76 +- src/cpp/daemon/py_monero_daemon_default.cpp | 72 -- src/cpp/daemon/py_monero_daemon_default.h | 25 - src/cpp/daemon/py_monero_daemon_model.cpp | 36 +- src/cpp/daemon/py_monero_daemon_model.h | 147 +-- src/cpp/daemon/py_monero_daemon_rpc.cpp | 52 +- src/cpp/daemon/py_monero_daemon_rpc.h | 48 +- src/cpp/py_monero.cpp | 126 +-- src/cpp/utils/py_monero_utils.cpp | 1 - src/cpp/wallet/py_monero_wallet.h | 8 - src/cpp/wallet/py_monero_wallet_full.cpp | 22 - src/cpp/wallet/py_monero_wallet_full.h | 22 - src/cpp/wallet/py_monero_wallet_model.cpp | 864 ++++++++++-------- src/cpp/wallet/py_monero_wallet_model.h | 391 ++------ src/cpp/wallet/py_monero_wallet_rpc.cpp | 30 +- src/cpp/wallet/py_monero_wallet_rpc.h | 5 +- .../monero_connection_priority_comparator.pyi | 4 +- src/python/monero_daemon_rpc.pyi | 13 +- src/python/monero_rpc_connection.pyi | 8 +- src/python/monero_wallet_rpc.pyi | 5 +- tests/test_monero_common.py | 8 +- tests/test_monero_rpc_connection.py | 44 +- tests/test_monero_wallet_common.py | 1 + tests/test_monero_wallet_full.py | 10 - tests/test_monero_wallet_interface.py | 18 +- tests/test_monero_wallet_rpc.py | 5 - tests/utils/assert_utils.py | 11 +- 31 files changed, 1086 insertions(+), 1385 deletions(-) delete mode 100644 src/cpp/daemon/py_monero_daemon_default.cpp delete mode 100644 src/cpp/daemon/py_monero_daemon_default.h delete mode 100644 src/cpp/wallet/py_monero_wallet_full.cpp delete mode 100644 src/cpp/wallet/py_monero_wallet_full.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f1baebc..3fd827a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,11 +22,9 @@ find_package(Boost REQUIRED COMPONENTS system thread serialization filesystem) set(SOURCES src/cpp/common/py_monero_common.cpp src/cpp/daemon/py_monero_daemon_model.cpp - src/cpp/daemon/py_monero_daemon_default.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_full.cpp src/cpp/wallet/py_monero_wallet_rpc.cpp src/cpp/utils/py_monero_utils.cpp src/cpp/py_monero.cpp diff --git a/setup.py b/setup.py index a7d847e..ce9c22c 100644 --- a/setup.py +++ b/setup.py @@ -21,11 +21,9 @@ [ 'src/cpp/common/py_monero_common.cpp', 'src/cpp/daemon/py_monero_daemon_model.cpp', - 'src/cpp/daemon/py_monero_daemon_default.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_full.cpp', 'src/cpp/wallet/py_monero_wallet_rpc.cpp', 'src/cpp/utils/py_monero_utils.cpp', 'src/cpp/py_monero.cpp' diff --git a/src/cpp/common/py_monero_common.cpp b/src/cpp/common/py_monero_common.cpp index 88edb2b..73506c9 100644 --- a/src/cpp/common/py_monero_common.cpp +++ b/src/cpp/common/py_monero_common.cpp @@ -1,12 +1,6 @@ #include "py_monero_common.h" #include "utils/monero_utils.h" -int PyMoneroConnectionPriorityComparator::compare(int p1, int p2) { - if (p1 == p2) return 0; - if (p1 == 0) return -1; - if (p2 == 0) return 1; - return p2 - p1; -} py::object PyGenUtils::convert_value(const std::string& val) { if (val == "true") return py::bool_(true); @@ -108,6 +102,64 @@ boost::property_tree::ptree PyGenUtils::parse_json_string(const std::string &jso return pt; } +PyMoneroPathRequest::PyMoneroPathRequest(const std::string& method, const boost::optional& params) { + m_method = method; + if (params != boost::none) m_params = std::make_shared(params); + else m_params = std::make_shared(); +} + +PyMoneroPathRequest::PyMoneroPathRequest(const std::string& method, const std::shared_ptr& params): + m_params(params) { + m_method = method; +} + +PyMoneroBinaryRequest::PyMoneroBinaryRequest(const std::string& method, const boost::optional& params) { + m_method = method; + if (params != boost::none) m_params = std::make_shared(params); + m_params = std::make_shared(); +} + +PyMoneroBinaryRequest::PyMoneroBinaryRequest(const std::string& method, const std::shared_ptr& params) { + m_method = method; + m_params = params; +} + +PyMoneroJsonRequestParams::PyMoneroJsonRequestParams(const boost::optional& py_params) { + m_py_params = py_params; +} + +PyMoneroJsonRequest::PyMoneroJsonRequest(): + m_version("2.0"), + m_id("0") { + m_params = std::make_shared(); +} + +PyMoneroJsonRequest::PyMoneroJsonRequest(const PyMoneroJsonRequest& request): + m_version(request.m_version), + m_id(request.m_id), + m_params(request.m_params) +{ + m_method = request.m_method; +} + +PyMoneroJsonRequest::PyMoneroJsonRequest(const std::string& method, const boost::optional& params): + m_version("2.0"), + m_id("0") { + m_method = method; + if (params != boost::none) { + m_params = std::make_shared(params); + } + else m_params = std::make_shared(); +} + +PyMoneroJsonRequest::PyMoneroJsonRequest(const std::string& method, const std::shared_ptr& params): + m_version("2.0"), + m_id("0"), + m_params(params) { + m_method = method; +} + + std::string PyMoneroBinaryRequest::to_binary_val() const { auto json_val = serialize(); std::string binary_val; @@ -227,40 +279,63 @@ PyMoneroRpcConnection::PyMoneroRpcConnection(const std::string& uri, const std:: 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("")); } -PyMoneroRpcConnection::PyMoneroRpcConnection(const PyMoneroRpcConnection& rpc) { - m_uri = rpc.m_uri; - m_proxy_uri = rpc.m_proxy_uri; - 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 PyMoneroConnectionPriorityComparator::compare(int p1, int p2) { + if (p1 == p2) return false; + if (p1 == 0) return true; + if (p2 == 0) return false; + return p1 > p2; } -int PyMoneroRpcConnection::compare(std::shared_ptr c1, std::shared_ptr c2, std::shared_ptr current_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 -1; - if (c2 == current_connection) return 1; + if (c1 == current_connection) return true; + if (c2 == current_connection) return false; // order by availability then priority then by name - if (c1->is_online() == c2->is_online()) { + if (c1->m_is_online == c2->m_is_online) { if (c1->m_priority == c2->m_priority) { - if (c1->m_uri == c2->m_uri) return 1; - else return -1; + return c1->m_uri.value_or("") < c2->m_uri.value_or(""); } - return PyMoneroConnectionPriorityComparator::compare(c1->m_priority, c2->m_priority) * -1; // order by priority in descending order + // order by priority in descending order + return !PyMoneroConnectionPriorityComparator::compare(c1->m_priority, c2->m_priority); } else { - if (c1->is_online()) return -1; - else if (c2->is_online()) return 1; - // TODO manage never connected - //else if (!c1->is_online()) return -1; - //else return 1; // c1 is offline - return -1; + 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; + return false; } } @@ -324,7 +399,7 @@ void PyMoneroRpcConnection::set_attribute(const std::string& key, const std::str m_attributes[key] = val; } -std::string PyMoneroRpcConnection::get_attribute(const std::string& key) { +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()) return std::string(""); @@ -347,7 +422,7 @@ bool PyMoneroRpcConnection::is_connected() const { return true; } -bool PyMoneroRpcConnection::check_connection(int timeout_ms) { +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); @@ -375,7 +450,7 @@ bool PyMoneroRpcConnection::check_connection(int timeout_ms) { throw std::runtime_error("Could not set rpc connection: " + m_uri.get()); } - m_http_client->connect(std::chrono::milliseconds(timeout_ms)); + m_http_client->connect(std::chrono::milliseconds(timeout_ms == boost::none ? m_timeout : *timeout_ms)); std::vector heights; heights.reserve(100); for(long i = 0; i < 100; i++) heights.push_back(i); @@ -420,6 +495,19 @@ void PyMoneroConnectionManager::add_listener(const std::shared_ptr &listener) { boost::lock_guard lock(m_listeners_mutex); m_listeners.erase(std::remove_if(m_listeners.begin(), m_listeners.end(), [&listener](std::shared_ptr iter){ return iter == listener; }), m_listeners.end()); @@ -434,6 +522,11 @@ std::vector> PyMoneroConnect return m_listeners; } +std::vector> PyMoneroConnectionManager::get_connections() const { + boost::lock_guard lock(m_connections_mutex); + return m_connections; +} + std::shared_ptr PyMoneroConnectionManager::get_connection_by_uri(const std::string &uri) { boost::lock_guard lock(m_connections_mutex); for(const auto &m_connection : m_connections) { @@ -443,7 +536,7 @@ std::shared_ptr PyMoneroConnectionManager::get_connection return nullptr; } -void PyMoneroConnectionManager::add_connection(std::shared_ptr connection) { +void PyMoneroConnectionManager::add_connection(const std::shared_ptr& connection) { if (connection->m_uri == boost::none) throw std::runtime_error("Invalid connection uri"); boost::lock_guard lock(m_connections_mutex); for(const auto &m_connection : m_connections) { @@ -474,7 +567,7 @@ void PyMoneroConnectionManager::remove_connection(const std::string &uri) { } } -void PyMoneroConnectionManager::set_connection(std::shared_ptr connection) { +void PyMoneroConnectionManager::set_connection(const std::shared_ptr& connection) { if (connection == m_current_connection) return; if (connection == nullptr) { @@ -554,27 +647,27 @@ void PyMoneroConnectionManager::stop_polling() { } } -void PyMoneroConnectionManager::start_polling(boost::optional period_ms, boost::optional auto_switch, boost::optional timeout_ms, boost::optional poll_type, boost::optional>> &excluded_connections) { +void PyMoneroConnectionManager::start_polling(const boost::optional& period_ms, const boost::optional& auto_switch, const boost::optional& timeout_ms, const boost::optional& poll_type, const boost::optional>> &excluded_connections) { // apply defaults - if (period_ms == boost::none) period_ms = DEFAULT_POLL_PERIOD; + uint64_t period = period_ms == boost::none ? DEFAULT_POLL_PERIOD : period_ms.get(); + PyMoneroConnectionPollType _pool_type = poll_type == boost::none ? PyMoneroConnectionPollType::PRIORITIZED : poll_type.get(); if (auto_switch != boost::none) set_auto_switch(auto_switch.get()); if (timeout_ms != boost::none) set_timeout(timeout_ms.get()); - if (poll_type == boost::none) poll_type = PyMoneroConnectionPollType::PRIORITIZED; // stop polling stop_polling(); // start polling - switch (poll_type.get()) { + switch (_pool_type) { case PyMoneroConnectionPollType::CURRENT: - start_polling_connection(period_ms.get()); + start_polling_connection(period); break; case PyMoneroConnectionPollType::ALL: - start_polling_connections(period_ms.get()); + start_polling_connections(period); break; case PyMoneroConnectionPollType::UNDEFINED: case PyMoneroConnectionPollType::PRIORITIZED: - start_polling_prioritized_connections(period_ms.get(), excluded_connections); + start_polling_prioritized_connections(period, excluded_connections); break; } } @@ -620,7 +713,7 @@ std::shared_ptr PyMoneroConnectionManager::get_best_avail return std::shared_ptr(nullptr); } -std::shared_ptr PyMoneroConnectionManager::get_best_available_connection(std::shared_ptr& excluded_connection) { +std::shared_ptr PyMoneroConnectionManager::get_best_available_connection(const std::shared_ptr& excluded_connection) { const std::set>& excluded_connections = { excluded_connection }; return get_best_available_connection(excluded_connections); @@ -635,8 +728,6 @@ void PyMoneroConnectionManager::disconnect() { } void PyMoneroConnectionManager::clear() { - boost::lock_guard lock(m_connections_mutex); - m_connections.clear(); if (m_current_connection != nullptr) { @@ -653,7 +744,7 @@ void PyMoneroConnectionManager::reset() { m_auto_switch = DEFAULT_AUTO_SWITCH; } -void PyMoneroConnectionManager::on_connection_changed(std::shared_ptr connection) { +void PyMoneroConnectionManager::on_connection_changed(const std::shared_ptr& connection) { boost::lock_guard lock(m_listeners_mutex); for (const auto &listener : m_listeners) { @@ -727,7 +818,7 @@ void PyMoneroConnectionManager::start_polling_connections(uint64_t period_ms) { m_thread.detach(); } -void PyMoneroConnectionManager::start_polling_prioritized_connections(uint64_t period_ms, boost::optional>> excluded_connections) { +void PyMoneroConnectionManager::start_polling_prioritized_connections(uint64_t period_ms, const boost::optional>>& excluded_connections) { m_is_polling = true; m_thread = std::thread([this, period_ms, &excluded_connections]() { while (m_is_polling) { @@ -773,7 +864,7 @@ bool PyMoneroConnectionManager::check_connections(const std::vector>> excluded_connections) { +void PyMoneroConnectionManager::check_prioritized_connections(const boost::optional>>& excluded_connections) { for (const auto &prioritized_connections : get_connections_in_ascending_priority()) { if (excluded_connections != boost::none) { std::set> ex(excluded_connections.get().begin(), excluded_connections.get().end()); diff --git a/src/cpp/common/py_monero_common.h b/src/cpp/common/py_monero_common.h index 9db9cd5..12e60c6 100644 --- a/src/cpp/common/py_monero_common.h +++ b/src/cpp/common/py_monero_common.h @@ -105,7 +105,7 @@ enum PyMoneroConnectionPollType : uint8_t { class PyMoneroConnectionPriorityComparator { public: - static int compare(int p1, int p2); + static bool compare(int p1, int p2); }; class PyGenUtils { @@ -132,17 +132,17 @@ class PyMoneroRequestParams : public PySerializableStruct { boost::optional m_py_params; PyMoneroRequestParams() { } - PyMoneroRequestParams(boost::optional py_params) { m_py_params = py_params; } + PyMoneroRequestParams(const boost::optional& py_params): m_py_params(py_params) {} std::string serialize() const override; rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override { throw std::runtime_error("PyMoneroRequestParams::to_rapid_json_value(): not implemented"); }; }; class PyMoneroRequestEmptyParams : public PyMoneroRequestParams { - public: - PyMoneroRequestEmptyParams() {} +public: + PyMoneroRequestEmptyParams() {} - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override { rapidjson::Value root(rapidjson::kObjectType); return root; }; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override { rapidjson::Value root(rapidjson::kObjectType); return root; }; }; class PyMoneroPathRequest : public PyMoneroRequest { @@ -150,35 +150,17 @@ class PyMoneroPathRequest : public PyMoneroRequest { boost::optional> m_params; PyMoneroPathRequest() { } - - PyMoneroPathRequest(std::string method, boost::optional params = boost::none) { - m_method = method; - if (params != boost::none) m_params = std::make_shared(params); - m_params = std::make_shared(); - } - - PyMoneroPathRequest(std::string method, std::shared_ptr params) { - m_method = method; - m_params = params; - } + PyMoneroPathRequest(const std::string& method, const boost::optional& params = boost::none); + PyMoneroPathRequest(const std::string& method, const std::shared_ptr& params); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; class PyMoneroBinaryRequest : public PyMoneroPathRequest { public: - PyMoneroBinaryRequest() {} - - PyMoneroBinaryRequest(std::string method, boost::optional params = boost::none) { - m_method = method; - if (params != boost::none) m_params = std::make_shared(params); - m_params = std::make_shared(); - } - - PyMoneroBinaryRequest(std::string method, std::shared_ptr params) { - m_method = method; - m_params = params; - } + PyMoneroBinaryRequest() { } + PyMoneroBinaryRequest(const std::string& method, const boost::optional& params = boost::none); + PyMoneroBinaryRequest(const std::string& method, const std::shared_ptr& params); std::string to_binary_val() const; }; @@ -186,14 +168,14 @@ class PyMoneroBinaryRequest : public PyMoneroPathRequest { class PyMoneroJsonRequestParams : public PyMoneroRequestParams { public: PyMoneroJsonRequestParams() { } - PyMoneroJsonRequestParams(boost::optional py_params) { m_py_params = py_params; } + PyMoneroJsonRequestParams(const boost::optional& py_params); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override { throw std::runtime_error("PyMoneroJsonRequestParams::to_rapid_json_value(): not implemented"); }; }; class PyMoneroJsonRequestEmptyParams : public PyMoneroJsonRequestParams { public: - PyMoneroJsonRequestEmptyParams() {} + PyMoneroJsonRequestEmptyParams() { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override { rapidjson::Value root(rapidjson::kObjectType); return root; }; }; @@ -204,35 +186,10 @@ class PyMoneroJsonRequest : public PyMoneroRequest { boost::optional m_id; boost::optional> m_params; - PyMoneroJsonRequest() { - m_version = "2.0"; - m_id = "0"; - m_params = std::make_shared(); - } - - PyMoneroJsonRequest(const PyMoneroJsonRequest& request) { - m_version = request.m_version; - m_id = request.m_id; - m_method = request.m_method; - m_params = request.m_params; - } - - PyMoneroJsonRequest(std::string method, boost::optional params = boost::none) { - m_version = "2.0"; - m_id = "0"; - m_method = method; - if (params != boost::none) { - m_params = std::make_shared(params); - } - else m_params = std::make_shared(); - } - - PyMoneroJsonRequest(std::string method, std::shared_ptr params) { - m_version = "2.0"; - m_id = "0"; - m_method = method; - m_params = params; - } + PyMoneroJsonRequest(); + PyMoneroJsonRequest(const PyMoneroJsonRequest& request); + PyMoneroJsonRequest(const std::string& method, const boost::optional& params = boost::none); + PyMoneroJsonRequest(const std::string& method, const std::shared_ptr& params); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -245,22 +202,8 @@ class PyMoneroJsonResponse { static std::shared_ptr deserialize(const std::string& response_json); - PyMoneroJsonResponse() { - m_jsonrpc = "2.0"; - m_id = "0"; - } - - PyMoneroJsonResponse(const PyMoneroJsonResponse& response) { - m_jsonrpc = response.m_jsonrpc; - m_id = response.m_id; - m_result = response.m_result; - } - - PyMoneroJsonResponse(boost::optional &result) { - m_jsonrpc = "2.0"; - m_id = "0"; - m_result = result; - } + PyMoneroJsonResponse(const PyMoneroJsonResponse& response): m_jsonrpc("2.0"), m_id("0"), m_result(response.m_result) {} + PyMoneroJsonResponse(const boost::optional &result = boost::none): m_jsonrpc("2.0"), m_id("0"), m_result(result) {} boost::optional get_result() const; }; @@ -270,14 +213,8 @@ class PyMoneroPathResponse { boost::optional m_response; PyMoneroPathResponse() { } - - PyMoneroPathResponse(const PyMoneroPathResponse& response) { - m_response = response.m_response; - } - - PyMoneroPathResponse(boost::optional &response) { - m_response = response; - } + PyMoneroPathResponse(const PyMoneroPathResponse& response): m_response(response.m_response) {} + PyMoneroPathResponse(const boost::optional &response): m_response(response) {} boost::optional get_response() const; static std::shared_ptr deserialize(const std::string& response_json); @@ -289,15 +226,8 @@ class PyMoneroBinaryResponse { boost::optional m_response; PyMoneroBinaryResponse() {} - - PyMoneroBinaryResponse(const std::string &binary) { - m_binary = binary; - } - - PyMoneroBinaryResponse(const PyMoneroBinaryResponse& response) { - m_binary = response.m_binary; - m_response = response.m_response; - } + PyMoneroBinaryResponse(const std::string &binary): m_binary(binary) {} + PyMoneroBinaryResponse(const PyMoneroBinaryResponse& response): m_binary(response.m_binary), m_response(response.m_response) {} static std::shared_ptr deserialize(const std::string& response_binary); boost::optional get_response() const; @@ -310,55 +240,22 @@ class PyMoneroRpcConnection : public monero::monero_rpc_connection { uint64_t m_timeout; boost::optional m_response_time; - static int compare(std::shared_ptr c1, std::shared_ptr c2, std::shared_ptr current_connection); + static bool before(const std::shared_ptr& c1, const std::shared_ptr& c2, const std::shared_ptr& current_connection); - 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 = 0); - PyMoneroRpcConnection(const PyMoneroRpcConnection& rpc); + 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); PyMoneroRpcConnection(const monero::monero_rpc_connection& rpc); + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; + bool is_onion() const; bool is_i2p() const; void set_credentials(const std::string& username, const std::string& password); void set_attribute(const std::string& key, const std::string& val); - std::string get_attribute(const std::string& key); + std::string get_attribute(const std::string& key) const; bool is_online() const; bool is_authenticated() const; bool is_connected() const; - bool check_connection(int timeout_ms = 2000); - - 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 { - if (!m_http_client) throw std::runtime_error("http client not set"); - - rapidjson::Document document(rapidjson::Type::kObjectType); - rapidjson::Value req = request.to_rapidjson_val(document.GetAllocator()); - rapidjson::StringBuffer sb; - rapidjson::Writer writer(sb); - req.Accept(writer); - std::string body = sb.GetString(); - - const epee::net_utils::http::http_response_info* response = invoke_post(uri, body, timeout); - - int status_code = response->m_response_code; - - if (status_code == 200) { - res = *t_response::deserialize(response->m_body); - } - - return status_code; - } - - inline 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 { - if (!m_http_client) throw std::runtime_error("http client not set"); - - std::shared_ptr _res = std::make_shared(); - const epee::net_utils::http::http_response_info* response = _res.get(); - boost::lock_guard lock(m_mutex); - - if (!m_http_client->invoke_post(uri, body, timeout, &response)) throw std::runtime_error("Network error"); - - return response; - } + bool check_connection(const boost::optional& timeout_ms = boost::none); inline const std::shared_ptr send_json_request(const PyMoneroJsonRequest &request, std::chrono::milliseconds timeout = std::chrono::seconds(15)) { PyMoneroJsonResponse response; @@ -398,19 +295,19 @@ class PyMoneroRpcConnection : public monero::monero_rpc_connection { // exposed python methods - inline boost::optional send_json_request(const std::string method, boost::optional parameters) { + inline boost::optional send_json_request(const std::string& method, const boost::optional& parameters) { PyMoneroJsonRequest request(method, parameters); auto response = send_json_request(request); return response->get_result(); } - inline boost::optional send_path_request(const std::string method, boost::optional parameters) { + inline boost::optional send_path_request(const std::string& method, const boost::optional& parameters) { PyMoneroPathRequest request(method, parameters); auto response = send_path_request(request); return response->get_response(); } - inline boost::optional send_binary_request(const std::string method, boost::optional parameters) { + inline boost::optional send_binary_request(const std::string& method, const boost::optional& parameters) { PyMoneroBinaryRequest request(method, parameters); auto response = send_binary_request(request); return response->m_binary; @@ -424,18 +321,53 @@ class PyMoneroRpcConnection : public monero::monero_rpc_connection { std::unordered_map m_attributes; boost::optional m_is_online; boost::optional m_is_authenticated; + + 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 { + if (!m_http_client) throw std::runtime_error("http client not set"); + + rapidjson::Document document(rapidjson::Type::kObjectType); + rapidjson::Value req = request.to_rapidjson_val(document.GetAllocator()); + rapidjson::StringBuffer sb; + rapidjson::Writer writer(sb); + req.Accept(writer); + std::string body = sb.GetString(); + + const epee::net_utils::http::http_response_info* response = invoke_post(uri, body, timeout); + + int status_code = response->m_response_code; + + if (status_code == 200) { + res = *t_response::deserialize(response->m_body); + } + + return status_code; + } + + inline 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 { + if (!m_http_client) throw std::runtime_error("http client not set"); + + std::shared_ptr _res = std::make_shared(); + const epee::net_utils::http::http_response_info* response = _res.get(); + boost::lock_guard lock(m_mutex); + + if (!m_http_client->invoke_post(uri, body, timeout, &response)) throw std::runtime_error("Network error"); + + return response; + } + }; struct monero_connection_manager_listener { public: - virtual void on_connection_changed(std::shared_ptr &connection) { + virtual void on_connection_changed(const std::shared_ptr &connection) { throw std::runtime_error("monero_connection_manager_listener::on_connection_changed(): not implemented"); } }; class PyMoneroConnectionManagerListener : public monero_connection_manager_listener { public: - void on_connection_changed(std::shared_ptr &connection) override { + void on_connection_changed(const std::shared_ptr &connection) override { PYBIND11_OVERRIDE_PURE(void, monero_connection_manager_listener, on_connection_changed, connection); } }; @@ -443,29 +375,23 @@ class PyMoneroConnectionManagerListener : public monero_connection_manager_liste class PyMoneroConnectionManager { public: + ~PyMoneroConnectionManager(); PyMoneroConnectionManager() { } - - PyMoneroConnectionManager(const PyMoneroConnectionManager &connection_manager) { - m_listeners = connection_manager.get_listeners(); - m_connections = connection_manager.get_connections(); - m_current_connection = connection_manager.get_connection(); - m_auto_switch = connection_manager.get_auto_switch(); - m_timeout = connection_manager.get_timeout(); - } + PyMoneroConnectionManager(const PyMoneroConnectionManager &connection_manager); void add_listener(const std::shared_ptr &listener); void remove_listener(const std::shared_ptr &listener); void remove_listeners(); std::vector> get_listeners() const; std::shared_ptr get_connection_by_uri(const std::string &uri); - void add_connection(std::shared_ptr connection); + void add_connection(const std::shared_ptr& connection); void add_connection(const std::string &uri); void remove_connection(const std::string &uri); - void set_connection(std::shared_ptr connection); + void set_connection(const std::shared_ptr& connection); void set_connection(const std::string& uri); bool has_connection(const std::string& uri); std::shared_ptr get_connection() const { return m_current_connection; } - std::vector> get_connections() const { return m_connections; } + std::vector> get_connections() const; bool get_auto_switch() const { return m_auto_switch; } void set_timeout(uint64_t timeout_ms) { m_timeout = timeout_ms; } uint64_t get_timeout() const { return m_timeout; } @@ -473,10 +399,10 @@ class PyMoneroConnectionManager { void check_connection(); void set_auto_switch(bool auto_switch); void stop_polling(); - void start_polling(boost::optional period_ms, boost::optional auto_switch, boost::optional timeout_ms, boost::optional poll_type, boost::optional>> &excluded_connections); + void start_polling(const boost::optional& period_ms, const boost::optional& auto_switch, const boost::optional& timeout_ms, const boost::optional& poll_type, const boost::optional>> &excluded_connections); std::vector> get_peer_connections() const { throw std::runtime_error("PyMoneroConnectionManager::get_peer_connections(): not implemented"); } std::shared_ptr get_best_available_connection(const std::set>& excluded_connections = {}); - std::shared_ptr get_best_available_connection(std::shared_ptr& excluded_connection); + std::shared_ptr get_best_available_connection(const std::shared_ptr& excluded_connection); void check_connections(); void disconnect(); void clear(); @@ -499,13 +425,13 @@ class PyMoneroConnectionManager { bool m_is_polling = false; std::thread m_thread; - void on_connection_changed(std::shared_ptr connection); + void on_connection_changed(const std::shared_ptr& connection); std::vector>> get_connections_in_ascending_priority(); void start_polling_connection(uint64_t period_ms); void start_polling_connections(uint64_t period_ms); - void start_polling_prioritized_connections(uint64_t period_ms, boost::optional>> excluded_connections); + void start_polling_prioritized_connections(uint64_t period_ms, const boost::optional>>& excluded_connections); bool check_connections(const std::vector>& connections, const std::set>& excluded_connections = {}); - void check_prioritized_connections(boost::optional>> excluded_connections); + void check_prioritized_connections(const boost::optional>>& excluded_connections); std::shared_ptr process_responses(const std::vector>& responses); std::shared_ptr get_best_connection_from_prioritized_responses(const std::vector>& responses); std::shared_ptr update_best_connection_in_priority(); diff --git a/src/cpp/daemon/py_monero_daemon.h b/src/cpp/daemon/py_monero_daemon.h index 43faad8..af8949e 100644 --- a/src/cpp/daemon/py_monero_daemon.h +++ b/src/cpp/daemon/py_monero_daemon.h @@ -5,7 +5,7 @@ class monero_daemon_listener { public: - virtual void on_block_header(const std::shared_ptr &header) { + virtual void on_block_header(const std::shared_ptr& header) { m_last_header = header; } @@ -14,7 +14,7 @@ class monero_daemon_listener { class PyMoneroDaemonListener : public monero_daemon_listener { public: - virtual void on_block_header(const std::shared_ptr &header) { + virtual void on_block_header(const std::shared_ptr& header) { PYBIND11_OVERRIDE(void, monero_daemon_listener, on_block_header, header); } }; @@ -24,7 +24,7 @@ class PyMoneroBlockNotifier : public PyMoneroDaemonListener { boost::mutex* temp; boost::condition_variable* cv; PyMoneroBlockNotifier(boost::mutex* temp, boost::condition_variable* cv) { this->temp = temp; this->cv = cv; } - void on_block_header(const std::shared_ptr &header) override { + void on_block_header(const std::shared_ptr& header) override { m_last_header = header; cv->notify_one(); } @@ -41,8 +41,8 @@ class PyMoneroDaemon { virtual bool is_trusted() { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual uint64_t get_height() { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::string get_block_hash(uint64_t height) { throw std::runtime_error("PyMoneroDaemon: not supported"); } - virtual std::shared_ptr get_block_template(std::string& wallet_address) { throw std::runtime_error("PyMoneroDaemon: not supported"); } - virtual std::shared_ptr get_block_template(std::string& wallet_address, int reserve_size) { throw std::runtime_error("PyMoneroDaemon: not supported"); } + virtual std::shared_ptr get_block_template(const std::string& wallet_address) { throw std::runtime_error("PyMoneroDaemon: not supported"); } + virtual std::shared_ptr get_block_template(const std::string& wallet_address, int reserve_size) { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::shared_ptr get_last_block_header() { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::shared_ptr get_block_header_by_hash(const std::string& hash) { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::shared_ptr get_block_header_by_height(uint64_t height) { throw std::runtime_error("PyMoneroDaemon: not supported"); } @@ -53,16 +53,41 @@ class PyMoneroDaemon { virtual std::vector> get_blocks_by_height(const std::vector& heights) { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::vector> get_blocks_by_range(boost::optional start_height, boost::optional end_height) { throw std::runtime_error("PyMoneroDaemon: 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("PyMoneroDaemon: not supported"); } - virtual std::vector get_block_hashes(std::vector block_hashes, uint64_t start_height) { throw std::runtime_error("PyMoneroDaemon: not supported"); } - virtual boost::optional> get_tx(const std::string& tx_hash, bool prune = false) { throw std::runtime_error("PyMoneroDaemon: not supported"); } + virtual std::vector get_block_hashes(const std::vector& block_hashes, uint64_t start_height) { throw std::runtime_error("PyMoneroDaemon: 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("PyMoneroDaemon: not supported"); } - virtual boost::optional get_tx_hex(const std::string& tx_hash, bool prune = false) { throw std::runtime_error("PyMoneroDaemon: 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("PyMoneroDaemon: not supported"); } virtual std::shared_ptr get_miner_tx_sum(uint64_t height, uint64_t num_blocks) { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::shared_ptr get_fee_estimate(uint64_t grace_blocks = 0) { throw std::runtime_error("PyMoneroDaemon: not supported"); } - virtual std::shared_ptr submit_tx_hex(std::string& tx_hex, bool do_not_relay = false) { throw std::runtime_error("PyMoneroDaemon: not supported"); } - virtual void relay_tx_by_hash(std::string& tx_hash) { throw std::runtime_error("PyMoneroDaemon: not supported"); } - virtual void relay_txs_by_hash(std::vector& tx_hashes) { throw std::runtime_error("PyMoneroDaemon: not supported"); } + virtual std::shared_ptr submit_tx_hex(const std::string& tx_hex, bool do_not_relay = false) { throw std::runtime_error("PyMoneroDaemon: 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("PyMoneroDaemon: not supported"); } virtual std::vector> get_tx_pool() { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::vector get_tx_pool_hashes() { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::vector get_tx_pool_backlog() { throw std::runtime_error("PyMoneroDaemon: not supported"); } @@ -70,12 +95,18 @@ class PyMoneroDaemon { virtual void flush_tx_pool() { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual void flush_tx_pool(const std::vector &hashes) { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual void flush_tx_pool(const std::string &hash) { throw std::runtime_error("PyMoneroDaemon: not supported"); } - virtual PyMoneroKeyImageSpentStatus get_key_image_spent_status(std::string& key_image) { throw std::runtime_error("PyMoneroDaemon: not supported"); } - virtual std::vector get_key_image_spent_statuses(std::vector& key_images) { throw std::runtime_error("PyMoneroDaemon: not supported"); } - virtual std::vector> get_outputs(std::vector& outputs) { throw std::runtime_error("PyMoneroDaemon: not supported"); } + virtual PyMoneroKeyImageSpentStatus 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("PyMoneroDaemon: not supported"); } + virtual std::vector> get_outputs(const std::vector& outputs) { throw std::runtime_error("PyMoneroDaemon: 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("PyMoneroDaemon: not supported"); } - virtual std::vector> get_output_distribution(std::vector amounts) { throw std::runtime_error("PyMoneroDaemon: not supported"); } - virtual std::vector> get_output_distribution(std::vector amounts, bool is_cumulative, uint64_t start_height, uint64_t end_height) { throw std::runtime_error("PyMoneroDaemon: not supported"); } + virtual std::vector> get_output_distribution(const std::vector& amounts) { throw std::runtime_error("PyMoneroDaemon: not supported"); } + virtual std::vector> get_output_distribution(const std::vector& amounts, bool is_cumulative, uint64_t start_height, uint64_t end_height) { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::shared_ptr get_info() { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::shared_ptr get_sync_info() { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::shared_ptr get_hard_fork_info() { throw std::runtime_error("PyMoneroDaemon: not supported"); } @@ -93,11 +124,20 @@ class PyMoneroDaemon { virtual void set_incoming_peer_limit(int limit) { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::vector> get_peer_bans() { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual void set_peer_bans(const std::vector>& bans) { throw std::runtime_error("PyMoneroDaemon: not supported"); } - virtual void set_peer_ban(const std::shared_ptr& ban) { throw std::runtime_error("PyMoneroDaemon: 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("PyMoneroDaemon: not supported"); } virtual void stop_mining() { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::shared_ptr get_mining_status() { throw std::runtime_error("PyMoneroDaemon: not supported"); } - virtual void submit_block(const std::string& block_blob) { throw std::runtime_error("PyMoneroDaemon: 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("PyMoneroDaemon: not supported"); } virtual std::shared_ptr prune_blockchain(bool check) { throw std::runtime_error("PyMoneroDaemon: not supported"); } virtual std::shared_ptr check_for_update() { throw std::runtime_error("PyMoneroDaemon: not supported"); } diff --git a/src/cpp/daemon/py_monero_daemon_default.cpp b/src/cpp/daemon/py_monero_daemon_default.cpp deleted file mode 100644 index b0d9870..0000000 --- a/src/cpp/daemon/py_monero_daemon_default.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "py_monero_daemon_default.h" - - -void PyMoneroDaemonDefault::add_listener(const std::shared_ptr &listener) { - boost::lock_guard lock(m_listeners_mutex); - m_listeners.push_back(listener); - refresh_listening(); -} - -void PyMoneroDaemonDefault::remove_listener(const std::shared_ptr &listener) { - boost::lock_guard lock(m_listeners_mutex); - m_listeners.erase(std::remove_if(m_listeners.begin(), m_listeners.end(), [&listener](std::shared_ptr iter){ return iter == listener; }), m_listeners.end()); - refresh_listening(); -} - -void PyMoneroDaemonDefault::remove_listeners() { - boost::lock_guard lock(m_listeners_mutex); - m_listeners.clear(); - refresh_listening(); -} - -boost::optional> PyMoneroDaemonDefault::get_tx(const std::string& tx_hash, bool prune) { - 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; -} - -void PyMoneroDaemonDefault::relay_tx_by_hash(std::string& tx_hash) { - std::vector tx_hashes; - tx_hashes.push_back(tx_hash); - relay_txs_by_hash(tx_hashes); -} - -PyMoneroKeyImageSpentStatus PyMoneroDaemonDefault::get_key_image_spent_status(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]; -} - -boost::optional PyMoneroDaemonDefault::get_tx_hex(const std::string& tx_hash, bool prune) { - 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; -} - -void PyMoneroDaemonDefault::submit_block(const std::string& block_blob) { - std::vector block_blobs; - block_blobs.push_back(block_blob); - return submit_blocks(block_blobs); -} - -void PyMoneroDaemonDefault::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); -} diff --git a/src/cpp/daemon/py_monero_daemon_default.h b/src/cpp/daemon/py_monero_daemon_default.h deleted file mode 100644 index b028ff6..0000000 --- a/src/cpp/daemon/py_monero_daemon_default.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "py_monero_daemon.h" - -class PyMoneroDaemonDefault : public PyMoneroDaemon { -public: - - std::vector> get_listeners() override { return m_listeners; } - void add_listener(const std::shared_ptr &listener) override; - void remove_listener(const std::shared_ptr &listener) override; - void remove_listeners() override; - boost::optional> get_tx(const std::string& tx_hash, bool prune = false) override; - void relay_tx_by_hash(std::string& tx_hash) override; - PyMoneroKeyImageSpentStatus get_key_image_spent_status(std::string& key_image) override; - boost::optional get_tx_hex(const std::string& tx_hash, bool prune = false); - void submit_block(const std::string& block_blob) override; - void set_peer_ban(const std::shared_ptr& ban) override; - -protected: - mutable boost::recursive_mutex m_listeners_mutex; - std::vector> m_listeners; - - virtual void refresh_listening() { } -}; - diff --git a/src/cpp/daemon/py_monero_daemon_model.cpp b/src/cpp/daemon/py_monero_daemon_model.cpp index f083966..6c7e539 100644 --- a/src/cpp/daemon/py_monero_daemon_model.cpp +++ b/src/cpp/daemon/py_monero_daemon_model.cpp @@ -1,6 +1,31 @@ #include "py_monero_daemon_model.h" #include "utils/monero_utils.h" +PyMoneroDownloadUpdateParams::PyMoneroDownloadUpdateParams(const std::string& command, const std::string& path): m_command(command) { + if (!path.empty()) m_path = path; +} + +PyMoneroStartMiningParams::PyMoneroStartMiningParams(const std::string& address, int num_threads, bool is_background, bool ignore_battery): + m_address(address), + m_num_threads(num_threads), + m_is_background(is_background), + m_ignore_battery(ignore_battery) { +} + +PyMoneroGetTxsParams::PyMoneroGetTxsParams(const std::vector &tx_hashes, bool prune, bool decode_as_json): + m_tx_hashes(tx_hashes), + m_prune(prune), + m_decode_as_json(decode_as_json) { +} + +PyMoneroGetOutputHistrogramParams::PyMoneroGetOutputHistrogramParams(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) { +} + 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; @@ -291,11 +316,9 @@ void PyMoneroTx::from_property_tree(const boost::property_tree::ptree& node, con 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; - std::vector signatures; for(auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - signatures.push_back(it2->second.data()); + tx->m_signatures.push_back(it2->second.data()); } - tx->m_signatures = signatures; } else if (key == std::string("last_failed_height")) { uint64_t last_failed_height = it->second.get_value(); @@ -836,13 +859,6 @@ rapidjson::Value PyMoneroDownloadUpdateParams::to_rapidjson_val(rapidjson::Docum return root; } -rapidjson::Value PyMoneroCheckUpdateParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - rapidjson::Value value_str(rapidjson::kStringType); - if (m_command != boost::none) monero_utils::add_json_member("command", m_command.get(), allocator, root, value_str); - return root; -} - rapidjson::Value PyMoneroStartMiningParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); rapidjson::Value value_str(rapidjson::kStringType); diff --git a/src/cpp/daemon/py_monero_daemon_model.h b/src/cpp/daemon/py_monero_daemon_model.h index 5110bb9..2f922dd 100644 --- a/src/cpp/daemon/py_monero_daemon_model.h +++ b/src/cpp/daemon/py_monero_daemon_model.h @@ -45,25 +45,7 @@ class PyMoneroDownloadUpdateParams : public PyMoneroRequestParams { boost::optional m_command; boost::optional m_path; - PyMoneroDownloadUpdateParams() { - m_command = "download"; - } - - PyMoneroDownloadUpdateParams(std::string path) { - m_command = "download"; - m_path = m_path; - } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - -class PyMoneroCheckUpdateParams : public PyMoneroRequestParams { -public: - boost::optional m_command; - - PyMoneroCheckUpdateParams() { - m_command = "check"; - } + PyMoneroDownloadUpdateParams(const std::string& command = "download", const std::string& path = ""); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -75,20 +57,7 @@ class PyMoneroStartMiningParams : public PyMoneroRequestParams { boost::optional m_is_background; boost::optional m_ignore_battery; - PyMoneroStartMiningParams() {} - - PyMoneroStartMiningParams(std::string address, int num_threads, bool is_background, bool ignore_battery) { - m_address = address; - m_num_threads = num_threads; - m_is_background = is_background; - m_ignore_battery = ignore_battery; - } - - PyMoneroStartMiningParams(int num_threads, bool is_background, bool ignore_battery) { - m_num_threads = num_threads; - m_is_background = is_background; - m_ignore_battery = ignore_battery; - } + PyMoneroStartMiningParams(const std::string& address, int num_threads, bool is_background, bool ignore_battery); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -97,9 +66,7 @@ class PyMoneroPruneBlockchainParams : public PyMoneroJsonRequestParams { public: boost::optional m_check; - PyMoneroPruneBlockchainParams(bool check = true) { - m_check = check; - } + PyMoneroPruneBlockchainParams(bool check = true): m_check(check) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -108,10 +75,7 @@ class PyMoneroSubmitBlocksParams : public PyMoneroJsonRequestParams { public: std::vector m_block_blobs; - PyMoneroSubmitBlocksParams() { } - PyMoneroSubmitBlocksParams(const std::vector& block_blobs) { - m_block_blobs = block_blobs; - } + PyMoneroSubmitBlocksParams(const std::vector& block_blobs): m_block_blobs(block_blobs) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -122,15 +86,8 @@ class PyMoneroGetBlockParams : public PyMoneroJsonRequestParams { boost::optional m_hash; boost::optional m_fill_pow_hash; - PyMoneroGetBlockParams(uint64_t height, bool fill_pow_hash = false) { - m_height = height; - m_fill_pow_hash = fill_pow_hash; - } - - PyMoneroGetBlockParams(std::string hash, bool fill_pow_hash = false) { - m_hash = hash; - m_fill_pow_hash = fill_pow_hash; - } + PyMoneroGetBlockParams(uint64_t height, bool fill_pow_hash = false): m_height(height), m_fill_pow_hash(fill_pow_hash) { } + PyMoneroGetBlockParams(const std::string& hash, bool fill_pow_hash = false): m_hash(hash), m_fill_pow_hash(fill_pow_hash) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -140,12 +97,7 @@ class PyMoneroGetBlockRangeParams : public PyMoneroJsonRequestParams { boost::optional m_start_height; boost::optional m_end_height; - PyMoneroGetBlockRangeParams() { } - - PyMoneroGetBlockRangeParams(uint64_t start_height, uint64_t end_height) { - m_start_height = start_height; - m_end_height = end_height; - } + PyMoneroGetBlockRangeParams(uint64_t start_height, uint64_t end_height): m_start_height(start_height), m_end_height(end_height) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -154,11 +106,7 @@ class PyMoneroGetBlockHashParams : public PyMoneroJsonRequestParams { public: boost::optional m_height; - PyMoneroGetBlockHashParams() {} - - PyMoneroGetBlockHashParams(uint64_t height) { - m_height = height; - } + PyMoneroGetBlockHashParams(uint64_t height): m_height(height) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -168,16 +116,7 @@ class PyMoneroGetBlockTemplateParams : public PyMoneroJsonRequestParams { boost::optional m_wallet_address; boost::optional m_reserve_size; - PyMoneroGetBlockTemplateParams() { } - - PyMoneroGetBlockTemplateParams(std::string wallet_address) { - m_wallet_address = wallet_address; - } - - PyMoneroGetBlockTemplateParams(std::string wallet_address, int reserve_size) { - m_wallet_address = wallet_address; - m_reserve_size = reserve_size; - } + PyMoneroGetBlockTemplateParams(const std::string& wallet_address, const boost::optional& reserve_size = boost::none): m_wallet_address(wallet_address), m_reserve_size(reserve_size) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -186,22 +125,13 @@ class PyMoneroGetBlocksByHeightRequest : public PyMoneroBinaryRequest { public: std::vector m_heights; - PyMoneroGetBlocksByHeightRequest(const std::vector& heights) { - m_method = "get_blocks_by_height.bin"; - m_heights = heights; - } + PyMoneroGetBlocksByHeightRequest(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; }; class PyMoneroVersion : public monero::monero_version { public: - PyMoneroVersion() {} - - PyMoneroVersion(uint32_t number, bool is_release) { - m_number = number; - m_is_release = is_release; - } static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& version); }; @@ -352,11 +282,7 @@ class PyMoneroSubmitTxParams : public PyMoneroRequestParams { boost::optional m_tx_hex; boost::optional m_do_not_relay; - PyMoneroSubmitTxParams() {} - PyMoneroSubmitTxParams(std::string tx_hex, bool do_not_relay) { - m_tx_hex = tx_hex; - m_do_not_relay = do_not_relay; - } + PyMoneroSubmitTxParams(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; }; @@ -365,10 +291,7 @@ class PyMoneroRelayTxParams : public PyMoneroJsonRequestParams { public: std::vector m_tx_hashes; - PyMoneroRelayTxParams() {} - PyMoneroRelayTxParams(const std::vector tx_hashes) { - m_tx_hashes = tx_hashes; - } + PyMoneroRelayTxParams(const std::vector& tx_hashes): m_tx_hashes(tx_hashes) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -523,11 +446,8 @@ class PyMoneroBandwithLimits : public PyMoneroRequestParams { boost::optional m_up; boost::optional m_down; - PyMoneroBandwithLimits() {} - PyMoneroBandwithLimits(int up, int down) { - m_up = up; - m_down = down; - } + PyMoneroBandwithLimits() { } + PyMoneroBandwithLimits(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); @@ -538,12 +458,6 @@ class PyMoneroPeerLimits : public PyMoneroRequestParams { boost::optional m_in_peers; boost::optional m_out_peers; - PyMoneroPeerLimits() {} - PyMoneroPeerLimits(int in, int out) { - m_in_peers = in; - m_out_peers = out; - } - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -560,11 +474,7 @@ class PyMoneroGetMinerTxSumParams : public PyMoneroJsonRequestParams { boost::optional m_height; boost::optional m_count; - PyMoneroGetMinerTxSumParams() {} - PyMoneroGetMinerTxSumParams(uint64_t height, uint64_t count) { - m_height = height; - m_count = count; - } + PyMoneroGetMinerTxSumParams(uint64_t height, uint64_t count): m_height(height), m_count(count) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -573,9 +483,7 @@ class PyMoneroGetFeeEstimateParams : public PyMoneroJsonRequestParams { public: boost::optional m_grace_blocks; - PyMoneroGetFeeEstimateParams(uint64_t grace_blocks = 0) { - m_grace_blocks = grace_blocks; - } + PyMoneroGetFeeEstimateParams(uint64_t grace_blocks = 0): m_grace_blocks(grace_blocks) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -584,10 +492,7 @@ class PyMoneroSetBansParams : public PyMoneroJsonRequestParams { public: std::vector> m_bans; - PyMoneroSetBansParams() {} - PyMoneroSetBansParams(const std::vector>& bans) { - m_bans = bans; - } + PyMoneroSetBansParams(const std::vector>& bans): m_bans(bans) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -598,11 +503,7 @@ class PyMoneroGetTxsParams : public PyMoneroRequestParams { boost::optional m_decode_as_json; boost::optional m_prune; - PyMoneroGetTxsParams(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; - } + PyMoneroGetTxsParams(const std::vector &tx_hashes, bool prune, bool decode_as_json = true); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -615,13 +516,7 @@ class PyMoneroGetOutputHistrogramParams : public PyMoneroJsonRequestParams { boost::optional m_is_unlocked; boost::optional m_recent_cutoff; - PyMoneroGetOutputHistrogramParams(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; - } + PyMoneroGetOutputHistrogramParams(const std::vector& amounts, const boost::optional& min_count, const boost::optional& max_count, const boost::optional& is_unlocked, const boost::optional& recent_cutoff); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -630,9 +525,7 @@ class PyMoneroIsKeyImageSpentParams : public PyMoneroRequestParams { public: std::vector m_key_images; - PyMoneroIsKeyImageSpentParams(const std::vector & key_images) { - m_key_images = key_images; - } + PyMoneroIsKeyImageSpentParams(const std::vector& key_images): m_key_images(key_images) { } 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 index 7bda45a..263f0d4 100644 --- a/src/cpp/daemon/py_monero_daemon_rpc.cpp +++ b/src/cpp/daemon/py_monero_daemon_rpc.cpp @@ -8,6 +8,10 @@ PyMoneroDaemonPoller::~PyMoneroDaemonPoller() { set_is_polling(false); } +PyMoneroDaemonPoller::PyMoneroDaemonPoller(PyMoneroDaemon* daemon, uint64_t poll_period_ms): m_poll_period_ms(poll_period_ms), m_is_polling(false) { + m_daemon = daemon; +} + void PyMoneroDaemonPoller::set_is_polling(bool is_polling) { if (is_polling == m_is_polling) return; m_is_polling = is_polling; @@ -59,6 +63,34 @@ void PyMoneroDaemonPoller::announce_block_header(const std::shared_ptr& rpc) { + m_rpc = rpc; + if (!rpc->is_online() && rpc->m_uri != boost::none) rpc->check_connection(); +} + +PyMoneroDaemonRpc::PyMoneroDaemonRpc(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(); +} + +void PyMoneroDaemonRpc::add_listener(const std::shared_ptr &listener) { + boost::lock_guard lock(m_listeners_mutex); + m_listeners.push_back(listener); + refresh_listening(); +} + +void PyMoneroDaemonRpc::remove_listener(const std::shared_ptr &listener) { + boost::lock_guard lock(m_listeners_mutex); + m_listeners.erase(std::remove_if(m_listeners.begin(), m_listeners.end(), [&listener](std::shared_ptr iter){ return iter == listener; }), m_listeners.end()); + refresh_listening(); +} + +void PyMoneroDaemonRpc::remove_listeners() { + boost::lock_guard lock(m_listeners_mutex); + m_listeners.clear(); + refresh_listening(); +} + std::shared_ptr PyMoneroDaemonRpc::get_rpc_connection() const { return m_rpc; } @@ -123,7 +155,7 @@ std::string PyMoneroDaemonRpc::get_block_hash(uint64_t height) { return res.data(); } -std::shared_ptr PyMoneroDaemonRpc::get_block_template(std::string& wallet_address, int reserve_size) { +std::shared_ptr PyMoneroDaemonRpc::get_block_template(const std::string& wallet_address, int reserve_size) { auto params = std::make_shared(wallet_address, reserve_size); PyMoneroJsonRequest request("get_block_template", params); std::shared_ptr response = m_rpc->send_json_request(request); @@ -136,7 +168,7 @@ std::shared_ptr PyMoneroDaemonRpc::get_block_template(std return tmplt; } -std::shared_ptr PyMoneroDaemonRpc::get_block_template(std::string& wallet_address) { +std::shared_ptr PyMoneroDaemonRpc::get_block_template(const std::string& wallet_address) { auto params = std::make_shared(wallet_address); PyMoneroJsonRequest request("get_block_template", params); std::shared_ptr response = m_rpc->send_json_request(request); @@ -333,7 +365,7 @@ std::vector> PyMoneroDaemonRpc::get_max_bl return std::vector>(); } -std::vector PyMoneroDaemonRpc::get_block_hashes(std::vector block_hashes, uint64_t start_height) { +std::vector PyMoneroDaemonRpc::get_block_hashes(const std::vector& block_hashes, uint64_t start_height) { throw std::runtime_error("PyMoneroDaemonRpc::get_block_hashes(): not implemented"); } @@ -391,7 +423,7 @@ std::shared_ptr PyMoneroDaemonRpc::get_fee_estimate(uint64_ return estimate; } -std::shared_ptr PyMoneroDaemonRpc::submit_tx_hex(std::string& tx_hex, bool do_not_relay) { +std::shared_ptr PyMoneroDaemonRpc::submit_tx_hex(const std::string& tx_hex, bool do_not_relay) { auto params = std::make_shared(tx_hex, do_not_relay); PyMoneroPathRequest request("send_raw_transaction", params); std::shared_ptr response = m_rpc->send_path_request(request); @@ -410,7 +442,7 @@ std::shared_ptr PyMoneroDaemonRpc::submit_tx_hex(std::st return sum; } -void PyMoneroDaemonRpc::relay_txs_by_hash(std::vector& tx_hashes) { +void PyMoneroDaemonRpc::relay_txs_by_hash(const std::vector& tx_hashes) { auto params = std::make_shared(tx_hashes); PyMoneroJsonRequest request("relay_tx", params); std::shared_ptr response = m_rpc->send_json_request(request); @@ -463,7 +495,7 @@ void PyMoneroDaemonRpc::flush_tx_pool(const std::string &hash) { flush_tx_pool(hashes); } -std::vector PyMoneroDaemonRpc::get_key_image_spent_statuses(std::vector& key_images) { +std::vector PyMoneroDaemonRpc::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); PyMoneroPathRequest request("is_key_image_spent", params); @@ -492,7 +524,7 @@ std::vector PyMoneroDaemonRpc::get_key_image_spent_ return statuses; } -std::vector> PyMoneroDaemonRpc::get_outputs(std::vector& outputs) { +std::vector> PyMoneroDaemonRpc::get_outputs(const std::vector& outputs) { throw std::runtime_error("PyMoneroDaemonRpc::get_outputs(): not implemented"); } @@ -724,7 +756,7 @@ std::shared_ptr PyMoneroDaemonRpc::prune_blockchain(bool ch } std::shared_ptr PyMoneroDaemonRpc::check_for_update() { - auto params = std::make_shared(); + auto params = std::make_shared("check"); PyMoneroPathRequest request("update", params); auto response = m_rpc->send_path_request(request); check_response_status(response); @@ -735,7 +767,7 @@ std::shared_ptr PyMoneroDaemonRpc::check_for_up } std::shared_ptr PyMoneroDaemonRpc::download_update(const std::string& path) { - auto params = std::make_shared(path); + auto params = std::make_shared("download", path); PyMoneroPathRequest request("update", params); auto response = m_rpc->send_path_request(request); check_response_status(response); @@ -840,5 +872,5 @@ void PyMoneroDaemonRpc::check_response_status(const std::shared_ptr& header); }; -class PyMoneroDaemonRpc : public PyMoneroDaemonDefault { +class PyMoneroDaemonRpc : public PyMoneroDaemon { public: - PyMoneroDaemonRpc() { - m_rpc = std::make_shared(); - } - - PyMoneroDaemonRpc(std::shared_ptr rpc) { - m_rpc = rpc; - if (!rpc->is_online() && !rpc->m_uri->empty()) rpc->check_connection(); - } - - PyMoneroDaemonRpc(const std::string& uri, const std::string& username = "", const std::string& password = "") { - m_rpc = std::make_shared(); - m_rpc->m_uri = uri; - if (!username.empty() && !password.empty()) m_rpc->set_credentials(username, password); - if (!uri.empty()) m_rpc->check_connection(); - } ~PyMoneroDaemonRpc(); + PyMoneroDaemonRpc(const std::shared_ptr& rpc); + PyMoneroDaemonRpc(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); + std::vector> get_listeners() override { return m_listeners; } + void add_listener(const std::shared_ptr &listener) override; + void remove_listener(const std::shared_ptr &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(std::string& wallet_address, int reserve_size) override; - std::shared_ptr get_block_template(std::string& wallet_address) override; + std::shared_ptr get_block_template(const std::string& wallet_address, int reserve_size) override; + std::shared_ptr get_block_template(const std::string& wallet_address) 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; @@ -61,21 +51,21 @@ class PyMoneroDaemonRpc : public PyMoneroDaemonDefault { 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(std::vector block_hashes, uint64_t start_height) 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(std::string& tx_hex, bool do_not_relay = false) override; - void relay_txs_by_hash(std::vector& tx_hashes) 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(std::vector& key_images) override; - std::vector> get_outputs(std::vector& outputs) 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::shared_ptr get_info() override; std::shared_ptr get_sync_info() override; @@ -108,6 +98,8 @@ class PyMoneroDaemonRpc : public PyMoneroDaemonDefault { static void check_response_status(const std::shared_ptr& response); protected: + mutable boost::recursive_mutex m_listeners_mutex; + std::vector> m_listeners; std::shared_ptr m_rpc; std::shared_ptr m_poller; std::unordered_map> m_cached_headers; @@ -116,6 +108,6 @@ class PyMoneroDaemonRpc : public PyMoneroDaemonDefault { 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() override; + void refresh_listening(); static void check_response_status(const boost::property_tree::ptree& node); }; diff --git a/src/cpp/py_monero.cpp b/src/cpp/py_monero.cpp index db31127..00a5f64 100644 --- a/src/cpp/py_monero.cpp +++ b/src/cpp/py_monero.cpp @@ -1,7 +1,7 @@ #include "daemon/py_monero_daemon_rpc.h" -#include "wallet/py_monero_wallet_full.h" #include "wallet/py_monero_wallet_rpc.h" #include "wallet/monero_wallet_keys.h" +#include "wallet/monero_wallet_full.h" #include "utils/py_monero_utils.h" #define MONERO_CATCH_AND_RETHROW(expr) \ @@ -80,11 +80,10 @@ PYBIND11_MODULE(monero, m) { 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_default = py::class_>(m, "MoneroDaemonDefault"); - auto py_monero_daemon_rpc = py::class_>(m, "MoneroDaemonRpc"); + 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_full = py::class_>(m, "MoneroWalletFull"); auto py_monero_wallet_rpc = py::class_>(m, "MoneroWalletRpc"); auto py_monero_utils = py::class_(m, "MoneroUtils"); @@ -257,7 +256,7 @@ PYBIND11_MODULE(monero, m) { .def(py::init<>()) .def(py::init(), py::arg("request")) .def(py::init(), py::arg("method")) - .def(py::init>(), py::arg("method"), py::arg("params")) + .def(py::init&>(), py::arg("method"), py::arg("params")) .def_readwrite("version", &PyMoneroJsonRequest::m_version) .def_readwrite("id", &PyMoneroJsonRequest::m_id) .def_readwrite("params", &PyMoneroJsonRequest::m_params); @@ -271,7 +270,7 @@ PYBIND11_MODULE(monero, m) { }, py::arg("response_json")) .def_readwrite("jsonrpc", &PyMoneroJsonResponse::m_jsonrpc) .def_readwrite("id", &PyMoneroJsonResponse::m_id) - .def("get_result", [](PyMoneroJsonResponse& self) { + .def("get_result", [](const PyMoneroJsonResponse& self) { MONERO_CATCH_AND_RETHROW(self.get_result()); }); @@ -300,10 +299,10 @@ PYBIND11_MODULE(monero, m) { // 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") = 0) - .def(py::init(), py::arg("rpc")) - .def_static("compare", [](const std::shared_ptr c1, const std::shared_ptr c2, std::shared_ptr current_connection) { - MONERO_CATCH_AND_RETHROW(PyMoneroRpcConnection::compare(c1, c2, current_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)); }, py::arg("c1"), py::arg("c2"), py::arg("current_connection")) .def_property("uri", [](const PyMoneroRpcConnection& self) { return self.m_uri; }, @@ -342,66 +341,66 @@ PYBIND11_MODULE(monero, m) { .def("set_attribute", [](PyMoneroRpcConnection& 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", [](PyMoneroRpcConnection& self, const std::string& key) { + .def("get_attribute", [](const PyMoneroRpcConnection& 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) { MONERO_CATCH_AND_RETHROW(self.set_credentials(username, password)); }, py::arg("username"), py::arg("password")) - .def("is_onion", [](PyMoneroRpcConnection& self) { + .def("is_onion", [](const PyMoneroRpcConnection& self) { MONERO_CATCH_AND_RETHROW(self.is_onion()); }) - .def("is_i2p", [](PyMoneroRpcConnection& self) { + .def("is_i2p", [](const PyMoneroRpcConnection& self) { MONERO_CATCH_AND_RETHROW(self.is_i2p()); }) - .def("is_online", [](PyMoneroRpcConnection& self) { + .def("is_online", [](const PyMoneroRpcConnection& self) { MONERO_CATCH_AND_RETHROW(self.is_online()); }) - .def("is_authenticated", [](PyMoneroRpcConnection& self) { + .def("is_authenticated", [](const PyMoneroRpcConnection& self) { MONERO_CATCH_AND_RETHROW(self.is_authenticated()); }) - .def("is_connected", [](PyMoneroRpcConnection& self) { + .def("is_connected", [](const PyMoneroRpcConnection& self) { MONERO_CATCH_AND_RETHROW(self.is_connected()); }) .def("check_connection", [](PyMoneroRpcConnection& self, int timeout_ms) { MONERO_CATCH_AND_RETHROW(self.check_connection(timeout_ms)); - }, py::arg("timeout_ms") = 2000) - .def("send_json_request", [](PyMoneroRpcConnection& self, const std::string &method, const boost::optional parameters) { + }, py::arg("timeout_ms") = 20000) + .def("send_json_request", [](PyMoneroRpcConnection& self, const std::string &method, const boost::optional& parameters) { MONERO_CATCH_AND_RETHROW(self.send_json_request(method, parameters)); }, py::arg("method"), py::arg("parameters") = py::none()) - .def("send_path_request", [](PyMoneroRpcConnection& self, const std::string &method, const boost::optional parameters) { + .def("send_path_request", [](PyMoneroRpcConnection& self, const std::string &method, const boost::optional& parameters) { MONERO_CATCH_AND_RETHROW(self.send_path_request(method, parameters)); }, py::arg("method"), py::arg("parameters") = py::none()) - .def("send_binary_request", [](PyMoneroRpcConnection& self, const std::string &method, const boost::optional parameters) { + .def("send_binary_request", [](PyMoneroRpcConnection& self, const std::string &method, const boost::optional& parameters) { MONERO_CATCH_AND_RETHROW(self.send_binary_request(method, parameters)); }, py::arg("method"), py::arg("parameters") = py::none()); // monero_connection_manager_listener py_monero_connection_manager_listener .def(py::init<>()) - .def("on_connection_changed", [](monero_connection_manager_listener& self, std::shared_ptr &connection) { + .def("on_connection_changed", [](monero_connection_manager_listener& self, const std::shared_ptr &connection) { MONERO_CATCH_AND_RETHROW(self.on_connection_changed(connection)); }, py::arg("connection")); // monero_connection_manager py_monero_connection_manager .def(py::init<>()) - .def("add_listener", [](PyMoneroConnectionManager& self, std::shared_ptr &listener) { + .def("add_listener", [](PyMoneroConnectionManager& self, const std::shared_ptr &listener) { MONERO_CATCH_AND_RETHROW(self.add_listener(listener)); }, py::arg("listener")) - .def("remove_listener", [](PyMoneroConnectionManager& self, std::shared_ptr &listener) { + .def("remove_listener", [](PyMoneroConnectionManager& self, const std::shared_ptr &listener) { MONERO_CATCH_AND_RETHROW(self.remove_listener(listener)); }, py::arg("listener")) .def("remove_listeners", [](PyMoneroConnectionManager& self) { MONERO_CATCH_AND_RETHROW(self.remove_listeners()); }) - .def("get_listeners", [](PyMoneroConnectionManager& self) { + .def("get_listeners", [](const PyMoneroConnectionManager& self) { MONERO_CATCH_AND_RETHROW(self.get_listeners()); }) .def("get_connection_by_uri", [](PyMoneroConnectionManager& self, const std::string& uri) { MONERO_CATCH_AND_RETHROW(self.get_connection_by_uri(uri)); }, py::arg("uri")) - .def("add_connection", [](PyMoneroConnectionManager& self, std::shared_ptr &connection) { + .def("add_connection", [](PyMoneroConnectionManager& self, const std::shared_ptr &connection) { MONERO_CATCH_AND_RETHROW(self.add_connection(connection)); }, py::arg("connection")) .def("add_connection", [](PyMoneroConnectionManager& self, const std::string &uri) { @@ -416,22 +415,22 @@ PYBIND11_MODULE(monero, m) { .def("set_connection", [](PyMoneroConnectionManager& self, const std::string &uri) { MONERO_CATCH_AND_RETHROW(self.set_connection(uri)); }, py::arg("uri")) - .def("get_connection", [](PyMoneroConnectionManager& self) { + .def("get_connection", [](const PyMoneroConnectionManager& self) { MONERO_CATCH_AND_RETHROW(self.get_connection()); }) .def("has_connection", [](PyMoneroConnectionManager& self, const std::string &uri) { MONERO_CATCH_AND_RETHROW(self.has_connection(uri)); }, py::arg("uri")) - .def("get_connections", [](PyMoneroConnectionManager& self) { + .def("get_connections", [](const PyMoneroConnectionManager& self) { MONERO_CATCH_AND_RETHROW(self.get_connections()); }) - .def("is_connected", [](PyMoneroConnectionManager& self) { + .def("is_connected", [](const PyMoneroConnectionManager& self) { MONERO_CATCH_AND_RETHROW(self.is_connected()); }) .def("check_connection", [](PyMoneroConnectionManager& self) { MONERO_CATCH_AND_RETHROW(self.check_connection()); }) - .def("start_polling", [](PyMoneroConnectionManager& self, boost::optional period_ms, boost::optional auto_switch, boost::optional timeout_ms, boost::optional poll_type, boost::optional>> excluded_connections) { + .def("start_polling", [](PyMoneroConnectionManager& self, const boost::optional& period_ms, const boost::optional& auto_switch, const boost::optional& timeout_ms, const boost::optional& poll_type, const boost::optional>>& excluded_connections) { MONERO_CATCH_AND_RETHROW(self.start_polling(period_ms, auto_switch, timeout_ms, poll_type, excluded_connections)); }, py::arg("period_ms") = py::none(), py::arg("auto_switch") = py::none(), py::arg("timeout_ms") = py::none(), py::arg("poll_type") = py::none(), py::arg("excluded_connections") = py::none()) .def("stop_polling", [](PyMoneroConnectionManager& self) { @@ -440,16 +439,16 @@ PYBIND11_MODULE(monero, m) { .def("set_auto_switch", [](PyMoneroConnectionManager& self, bool auto_switch) { MONERO_CATCH_AND_RETHROW(self.set_auto_switch(auto_switch)); }, py::arg("auto_switch")) - .def("get_auto_switch", [](PyMoneroConnectionManager& self) { + .def("get_auto_switch", [](const PyMoneroConnectionManager& self) { MONERO_CATCH_AND_RETHROW(self.get_auto_switch()); }) .def("set_timeout", [](PyMoneroConnectionManager& self, uint64_t timeout_ms) { MONERO_CATCH_AND_RETHROW(self.set_timeout(timeout_ms)); }, py::arg("timeout_ms")) - .def("get_timeout", [](PyMoneroConnectionManager& self) { + .def("get_timeout", [](const PyMoneroConnectionManager& self) { MONERO_CATCH_AND_RETHROW(self.get_timeout()); }) - .def("get_peer_connections", [](PyMoneroConnectionManager& self) { + .def("get_peer_connections", [](const PyMoneroConnectionManager& self) { MONERO_CATCH_AND_RETHROW(self.get_peer_connections()); }) .def("disconnect", [](PyMoneroConnectionManager& self) { @@ -1346,10 +1345,10 @@ PYBIND11_MODULE(monero, m) { // monero_daemon py_monero_daemon .def(py::init<>()) - .def("add_listener", [](PyMoneroDaemon& self, const std::shared_ptr &listener) { + .def("add_listener", [](PyMoneroDaemon& self, const std::shared_ptr& listener) { MONERO_CATCH_AND_RETHROW(self.add_listener(listener)); }, py::arg("listener")) - .def("remove_listener", [](PyMoneroDaemon& self, const std::shared_ptr &listener) { + .def("remove_listener", [](PyMoneroDaemon& self, const std::shared_ptr& listener) { MONERO_CATCH_AND_RETHROW(self.remove_listener(listener)); }, py::arg("listener")) .def("get_listeners", [](PyMoneroDaemon& self) { @@ -1367,16 +1366,16 @@ PYBIND11_MODULE(monero, m) { .def("get_block_hash", [](PyMoneroDaemon& self, uint64_t height) { MONERO_CATCH_AND_RETHROW(self.get_block_hash(height)); }, py::arg("height")) - .def("get_block_template", [](PyMoneroDaemon& self, std::string& wallet_address) { + .def("get_block_template", [](PyMoneroDaemon& self, const std::string& wallet_address) { MONERO_CATCH_AND_RETHROW(self.get_block_template(wallet_address)); }, py::arg("wallet_address")) - .def("get_block_template", [](PyMoneroDaemon& self, std::string& wallet_address, int reserve_size) { + .def("get_block_template", [](PyMoneroDaemon& self, const std::string& wallet_address, int reserve_size) { MONERO_CATCH_AND_RETHROW(self.get_block_template(wallet_address, reserve_size)); }, py::arg("wallet_address"), py::arg("reserve_size")) .def("get_last_block_header", [](PyMoneroDaemon& self) { MONERO_CATCH_AND_RETHROW(self.get_last_block_header()); }) - .def("get_block_header_by_hash", [](PyMoneroDaemon& self, std::string& hash) { + .def("get_block_header_by_hash", [](PyMoneroDaemon& self, const std::string& hash) { MONERO_CATCH_AND_RETHROW(self.get_block_header_by_hash(hash)); }, py::arg("hash")) .def("get_block_header_by_height", [](PyMoneroDaemon& self, uint64_t height) { @@ -1385,7 +1384,7 @@ PYBIND11_MODULE(monero, m) { .def("get_block_headers_by_range", [](PyMoneroDaemon& self, uint64_t start_height, uint64_t end_height) { MONERO_CATCH_AND_RETHROW(self.get_block_headers_by_range(start_height, end_height)); }, py::arg("start_height"), py::arg("end_height")) - .def("get_block_by_hash", [](PyMoneroDaemon& self, std::string& hash) { + .def("get_block_by_hash", [](PyMoneroDaemon& self, const std::string& hash) { MONERO_CATCH_AND_RETHROW(self.get_block_by_hash(hash)); }, py::arg("hash")) .def("get_blocks_by_hash", [](PyMoneroDaemon& self, const std::vector& block_hashes, uint64_t start_height, bool prune) { @@ -1424,13 +1423,13 @@ PYBIND11_MODULE(monero, m) { .def("get_fee_estimate", [](PyMoneroDaemon& self, uint64_t grace_blocks) { MONERO_CATCH_AND_RETHROW(self.get_fee_estimate(grace_blocks)); }, py::arg("grace_blocks") = 0) - .def("submit_tx_hex", [](PyMoneroDaemon& self, std::string& tx_hex, bool do_not_relay) { + .def("submit_tx_hex", [](PyMoneroDaemon& self, const std::string& tx_hex, bool do_not_relay) { MONERO_CATCH_AND_RETHROW(self.submit_tx_hex(tx_hex, do_not_relay)); }, py::arg("tx_hex"), py::arg("do_not_relay") = false) - .def("relay_tx_by_hash", [](PyMoneroDaemon& self, std::string& tx_hash) { + .def("relay_tx_by_hash", [](PyMoneroDaemon& self, const std::string& tx_hash) { MONERO_CATCH_AND_RETHROW(self.relay_tx_by_hash(tx_hash)); }, py::arg("tx_hash")) - .def("relay_txs_by_hash", [](PyMoneroDaemon& self, std::vector& tx_hashes) { + .def("relay_txs_by_hash", [](PyMoneroDaemon& self, const std::vector& tx_hashes) { MONERO_CATCH_AND_RETHROW(self.relay_txs_by_hash(tx_hashes)); }, py::arg("tx_hashes")) .def("get_tx_pool", [](PyMoneroDaemon& self) { @@ -1448,28 +1447,28 @@ PYBIND11_MODULE(monero, m) { .def("flush_tx_pool", [](PyMoneroDaemon& self) { MONERO_CATCH_AND_RETHROW(self.flush_tx_pool()); }) - .def("flush_tx_pool", [](PyMoneroDaemon& self, std::vector& hashes) { + .def("flush_tx_pool", [](PyMoneroDaemon& self, const std::vector& hashes) { MONERO_CATCH_AND_RETHROW(self.flush_tx_pool(hashes)); }, py::arg("hashes")) .def("flush_tx_pool", [](PyMoneroDaemon& self, const std::string& hash) { MONERO_CATCH_AND_RETHROW(self.flush_tx_pool(hash)); }, py::arg("hash")) - .def("get_key_image_spent_status", [](PyMoneroDaemon& self, std::string& key_image) { + .def("get_key_image_spent_status", [](PyMoneroDaemon& self, const std::string& key_image) { MONERO_CATCH_AND_RETHROW(self.get_key_image_spent_status(key_image)); }, py::arg("key_image")) - .def("get_key_image_spent_statuses", [](PyMoneroDaemon& self, std::vector& key_images) { + .def("get_key_image_spent_statuses", [](PyMoneroDaemon& self, const std::vector& key_images) { MONERO_CATCH_AND_RETHROW(self.get_key_image_spent_statuses(key_images)); }, py::arg("key_images")) - .def("get_outputs", [](PyMoneroDaemon& self, std::vector& outputs) { + .def("get_outputs", [](PyMoneroDaemon& self, const std::vector& outputs) { MONERO_CATCH_AND_RETHROW(self.get_outputs(outputs)); }, py::arg("outputs")) .def("get_output_histogram", [](PyMoneroDaemon& 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) { MONERO_CATCH_AND_RETHROW(self.get_output_histogram(amounts, min_count, max_count, is_unlocked, recent_cutoff)); }, py::arg("amounts"), py::arg("min_count"), py::arg("max_count"), py::arg("is_unlocked"), py::arg("recent_cutoff")) - .def("get_output_distribution", [](PyMoneroDaemon& self, std::vector& amounts) { + .def("get_output_distribution", [](PyMoneroDaemon& self, const std::vector& amounts) { MONERO_CATCH_AND_RETHROW(self.get_output_distribution(amounts)); }, py::arg("amounts")) - .def("get_output_distribution", [](PyMoneroDaemon& self, std::vector& amounts, bool is_cumulative, uint64_t start_height, uint64_t end_height) { + .def("get_output_distribution", [](PyMoneroDaemon& self, const std::vector& amounts, bool is_cumulative, uint64_t start_height, uint64_t end_height) { MONERO_CATCH_AND_RETHROW(self.get_output_distribution(amounts, is_cumulative, start_height, end_height)); }, py::arg("amounts"), py::arg("is_cumulative"), py::arg("start_height"), py::arg("end_height")) .def("get_info", [](PyMoneroDaemon& self) { @@ -1526,7 +1525,7 @@ PYBIND11_MODULE(monero, m) { .def("set_peer_ban", [](PyMoneroDaemon& self, const std::shared_ptr& ban) { MONERO_CATCH_AND_RETHROW(self.set_peer_ban(ban)); }, py::arg("ban")) - .def("start_mining", [](PyMoneroDaemon& self, std::string& address, uint64_t num_threads, bool is_background, bool ignore_battery) { + .def("start_mining", [](PyMoneroDaemon& self, const std::string& address, uint64_t num_threads, bool is_background, bool ignore_battery) { MONERO_CATCH_AND_RETHROW(self.start_mining(address, num_threads, is_background, ignore_battery)); }, py::arg("address"), py::arg("num_threads"), py::arg("is_background"), py::arg("ignore_battery")) .def("stop_mining", [](PyMoneroDaemon& self) { @@ -1535,10 +1534,10 @@ PYBIND11_MODULE(monero, m) { .def("get_mining_status", [](PyMoneroDaemon& self) { MONERO_CATCH_AND_RETHROW(self.get_mining_status()); }) - .def("submit_block", [](PyMoneroDaemon& self, std::string& block_blob) { + .def("submit_block", [](PyMoneroDaemon& self, const std::string& block_blob) { MONERO_CATCH_AND_RETHROW(self.submit_block(block_blob)); }, py::arg("block_blob")) - .def("submit_blocks", [](PyMoneroDaemon& self, std::vector& block_blobs) { + .def("submit_blocks", [](PyMoneroDaemon& self, const std::vector& block_blobs) { MONERO_CATCH_AND_RETHROW(self.submit_blocks(block_blobs)); }, py::arg("block_blobs")) .def("prune_blockchain", [](PyMoneroDaemon& self, bool check) { @@ -1550,7 +1549,7 @@ PYBIND11_MODULE(monero, m) { .def("download_update", [](PyMoneroDaemon& self) { MONERO_CATCH_AND_RETHROW(self.download_update()); }) - .def("download_update", [](PyMoneroDaemon& self, std::string& download_path) { + .def("download_update", [](PyMoneroDaemon& self, const std::string& download_path) { MONERO_CATCH_AND_RETHROW(self.download_update(download_path)); }, py::arg("download_path")) .def("stop", [](PyMoneroDaemon& self) { @@ -1560,16 +1559,10 @@ PYBIND11_MODULE(monero, m) { MONERO_CATCH_AND_RETHROW(self.wait_for_next_block_header()); }); - // monero_daemon_default - // TODO move monero_daemon_default to monero_daemon - py_monero_daemon_default - .def(py::init<>()); - // monero_daemon_rpc py_monero_daemon_rpc - .def(py::init<>()) - .def(py::init>(), py::arg("rpc")) - .def(py::init(), py::arg("uri"), py::arg("username") = "", py::arg("password") = "") + .def(py::init&>(), py::arg("rpc")) + .def(py::init(), py::arg("uri"), py::arg("username") = "", py::arg("password") = "", py::arg("proxy_uri") = "", py::arg("zmq_uri") = "", py::arg("timeout") = 20000) .def("get_rpc_connection", [](const PyMoneroDaemonRpc& self) { MONERO_CATCH_AND_RETHROW(self.get_rpc_connection()); }) @@ -1851,7 +1844,7 @@ PYBIND11_MODULE(monero, m) { MONERO_CATCH_AND_RETHROW(self.import_key_images(key_images)); }, py::arg("key_images")) .def("get_new_key_images_from_last_import", [](PyMoneroWallet& self) { - MONERO_CATCH_AND_RETHROW(self.get_new_key_images_from_last_import()); + MONERO_CATCH_AND_RETHROW(self.export_key_images(false)); }) .def("freeze_output", [](PyMoneroWallet& self, const std::string& key_image) { MONERO_CATCH_AND_RETHROW(self.freeze_output(key_image)); @@ -1990,7 +1983,7 @@ PYBIND11_MODULE(monero, m) { MONERO_CATCH_AND_RETHROW(self.set_account_tag_label(tag, label)); }, py::arg("tag"), py::arg("label")) .def("set_account_label", [](PyMoneroWallet& self, uint32_t account_idx, const std::string& label) { - MONERO_CATCH_AND_RETHROW(self.set_account_label(account_idx, label)); + MONERO_CATCH_AND_RETHROW(self.set_subaddress_label(account_idx, 0, label)); }, py::arg("account_idx"), py::arg("label")) .def("get_payment_uri", [](PyMoneroWallet& self, const monero::monero_tx_config& config) { MONERO_CATCH_AND_RETHROW(self.get_payment_uri(config)); @@ -2092,7 +2085,14 @@ PYBIND11_MODULE(monero, m) { 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")) .def_static("create_wallet", [](const PyMoneroWalletConfig& config) { - MONERO_CATCH_AND_RETHROW(PyMoneroWalletFull::create_wallet(config)); + try { + return monero_wallet_full::create_wallet(config); + } catch(const std::exception& ex) { + std::string msg = ex.what(); + if (msg.find("file already exists") != std::string::npos && config.m_path != boost::none) + msg = std::string("Wallet already exists: ") + config.m_path.get(); + throw PyMoneroError(msg); + } }, py::arg("config")) .def_static("get_seed_languages", []() { MONERO_CATCH_AND_RETHROW(monero::monero_wallet_full::get_seed_languages()); @@ -2107,7 +2107,7 @@ PYBIND11_MODULE(monero, m) { // monero_wallet_rpc py_monero_wallet_rpc .def(py::init&>(), py::arg("rpc_connection")) - .def(py::init(), py::arg("uri") = "", py::arg("username") = "", py::arg("password") = "") + .def(py::init(), py::arg("uri") = "", py::arg("username") = "", py::arg("password") = "", py::arg("proxy_uri") = "", py::arg("zmq_uri") = "", py::arg("timeout") = 20000) .def("create_wallet", [](PyMoneroWalletRpc& self, const std::shared_ptr& config) { try { self.create_wallet(config); diff --git a/src/cpp/utils/py_monero_utils.cpp b/src/cpp/utils/py_monero_utils.cpp index 13ac8a0..76f01c2 100644 --- a/src/cpp/utils/py_monero_utils.cpp +++ b/src/cpp/utils/py_monero_utils.cpp @@ -15,7 +15,6 @@ 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); } diff --git a/src/cpp/wallet/py_monero_wallet.h b/src/cpp/wallet/py_monero_wallet.h index e756a1b..0ca77cc 100644 --- a/src/cpp/wallet/py_monero_wallet.h +++ b/src/cpp/wallet/py_monero_wallet.h @@ -60,10 +60,6 @@ class PyMoneroWallet : public monero::monero_wallet { PYBIND11_OVERRIDE_PURE(void, PyMoneroWallet, set_account_tag_label); } - virtual void set_account_label(uint32_t account_idx, const std::string& label) { - PYBIND11_OVERRIDE_PURE(void, PyMoneroWallet, set_account_label); - } - bool is_view_only() const override { PYBIND11_OVERRIDE(bool, monero_wallet, is_view_only); } @@ -320,10 +316,6 @@ class PyMoneroWallet : public monero::monero_wallet { PYBIND11_OVERRIDE(std::shared_ptr, monero_wallet, import_key_images, key_images); } - virtual std::vector> get_new_key_images_from_last_import() { - PYBIND11_OVERRIDE_PURE(std::vector>, PyMoneroWallet, get_new_key_images_from_last_import); - } - void freeze_output(const std::string& key_image) override { PYBIND11_OVERRIDE(void, monero_wallet, freeze_output, key_image); } diff --git a/src/cpp/wallet/py_monero_wallet_full.cpp b/src/cpp/wallet/py_monero_wallet_full.cpp deleted file mode 100644 index e42993f..0000000 --- a/src/cpp/wallet/py_monero_wallet_full.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "py_monero_wallet_full.h" - - -void PyMoneroWalletFull::close(bool save) { - if (m_is_closed) throw std::runtime_error("Wallet already closed"); - monero::monero_wallet_full::close(save); -} - -void PyMoneroWalletFull::set_account_label(uint32_t account_idx, const std::string& label) { - set_subaddress_label(account_idx, 0, label); -} - -monero_wallet_full* PyMoneroWalletFull::create_wallet(const monero_wallet_config& config, std::unique_ptr http_client_factory) { - try { - return monero_wallet_full::create_wallet(config, std::move(http_client_factory)); - } catch(const std::exception& ex) { - std::string msg = ex.what(); - if (msg.find("file already exists") != std::string::npos && config.m_path != boost::none) - msg = std::string("Wallet already exists: ") + config.m_path.get(); - throw PyMoneroError(msg); - } -} diff --git a/src/cpp/wallet/py_monero_wallet_full.h b/src/cpp/wallet/py_monero_wallet_full.h deleted file mode 100644 index d3d377f..0000000 --- a/src/cpp/wallet/py_monero_wallet_full.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "py_monero_wallet.h" -#include "wallet/monero_wallet_full.h" - - -class PyMoneroWalletFull : public monero::monero_wallet_full { -public: - - static monero_wallet_full* create_wallet(const monero_wallet_config& config, std::unique_ptr http_client_factory = nullptr); - - bool is_closed() const { return m_is_closed; } - void close(bool save = false) override; - void set_account_label(uint32_t account_idx, const std::string& label); - - std::vector> get_new_key_images_from_last_import() { - throw std::runtime_error("get_new_key_images_from_last_import(): not implemented"); - } - -protected: - bool m_is_closed = false; -}; diff --git a/src/cpp/wallet/py_monero_wallet_model.cpp b/src/cpp/wallet/py_monero_wallet_model.cpp index c6c38e1..c407e61 100644 --- a/src/cpp/wallet/py_monero_wallet_model.cpp +++ b/src/cpp/wallet/py_monero_wallet_model.cpp @@ -125,6 +125,225 @@ bool PyOutputComparator::operator()(const monero::monero_output_wallet& o1, cons return o1.m_key_image.get()->m_hex.value() < o2.m_key_image.get()->m_hex.value(); } +PyMoneroWalletConfig::PyMoneroWalletConfig(const PyMoneroWalletConfig& config) { + m_path = config.m_path; + m_password = config.m_password; + m_network_type = config.m_network_type; + m_server = config.m_server; + m_seed = config.m_seed; + m_seed_offset = config.m_seed_offset; + m_primary_address = config.m_primary_address; + m_private_view_key = config.m_private_view_key; + m_private_spend_key = config.m_private_spend_key; + m_restore_height = config.m_restore_height; + m_language = config.m_language; + m_save_current = config.m_save_current; + m_account_lookahead = config.m_account_lookahead; + m_subaddress_lookahead = config.m_subaddress_lookahead; + m_is_multisig = config.m_is_multisig; + m_connection_manager = config.m_connection_manager; +} + +PyMoneroKeyImage::PyMoneroKeyImage(const monero::monero_key_image &key_image) { + m_hex = key_image.m_hex; + m_signature = key_image.m_signature; +} + +PyMoneroDecodedAddress::PyMoneroDecodedAddress(const std::string& address, PyMoneroAddressType address_type, monero::monero_network_type network_type): + m_address(address), + m_address_type(address_type), + m_network_type(network_type) { +} + +PyMoneroGetBalanceParams::PyMoneroGetBalanceParams(uint32_t account_idx, const std::vector& address_indices, bool all_accounts, bool strict): + m_account_idx(account_idx), + m_address_indices(address_indices), + m_all_accounts(all_accounts), + m_strict(strict) { +} + +PyMoneroGetBalanceParams::PyMoneroGetBalanceParams(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()); +} + +PyMoneroGetBalanceResponse::PyMoneroGetBalanceResponse(uint64_t balance, uint64_t unlocked_balance, bool multisig_import_needed, uint64_t time_to_unlock, uint64_t blocks_to_unlock): + m_balance(balance), + m_unlocked_balance(unlocked_balance), + m_multisig_import_needed(multisig_import_needed), + m_time_to_unlock(time_to_unlock), + m_blocks_to_unlock(blocks_to_unlock) { +} + +PyMoneroAddressBookEntryParams::PyMoneroAddressBookEntryParams(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) { +} + +PyMoneroVerifySignMessageParams::PyMoneroVerifySignMessageParams(const std::string &data, const std::string &address, const std::string& signature): + m_data(data), + m_address(address), + m_signature(signature) { +} + +PyMoneroVerifySignMessageParams::PyMoneroVerifySignMessageParams(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) { +} + +PyMoneroCheckTxKeyParams::PyMoneroCheckTxKeyParams(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) { +} + +PyMoneroSetSubaddressLabelParams::PyMoneroSetSubaddressLabelParams(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) { +} + +PyMoneroImportExportKeyImagesParams::PyMoneroImportExportKeyImagesParams(const std::vector> &key_images) { + for(const auto &key_image : key_images) { + m_key_images.push_back(std::make_shared(*key_image)); + } +} + +PyMoneroGetPaymentUriParams::PyMoneroGetPaymentUriParams(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; + } +} + +PyMoneroSweepParams::PyMoneroSweepParams(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) { +} + +PyMoneroCreateOpenWalletParams::PyMoneroCreateOpenWalletParams(const boost::optional& filename, const boost::optional &password): + m_filename(filename), m_password(password), m_autosave_current(false) { +} + +PyMoneroCreateOpenWalletParams::PyMoneroCreateOpenWalletParams(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) { +} + +PyMoneroCreateOpenWalletParams::PyMoneroCreateOpenWalletParams(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) { +} + +PyMoneroCreateOpenWalletParams::PyMoneroCreateOpenWalletParams(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) { +} + +PyMoneroReserveProofParams::PyMoneroReserveProofParams(const std::string &message, bool all): + m_all(all), m_message(message) { +} + +PyMoneroReserveProofParams::PyMoneroReserveProofParams(const std::string &address, const std::string &message, const std::string &signature): + m_address(address), m_message(message), m_signature(signature) { +} + +PyMoneroReserveProofParams::PyMoneroReserveProofParams(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) { +} + +PyMoneroReserveProofParams::PyMoneroReserveProofParams(const std::string &tx_hash, const std::string &message): + m_tx_hash(tx_hash), m_message(message) { +} + +PyMoneroReserveProofParams::PyMoneroReserveProofParams(uint32_t account_index, uint64_t amount, const std::string &message): + m_account_index(account_index), m_amount(amount), m_message(message) { +} + +PyMoneroTransferParams::PyMoneroTransferParams(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; +} + +PyMoneroGetIncomingTransfersParams::PyMoneroGetIncomingTransfersParams(const std::string& transfer_type, bool verbose): + m_transfer_type(transfer_type), m_verbose(verbose) { +} + std::shared_ptr PyMoneroTxQuery::decontextualize(const std::shared_ptr &query) { query->m_is_incoming = boost::none; query->m_is_outgoing = boost::none; @@ -864,19 +1083,6 @@ void PyMoneroTxSet::from_describe_transfer(const boost::property_tree::ptree& no } } -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; -} - 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; @@ -940,13 +1146,6 @@ void PyMoneroMultisigSignResult::from_property_tree(const boost::property_tree:: } } -rapidjson::Value PyMoneroMultisigTxDataParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - rapidjson::Value value_str(rapidjson::kStringType); - if (m_multisig_tx_hex != boost::none) monero_utils::add_json_member("tx_data_hex", m_multisig_tx_hex.get(), allocator, root, value_str); - return root; -} - void PyMoneroAccountTag::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; @@ -1068,78 +1267,19 @@ uint64_t PyMoneroWalletGetHeightResponse::from_property_tree(const boost::proper throw std::runtime_error("Invalid get_height response"); } -rapidjson::Value PyMoneroQueryKeyParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - 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; -} - -rapidjson::Value PyMoneroQueryOutputParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - 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; -} - -rapidjson::Value PyMoneroGetAddressParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - rapidjson::Value value_num(rapidjson::kNumberType); - if (!m_subaddress_indices.empty()) root.AddMember("address_index", monero_utils::to_rapidjson_val(allocator, m_subaddress_indices), allocator); - if (m_account_index != boost::none) monero_utils::add_json_member("account_index", m_account_index.get(), allocator, root, value_num); - return root; -} - -rapidjson::Value PyMoneroGetAddressIndexParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - rapidjson::Value value_str(rapidjson::kStringType); - if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); - return root; -} - -rapidjson::Value PyMoneroMakeIntegratedAddressParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - 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); - return root; -} - -rapidjson::Value PyMoneroSplitIntegratedAddressParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - rapidjson::Value value_str(rapidjson::kStringType); - if (m_integrated_address != boost::none) monero_utils::add_json_member("integrated_address", m_integrated_address.get(), allocator, root, value_str); - return root; -} - -rapidjson::Value PyMoneroWalletStartMiningParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - rapidjson::Value value_str(rapidjson::kStringType); - 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); - 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; -} - -rapidjson::Value PyMoneroPrepareMultisigParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - if (m_enable_multisig_experimental != boost::none) monero_utils::add_json_member("enable_multisig_experimental", m_enable_multisig_experimental.get(), allocator, root); - return root; -} - -std::string PyMoneroExportMultisigHexResponse::from_property_tree(const boost::property_tree::ptree& node) { +void PyMoneroParsePaymentUriResponse::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("info")) return it->second.data(); + if (key == std::string("uri")) { + PyMoneroParsePaymentUriResponse::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(); } - throw std::runtime_error("Invalid prepare multisig response"); -} - -rapidjson::Value PyMoneroImportMultisigHexParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - if (!m_multisig_hexes.empty()) root.AddMember("info", monero_utils::to_rapidjson_val(allocator, m_multisig_hexes), allocator); - return root; } int PyMoneroImportMultisigHexResponse::from_property_tree(const boost::property_tree::ptree& node) { @@ -1150,30 +1290,74 @@ int PyMoneroImportMultisigHexResponse::from_property_tree(const boost::property_ throw std::runtime_error("Invalid prepare multisig response"); } -std::vector PyMoneroSubmitMultisigTxHexResponse::from_property_tree(const boost::property_tree::ptree& node) { +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("tx_hash_list")) { - auto node2 = it->second; - std::vector hashes; - for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { - hashes.push_back(it2->second.data()); - } - return hashes; - } + 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 PyMoneroGetBalanceResponse::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); + } + } + } +} + +std::string PyMoneroExportMultisigHexResponse::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("info")) return it->second.data(); } throw std::runtime_error("Invalid prepare multisig response"); } -rapidjson::Value PyMoneroMakeMultisigParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - rapidjson::Value val_num(rapidjson::kNumberType); - rapidjson::Value val_str(rapidjson::kStringType); - if (!m_multisig_info.empty()) root.AddMember("multisig_info", monero_utils::to_rapidjson_val(allocator, m_multisig_info), allocator); - if (m_threshold != boost::none) monero_utils::add_json_member("threshold", m_threshold.get(), allocator, root, val_num); - if (m_password != boost::none) monero_utils::add_json_member("password", m_password.get(), allocator, root, val_str); - return root; +std::vector PyMoneroSubmitMultisigTxHexResponse::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("tx_hash_list")) { + auto node2 = it->second; + std::vector hashes; + for (auto it2 = node2.begin(); it2 != node2.end(); ++it2) { + hashes.push_back(it2->second.data()); + } + + return hashes; + } + } + throw std::runtime_error("Invalid prepare multisig response"); } std::string PyMoneroPrepareMakeMultisigResponse::from_property_tree(const boost::property_tree::ptree& node) { @@ -1184,64 +1368,201 @@ std::string PyMoneroPrepareMakeMultisigResponse::from_property_tree(const boost: throw std::runtime_error("Invalid prepare multisig response"); } -rapidjson::Value PyMoneroExchangeMultisigKeysParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - rapidjson::Value val_num(rapidjson::kNumberType); - rapidjson::Value val_str(rapidjson::kStringType); - if (!m_multisig_info.empty()) root.AddMember("multisig_info", monero_utils::to_rapidjson_val(allocator, m_multisig_info), allocator); - if (m_password != boost::none) monero_utils::add_json_member("password", m_password.get(), allocator, root, val_str); - return root; +std::string PyMoneroGetPaymentUriResponse::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"); } -rapidjson::Value PyMoneroParsePaymentUriParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value root(rapidjson::kObjectType); - rapidjson::Value val_str(rapidjson::kStringType); - if (m_uri != boost::none) monero_utils::add_json_member("uri", m_uri.get(), allocator, root, val_str); - return root; +void PyMoneroWalletAttributeParams::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(); + } } -std::shared_ptr PyMoneroParsePaymentUriResponse::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; +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 PyMoneroParsePaymentUriResponse::from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& response) { +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("uri")) { - PyMoneroParsePaymentUriResponse::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(); + 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; } } -PyMoneroGetPaymentUriParams::PyMoneroGetPaymentUriParams(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; +std::string PyMoneroReserveProofSignature::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(); + } - 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; + throw std::runtime_error("Invalid reserve proof response"); +} + +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(); } } +rapidjson::Value PyMoneroAccountTag::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; +} + +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("keyImage", 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; +} + +rapidjson::Value PyMoneroMultisigTxDataParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value root(rapidjson::kObjectType); + rapidjson::Value value_str(rapidjson::kStringType); + if (m_multisig_tx_hex != boost::none) monero_utils::add_json_member("tx_data_hex", m_multisig_tx_hex.get(), allocator, root, value_str); + return root; +} + +rapidjson::Value PyMoneroQueryKeyParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value root(rapidjson::kObjectType); + 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; +} + +rapidjson::Value PyMoneroQueryOutputParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value root(rapidjson::kObjectType); + 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; +} + +rapidjson::Value PyMoneroGetAddressParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value root(rapidjson::kObjectType); + rapidjson::Value value_num(rapidjson::kNumberType); + if (!m_subaddress_indices.empty()) root.AddMember("address_index", monero_utils::to_rapidjson_val(allocator, m_subaddress_indices), allocator); + if (m_account_index != boost::none) monero_utils::add_json_member("account_index", m_account_index.get(), allocator, root, value_num); + return root; +} + +rapidjson::Value PyMoneroGetAddressIndexParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value root(rapidjson::kObjectType); + rapidjson::Value value_str(rapidjson::kStringType); + if (m_address != boost::none) monero_utils::add_json_member("address", m_address.get(), allocator, root, value_str); + return root; +} + +rapidjson::Value PyMoneroMakeIntegratedAddressParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value root(rapidjson::kObjectType); + 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); + return root; +} + +rapidjson::Value PyMoneroSplitIntegratedAddressParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value root(rapidjson::kObjectType); + rapidjson::Value value_str(rapidjson::kStringType); + if (m_integrated_address != boost::none) monero_utils::add_json_member("integrated_address", m_integrated_address.get(), allocator, root, value_str); + return root; +} + +rapidjson::Value PyMoneroWalletStartMiningParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value root(rapidjson::kObjectType); + rapidjson::Value value_str(rapidjson::kStringType); + 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); + 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; +} + +rapidjson::Value PyMoneroPrepareMultisigParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value root(rapidjson::kObjectType); + if (m_enable_multisig_experimental != boost::none) monero_utils::add_json_member("enable_multisig_experimental", m_enable_multisig_experimental.get(), allocator, root); + return root; +} + +rapidjson::Value PyMoneroImportMultisigHexParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value root(rapidjson::kObjectType); + if (!m_multisig_hexes.empty()) root.AddMember("info", monero_utils::to_rapidjson_val(allocator, m_multisig_hexes), allocator); + return root; +} + +rapidjson::Value PyMoneroMakeMultisigParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value root(rapidjson::kObjectType); + rapidjson::Value val_num(rapidjson::kNumberType); + rapidjson::Value val_str(rapidjson::kStringType); + if (!m_multisig_info.empty()) root.AddMember("multisig_info", monero_utils::to_rapidjson_val(allocator, m_multisig_info), allocator); + if (m_threshold != boost::none) monero_utils::add_json_member("threshold", m_threshold.get(), allocator, root, val_num); + if (m_password != boost::none) monero_utils::add_json_member("password", m_password.get(), allocator, root, val_str); + return root; +} + +rapidjson::Value PyMoneroParsePaymentUriParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value root(rapidjson::kObjectType); + rapidjson::Value val_str(rapidjson::kStringType); + if (m_uri != boost::none) monero_utils::add_json_member("uri", m_uri.get(), allocator, root, val_str); + return root; +} + rapidjson::Value PyMoneroGetPaymentUriParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); rapidjson::Value value_str(rapidjson::kStringType); @@ -1254,14 +1575,6 @@ rapidjson::Value PyMoneroGetPaymentUriParams::to_rapidjson_val(rapidjson::Docume return root; } -std::string PyMoneroGetPaymentUriResponse::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"); -} - rapidjson::Value PyMoneroGetBalanceParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); rapidjson::Value value_num(rapidjson::kNumberType); @@ -1272,26 +1585,6 @@ rapidjson::Value PyMoneroGetBalanceParams::to_rapidjson_val(rapidjson::Document: return root; } -void PyMoneroGetBalanceResponse::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); - } - } - } -} - rapidjson::Value PyMoneroCreateAccountParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); rapidjson::Value value_str(rapidjson::kStringType); @@ -1321,17 +1614,6 @@ rapidjson::Value PyMoneroWalletAttributeParams::to_rapidjson_val(rapidjson::Docu return root; } -void PyMoneroWalletAttributeParams::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 PyMoneroScanTxParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); if (!m_tx_hashes.empty()) root.AddMember("txids", monero_utils::to_rapidjson_val(allocator, m_tx_hashes), allocator); @@ -1397,32 +1679,6 @@ rapidjson::Value PyMoneroAddressBookEntryParams::to_rapidjson_val(rapidjson::Doc return root; } -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); - } - } - } -} - rapidjson::Value PyMoneroGetAccountsParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); rapidjson::Value value_str(rapidjson::kStringType); @@ -1476,20 +1732,6 @@ rapidjson::Value PyMoneroWalletRelayTxParams::to_rapidjson_val(rapidjson::Docume return root; } -PyMoneroSweepParams::PyMoneroSweepParams(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 PyMoneroSweepParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); rapidjson::Value val_str(rapidjson::kStringType); @@ -1566,35 +1808,6 @@ rapidjson::Value PyMoneroImportExportKeyImagesParams::to_rapidjson_val(rapidjson return root; } -PyMoneroCreateOpenWalletParams::PyMoneroCreateOpenWalletParams(const boost::optional& filename, const boost::optional &password): - m_filename(filename), m_password(password), m_autosave_current(false) { -} - -PyMoneroCreateOpenWalletParams::PyMoneroCreateOpenWalletParams(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) { -} - -PyMoneroCreateOpenWalletParams::PyMoneroCreateOpenWalletParams(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) { -} - -PyMoneroCreateOpenWalletParams::PyMoneroCreateOpenWalletParams(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 PyMoneroCreateOpenWalletParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); rapidjson::Value val_str(rapidjson::kStringType); @@ -1613,26 +1826,6 @@ rapidjson::Value PyMoneroCreateOpenWalletParams::to_rapidjson_val(rapidjson::Doc return root; } -PyMoneroReserveProofParams::PyMoneroReserveProofParams(const std::string &message, bool all): - m_all(all), m_message(message) { -} - -PyMoneroReserveProofParams::PyMoneroReserveProofParams(const std::string &address, const std::string &message, const std::string &signature): - m_address(address), m_message(message), m_signature(signature) { -} - -PyMoneroReserveProofParams::PyMoneroReserveProofParams(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) { -} - -PyMoneroReserveProofParams::PyMoneroReserveProofParams(const std::string &tx_hash, const std::string &message): - m_tx_hash(tx_hash), m_message(message) { -} - -PyMoneroReserveProofParams::PyMoneroReserveProofParams(uint32_t account_index, uint64_t amount, const std::string &message): - m_account_index(account_index), m_amount(amount), m_message(message) { -} - rapidjson::Value PyMoneroReserveProofParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); rapidjson::Value value_str(rapidjson::kStringType); @@ -1656,52 +1849,6 @@ rapidjson::Value PyMoneroRefreshWalletParams::to_rapidjson_val(rapidjson::Docume return root; } -PyMoneroTransferParams::PyMoneroTransferParams(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 PyMoneroTransferParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); rapidjson::Value value_num(rapidjson::kNumberType); @@ -1728,10 +1875,6 @@ rapidjson::Value PyMoneroTransferParams::to_rapidjson_val(rapidjson::Document::A return root; } -PyMoneroGetIncomingTransfersParams::PyMoneroGetIncomingTransfersParams(const std::string& transfer_type, bool verbose): - m_transfer_type(transfer_type), m_verbose(verbose) { -} - rapidjson::Value PyMoneroGetIncomingTransfersParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); rapidjson::Value value_num(rapidjson::kNumberType); @@ -1762,61 +1905,14 @@ rapidjson::Value PyMoneroGetTransfersParams::to_rapidjson_val(rapidjson::Documen return root; } -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; - } -} - -std::string PyMoneroReserveProofSignature::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"); -} - -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(); - } +std::shared_ptr PyMoneroParsePaymentUriResponse::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; } diff --git a/src/cpp/wallet/py_monero_wallet_model.h b/src/cpp/wallet/py_monero_wallet_model.h index ac1da46..8f1586f 100644 --- a/src/cpp/wallet/py_monero_wallet_model.h +++ b/src/cpp/wallet/py_monero_wallet_model.h @@ -50,29 +50,8 @@ struct PyMoneroWalletConfig : public monero::monero_wallet_config { public: boost::optional> m_connection_manager; - PyMoneroWalletConfig() { - m_connection_manager = boost::none; - } - - PyMoneroWalletConfig(const PyMoneroWalletConfig& config) { - m_path = config.m_path; - m_password = config.m_password; - m_network_type = config.m_network_type; - m_server = config.m_server; - m_seed = config.m_seed; - m_seed_offset = config.m_seed_offset; - m_primary_address = config.m_primary_address; - m_private_view_key = config.m_private_view_key; - m_private_spend_key = config.m_private_spend_key; - m_restore_height = config.m_restore_height; - m_language = config.m_language; - m_save_current = config.m_save_current; - m_account_lookahead = config.m_account_lookahead; - m_subaddress_lookahead = config.m_subaddress_lookahead; - m_is_multisig = config.m_is_multisig; - m_connection_manager = config.m_connection_manager; - } - + PyMoneroWalletConfig() { } + PyMoneroWalletConfig(const PyMoneroWalletConfig& config); }; class PyMoneroTxWallet : public monero::monero_tx_wallet { @@ -101,11 +80,8 @@ class PyMoneroTxSet : public monero::monero_tx_set { class PyMoneroKeyImage : public monero::monero_key_image { public: - PyMoneroKeyImage() {} - PyMoneroKeyImage(const monero::monero_key_image &key_image) { - m_hex = key_image.m_hex; - m_signature = key_image.m_signature; - } + + 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); @@ -140,10 +116,7 @@ class PyMoneroMultisigTxDataParams : public PyMoneroJsonRequestParams { public: boost::optional m_multisig_tx_hex; - PyMoneroMultisigTxDataParams() {} - PyMoneroMultisigTxDataParams(const std::string& multisig_tx_hex) { - m_multisig_tx_hex = multisig_tx_hex; - } + PyMoneroMultisigTxDataParams(const std::string& multisig_tx_hex): m_multisig_tx_hex(multisig_tx_hex) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -154,32 +127,20 @@ class PyMoneroDecodedAddress { PyMoneroAddressType m_address_type; monero::monero_network_type m_network_type; - PyMoneroDecodedAddress(std::string& address, PyMoneroAddressType address_type, monero::monero_network_type network_type) { - m_address = address; - m_address_type = address_type; - m_network_type = network_type; - } - + PyMoneroDecodedAddress(const std::string& address, PyMoneroAddressType address_type, monero::monero_network_type network_type); }; -class PyMoneroAccountTag { +struct PyMoneroAccountTag : public monero::serializable_struct { public: boost::optional m_tag; boost::optional m_label; std::vector m_account_indices; PyMoneroAccountTag() { } + PyMoneroAccountTag(const std::string& tag, const std::string& label): m_tag(tag), m_label(label) { } + PyMoneroAccountTag(const std::string& tag, const std::string& label, const std::vector& account_indices): m_tag(tag), m_label(label), m_account_indices(account_indices) { } - PyMoneroAccountTag(std::string& tag, std::string& label) { - m_tag = tag; - m_label = label; - } - - PyMoneroAccountTag(std::string& tag, std::string& label, 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); @@ -226,10 +187,7 @@ class PyMoneroQueryKeyParams : public PyMoneroJsonRequestParams { public: boost::optional m_key_type; - PyMoneroQueryKeyParams() { } - PyMoneroQueryKeyParams(const std::string& key_type) { - m_key_type = key_type; - } + PyMoneroQueryKeyParams(const std::string& key_type): m_key_type(key_type) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -238,10 +196,7 @@ class PyMoneroQueryOutputParams : public PyMoneroJsonRequestParams { public: boost::optional m_key_image; - PyMoneroQueryOutputParams() { } - PyMoneroQueryOutputParams(const std::string& key_image) { - m_key_image = key_image; - } + PyMoneroQueryOutputParams(const std::string& key_image): m_key_image(key_image) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -251,14 +206,8 @@ class PyMoneroGetAddressParams : public PyMoneroJsonRequestParams { boost::optional m_account_index; std::vector m_subaddress_indices; - PyMoneroGetAddressParams() { } - PyMoneroGetAddressParams(uint32_t account_index, const std::vector& subaddress_indices) { - m_account_index = account_index; - m_subaddress_indices = subaddress_indices; - } - PyMoneroGetAddressParams(uint32_t account_index) { - m_account_index = account_index; - } + PyMoneroGetAddressParams(uint32_t account_index): m_account_index(account_index) { } + PyMoneroGetAddressParams(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; }; @@ -267,10 +216,7 @@ class PyMoneroGetAddressIndexParams : public PyMoneroJsonRequestParams { public: boost::optional m_address; - PyMoneroGetAddressIndexParams() { } - PyMoneroGetAddressIndexParams(const std::string& address) { - m_address = address; - } + PyMoneroGetAddressIndexParams(const std::string& address): m_address(address) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -280,11 +226,7 @@ class PyMoneroMakeIntegratedAddressParams : public PyMoneroJsonRequestParams { boost::optional m_standard_address; boost::optional m_payment_id; - PyMoneroMakeIntegratedAddressParams() { } - PyMoneroMakeIntegratedAddressParams(const std::string& standard_address, const std::string& payment_id) { - m_standard_address = standard_address; - m_payment_id = payment_id; - } + PyMoneroMakeIntegratedAddressParams(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; }; @@ -293,10 +235,7 @@ class PyMoneroSplitIntegratedAddressParams : public PyMoneroJsonRequestParams { public: boost::optional m_integrated_address; - PyMoneroSplitIntegratedAddressParams() { } - PyMoneroSplitIntegratedAddressParams(const std::string& integrated_address) { - m_integrated_address = integrated_address; - } + PyMoneroSplitIntegratedAddressParams(const std::string& integrated_address): m_integrated_address(integrated_address) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -307,13 +246,7 @@ class PyMoneroWalletStartMiningParams : public PyMoneroJsonRequestParams { boost::optional m_is_background; boost::optional m_ignore_battery; - PyMoneroWalletStartMiningParams() { } - - PyMoneroWalletStartMiningParams(int num_threads, bool is_background, bool ignore_battery) { - m_num_threads = num_threads; - m_is_background = is_background; - m_ignore_battery = ignore_battery; - } + PyMoneroWalletStartMiningParams(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; }; @@ -322,9 +255,8 @@ class PyMoneroPrepareMultisigParams : public PyMoneroJsonRequestParams { public: // TODO monero-docs document this parameter boost::optional m_enable_multisig_experimental; - PyMoneroPrepareMultisigParams(bool enable_multisig_experimental = true) { - m_enable_multisig_experimental = enable_multisig_experimental; - } + + PyMoneroPrepareMultisigParams(bool enable_multisig_experimental = true): m_enable_multisig_experimental(enable_multisig_experimental) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -339,11 +271,7 @@ class PyMoneroImportMultisigHexParams : public PyMoneroJsonRequestParams { public: std::vector m_multisig_hexes; - PyMoneroImportMultisigHexParams() {} - - PyMoneroImportMultisigHexParams(const std::vector& multisig_hexes) { - m_multisig_hexes = multisig_hexes; - } + PyMoneroImportMultisigHexParams(const std::vector& multisig_hexes): m_multisig_hexes(multisig_hexes) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -356,7 +284,7 @@ class PyMoneroImportMultisigHexResponse { class PyMoneroSubmitMultisigTxHexResponse { public: - PyMoneroSubmitMultisigTxHexResponse() {} + static std::vector from_property_tree(const boost::property_tree::ptree& node); }; @@ -366,11 +294,8 @@ class PyMoneroMakeMultisigParams : public PyMoneroJsonRequestParams { boost::optional m_threshold; boost::optional m_password; - PyMoneroMakeMultisigParams(const std::vector& multisig_hexes, int threshold, const std::string& password) { - m_multisig_info = multisig_hexes; - m_threshold = threshold; - m_password = password; - } + PyMoneroMakeMultisigParams(const std::vector& multisig_hexes, const std::string& password): m_multisig_info(multisig_hexes), m_password(password) { } + PyMoneroMakeMultisigParams(const std::vector& multisig_hexes, int threshold, const std::string& password): m_multisig_info(multisig_hexes), m_threshold(threshold), m_password(password) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -380,28 +305,11 @@ class PyMoneroPrepareMakeMultisigResponse { static std::string from_property_tree(const boost::property_tree::ptree& node); }; -class PyMoneroExchangeMultisigKeysParams : public PyMoneroJsonRequestParams { -public: - std::vector m_multisig_info; - boost::optional m_password; - - PyMoneroExchangeMultisigKeysParams() {} - PyMoneroExchangeMultisigKeysParams(const std::vector& multisig_hexes, const std::string& password) { - m_multisig_info = multisig_hexes; - m_password = password; - } - - rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; -}; - class PyMoneroParsePaymentUriParams : public PyMoneroJsonRequestParams { public: boost::optional m_uri; - PyMoneroParsePaymentUriParams() {} - PyMoneroParsePaymentUriParams(const std::string& uri) { - m_uri = uri; - } + PyMoneroParsePaymentUriParams(const std::string& uri): m_uri(uri) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -414,8 +322,6 @@ class PyMoneroParsePaymentUriResponse { boost::optional m_recipient_name; boost::optional m_tx_description; - PyMoneroParsePaymentUriResponse() {} - std::shared_ptr to_tx_config() const; static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& response); }; @@ -429,8 +335,7 @@ class PyMoneroGetPaymentUriParams : public PyMoneroJsonRequestParams { boost::optional m_recipient_name; boost::optional m_tx_description; - PyMoneroGetPaymentUriParams() {} - PyMoneroGetPaymentUriParams(const monero_tx_config & config); + PyMoneroGetPaymentUriParams(const monero_tx_config& config); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -447,24 +352,9 @@ class PyMoneroGetBalanceParams : public PyMoneroJsonRequestParams { boost::optional m_all_accounts; boost::optional m_strict; - PyMoneroGetBalanceParams() {}; - PyMoneroGetBalanceParams(bool all_accounts, bool strict = false) { - m_all_accounts = all_accounts; - m_strict = strict; - }; - - PyMoneroGetBalanceParams(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; - } - PyMoneroGetBalanceParams(uint32_t account_idx, boost::optional address_idx, bool all_accounts = false, bool strict = false) { - m_account_idx = account_idx; - if (address_idx != boost::none) m_address_indices.push_back(address_idx.get()); - m_all_accounts = all_accounts; - m_strict = strict; - } + PyMoneroGetBalanceParams(bool all_accounts, bool strict = false): m_all_accounts(all_accounts), m_strict(strict) { } + PyMoneroGetBalanceParams(uint32_t account_idx, const std::vector& address_indices, bool all_accounts = false, bool strict = false); + PyMoneroGetBalanceParams(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; }; @@ -478,18 +368,8 @@ class PyMoneroGetBalanceResponse { boost::optional m_blocks_to_unlock; std::vector> m_per_subaddress; - PyMoneroGetBalanceResponse() { - m_balance = 0; - m_unlocked_balance = 0; - } - - PyMoneroGetBalanceResponse(uint64_t balance, uint64_t unlocked_balance, bool multisig_import_needed, uint64_t time_to_unlock, uint64_t blocks_to_unlock) { - m_balance = balance; - m_unlocked_balance = unlocked_balance; - m_multisig_import_needed = multisig_import_needed; - m_time_to_unlock = time_to_unlock; - m_blocks_to_unlock = blocks_to_unlock; - } + PyMoneroGetBalanceResponse(): m_balance(0), m_unlocked_balance(0) { } + PyMoneroGetBalanceResponse(uint64_t balance, uint64_t unlocked_balance, bool multisig_import_needed, uint64_t time_to_unlock, uint64_t blocks_to_unlock); static void from_property_tree(const boost::property_tree::ptree& node, const std::shared_ptr& response); }; @@ -498,9 +378,7 @@ class PyMoneroCreateAccountParams : public PyMoneroJsonRequestParams { public: boost::optional m_tag; - PyMoneroCreateAccountParams(const std::string& tag = "") { - m_tag = tag; - } + PyMoneroCreateAccountParams(const std::string& tag = ""): m_tag(tag) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -509,9 +387,7 @@ class PyMoneroCloseWalletParams : public PyMoneroJsonRequestParams { public: boost::optional m_save; - PyMoneroCloseWalletParams(bool save = false) { - m_save = save; - }; + PyMoneroCloseWalletParams(bool save = false): m_save(save) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -521,10 +397,7 @@ class PyMoneroChangeWalletPasswordParams : public PyMoneroJsonRequestParams { boost::optional m_old_password; boost::optional m_new_password; - PyMoneroChangeWalletPasswordParams(const std::string& old_password, const std::string& new_password) { - m_old_password = old_password; - m_new_password = new_password; - } + PyMoneroChangeWalletPasswordParams(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; }; @@ -534,14 +407,8 @@ class PyMoneroWalletAttributeParams : public PyMoneroJsonRequestParams { boost::optional m_key; boost::optional m_value; - PyMoneroWalletAttributeParams(const std::string& key, const std::string& value) { - m_key = key; - m_value = value; - } - - PyMoneroWalletAttributeParams(const std::string& key) { - m_key = key; - } + PyMoneroWalletAttributeParams(const std::string& key): m_key(key) { } + PyMoneroWalletAttributeParams(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); @@ -551,10 +418,7 @@ class PyMoneroScanTxParams : public PyMoneroJsonRequestParams { public: std::vector m_tx_hashes; - PyMoneroScanTxParams() {} - PyMoneroScanTxParams(const std::vector& tx_hashes) { - m_tx_hashes = tx_hashes; - } + PyMoneroScanTxParams(const std::vector& tx_hashes): m_tx_hashes(tx_hashes) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -589,11 +453,7 @@ class PyMoneroSetAccountTagDescriptionParams : public PyMoneroJsonRequestParams boost::optional m_tag; boost::optional m_label; - PyMoneroSetAccountTagDescriptionParams() {} - PyMoneroSetAccountTagDescriptionParams(const std::string& tag, const std::string& label) { - m_tag = tag; - m_label = label; - } + PyMoneroSetAccountTagDescriptionParams(const std::string& tag, const std::string& label): m_tag(tag), m_label(label) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -603,14 +463,8 @@ class PyMoneroTagAccountsParams : public PyMoneroJsonRequestParams { std::vector m_account_indices; boost::optional m_tag; - PyMoneroTagAccountsParams() {} - PyMoneroTagAccountsParams(const std::vector& account_indices) { - m_account_indices = account_indices; - } - PyMoneroTagAccountsParams(const std::string& tag, const std::vector& account_indices) { - m_account_indices = account_indices; - m_tag = tag; - } + PyMoneroTagAccountsParams(const std::vector& account_indices): m_account_indices(account_indices) { } + PyMoneroTagAccountsParams(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; }; @@ -620,14 +474,8 @@ class PyMoneroTxNotesParams : public PyMoneroJsonRequestParams { std::vector m_tx_hashes; std::vector m_notes; - PyMoneroTxNotesParams(const std::vector& tx_hashes) { - m_tx_hashes = tx_hashes; - } - - PyMoneroTxNotesParams(const std::vector& tx_hashes, const std::vector& notes) { - m_tx_hashes = tx_hashes; - m_notes = notes; - } + PyMoneroTxNotesParams(const std::vector& tx_hashes): m_tx_hashes(tx_hashes) { } + PyMoneroTxNotesParams(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; }; @@ -641,24 +489,10 @@ class PyMoneroAddressBookEntryParams : public PyMoneroJsonRequestParams { boost::optional m_description; std::vector m_entries; - PyMoneroAddressBookEntryParams() {} - PyMoneroAddressBookEntryParams(uint64_t index) { - m_index = index; - } - PyMoneroAddressBookEntryParams(const std::vector& entries) { - m_entries = entries; - } - PyMoneroAddressBookEntryParams(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; - } - PyMoneroAddressBookEntryParams(const std::string& address, const std::string& description) { - m_address = address; - m_description = description; - } + PyMoneroAddressBookEntryParams(uint64_t index): m_index(index) { } + PyMoneroAddressBookEntryParams(const std::vector& entries): m_entries(entries) { } + PyMoneroAddressBookEntryParams(uint64_t index, bool set_address, const std::string& address, bool set_description, const std::string& description); + PyMoneroAddressBookEntryParams(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; }; @@ -675,20 +509,14 @@ class PyMoneroWalletBalance { uint64_t m_balance; uint64_t m_unlocked_balance; - PyMoneroWalletBalance(uint64_t balance = 0, uint64_t unlocked_balance = 0) { - m_balance = balance; - m_unlocked_balance = unlocked_balance; - } + PyMoneroWalletBalance(uint64_t balance = 0, uint64_t unlocked_balance = 0): m_balance(balance), m_unlocked_balance(unlocked_balance) { } }; class PyMoneroGetAccountsParams : public PyMoneroJsonRequestParams { public: boost::optional m_label; - PyMoneroGetAccountsParams() {} - PyMoneroGetAccountsParams(const std::string& label) { - m_label = label; - } + PyMoneroGetAccountsParams(const std::string& label): m_label(label) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -699,25 +527,11 @@ class PyMoneroVerifySignMessageParams : public PyMoneroJsonRequestParams { boost::optional m_address; boost::optional m_signature; boost::optional m_signature_type; - boost::optional m_account_index; boost::optional m_address_index; - - PyMoneroVerifySignMessageParams() {} - - PyMoneroVerifySignMessageParams(const std::string &data, const std::string &address, const std::string& signature) { - m_data = data; - m_address = address; - m_signature = signature; - } - - PyMoneroVerifySignMessageParams(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; - } + PyMoneroVerifySignMessageParams(const std::string &data, const std::string &address, const std::string& signature); + PyMoneroVerifySignMessageParams(const std::string &data, monero::monero_message_signature_type signature_type, uint32_t account_index, uint32_t address_index); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -728,17 +542,8 @@ class PyMoneroCheckTxKeyParams : public PyMoneroJsonRequestParams { boost::optional m_address; boost::optional m_tx_key; - PyMoneroCheckTxKeyParams() {} - - PyMoneroCheckTxKeyParams(const std::string &tx_hash) { - m_tx_hash = tx_hash; - } - - PyMoneroCheckTxKeyParams(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; - } + PyMoneroCheckTxKeyParams(const std::string &tx_hash): m_tx_hash(tx_hash) { } + PyMoneroCheckTxKeyParams(const std::string &tx_hash, const std::string &tx_key, const std::string &address); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -748,16 +553,9 @@ class PyMoneroSignDescribeTransferParams : public PyMoneroJsonRequestParams { boost::optional m_unsigned_txset; boost::optional m_multisig_txset; - PyMoneroSignDescribeTransferParams() {} - - PyMoneroSignDescribeTransferParams(const std::string &unsigned_txset) { - m_unsigned_txset = unsigned_txset; - } - - PyMoneroSignDescribeTransferParams(const std::string &unsigned_txset, const std::string &multisig_txset) { - m_unsigned_txset = unsigned_txset; - m_multisig_txset = multisig_txset; - } + PyMoneroSignDescribeTransferParams() { } + PyMoneroSignDescribeTransferParams(const std::string &unsigned_txset) : m_unsigned_txset(unsigned_txset) { } + PyMoneroSignDescribeTransferParams(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; }; @@ -766,11 +564,7 @@ class PyMoneroWalletRelayTxParams : public PyMoneroJsonRequestParams { public: boost::optional m_hex; - PyMoneroWalletRelayTxParams() {} - - PyMoneroWalletRelayTxParams(const std::string &hex) { - m_hex = hex; - } + PyMoneroWalletRelayTxParams(const std::string &hex): m_hex(hex) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -790,10 +584,7 @@ class PyMoneroSweepParams : public PyMoneroJsonRequestParams { boost::optional m_get_tx_hex; boost::optional m_get_tx_metadata; - PyMoneroSweepParams(bool relay = false) { - m_relay = relay; - } - + PyMoneroSweepParams(bool relay = false): m_relay(relay) { } PyMoneroSweepParams(const monero_tx_config& config); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; @@ -803,10 +594,7 @@ class PyMoneroSubmitTransferParams : public PyMoneroJsonRequestParams { public: boost::optional m_signed_tx_hex; - PyMoneroSubmitTransferParams() {} - PyMoneroSubmitTransferParams(const std::string& signed_tx_hex) { - m_signed_tx_hex = signed_tx_hex; - } + PyMoneroSubmitTransferParams(const std::string& signed_tx_hex): m_signed_tx_hex(signed_tx_hex) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -817,11 +605,7 @@ class PyMoneroCreateSubaddressParams : public PyMoneroJsonRequestParams { boost::optional m_account_index; boost::optional m_subaddress_index; - PyMoneroCreateSubaddressParams() {} - PyMoneroCreateSubaddressParams(uint32_t account_idx, const std::string& label) { - m_account_index = account_idx; - m_label = label; - } + PyMoneroCreateSubaddressParams(uint32_t account_idx, const std::string& label): m_account_index(account_idx), m_label(label) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -832,12 +616,7 @@ class PyMoneroSetSubaddressLabelParams : public PyMoneroJsonRequestParams { boost::optional m_account_index; boost::optional m_subaddress_index; - PyMoneroSetSubaddressLabelParams() {} - PyMoneroSetSubaddressLabelParams(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; - } + PyMoneroSetSubaddressLabelParams(uint32_t account_idx, uint32_t subaddress_idx, const std::string& label); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -847,13 +626,8 @@ class PyMoneroImportExportOutputsParams : public PyMoneroJsonRequestParams { boost::optional m_outputs_hex; boost::optional m_all; - PyMoneroImportExportOutputsParams() {} - PyMoneroImportExportOutputsParams(bool all) { - m_all = all; - } - PyMoneroImportExportOutputsParams(const std::string& outputs_hex) { - m_outputs_hex = outputs_hex; - } + PyMoneroImportExportOutputsParams(bool all): m_all(all) { } + PyMoneroImportExportOutputsParams(const std::string& outputs_hex): m_outputs_hex(outputs_hex) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -863,18 +637,9 @@ class PyMoneroImportExportKeyImagesParams : public PyMoneroJsonRequestParams { boost::optional m_all; std::vector> m_key_images; - PyMoneroImportExportKeyImagesParams() {} - PyMoneroImportExportKeyImagesParams(const std::vector> &key_images) { - for(const auto &key_image : key_images) { - m_key_images.push_back(std::make_shared(*key_image)); - } - } - PyMoneroImportExportKeyImagesParams(const std::vector> &key_images) { - m_key_images = key_images; - } - PyMoneroImportExportKeyImagesParams(bool all) { - m_all = all; - } + PyMoneroImportExportKeyImagesParams(const std::vector> &key_images); + PyMoneroImportExportKeyImagesParams(const std::vector> &key_images): m_key_images(key_images) { } + PyMoneroImportExportKeyImagesParams(bool all): m_all(all) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -893,14 +658,9 @@ class PyMoneroCreateOpenWalletParams : public PyMoneroJsonRequestParams { boost::optional m_view_key; boost::optional m_spend_key; - PyMoneroCreateOpenWalletParams() {} - PyMoneroCreateOpenWalletParams(const boost::optional& filename, const boost::optional &password); - PyMoneroCreateOpenWalletParams(const boost::optional& filename, const boost::optional &password, const boost::optional &language); - PyMoneroCreateOpenWalletParams(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); - PyMoneroCreateOpenWalletParams(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); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; @@ -916,16 +676,10 @@ class PyMoneroReserveProofParams : public PyMoneroJsonRequestParams { boost::optional m_address; boost::optional m_signature; - PyMoneroReserveProofParams() {} - PyMoneroReserveProofParams(const std::string &message, bool all = true); - PyMoneroReserveProofParams(const std::string &address, const std::string &message, const std::string &signature); - PyMoneroReserveProofParams(const std::string &tx_hash, const std::string &address, const std::string &message, const std::string &signature); - PyMoneroReserveProofParams(const std::string &tx_hash, const std::string &message); - PyMoneroReserveProofParams(uint32_t account_index, uint64_t amount, const std::string &message); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; @@ -937,16 +691,9 @@ class PyMoneroRefreshWalletParams : public PyMoneroJsonRequestParams { boost::optional m_period; boost::optional m_start_height; - PyMoneroRefreshWalletParams() {} - - PyMoneroRefreshWalletParams(bool enable, uint64_t period) { - m_enable = enable; - m_period = period; - } - - PyMoneroRefreshWalletParams(uint64_t start_height) { - m_start_height = start_height; - } + PyMoneroRefreshWalletParams() { } + PyMoneroRefreshWalletParams(bool enable, uint64_t period): m_enable(enable), m_period(period) { } + PyMoneroRefreshWalletParams(uint64_t start_height): m_start_height(start_height) { } rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; }; @@ -965,7 +712,6 @@ class PyMoneroTransferParams : public PyMoneroJsonRequestParams { boost::optional m_get_tx_key; std::vector> m_destinations; - PyMoneroTransferParams() {} PyMoneroTransferParams(const monero::monero_tx_config &config); rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const override; @@ -984,7 +730,6 @@ class PyMoneroGetTransfersParams : public PyMoneroJsonRequestParams { boost::optional m_account_index; std::vector m_subaddr_indices; - PyMoneroGetTransfersParams() {} 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; }; diff --git a/src/cpp/wallet/py_monero_wallet_rpc.cpp b/src/cpp/wallet/py_monero_wallet_rpc.cpp index f153ff5..f2daa2a 100644 --- a/src/cpp/wallet/py_monero_wallet_rpc.cpp +++ b/src/cpp/wallet/py_monero_wallet_rpc.cpp @@ -219,18 +219,14 @@ bool PyMoneroWalletPoller::check_for_changed_balances() { return false; } -PyMoneroWalletRpc::PyMoneroWalletRpc() { - m_rpc = std::make_shared(); -} - PyMoneroWalletRpc::PyMoneroWalletRpc(const std::shared_ptr& rpc_connection) { m_rpc = rpc_connection; - if (!m_rpc->is_online() && !m_rpc->m_uri->empty()) m_rpc->check_connection(); + if (!m_rpc->is_online() && m_rpc->m_uri != boost::none) m_rpc->check_connection(); } -PyMoneroWalletRpc::PyMoneroWalletRpc(const std::string& uri, const std::string& username, const std::string& password) { - m_rpc = std::make_shared(uri, username, password); - if (!m_rpc->m_uri->empty()) m_rpc->check_connection(); +PyMoneroWalletRpc::PyMoneroWalletRpc(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(); } PyMoneroWalletRpc::~PyMoneroWalletRpc() { @@ -921,14 +917,18 @@ int PyMoneroWalletRpc::import_outputs(const std::string& outputs_hex) { auto response = m_rpc->send_json_request(request); if (response->m_result == boost::none) throw std::runtime_error("Invalid Monero JSONRPC response"); auto node = response->m_result.get(); + int num_imported = 0; for (auto it = node.begin(); it != node.end(); ++it) { std::string key = it->first; - if (key == std::string("num_imported")) return it->second.get_value(); + if (key == std::string("num_imported")) { + num_imported = it->second.get_value(); + break; + } } - return 0; + return num_imported; } std::vector> PyMoneroWalletRpc::export_key_images(bool all) const { @@ -953,10 +953,6 @@ std::shared_ptr PyMoneroWalletRpc::import_key_im return import_result; } -std::vector> PyMoneroWalletRpc::get_new_key_images_from_last_import() { - throw std::runtime_error("get_new_key_images_from_last_import(): not implemented"); -} - void PyMoneroWalletRpc::freeze_output(const std::string& key_image) { auto params = std::make_shared(key_image); PyMoneroJsonRequest request("freeze", params); @@ -1566,10 +1562,6 @@ void PyMoneroWalletRpc::set_account_tag_label(const std::string& tag, const std: m_rpc->send_json_request(request); } -void PyMoneroWalletRpc::set_account_label(uint32_t account_index, const std::string& label) { - set_subaddress_label(account_index, 0, label); -} - std::string PyMoneroWalletRpc::get_payment_uri(const monero_tx_config& config) const { auto params = std::make_shared(config); PyMoneroJsonRequest request("make_uri", params); @@ -1671,7 +1663,7 @@ std::string PyMoneroWalletRpc::make_multisig(const std::vector& mul } monero_multisig_init_result PyMoneroWalletRpc::exchange_multisig_keys(const std::vector& multisig_hexes, const std::string& password) { - auto params = std::make_shared(multisig_hexes, password); + auto params = std::make_shared(multisig_hexes, password); PyMoneroJsonRequest request("exchange_multisig_keys", params); auto response = m_rpc->send_json_request(request); clear_address_cache(); diff --git a/src/cpp/wallet/py_monero_wallet_rpc.h b/src/cpp/wallet/py_monero_wallet_rpc.h index 610ac0b..e962f50 100644 --- a/src/cpp/wallet/py_monero_wallet_rpc.h +++ b/src/cpp/wallet/py_monero_wallet_rpc.h @@ -39,9 +39,8 @@ class PyMoneroWalletRpc : public PyMoneroWallet { public: ~PyMoneroWalletRpc(); - PyMoneroWalletRpc(); PyMoneroWalletRpc(const std::shared_ptr& rpc_connection); - PyMoneroWalletRpc(const std::string& uri = "", const std::string& username = "", const std::string& password = ""); + PyMoneroWalletRpc(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); PyMoneroWalletRpc* open_wallet(const std::shared_ptr &config); PyMoneroWalletRpc* open_wallet(const std::string& name, const std::string& password); @@ -106,7 +105,6 @@ class PyMoneroWalletRpc : public PyMoneroWallet { 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; - std::vector> get_new_key_images_from_last_import() 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; @@ -143,7 +141,6 @@ class PyMoneroWalletRpc : public PyMoneroWallet { 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; - void set_account_label(uint32_t account_index, const std::string& label) override; std::string get_payment_uri(const monero_tx_config& config) const override; // TODO why no override ? std::shared_ptr parse_payment_uri(const std::string& uri) const; diff --git a/src/python/monero_connection_priority_comparator.pyi b/src/python/monero_connection_priority_comparator.pyi index 0b24a10..13bb91f 100644 --- a/src/python/monero_connection_priority_comparator.pyi +++ b/src/python/monero_connection_priority_comparator.pyi @@ -1,12 +1,12 @@ class MoneroConnectionProriotyComparator: @staticmethod - def compare(p1: int, p2: int) -> int: + def compare(p1: int, p2: int) -> bool: """ Compare connection priorities. :param int p1: Priority 1. :param int p2: Priority 2. - :return int: `1`, `-1` or `0` + :return bool: `True` if `p1` comes before `p2`, `False` otherwise. """ ... diff --git a/src/python/monero_daemon_rpc.pyi b/src/python/monero_daemon_rpc.pyi index 4fdb0e2..363d605 100644 --- a/src/python/monero_daemon_rpc.pyi +++ b/src/python/monero_daemon_rpc.pyi @@ -16,31 +16,34 @@ class MoneroDaemonRpc(MoneroDaemonDefault): def __init__(self, rpc: MoneroRpcConnection) -> None: """ Initialize a Monero daemon RPC. - + :param MoneroRpcConnection rpc: A Monero RPC connection. """ ... @typing.overload - def __init__(self, uri: str, username: str = '', password: str = '') -> None: + def __init__(self, uri: str, username: str = '', password: str = '', proxy_uri: str = '', zmq_uri: str = '', timeout: int = 20000) -> None: """ Initialize a Monero daemon RPC. :param str uri: The daemon RPC uri. :param str username: Authentication username for daemon RPC. :param str password: Authentication password for daemon RPC. + :param str proxy_uri: Connection proxy. + :param str zmq_uri: RPC ZMQ uri. + :param int timeout: Connection timeout in milliseconds. """ ... def get_rpc_connection(self) -> MoneroRpcConnection: """ Get the daemon's RPC connection. - + :return MoneroRpcConnection: the daemon's rpc connection """ ... def is_connected(self) -> bool: """ Indicates if the client is connected to the daemon via RPC. - + :return bool: true if the client is connected to the daemon, false otherwise """ - ... \ No newline at end of file + ... diff --git a/src/python/monero_rpc_connection.pyi b/src/python/monero_rpc_connection.pyi index 2aa44ef..796563c 100644 --- a/src/python/monero_rpc_connection.pyi +++ b/src/python/monero_rpc_connection.pyi @@ -34,18 +34,18 @@ class MoneroRpcConnection(SerializableStruct): ... @staticmethod - def compare(c1: MoneroRpcConnection, c2: MoneroRpcConnection, current_connection: MoneroRpcConnection) -> int: + def before(c1: MoneroRpcConnection, c2: MoneroRpcConnection, current_connection: MoneroRpcConnection) -> bool: """ Compare RPC connections. :param MoneroRpcConnection c1: connection :param MoneroRpcConnection c2: other connection :param MoneroRpcConnection current_connection: current connection - :return: 0, 1 or -1 + :return bool: `True` if `c1` comes before `c2`, `False` otherwise. """ ... @typing.overload - def __init__(self, uri: str = '', username: str = '', password: str = '', proxy_uri: str = '', zmq_uri: str = '', priority: int = 0, timeout: int = 0) -> None: + def __init__(self, uri: str = '', username: str = '', password: str = '', proxy_uri: str = '', zmq_uri: str = '', priority: int = 0, timeout: int = 20000) -> None: """ Initialize a RPC connection. @@ -66,7 +66,7 @@ class MoneroRpcConnection(SerializableStruct): :param MoneroRpcConnection rpc: RPC connection to copy. """ ... - def check_connection(self, timeout_ms: int = 2000) -> bool: + def check_connection(self, timeout_ms: int = 20000) -> bool: """ Check the connection and update online, authentication, and response time status. diff --git a/src/python/monero_wallet_rpc.pyi b/src/python/monero_wallet_rpc.pyi index d0e577b..f581dc2 100644 --- a/src/python/monero_wallet_rpc.pyi +++ b/src/python/monero_wallet_rpc.pyi @@ -19,13 +19,16 @@ class MoneroWalletRpc(MoneroWallet): """ ... @typing.overload - def __init__(self, uri: str = '', username: str = '', password: str = '') -> None: + def __init__(self, uri: str = '', username: str = '', password: str = '', proxy_uri: str = '', zmq_uri: str = '', timeout: int = 20000) -> None: """ Initialize a Monero wallet RPC. :param str uri: Connection uri. :param str username: Authentication connection username. :param str password: Authentication connection password. + :param str proxy_uri: Connection proxy. + :param str zmq_uri: RPC ZMQ uri. + :param int timeout: Connection timeout. """ ... def create_wallet(self, config: MoneroWalletConfig) -> MoneroWalletRpc: diff --git a/tests/test_monero_common.py b/tests/test_monero_common.py index fd4eacd..838dcb4 100644 --- a/tests/test_monero_common.py +++ b/tests/test_monero_common.py @@ -2,7 +2,7 @@ import logging from monero import ( - MoneroError, MoneroRpcError + MoneroError, MoneroRpcError, SerializableStruct ) logger: logging.Logger = logging.getLogger("TestMoneroCommon") @@ -32,3 +32,9 @@ def test_monero_error(self) -> None: assert isinstance(monero_rpc_err, MoneroError) assert str(monero_rpc_err) == "Test monero rpc error" assert monero_rpc_err.code == -1 + + # test serializable struct + @pytest.mark.not_implemented + def test_serializable_struct(self) -> None: + ser_struct: SerializableStruct = SerializableStruct() + ser_struct.serialize() diff --git a/tests/test_monero_rpc_connection.py b/tests/test_monero_rpc_connection.py index c8e3508..a214861 100644 --- a/tests/test_monero_rpc_connection.py +++ b/tests/test_monero_rpc_connection.py @@ -1,7 +1,10 @@ import pytest import logging -from monero import MoneroRpcConnection, MoneroConnectionType, MoneroRpcError, MoneroUtils +from monero import ( + MoneroRpcConnection, MoneroConnectionType, MoneroRpcError, + MoneroUtils, MoneroConnectionProriotyComparator +) from utils import TestUtils as Utils, DaemonUtils, StringUtils logger: logging.Logger = logging.getLogger("TestMoneroRpcConnection") @@ -11,6 +14,9 @@ class TestMoneroRpcConnection: """Rpc connection integration tests""" + TIMEOUT_MS: int = Utils.AUTO_CONNECT_TIMEOUT_MS * 5 + """Rpc connection timeout in milliseconds.""" + # region Fixtures # Setup and teardown of test class @@ -38,13 +44,13 @@ def setup_and_teardown(self, request: pytest.FixtureRequest): @pytest.fixture(scope="class") def node_connection(self) -> MoneroRpcConnection: """Rpc connection test instance.""" - return MoneroRpcConnection(Utils.DAEMON_RPC_URI, Utils.DAEMON_RPC_USERNAME, Utils.DAEMON_RPC_PASSWORD) + return MoneroRpcConnection(Utils.DAEMON_RPC_URI, Utils.DAEMON_RPC_USERNAME, Utils.DAEMON_RPC_PASSWORD, timeout=self.TIMEOUT_MS) # Wallet rpc connection fixture @pytest.fixture(scope="class") def wallet_connection(self) -> MoneroRpcConnection: """Rpc connection test instance.""" - return MoneroRpcConnection(Utils.WALLET_RPC_URI, Utils.WALLET_RPC_USERNAME, Utils.WALLET_RPC_PASSWORD) + return MoneroRpcConnection(Utils.WALLET_RPC_URI, Utils.WALLET_RPC_USERNAME, Utils.WALLET_RPC_PASSWORD, timeout=self.TIMEOUT_MS) #endregion @@ -55,14 +61,25 @@ def wallet_connection(self) -> MoneroRpcConnection: def test_rpc_connection_serialization(self, node_connection: MoneroRpcConnection, wallet_connection: MoneroRpcConnection) -> None: # test node connection serialization connection_str: str = node_connection.serialize() - assert '{"uri":"http://127.0.0.1:18081","username":"rpc_daemon_user","password":"abc123"}' == connection_str + assert '{"uri":"http://127.0.0.1:18081","username":"rpc_daemon_user","password":"abc123","priority":0,"timeout":25000}' == connection_str # node wallet connection serialization connection_str = wallet_connection.serialize() - assert '{"uri":"127.0.0.1:18082","username":"rpc_user","password":"abc123"}' == connection_str + assert '{"uri":"127.0.0.1:18082","username":"rpc_user","password":"abc123","priority":0,"timeout":25000}' == connection_str + + # test empty connection + connection: MoneroRpcConnection = MoneroRpcConnection() + connection_str = connection.serialize() + assert '{"priority":0,"timeout":20000}' == connection.serialize() + + # 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 # Can copy a rpc connection @pytest.mark.skipif(Utils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") + @pytest.mark.xfail(raises=AssertionError, reason="TODO monero-cpp PyMoneroWalletConfig has custom fields serialization") def test_connection_copy(self, node_connection: MoneroRpcConnection) -> None: # test copy copy: MoneroRpcConnection = MoneroRpcConnection(node_connection) @@ -169,7 +186,7 @@ def test_set_invalid_credentials(self) -> None: assert connection.check_connection() assert not connection.is_authenticated() - # TODO internal http client throwing "Network error" instaead of 201 http error + # TODO internal http client throwing "Network error" instaead of 401 http error #assert connection.is_online() #assert connection.is_connected() assert not connection.is_online() @@ -179,8 +196,13 @@ def test_set_invalid_credentials(self) -> None: @pytest.mark.skipif(Utils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") def test_set_attributes(self, node_connection: MoneroRpcConnection) -> None: # set attributes + attr_range: range = range(100) + + for i in attr_range: + assert node_connection.get_attribute(f"attr{i}") == "" + attrs: dict[str, str] = {} - for i in range(5): + for i in attr_range: key: str = f"attr{i}" val: str = StringUtils.get_random_string() attrs[key] = val @@ -191,6 +213,14 @@ def test_set_attributes(self, node_connection: MoneroRpcConnection) -> None: val = attrs[key] assert val == node_connection.get_attribute(key) + # Test connection priorities + @pytest.mark.skipif(Utils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") + def test_priority(self) -> None: + for i in range(100): + for j in range(100): + expected: bool = (i == 0 and j != 0) or (i != 0 and j != 0 and i > j) + assert MoneroConnectionProriotyComparator.compare(i, j) is expected + # Can send json request @pytest.mark.skipif(Utils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") def test_send_json_request(self, node_connection: MoneroRpcConnection) -> None: diff --git a/tests/test_monero_wallet_common.py b/tests/test_monero_wallet_common.py index a7968a0..6fe1ad7 100644 --- a/tests/test_monero_wallet_common.py +++ b/tests/test_monero_wallet_common.py @@ -2834,6 +2834,7 @@ def test_export_key_images(self, wallet: MoneroWallet) -> None: # Can get new key images from the last import @pytest.mark.skipif(TestUtils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") + @pytest.mark.xfail(raises=Exception, reason="TODO these are already known to the wallet, so no new key images will be imported") def test_get_new_key_images_from_last_import(self, wallet: MoneroWallet) -> None: # get outputs hex outputs_hex = wallet.export_outputs() diff --git a/tests/test_monero_wallet_full.py b/tests/test_monero_wallet_full.py index ffe98ce..da02649 100644 --- a/tests/test_monero_wallet_full.py +++ b/tests/test_monero_wallet_full.py @@ -681,16 +681,6 @@ def test_get_height_by_date_regtest(self, wallet: MoneroWallet): def test_import_key_images(self, wallet: MoneroWallet): return super().test_import_key_images(wallet) - @pytest.mark.skip(reason="TODO fix segmentation fault") - @override - def test_get_new_key_images_from_last_import(self, wallet: MoneroWallet): - return super().test_get_new_key_images_from_last_import(wallet) - - @pytest.mark.skip(reason="TODO fix segmentation fault") - @override - def test_set_account_label(self, wallet: MoneroWallet) -> None: - super().test_set_account_label(wallet) - #endregion #region Utils diff --git a/tests/test_monero_wallet_interface.py b/tests/test_monero_wallet_interface.py index 62b05cf..b4f96c4 100644 --- a/tests/test_monero_wallet_interface.py +++ b/tests/test_monero_wallet_interface.py @@ -8,7 +8,7 @@ MoneroTxWallet ) -from utils import WalletUtils +from utils import WalletUtils, StringUtils logger: logging.Logger = logging.getLogger("TestMoneroWalletInterface") @@ -310,8 +310,7 @@ def test_export_key_images(self, wallet: MoneroWallet) -> None: def test_import_key_images(self, wallet: MoneroWallet) -> None: wallet.import_key_images([]) - #@pytest.mark.not_supported - @pytest.mark.skip(reason="TODO segmentation fault") + @pytest.mark.not_supported def test_get_new_key_images_from_last_import(self, wallet: MoneroWallet) -> None: wallet.get_new_key_images_from_last_import() @@ -353,12 +352,14 @@ def test_sweep_dust(self, wallet: MoneroWallet) -> None: @pytest.mark.not_supported def test_relay_tx_metadata(self, wallet: MoneroWallet) -> None: - wallet.relay_tx("") + wallet.relay_tx(StringUtils.get_random_string()) - #@pytest.mark.not_supported - @pytest.mark.skip(reason="TODO aborted: insert check for tx.metadata != boost::none") + @pytest.mark.not_supported def test_relay_tx(self, wallet: MoneroWallet) -> None: - wallet.relay_tx(MoneroTxWallet()) + tx: MoneroTxWallet = MoneroTxWallet() + # TODO monero-cpp insert check in monero_wallet::relay_tx + tx.metadata = StringUtils.get_random_string() + wallet.relay_tx(tx) @pytest.mark.not_supported def test_relay_txs(self, wallet: MoneroWallet) -> None: @@ -460,8 +461,7 @@ def test_get_account_tags(self, wallet: MoneroWallet) -> None: def test_set_account_tag_label(self, wallet: MoneroWallet) -> None: wallet.set_account_tag_label("", "") - # TODO move definitions to monero-cpp - #@pytest.mark.not_supported + @pytest.mark.not_supported def test_set_account_label(self, wallet: MoneroWallet) -> None: wallet.set_account_label(0, "") diff --git a/tests/test_monero_wallet_rpc.py b/tests/test_monero_wallet_rpc.py index 55a5c6f..84f9d7a 100644 --- a/tests/test_monero_wallet_rpc.py +++ b/tests/test_monero_wallet_rpc.py @@ -330,11 +330,6 @@ def test_get_public_spend_key(self, wallet: MoneroWallet) -> None: def test_import_key_images(self, wallet: MoneroWallet) -> None: return super().test_import_key_images(wallet) - @pytest.mark.skip(reason="TODO") - @override - def test_get_new_key_images_from_last_import(self, wallet: MoneroWallet) -> None: - return super().test_get_new_key_images_from_last_import(wallet) - @pytest.mark.skip(reason="TODO setup another docker monero-wallet-rpc resource") @override def test_view_only_and_offline_wallets(self, wallet: MoneroWallet) -> None: diff --git a/tests/utils/assert_utils.py b/tests/utils/assert_utils.py index 196796d..2729394 100644 --- a/tests/utils/assert_utils.py +++ b/tests/utils/assert_utils.py @@ -4,7 +4,8 @@ from os import getenv from typing import Any, Optional from monero import ( - SerializableStruct, MoneroSubaddress + SerializableStruct, MoneroSubaddress, + MoneroRpcConnection ) logger: logging.Logger = logging.getLogger("AssertUtils") @@ -16,7 +17,13 @@ class AssertUtils(ABC): @classmethod def assert_equals(cls, expr1: Any, expr2: Any, message: str = "assertion failed"): - if isinstance(expr1, SerializableStruct) and isinstance(expr2, SerializableStruct): + 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 + elif isinstance(expr1, SerializableStruct) and isinstance(expr2, SerializableStruct): str1 = expr1.serialize() str2 = expr2.serialize() assert str1 == str2, f"{message}: {str1} == {str2}"