Skip to content

Repository files navigation

Monero Python Library

Codacy Badge Codacy Badge Build

Build Debian Packages

Pybind Python Docs Matrix

A Python library for creating Monero applications using RPC and Python bindings to monero v0.18.5.3 'Fluorine Fermi'.

  • Supports wallet and daemon RPC clients.
  • Supports client-side wallets using Python bindings.
  • Supports a keys-only wallet, which has the keys, the seed and the addresses of an account and needs no daemon.
  • Supports multisig, view-only, and offline wallets.
  • Wallet types are interchangeable by conforming to a common interface.
  • Uses a clearly defined data model and API specification intended to be intuitive and robust.
  • Query wallet transactions, transfers, and outputs by their properties.
  • Fetch and process binary data from the daemon (e.g. raw blocks).
  • Receive notifications when blocks are added to the chain or when wallets sync, send, or receive.

Architecture


Build Python applications using RPC or Python bindings to monero-project/monero. Wallet implementations are interchangeable by conforming to a common interface, MoneroWallet.

Sample code

from monero import *

# custom wallet listener implementation
class MyWalletListener(MoneroWalletListener):
    def on_sync_progress(self, height: int, start_height: int, end_height: int, percent_done: float, message: str) -> None:
        pass # feed a progress bar?

    def on_output_received(self, output: MoneroOutputWallet) -> None:
        amount: int = output.amount
        tx_hash: str = output.tx.hash
        is_confirmed: bool = output.tx.is_confirmed
        is_locked: bool = output.tx.is_locked

# connect to daemon
daemon: MoneroDaemon = MoneroDaemonRpc("http://localhost:38081", "superuser", "abctesting123")
height: int = daemon.get_height() # 1523651
txs_in_pool: list[MoneroTx] = daemon.get_tx_pool() # get transactions in the pool

# create wallet from mnemonic phrase using Python bindings to monero-project

wallet_config = MoneroWalletConfig()
wallet_config.path = "sample_wallet_full"
wallet_config.password = "supersecretpassword123"
wallet_config.network_type = MoneroNetworkType.STAGENET
wallet_config.server = MoneroRpcConnection()
wallet_config.server.username = "superuser"
wallet_config.server.password = "abctesting123"
wallet_config.seed = "hefty value scenic..."
wallet_config.restore_height = 573936
wallet_full: MoneroWallet = MoneroWalletFull.create_wallet(wallet_config)

listener: MoneroWalletListener = MyWalletListener()

# synchronize the wallet and receive progress notifications
wallet_full.sync(listener)

# synchronize in the background every 5 seconds
wallet_full.start_syncing(5000)

# receive notifications when funds are received, confirmed, and unlocked
wallet_full.add_listener(listener)

# connect to wallet RPC and open wallet
wallet_rpc: MoneroWallet = MoneroWalletRpc("http://localhost:38083", "rpc_user", "abc123")
wallet_rpc.open_wallet("sample_wallet_rpc", "supersecretpassword123")
primary_address: str = wallet_rpc.get_primary_address() # 555zgduFhmKd2o8rPUz...
balance: int = wallet_rpc.get_balance() # 533648366742
txs: list[MoneroTxWallet] = wallet_rpc.get_txs() # get transactions containing transfers to/from the wallet

# send funds from RPC wallet to full wallet
tx_config = MoneroTxConfig()
tx_config.account_index = 0
tx_config.address = wallet_full.get_address(1, 0)
tx_config.amount = 250000000000 # send 0.25 XMR (denominated in atomic units)
tx_config.relay = False # create transaction and relay to the network if true

created_tx: MoneroTxWallet = wallet_rpc.create_tx(tx_config)
fee: int = created_tx.fee # "Are you sure you want to send... ?"
wallet_rpc.relay_tx(created_tx) # relay the transaction

# save and close wallet
wallet_full.close(True)

Installation

Every release has prebuilt packages attached:

  • Debian and Ubuntu: python3-monero_<version>-1<distro>1_<arch>.deb for bookworm, trixie, jammy and noble on amd64, arm64 and armhf, installed for the system Python 3:
    sudo apt install ./python3-monero_0.9.10-1noble1_amd64.deb
  • macOS and Windows: one wheel per Python version, monero-<version>-<python>-<platform>.whl:
    pip3 install monero-0.9.10-cp313-cp313-win_amd64.whl

On anything else, build it from source.

Building monero-python from source

Linux and macOS

  1. Install build dependencies:

    # Ubuntu/Debian
    
    sudo apt install -y python3-all python3-pip python3-pybind11
  2. Clone the project repository:

    git clone --recurse-submodules https://github.com/libmonero/monero-python.git
  3. Build the monero-cpp submodule (located at ./external/monero-cpp) as a native library by following instructions for your system.

  4. Build monero-python to ./build/:

    cd monero-python
    mkdir -p build
    cd build
    cmake ..
    make
  5. Or build and install monero-python with pip:

    pip3 install . --break-system-packages
  6. Or run build script: ./bin/build_libmonero_python.sh

Faster rebuilds: if ccache is installed it is used automatically for monero and monero-python (pass -DUSE_CCACHE=OFF to cmake to disable it). To use it for monero-cpp as well, build that with -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache.

Debian package

The package is built from debian/ with dpkg-buildpackage, the way CI does it. It installs the build dependencies and some static libraries system wide, so build it in a container of the release you want it for (ubuntu:24.04, ubuntu:22.04, debian:trixie or debian:bookworm).

  1. Install Docker

  2. Clone the repository

    git clone --recursive https://github.com/libmonero/monero-python.git
  3. Build, replacing ubuntu:24.04 with the release you want

    docker run --rm -it -v <MONERO_PYTHON_DIR_FULL_PATH>:/monero-python -w /monero-python ubuntu:24.04 bash -c '
      apt-get update && apt-get install -y dpkg-dev &&
      apt-get build-dep -y ./ &&
      debian/set-version.sh &&
      dpkg-buildpackage --build=binary --no-sign &&
      mkdir -p debian/artifacts && mv ../python3-monero_* debian/artifacts/'
    • MONERO_PYTHON_DIR_FULL_PATH - full path to monero-python directory
    • debian/set-version.sh adds an entry for the version of pyproject.toml to debian/changelog, there is no need to commit it
    • add --jobs=4 to dpkg-buildpackage to build faster, each compiler needs 1 to 2 GB of memory
  4. The package is placed in monero-python/debian/artifacts

Windows

  1. Download and install MSYS2.

  2. Press the Windows button and launch MSYS2 MINGW64.

  3. Update packages: pacman -Syu and confirm at prompts.

  4. Relaunch MSYS2 (if necessary) and install dependencies:

    pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-unbound mingw-w64-x86_64-protobuf git gettext base-devel wget
    wget https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-icu-78.3-4-any.pkg.tar.zst
    echo "8486a018aca2e56d1fcd2eed2069011f2e1da02e03af72b38916ee06cbe7203f  mingw-w64-x86_64-icu-78.3-4-any.pkg.tar.zst" | sha256sum -c
    pacman -U mingw-w64-x86_64-icu-78.3-4-any.pkg.tar.zst
    # hidapi and libusb were removed from the msys2 mingw64 repo, install the archived packages
    wget https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-hidapi-0.15.0-2-any.pkg.tar.zst https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-libusb-1.0.30-1-any.pkg.tar.zst
    echo "89fb61549a437d65076a092a367fcb264fc7045ee9ebef48cd81f5a76a5588f8  mingw-w64-x86_64-hidapi-0.15.0-2-any.pkg.tar.zst" | sha256sum -c
    echo "124edc26b009678a4c5e759481a364abf63ed7f2f49a53092e8bd0a47c0c0740  mingw-w64-x86_64-libusb-1.0.30-1-any.pkg.tar.zst" | sha256sum -c
    pacman -U mingw-w64-x86_64-hidapi-0.15.0-2-any.pkg.tar.zst mingw-w64-x86_64-libusb-1.0.30-1-any.pkg.tar.zst
    wget https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-boost-1.87.0-3-any.pkg.tar.zst
    echo "241919a5885a9270d0e0937e71cf5e146c2a8cabecc2714f09248350181cb1b6  mingw-w64-x86_64-boost-1.87.0-3-any.pkg.tar.zst" | sha256sum -c
    wget https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-boost-libs-1.87.0-3-any.pkg.tar.zst
    echo "5fd77df3e5983ba0d9c689f46151119e0e59b3da6850c5a0ba54068eeae7749c  mingw-w64-x86_64-boost-libs-1.87.0-3-any.pkg.tar.zst" | sha256sum -c
    pacman -U mingw-w64-x86_64-boost-1.87.0-3-any.pkg.tar.zst mingw-w64-x86_64-boost-libs-1.87.0-3-any.pkg.tar.zst
    wget https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-pybind11-2.13.6-2-any.pkg.tar.zst
    echo "5b56ad87bc544336b2d51edb8bb0614f46542571362daf4d7e53bf23120175a1  mingw-w64-x86_64-pybind11-2.13.6-2-any.pkg.tar.zst" | sha256sum -c
    pacman -U mingw-w64-x86_64-pybind11-2.13.6-2-any.pkg.tar.zst
    

    These are the versions CI uses. CI also pins the MinGW toolchain, see build-windows.yml.

  5. Clone repo: git clone --recurse-submodules https://github.com/libmonero/monero-python.git

  6. Build monero-cpp, located as a submodule at ./external/monero-cpp:

    cd external/monero-cpp
    ./bin/build_libmonero_cpp.sh
    cd ../..
    
  7. Build monero-python:

    mkdir -p build &&
    cd build &&
    cmake ..
    cmake --build .
    
  8. Or run build script: ./bin/build_libmonero_python.sh

Use RPC servers in your project:

  1. Download and install Monero CLI.
  2. Start monerod, e.g.: ./monerod --stagenet (or use a remote daemon).
  3. Start monero-wallet-rpc, e.g.: ./monero-wallet-rpc --daemon-address http://localhost:38081 --stagenet --rpc-bind-port 38083 --rpc-login rpc_user:abc123 --wallet-dir ./

Note

On Windows, first install MSYS2:

  1. Install MSYS2.
  2. Environment variables > System variables > Path > Edit > New > C:\msys64\mingw64\bin

Memory Growth

If you see unrestricted memory growth using monero-python, consider applying jemalloc to improve memory management with malloc. In many cases, this can completely resolve the memory growth.

For example: export LD_PRELOAD=/path/to/libjemalloc.so.2 then run your app. It has to be the shared library, on Debian and Ubuntu it comes with the libjemalloc2 package. A static .a archive is ignored.

Running Python tests

  1. Install the test dependencies, with the versions that the CI runs the tests with (tests/requirements.txt), in a virtual environment:

    python3 -m venv .venv
    . .venv/bin/activate
    pip install -r tests/requirements.txt

    The monero module has to be importable in it: install it in the environment (pip install .), or set PYTHONPATH to the folder that has the built module.

  2. Clone the project repository:

    git clone --recurse-submodules https://github.com/libmonero/monero-python.git
    
    cd monero-python
  3. Setup docker test environment

    docker compose -f tests/docker-compose.yml up -d node_1 node_2 xmr_wallet_1 xmr_wallet_2 xmr_wallet_3
  4. Or start RPC servers locally:

    1. Download and install Monero CLI.
    2. Start monerod, e.g.: ./monerod --stagenet (or use a remote daemon).
    3. Start monero-wallet-rpc, e.g.: ./monero-wallet-rpc --daemon-address http://localhost:38081 --stagenet --rpc-bind-port 38083 --rpc-login rpc_user:abc123 --wallet-dir ./
  5. Configure the appropriate RPC endpoints, authentication, and other settings in config.ini.

  6. Run all python tests with:

    pytest

    The tests assume the RPC servers of the docker environment. If you started them locally, set IN_CONTAINER=false.

    To run only the unit tests, which need no daemon or wallet RPC server:

    pytest -m unit

    The wallet tests are in tests/wallet, a file for each topic (test_sweep.py, test_txs.py, test_outputs.py...). Each file has a base class with the tests that every wallet should pass, and a class for each wallet type (TestMoneroWalletFullSweep, TestMoneroWalletRpcSweep, TestMoneroWalletKeysSweep) with what that type does differently. To run one topic, or one wallet type:

    pytest tests/wallet/test_sweep.py
    pytest tests/wallet -k Rpc

    The daemon tests are split in the same way: tests/daemon/rpc has the integration tests of the rpc daemon (a file for each topic, such as test_blocks.py, test_tx_pool.py and test_peers.py), tests/daemon/model the unit tests of the daemon models, grouped by model, and tests/daemon/test_interface.py the ones of the daemon interface.

    The wallet models are tested in tests/wallet/model (a file for each kind of model: queries, transfers, outputs, accounts...), the calls of the wallet interface in tests/wallet/test_interface.py, and the tests of what is not about a wallet or a daemon, such as the rpc connection, in tests/common, where the tests of MoneroUtils are split by topic in tests/common/monero_utils.

  7. Cleanup docker test environment

    docker compose -f tests/docker-compose.yml down -v

Related projects

License

This project is licensed under MIT.

Sponsors

We would like to thank our sponsors for their financial contributions that keep this project up and running!

Monero Community
Monero Community
The maintenance of this project for a first stable release has been generously funded by the Monero Community Crowdfunding System (see proposal).

Donations

If this library has been valuable to you, please consider donating to support its continued development. 🙏

XMR

84rXAu3QhsfbQ2vbxyoEptbRLZ2gtyL8k2qCeJwM5AU4FcxVDEbLRuxMZD5pXD1TR295Nodn7y9mkjoMemHrnMqa9ZnJTza

Releases

Packages

Used by

Contributors

Languages