From da457162424dc44af16de46eec35a5aa8b00ac0f Mon Sep 17 00:00:00 2001 From: everoddandeven Date: Mon, 26 Jan 2026 18:24:24 +0100 Subject: [PATCH] Add other wallet common tests and fixes * Added tests `test_get_daemon_max_peer_height`, `test_daemon`, `test_change_password`, `test_save_and_close` and fix related logic * Bind missing PyMoneroSslOptions struct * Fix PyMoneroWallet::get_attribute binding * Bind PyMoneroWalletRpc::set_daemon_connection with trusted option * Fix PyMoneroCloseWalletParams and PyMoneroWalletAttributeParams --- setup.py | 2 +- src/cpp/common/py_monero_common.h | 2 +- src/cpp/py_monero.cpp | 30 +++- src/cpp/wallet/py_monero_wallet_model.cpp | 9 +- src/cpp/wallet/py_monero_wallet_model.h | 2 +- src/cpp/wallet/py_monero_wallet_rpc.cpp | 22 +-- src/cpp/wallet/py_monero_wallet_rpc.h | 2 +- src/python/__init__.pyi | 162 +++++++++++----------- src/python/monero_ssl_options.pyi | 11 ++ src/python/monero_wallet_rpc.pyi | 19 ++- tests/test_monero_wallet_common.py | 104 +++++++++++++- tests/test_monero_wallet_keys.py | 20 +++ tests/test_monero_wallet_rpc.py | 14 +- tests/utils/test_utils.py | 6 +- 14 files changed, 289 insertions(+), 116 deletions(-) create mode 100644 src/python/monero_ssl_options.pyi diff --git a/setup.py b/setup.py index 388e62a..51a0742 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ coverage = os.environ.get("COVERAGE") == "1" this_dir = Path(__file__).parent.resolve() extra_compile_args = ['/std:c++17'] if sys.platform == "win32" else ['-std=c++17'] -extra_link_args = [] +extra_link_args: list[str] = [] if coverage: extra_compile_args += ['-O0', '-g', '--coverage'] diff --git a/src/cpp/common/py_monero_common.h b/src/cpp/common/py_monero_common.h index 404a9d2..428d005 100644 --- a/src/cpp/common/py_monero_common.h +++ b/src/cpp/common/py_monero_common.h @@ -49,7 +49,7 @@ class PyMoneroSslOptions { boost::optional m_ssl_ca_file; std::vector m_ssl_allowed_fingerprints; boost::optional m_ssl_allow_any_cert; - + PyMoneroSslOptions() {} }; diff --git a/src/cpp/py_monero.cpp b/src/cpp/py_monero.cpp index 1127251..f746e53 100644 --- a/src/cpp/py_monero.cpp +++ b/src/cpp/py_monero.cpp @@ -29,6 +29,7 @@ PYBIND11_MODULE(monero, m) { m.doc() = ""; auto py_serializable_struct = py::class_>(m, "SerializableStruct"); + auto py_monero_ssl_options = py::class_(m, "MoneroSslOptions"); auto py_monero_version = py::class_>(m, "MoneroVersion"); auto py_monero_block_header = py::class_>(m, "MoneroBlockHeader"); auto py_monero_block = py::class_>(m, "MoneroBlock"); @@ -192,6 +193,15 @@ PYBIND11_MODULE(monero, m) { MONERO_CATCH_AND_RETHROW(self.serialize()); }); + // monero_ssl_options + py_monero_ssl_options + .def(py::init<>()) + .def_readwrite("ssl_private_key_path", &PyMoneroSslOptions::m_ssl_private_key_path) + .def_readwrite("ssl_certificate_path", &PyMoneroSslOptions::m_ssl_certificate_path) + .def_readwrite("ssl_ca_file", &PyMoneroSslOptions::m_ssl_ca_file) + .def_readwrite("ssl_allowed_fingerprints", &PyMoneroSslOptions::m_ssl_allowed_fingerprints) + .def_readwrite("ssl_allow_any_cert", &PyMoneroSslOptions::m_ssl_allow_any_cert); + // monero_json_request_params py::class_>(m, "MoneroJsonRequestParams") .def(py::init()); @@ -1776,13 +1786,9 @@ PYBIND11_MODULE(monero, m) { MONERO_CATCH_AND_RETHROW(self.parse_payment_uri(uri)); }, py::arg("uri")) .def("get_attribute", [](PyMoneroWallet& self, const std::string& key) { - try { - std::string val; - self.get_attribute(key, val); - return val; - } catch (const std::exception& e) { - throw PyMoneroError(e.what()); - } + std::string val; + self.get_attribute(key, val); + return val; }, py::arg("key")) .def("set_attribute", [](PyMoneroWallet& self, const std::string& key, const std::string& val) { MONERO_CATCH_AND_RETHROW(self.set_attribute(key, val)); @@ -1936,6 +1942,16 @@ PYBIND11_MODULE(monero, m) { .def("get_rpc_connection", [](PyMoneroWalletRpc& self) { MONERO_CATCH_AND_RETHROW(self.get_rpc_connection()); }) + // this because of function hiding + .def("set_daemon_connection", [](PyMoneroWallet& self, const boost::optional& connection) { + MONERO_CATCH_AND_RETHROW(self.set_daemon_connection(connection)); + }, py::arg("connection")) + .def("set_daemon_connection", [](PyMoneroWallet& self, const std::string& uri, const std::string& username, const std::string& password, const std::string& proxy) { + MONERO_CATCH_AND_RETHROW(self.set_daemon_connection(uri, username, password, proxy)); + }, py::arg("uri"), py::arg("username") = "", py::arg("password") = "", py::arg("proxy") = "") + .def("set_daemon_connection", [](PyMoneroWalletRpc& self, const boost::optional& connection, bool is_trusted, const boost::optional& ssl_options) { + MONERO_CATCH_AND_RETHROW(self.set_daemon_connection(connection, is_trusted, ssl_options)); + }, py::arg("connection"), py::arg("is_trusted"), py::arg("ssl_options")) .def("stop", [](PyMoneroWalletRpc& self) { MONERO_CATCH_AND_RETHROW(self.stop()); }); diff --git a/src/cpp/wallet/py_monero_wallet_model.cpp b/src/cpp/wallet/py_monero_wallet_model.cpp index 6c07e1e..55255b8 100644 --- a/src/cpp/wallet/py_monero_wallet_model.cpp +++ b/src/cpp/wallet/py_monero_wallet_model.cpp @@ -1043,7 +1043,7 @@ rapidjson::Value PyMoneroCreateAccountParams::to_rapidjson_val(rapidjson::Docume rapidjson::Value PyMoneroCloseWalletParams::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); - if (m_save != boost::none) monero_utils::add_json_member("save", m_save.get(), allocator, root); + if (m_save != boost::none) monero_utils::add_json_member("autosave_current", m_save.get(), allocator, root); return root; } @@ -1064,6 +1064,9 @@ rapidjson::Value PyMoneroWalletAttributeParams::to_rapidjson_val(rapidjson::Docu } 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(); @@ -1301,10 +1304,10 @@ rapidjson::Value PyMoneroImportExportKeyImagesParams::to_rapidjson_val(rapidjson } PyMoneroCreateOpenWalletParams::PyMoneroCreateOpenWalletParams(const boost::optional& filename, const boost::optional &password): - m_filename(filename), m_password(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_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), diff --git a/src/cpp/wallet/py_monero_wallet_model.h b/src/cpp/wallet/py_monero_wallet_model.h index a502fa3..7d13c87 100644 --- a/src/cpp/wallet/py_monero_wallet_model.h +++ b/src/cpp/wallet/py_monero_wallet_model.h @@ -495,7 +495,7 @@ class PyMoneroCloseWalletParams : public PyMoneroJsonRequestParams { public: boost::optional m_save; - PyMoneroCloseWalletParams(bool save = true) { + PyMoneroCloseWalletParams(bool save = false) { m_save = save; }; diff --git a/src/cpp/wallet/py_monero_wallet_rpc.cpp b/src/cpp/wallet/py_monero_wallet_rpc.cpp index 48a2fa1..3e1f13e 100644 --- a/src/cpp/wallet/py_monero_wallet_rpc.cpp +++ b/src/cpp/wallet/py_monero_wallet_rpc.cpp @@ -320,8 +320,7 @@ void PyMoneroWalletRpc::set_daemon_connection(const std::string& uri, const std: set_daemon_connection(rpc); } - -void PyMoneroWalletRpc::set_daemon_connection(const boost::optional& connection, bool is_trusted, const boost::optional> ssl_options) { +void PyMoneroWalletRpc::set_daemon_connection(const boost::optional& connection, bool is_trusted, const boost::optional& ssl_options) { auto params = std::make_shared(); if (connection == boost::none) { params->m_address = "placeholder"; @@ -338,11 +337,11 @@ void PyMoneroWalletRpc::set_daemon_connection(const boost::optionalm_ssl_support = "autodetect"; if (ssl_options != boost::none) { - params->m_ssl_private_key_path = ssl_options.get()->m_ssl_private_key_path; - params->m_ssl_certificate_path = ssl_options.get()->m_ssl_certificate_path; - params->m_ssl_ca_file = ssl_options.get()->m_ssl_ca_file; - params->m_ssl_allowed_fingerprints = ssl_options.get()->m_ssl_allowed_fingerprints; - params->m_ssl_allow_any_cert = ssl_options.get()->m_ssl_allow_any_cert; + params->m_ssl_private_key_path = ssl_options->m_ssl_private_key_path; + params->m_ssl_certificate_path = ssl_options->m_ssl_certificate_path; + params->m_ssl_ca_file = ssl_options->m_ssl_ca_file; + params->m_ssl_allowed_fingerprints = ssl_options->m_ssl_allowed_fingerprints; + params->m_ssl_allow_any_cert = ssl_options->m_ssl_allow_any_cert; } PyMoneroJsonRequest request("set_daemon", params); @@ -1387,9 +1386,14 @@ bool PyMoneroWalletRpc::get_attribute(const std::string& key, std::string& value value = params->m_value.get(); return true; } - catch (...) { - return false; + catch (const PyMoneroRpcError& ex) { + if (ex.code == -45) { // attribute not found + value = std::string(""); + return true; + } } + + return false; } void PyMoneroWalletRpc::start_mining(boost::optional num_threads, boost::optional background_mining, boost::optional ignore_battery) { diff --git a/src/cpp/wallet/py_monero_wallet_rpc.h b/src/cpp/wallet/py_monero_wallet_rpc.h index 2a209ce..ec978cb 100644 --- a/src/cpp/wallet/py_monero_wallet_rpc.h +++ b/src/cpp/wallet/py_monero_wallet_rpc.h @@ -66,7 +66,7 @@ class PyMoneroWalletRpc : public PyMoneroWallet { void stop(); bool is_view_only() const override; boost::optional get_daemon_connection() const override; - void set_daemon_connection(const boost::optional& connection, bool is_trusted, const boost::optional> ssl_options); + void set_daemon_connection(const boost::optional& connection, bool is_trusted, const boost::optional& ssl_options); void set_daemon_connection(const boost::optional& connection) override; void set_daemon_connection(const std::string& uri, const std::string& username = "", const std::string& password = "", const std::string& proxy_uri = "") override; bool is_connected_to_daemon() const override; diff --git a/src/python/__init__.pyi b/src/python/__init__.pyi index 333156b..c0f05d1 100644 --- a/src/python/__init__.pyi +++ b/src/python/__init__.pyi @@ -116,6 +116,7 @@ from .monero_prune_result import MoneroPruneResult from .monero_request import MoneroRequest from .monero_rpc_connection import MoneroRpcConnection from .monero_rpc_error import MoneroRpcError +from .monero_ssl_options import MoneroSslOptions from .monero_subaddress import MoneroSubaddress from .monero_submit_tx_result import MoneroSubmitTxResult from .monero_sync_result import MoneroSyncResult @@ -139,85 +140,86 @@ from .monero_wallet_rpc import MoneroWalletRpc __all__ = [ - 'MoneroAccount', - 'MoneroAccountTag', - 'MoneroAddressBookEntry', - 'MoneroAddressType', - 'MoneroAltChain', - 'MoneroBan', - 'MoneroBlock', - 'MoneroBlockHeader', - 'MoneroBlockTemplate', - 'MoneroCheck', - 'MoneroCheckReserve', - 'MoneroCheckTx', - 'MoneroConnectionManager', - 'MoneroConnectionManagerListener', - 'MoneroConnectionPollType', - 'MoneroConnectionProriotyComparator', - 'MoneroConnectionSpan', - 'MoneroConnectionType', - 'MoneroDaemon', - 'MoneroDaemonDefault', - 'MoneroDaemonInfo', - 'MoneroDaemonListener', - 'MoneroDaemonRpc', - 'MoneroDaemonSyncInfo', - 'MoneroDaemonUpdateCheckResult', - 'MoneroDaemonUpdateDownloadResult', - 'MoneroDecodedAddress', - 'MoneroDestination', - 'MoneroError', - 'MoneroFeeEstimate', - 'MoneroHardForkInfo', - 'MoneroIncomingTransfer', - 'MoneroIntegratedAddress', - 'MoneroJsonRequest', - 'MoneroJsonRequestParams', - 'MoneroJsonResponse', - 'MoneroKeyImage', - 'MoneroKeyImageImportResult', - 'MoneroKeyImageSpentStatus', - 'MoneroMessageSignatureResult', - 'MoneroMessageSignatureType', - 'MoneroMinerTxSum', - 'MoneroMiningStatus', - 'MoneroMultisigInfo', - 'MoneroMultisigInitResult', - 'MoneroMultisigSignResult', - 'MoneroNetworkType', - 'MoneroOutgoingTransfer', - 'MoneroOutput', - 'MoneroOutputDistributionEntry', - 'MoneroOutputHistogramEntry', - 'MoneroOutputQuery', - 'MoneroOutputWallet', - 'MoneroPathRequest', - 'MoneroPeer', - 'MoneroPruneResult', - 'MoneroRequest', - 'MoneroRpcConnection', - 'MoneroRpcError', - 'MoneroSubaddress', - 'MoneroSubmitTxResult', - 'MoneroSyncResult', - 'MoneroTransfer', - 'MoneroTransferQuery', - 'MoneroTx', - 'MoneroTxBacklogEntry', - 'MoneroTxConfig', - 'MoneroTxPoolStats', - 'MoneroTxPriority', - 'MoneroTxQuery', - 'MoneroTxSet', - 'MoneroTxWallet', - 'MoneroUtils', - 'MoneroVersion', - 'MoneroWallet', - 'MoneroWalletConfig', - 'MoneroWalletFull', - 'MoneroWalletKeys', - 'MoneroWalletListener', - 'MoneroWalletRpc', + 'MoneroAccount', + 'MoneroAccountTag', + 'MoneroAddressBookEntry', + 'MoneroAddressType', + 'MoneroAltChain', + 'MoneroBan', + 'MoneroBlock', + 'MoneroBlockHeader', + 'MoneroBlockTemplate', + 'MoneroCheck', + 'MoneroCheckReserve', + 'MoneroCheckTx', + 'MoneroConnectionManager', + 'MoneroConnectionManagerListener', + 'MoneroConnectionPollType', + 'MoneroConnectionProriotyComparator', + 'MoneroConnectionSpan', + 'MoneroConnectionType', + 'MoneroDaemon', + 'MoneroDaemonDefault', + 'MoneroDaemonInfo', + 'MoneroDaemonListener', + 'MoneroDaemonRpc', + 'MoneroDaemonSyncInfo', + 'MoneroDaemonUpdateCheckResult', + 'MoneroDaemonUpdateDownloadResult', + 'MoneroDecodedAddress', + 'MoneroDestination', + 'MoneroError', + 'MoneroFeeEstimate', + 'MoneroHardForkInfo', + 'MoneroIncomingTransfer', + 'MoneroIntegratedAddress', + 'MoneroJsonRequest', + 'MoneroJsonRequestParams', + 'MoneroJsonResponse', + 'MoneroKeyImage', + 'MoneroKeyImageImportResult', + 'MoneroKeyImageSpentStatus', + 'MoneroMessageSignatureResult', + 'MoneroMessageSignatureType', + 'MoneroMinerTxSum', + 'MoneroMiningStatus', + 'MoneroMultisigInfo', + 'MoneroMultisigInitResult', + 'MoneroMultisigSignResult', + 'MoneroNetworkType', + 'MoneroOutgoingTransfer', + 'MoneroOutput', + 'MoneroOutputDistributionEntry', + 'MoneroOutputHistogramEntry', + 'MoneroOutputQuery', + 'MoneroOutputWallet', + 'MoneroPathRequest', + 'MoneroPeer', + 'MoneroPruneResult', + 'MoneroRequest', + 'MoneroRpcConnection', + 'MoneroRpcError', + 'MoneroSubaddress', + 'MoneroSubmitTxResult', + 'MoneroSyncResult', + 'MoneroTransfer', + 'MoneroTransferQuery', + 'MoneroTx', + 'MoneroTxBacklogEntry', + 'MoneroTxConfig', + 'MoneroTxPoolStats', + 'MoneroTxPriority', + 'MoneroTxQuery', + 'MoneroTxSet', + 'MoneroTxWallet', + 'MoneroUtils', + 'MoneroVersion', + 'MoneroWallet', + 'MoneroWalletConfig', + 'MoneroWalletFull', + 'MoneroWalletKeys', + 'MoneroWalletListener', + 'MoneroWalletRpc', + 'MoneroSslOptions', 'SerializableStruct' ] diff --git a/src/python/monero_ssl_options.pyi b/src/python/monero_ssl_options.pyi new file mode 100644 index 0000000..feeca09 --- /dev/null +++ b/src/python/monero_ssl_options.pyi @@ -0,0 +1,11 @@ +class MoneroSslOptions: + ssl_private_key_path: str + """Path to private ssl key""" + ssl_certificate_path: str + """Path to private ssl certificate""" + ssl_ca_file: str + """Path to ssl CA file""" + ssl_allowed_fingerprints: list[str] + """Allowed ssl fingerprints""" + ssl_allow_any_cert: bool | None + """Allow any certificate""" diff --git a/src/python/monero_wallet_rpc.pyi b/src/python/monero_wallet_rpc.pyi index ff443cc..d0e577b 100644 --- a/src/python/monero_wallet_rpc.pyi +++ b/src/python/monero_wallet_rpc.pyi @@ -3,6 +3,7 @@ import typing from .monero_wallet import MoneroWallet from .monero_wallet_config import MoneroWalletConfig from .monero_rpc_connection import MoneroRpcConnection +from .monero_ssl_options import MoneroSslOptions class MoneroWalletRpc(MoneroWallet): @@ -38,7 +39,7 @@ class MoneroWalletRpc(MoneroWallet): def get_rpc_connection(self) -> MoneroRpcConnection | None: """ Get the wallet's RPC connection. - + :return MoneroRpcConnection | None: the wallet's rpc connection """ ... @@ -46,7 +47,7 @@ class MoneroWalletRpc(MoneroWallet): def open_wallet(self, config: MoneroWalletConfig) -> MoneroWalletRpc: """ Open an existing wallet on the monero-wallet-rpc server. - + :param MoneroWalletConfig config: configures the wallet to open :return MoneroWalletRpc: this wallet client """ @@ -55,7 +56,7 @@ class MoneroWalletRpc(MoneroWallet): def open_wallet(self, name: str, password: str) -> MoneroWalletRpc: """ Open an existing wallet on the monero-wallet-rpc server. - + :param str name: is the name of the wallet file to open :param str password: is the wallet's password :return MoneroWalletRpc: this wallet client @@ -67,9 +68,13 @@ class MoneroWalletRpc(MoneroWallet): """ ... def get_seed_languages(self) -> list[str]: - """_summary_ - - Returns: - list[str]: _description_ + """ + Get all supported wallet seed languages. + """ + ... + @typing.overload + def set_daemon_connection(self, connection: MoneroRpcConnection | None, is_trusted: bool, ssl_options: MoneroSslOptions | None) -> None: # type: ignore + """ + Set daemon connection """ ... diff --git a/tests/test_monero_wallet_common.py b/tests/test_monero_wallet_common.py index d6bf59c..a21bd0c 100644 --- a/tests/test_monero_wallet_common.py +++ b/tests/test_monero_wallet_common.py @@ -9,7 +9,7 @@ from monero import ( MoneroWallet, MoneroWalletRpc, MoneroDaemonRpc, MoneroWalletConfig, MoneroTxConfig, MoneroDestination, MoneroRpcConnection, MoneroError, - MoneroKeyImage, MoneroTxQuery, MoneroUtils + MoneroKeyImage, MoneroTxQuery, MoneroUtils, MoneroWalletFull ) from utils import TestUtils, WalletEqualityUtils, MiningUtils @@ -99,6 +99,22 @@ def before_each(self, request: pytest.FixtureRequest): #region Tests + # Can get the daemon's max peer height + @pytest.mark.skipif(TestUtils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") + def test_get_daemon_max_peer_height(self) -> None: + height: int = 0 + if isinstance(self._wallet, MoneroWalletFull): + height = self._wallet.get_daemon_max_peer_height() + + assert height > 0 + + # Can get the daemon's height + @pytest.mark.skipif(TestUtils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") + def test_daemon(self) -> None: + assert self._wallet.is_connected_to_daemon(), "Wallet is not connected to daemon" + daemon_height = self._wallet.get_daemon_height() + assert daemon_height > 0 + @pytest.mark.skipif(TestUtils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") def test_create_wallet_random(self) -> None: """ @@ -982,4 +998,90 @@ def test_mining(self): wallet.start_mining(2, False, True) wallet.stop_mining() + # Can change the wallet password + def test_change_password(self) -> None: + # create random wallet + config = MoneroWalletConfig() + config.password = TestUtils.WALLET_PASSWORD + wallet = self._create_wallet(config) + path: str = wallet.get_path() + + # change password + new_password: str = "" + wallet.change_password(TestUtils.WALLET_PASSWORD, new_password) + + # close wallet without saving + self._close_wallet(wallet) + + # old password does not work (password change is auto saved) + try: + config = MoneroWalletConfig() + config.path = path + config.password = TestUtils.WALLET_PASSWORD + self._open_wallet(config) + raise Exception("Should have thrown") + except Exception as e: + # TODO: different errors from rpc and wallet2 + e_str = str(e).lower() + assert "failed to open wallet" in e_str or "invalid password" in e_str, e_str + + # open wallet with new password + config = MoneroWalletConfig() + config.path = path + config.password = new_password + wallet = self._open_wallet(config) + + # change password with incorrect password + try: + wallet.change_password("badpassword", new_password) + raise Exception("Should have throw") + except Exception as e: + e_str = str(e) + assert "Invalid original password." == e_str, e_str + + # save and close + self._close_wallet(wallet, True) + + # open wallet + config = MoneroWalletConfig() + config.path = path + config.password = new_password + wallet = self._open_wallet(config) + + # close wallet + self._close_wallet(wallet) + + # Can save and close the wallet in a single call + @pytest.mark.skipif(TestUtils.TEST_NON_RELAYS is False, reason="TEST_NON_RELAYS disabled") + def test_save_and_close(self) -> None: + # create random wallet + password: str = "" + config = MoneroWalletConfig() + config.password = password + wallet = self._create_wallet(config) + path: str = wallet.get_path() + + # set an attribute + uuid: str = TestUtils.get_random_string() + wallet.set_attribute("id", uuid) + + # close the wallet without saving + self._close_wallet(wallet) + + # re-open the wallet and ensure attribute was not saved + config = MoneroWalletConfig() + config.path = path + config.password = password + wallet = self._open_wallet(config) + assert wallet.get_attribute("id") == "" + + # set the attribute and close with saving + wallet.set_attribute("id", uuid) + self._close_wallet(wallet, True) + + # re-open the wallet and ensure attribute was saved + wallet = self._open_wallet(config) + assert uuid == wallet.get_attribute("id") + self._close_wallet(wallet) + #endregion diff --git a/tests/test_monero_wallet_keys.py b/tests/test_monero_wallet_keys.py index dd39b4a..376e2fc 100644 --- a/tests/test_monero_wallet_keys.py +++ b/tests/test_monero_wallet_keys.py @@ -80,6 +80,16 @@ def get_test_wallet(self) -> MoneroWallet: #region Disabled Tests + @pytest.mark.skip(reason="Daemon not supported") + @override + def test_daemon(self) -> None: + return super().test_daemon() + + @pytest.mark.skip(reason="Daemon not supported") + @override + def test_get_daemon_max_peer_height(self) -> None: + return super().test_get_daemon_max_peer_height() + @pytest.mark.skip(reason="Wallet path not supported") @override def test_get_path(self) -> None: @@ -195,6 +205,16 @@ def test_get_payment_uri(self): def test_mining(self): return super().test_mining() + @pytest.mark.skip(reason="Password not supported") + @override + def test_change_password(self) -> None: + return super().test_change_password() + + @pytest.mark.skip(reason="Close and save not supported") + @override + def test_save_and_close(self) -> None: + return super().test_save_and_close() + #endregion #region Tests diff --git a/tests/test_monero_wallet_rpc.py b/tests/test_monero_wallet_rpc.py index 854e8c3..9a6596c 100644 --- a/tests/test_monero_wallet_rpc.py +++ b/tests/test_monero_wallet_rpc.py @@ -23,7 +23,11 @@ def get_test_wallet(self) -> MoneroWallet: @override def _open_wallet(self, config: MoneroWalletConfig | None) -> MoneroWallet: - return Utils.open_wallet_rpc(config) + try: + return Utils.open_wallet_rpc(config) + except Exception as e: + Utils.free_wallet_rpc_resources() + raise e @override def _create_wallet(self, config: MoneroWalletConfig) -> MoneroWallet: @@ -74,6 +78,14 @@ def test_save(self): #region Disabled Tests + @pytest.mark.skip(reason="Not implemented for wallet rpc") + def test_get_daemon_max_peer_height(self) -> None: + return super().test_get_daemon_max_peer_height() + + @pytest.mark.skip(reason="Not supported") + def test_daemon(self) -> None: + return super().test_daemon() + @pytest.mark.skip(reason="Not supported") @override def test_get_seed_language(self): diff --git a/tests/utils/test_utils.py b/tests/utils/test_utils.py index af68f55..b5e28a4 100644 --- a/tests/utils/test_utils.py +++ b/tests/utils/test_utils.py @@ -434,8 +434,7 @@ def open_wallet_rpc(cls, c: Optional[MoneroWalletConfig]) -> MoneroWalletRpc: # open wallet cls._WALLET_RPC_2.stop_syncing() cls._WALLET_RPC_2.open_wallet(config) - # TODO set trusted daemon connection - # cls._WALLET_RPC_2.set_daemon_connection() + cls._WALLET_RPC_2.set_daemon_connection(cls._WALLET_RPC_2.get_daemon_connection(), True, None) if cls._WALLET_RPC_2.is_connected_to_daemon(): cls._WALLET_RPC_2.start_syncing(TestUtils.SYNC_PERIOD_IN_MS) @@ -477,8 +476,7 @@ def create_wallet_rpc(cls, c: Optional[MoneroWalletConfig]) -> MoneroWalletRpc: # create wallet wallet_rpc.stop_syncing() wallet_rpc.create_wallet(config) - # TODO set trusted daemon connection - # cls._WALLET_RPC_2.set_daemon_connection() + wallet_rpc.set_daemon_connection(wallet_rpc.get_daemon_connection(), True, None) if wallet_rpc.is_connected_to_daemon(): wallet_rpc.start_syncing(TestUtils.SYNC_PERIOD_IN_MS)