Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/codacy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ permissions:

jobs:
report-coverage-linux:
if: github.repository == 'everoddandeven/monero-python' && (github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success')
if: github.repository == 'everoddandeven/monero-python' && (github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion != 'cancelled')
runs-on: ubuntu-latest
steps:
- name: Checkout code
Expand All @@ -22,27 +22,32 @@ jobs:
fetch-depth: 0

- name: Download coverage report
id: download
continue-on-error: true
uses: actions/download-artifact@v4
with:
name: coverage-reports-linux
github-token: ${{ secrets.API_GITHUB }}
run-id: ${{ github.event.workflow_run.id }}

- name: Report python coverage
if: steps.download.outcome == 'success'
uses: codacy/codacy-coverage-reporter-action@v1
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
language: python
coverage-reports: coverage.xml

- name: Report c++ coverage
if: steps.download.outcome == 'success'
uses: codacy/codacy-coverage-reporter-action@v1
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
language: cpp
coverage-reports: coverage.info

- name: Report c coverage
if: steps.download.outcome == 'success'
uses: codacy/codacy-coverage-reporter-action@v1
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
Expand Down
8 changes: 6 additions & 2 deletions bin/cleanup_test_environment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@

# remove docker containers
sudo docker compose -f tests/docker-compose.yml down -v
rm -rf test_wallets
rm monero_tests_*
rm -rf test_wallets 2>&1
rm monero_tests_* 2>&1
rm -rf .pytest_cache 2>&1
rm -rf __pycache__ 2>&1
rm -rf tests/__pycache__ 2>&1
rm -rf tests/utils/__pycache__ 2>&1
28 changes: 28 additions & 0 deletions src/cpp/utils/py_monero_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,34 @@
#include "py_monero_utils.h"


void PyMoneroUtils::validate_payment_id_long(const std::string& payment_id_str) {
crypto::hash payment_id;
if (!monero_utils::parse_payment_id_long(payment_id_str, payment_id)) throw std::runtime_error("Invalid long payment id");
}

void PyMoneroUtils::validate_payment_id_short(const std::string& payment_id_str) {
crypto::hash8 payment_id;
if (!monero_utils::parse_payment_id_short(payment_id_str, payment_id)) throw std::runtime_error("Invalid short payment id");
}

bool PyMoneroUtils::is_valid_payment_id_long(const std::string& payment_id_str) {
try {
validate_payment_id_long(payment_id_str);
return true;
} catch (...) {
return false;
}
}

bool PyMoneroUtils::is_valid_payment_id_short(const std::string& payment_id_str) {
try {
validate_payment_id_short(payment_id_str);
return true;
} catch (...) {
return false;
}
}

std::string PyMoneroUtils::json_to_binary(const std::string &json) {
std::string bin;
monero_utils::json_to_binary(json, bin);
Expand Down
5 changes: 5 additions & 0 deletions src/cpp/utils/py_monero_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ class PyMoneroUtils {
static std::string binary_blocks_to_json(const std::string &bin);
static std::string binary_blocks_fast_to_json(const std::string &bin);

static void validate_payment_id_long(const std::string& payment_id_str);
static void validate_payment_id_short(const std::string& payment_id_str);
static bool is_valid_payment_id_long(const std::string& payment_id_str);
static bool is_valid_payment_id_short(const std::string& payment_id_str);

static void sort_txs_wallet(std::vector<std::shared_ptr<monero_tx_wallet>>& txs, const std::vector<std::string>& hashes);
static std::vector<std::shared_ptr<monero_tx_wallet>> get_and_sort_txs(const monero_wallet& wallet, const std::vector<std::string>& tx_hashes);
static std::vector<std::shared_ptr<monero_tx_wallet>> get_and_sort_txs(const monero_wallet& wallet, const monero_tx_query& tx_query);
Expand Down
15 changes: 15 additions & 0 deletions src/cpp/utils/py_monero_utils_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ void py_monero_bind_utils(py::module_& m, PyMoneroTypes& t) {
.def_static("is_valid_payment_id", [](const std::string& payment_id) {
MONERO_CATCH_AND_RETHROW(monero_utils::is_valid_payment_id(payment_id));
}, py::arg("payment_id"))
.def_static("is_valid_payment_id_long", [](const std::string& payment_id) {
return PyMoneroUtils::is_valid_payment_id_long(payment_id);
}, py::arg("payment_id"))
.def_static("is_valid_payment_id_short", [](const std::string& payment_id) {
return PyMoneroUtils::is_valid_payment_id_short(payment_id);
}, py::arg("payment_id"))
.def_static("is_valid_mnemonic", [](const std::string& mnemonic, const std::string& language) {
MONERO_CATCH_AND_RETHROW(monero_utils::is_valid_mnemonic(mnemonic, language));
}, py::arg("mnemonic"), py::arg("language") = "")
Expand All @@ -116,6 +122,12 @@ void py_monero_bind_utils(py::module_& m, PyMoneroTypes& t) {
.def_static("validate_payment_id", [](const std::string& payment_id) {
MONERO_CATCH_AND_RETHROW(monero_utils::validate_payment_id(payment_id));
}, py::arg("payment_id"))
.def_static("validate_payment_id_long", [](const std::string& payment_id) {
MONERO_CATCH_AND_RETHROW(PyMoneroUtils::validate_payment_id_long(payment_id));
}, py::arg("payment_id"))
.def_static("validate_payment_id_short", [](const std::string& payment_id) {
MONERO_CATCH_AND_RETHROW(PyMoneroUtils::validate_payment_id_short(payment_id));
}, py::arg("payment_id"))
.def_static("validate_mnemonic", [](const std::string& mnemonic, const std::string& language) {
MONERO_CATCH_AND_RETHROW(monero_utils::validate_mnemonic(mnemonic, language));
}, py::arg("mnemonic"), py::arg("language") = "")
Expand Down Expand Up @@ -149,6 +161,9 @@ void py_monero_bind_utils(py::module_& m, PyMoneroTypes& t) {
.def_static("get_payment_uri", [](const monero_tx_config &config, monero_network_type network_type) {
MONERO_CATCH_AND_RETHROW(monero_utils::get_payment_uri(config, network_type));
}, py::arg("config"), py::arg("network_type") = monero_network_type::MAINNET)
.def_static("parse_payment_uri", [](const std::string& uri, monero_network_type network_type) {
MONERO_CATCH_AND_RETHROW(monero_utils::parse_payment_uri(uri, network_type));
}, py::arg("uri"), py::arg("network_type") = monero_network_type::MAINNET)
.def_static("xmr_to_atomic_units", [](double amount_xmr) {
MONERO_CATCH_AND_RETHROW(monero_utils::xmr_to_atomic_units(amount_xmr));
}, py::arg("amount_xmr"))
Expand Down
22 changes: 5 additions & 17 deletions src/cpp/wallet/py_monero_wallet_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -999,14 +999,9 @@ void py_monero_bind_wallet(py::module_& m, PyMoneroTypes& t) {
.def("parse_payment_uri", [](PyMoneroWallet& self, const std::string& uri) {
MONERO_CATCH_AND_RETHROW(self.parse_payment_uri(uri));
}, py::arg("uri"), py::call_guard<py::gil_scoped_release>())
.def("get_attribute", [](PyMoneroWallet& self, const std::string& key) {
try {
std::string val;
self.get_attribute(key, val);
return val;
} catch (const std::exception& ex) {
throw monero_error(ex.what());
}
.def("get_attribute", [](PyMoneroWallet& self, const std::string& key) -> std::string {
std::string val;
MONERO_CATCH_AND_RETHROW((self.get_attribute(key, val), val));
}, py::arg("key"), py::call_guard<py::gil_scoped_release>())
.def("set_attribute", [](PyMoneroWallet& self, const std::string& key, const std::string& val) {
MONERO_CATCH_AND_RETHROW(self.set_attribute(key, val));
Expand Down Expand Up @@ -1091,16 +1086,9 @@ void py_monero_bind_wallet(py::module_& m, PyMoneroTypes& t) {
}, py::arg("path"), py::arg("password"), py::arg("nettype"), py::arg("regtest") = false, py::call_guard<py::gil_scoped_release>())
.def_static("open_wallet_data", [](const std::string& password, monero_network_type nettype, const std::string& keys_data, const std::string& cache_data, const std::shared_ptr<monero_rpc_connection>& daemon_connection, bool regtest) {
MONERO_CATCH_AND_RETHROW(monero_wallet_full::open_wallet_data(password, nettype, keys_data, cache_data, daemon_connection, nullptr, regtest));
}, py::arg("password"), py::arg("nettype"), py::arg("keys_data"), py::arg("cache_data"), py::arg("daemon_connection") = std::make_shared<monero_rpc_connection>(), py::arg("regtest") = false, py::call_guard<py::gil_scoped_release>())
}, py::arg("password"), py::arg("nettype"), py::arg("keys_data"), py::arg("cache_data"), py::arg("daemon_connection") = py::none(), py::arg("regtest") = false, py::call_guard<py::gil_scoped_release>())
.def_static("create_wallet", [](const monero_wallet_config& 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 monero_error(msg);
}
MONERO_CATCH_AND_RETHROW(monero_wallet_full::create_wallet(config));
}, py::arg("config"), py::call_guard<py::gil_scoped_release>())
.def_static("get_seed_languages", []() {
MONERO_CATCH_AND_RETHROW(monero_wallet_full::get_seed_languages());
Expand Down
52 changes: 52 additions & 0 deletions src/python/monero_utils.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,18 @@ class MoneroUtils:
"""
...

@staticmethod
def parse_payment_uri(uri: str, network_type: MoneroNetworkType = MoneroNetworkType.MAINNET) -> MoneroTxConfig:
"""
Parses a payment URI into a tx configuration.

:param str uri: the payment URI to parse.
:param MoneroNetworkType network_type: address network type (optional).
:returns MoneroTxConfig: the parsed tx configuration.
:raise MoneroError: if the given URI is malformed.
"""
...

@staticmethod
def get_ring_size() -> int:
"""
Expand Down Expand Up @@ -259,6 +271,26 @@ class MoneroUtils:
"""
...

@staticmethod
def is_valid_payment_id_long(payment_id: str) -> bool:
"""
Indicates if a long (64 hex character) payment id is valid.

:param str payment_id: is the payment id to validate.
:returns bool: `True` if the payment id is a valid long payment id, `False` otherwise.
"""
...

@staticmethod
def is_valid_payment_id_short(payment_id: str) -> bool:
"""
Indicates if a short (16 hex character) payment id is valid.

:param str payment_id: is the payment id to validate.
:returns bool: `True` if the payment id is a valid short payment id, `False` otherwise.
"""
...

@staticmethod
def is_valid_private_spend_key(private_spend_key: str) -> bool:
"""
Expand Down Expand Up @@ -402,6 +434,26 @@ class MoneroUtils:
"""
...

@staticmethod
def validate_payment_id_long(payment_id: str) -> None:
"""
Validate a long (64 hex character) payment id.

:param str payment_id: is the payment id to validate.
:raise MoneroError: if the given payment id is not a valid long payment id.
"""
...

@staticmethod
def validate_payment_id_short(payment_id: str) -> None:
"""
Validate a short (16 hex character) payment id.

:param str payment_id: is the payment id to validate.
:raise MoneroError: if the given payment id is not a valid short payment id.
"""
...

@staticmethod
def validate_private_spend_key(private_spend_key: str) -> None:
"""
Expand Down
4 changes: 2 additions & 2 deletions src/python/monero_wallet_full.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class MoneroWalletFull(MoneroWallet):
nettype: MoneroNetworkType,
keys_data: bytes,
cache_data: bytes,
daemon_connection: MoneroRpcConnection = MoneroRpcConnection(),
daemon_connection: MoneroRpcConnection | None = None,
regtest: bool = False,
) -> MoneroWalletFull:
"""
Expand All @@ -65,7 +65,7 @@ class MoneroWalletFull(MoneroWallet):
:param MoneroNetworkType nettype: is the wallet's network type.
:param bytes keys_data: contains the contents of the ".keys" file (`b""` to open without one).
:param bytes cache_data: contents of the wallet cache file, no extension (`b""` for keys only).
:param MoneroRpcConnection daemon_connection: is connection information to a daemon (default = an unconnected wallet).
:param MoneroRpcConnection | None daemon_connection: is connection information to a daemon.
:param bool regtest: indicates if wallet to open is a regtest wallet (optional).
:returns MoneroWalletFull: reference to the wallet instance.
"""
Expand Down
1 change: 1 addition & 0 deletions tests/config/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ test_resets=True
network_type=regtest
auto_connect_timeout_ms=3000
log_level=3
log_categories=*:WARNING,net:FATAL,net.http:FATAL,net.ssl:FATAL,net.p2p:FATAL,net.cn:FATAL,daemon.rpc:FATAL,global:INFO,verify:FATAL,serialization:FATAL,daemon.rpc.payment:ERROR,stacktrace:INFO,logging:INFO,msgwriter:INFO

[daemon]
rpc_uri=http://127.0.0.1:18081
Expand Down
Loading
Loading