Skip to main content

pyrxd

Python SDK for the Radiant (RXD) blockchain.

License Python Docs

A typed, async-first SDK for building on Radiant — a UTXO chain with Bitcoin-style script plus induction (recursive covenants) and a native, consensus-enforced token layer. It ships transaction construction, HD wallets, the Glyph token protocol (NFT / FT / dMint), trustless cross-chain atomic swaps, SPV verification, and an ElectrumX client.

What you can build

Things that need a custodian or a bridge elsewhere — on Radiant they're trustless and enforced on-chain:

  • On-chain Glyph tokens (NFT / FT). Supply and transfers enforced by Radiant consensus, not an indexer or a sidecar. → mint an NFT · deploy an FT
  • Permissionless PoW token issuance (dMint). Deploy a token that anyone can mine — distributed issuance, no premine, secured by proof-of-work. Radiant-unique. → pyrxd glyph deploy-dmint / claim-dmint
  • Trustless cross-chain atomic swaps. Trade a Radiant asset (RXD / FT / NFT) against BTC or ETH — and EVM L2s (Base, Optimism, Arbitrum, Linea) — with no bridge and no custodian: a hash-timelock swap driven by a chain-neutral coordinator. Proven end-to-end on regtest and on small real-value mainnet / Sepolia runs. → build a cross-chain swap
  • Recursive covenants. Bitcoin-style script + induction lets a coin constrain the coin that spends it — soulbound NFTs, swap covenants, PoW-mint contracts. → covenant building blocks

New here? The 5-minute quickstart goes from pip install to a real on-chain token on a local regtest chain — no faucet, nothing at risk.

Status

Pre-1.0 software. APIs may change between minor versions before 1.0. pyrxd is open-source software, provided as-is, without warranty of any kind — see the LICENSE (Apache 2.0, §7–8). Cryptographic primitives have not been independently audited. See SECURITY.md for security policy and disclosure.

As with any wallet software on a young chain, verify your derivation paths and transaction outputs against an independent wallet before broadcasting on mainnet. If you find a bug that affects funds, report it via the security policy.

Working on mainnet today:

  • RXD send / send-max, balance and UTXO queries (pyrxd address / balance / utxos)
  • BIP32 / BIP39 / BIP44 HD wallets with optional encrypted persistence (HdWallet, pyrxd wallet)
  • Glyph NFT — mint (two-phase commit + reveal) and transfer (pyrxd glyph mint-nft / transfer-nft)
  • Glyph FT — premine deploy, conservation-enforced transfer, and one-transaction multi-recipient airdrop (pyrxd glyph deploy-ft / transfer-ft / airdrop-ft)
  • dMint permissionless PoW tokens (V1) — deploy (byte-equal to the live Glyph-protocol deploy, node-consensus-validated) and mine/claim from live mainnet contracts (pyrxd glyph deploy-dmint / claim-dmint)
  • dMint permissionless PoW tokens (V2) — the canonical Photonic redesign with adaptive difficulty (FIXED / ASERT / LWMA / EPOCH / SCHEDULE), byte-matched to upstream Photonic and node-consensus-validated on regtest and Radiant mainnet: the first V2 deploy + PoW mint and an on-chain difficulty retarget were confirmed on mainnet (pyrxd glyph deploy-dmint --v2 / claim-dmint)
  • List your Glyph tokens (pyrxd glyph list)
  • pyrxd agent — a per-spend-confirmed signing daemon that keeps the key out of the short-lived CLI process
  • ElectrumX async client with reconnect, balance, UTXOs, history, broadcast

Experimental — newer surface, proven on regtest / testnet (and small real-value runs):

  • Cross-chain HTLC atomic swaps (pyrxd.gravity) — RXD covenant + BTC Taproot + ETH Solidity legs driven by a chain-neutral coordinator; proven end-to-end on regtest (plus small real-value dust runs), against BTC, ETH, and EVM L2s (Base / Optimism / Arbitrum / Linea). This cross-chain swap stack is unaudited — verify it yourself before moving real value.

Upgrading

Pin pyrxd to a specific version in production and move versions deliberately. Between minor versions before 1.0, APIs can change in breaking ways (see CHANGELOG).

Do not downgrade after creating a wallet with a non-default coin_type. Since 0.3.0, HdWallet stores the derivation coin_type in the wallet file and validates it on load. If you:

  1. Create a wallet at coin_type=0 (e.g. for Photonic recovery)
  2. Downgrade to a pre-0.3.0 pyrxd
  3. Save the wallet under the old code

…the old code will overwrite the stored coin_type with its hardcoded default (512) while the derived keys remain rooted at m/44'/0'/…. A subsequent upgrade and load(..., coin_type=0) will fail validation against the now-corrupted 512 value, locking you out of the friendly recovery path. The underlying funds are still recoverable from the mnemonic, but you will need to re-create the wallet file explicitly with coin_type=0.

Mitigation: pin all machines accessing the same wallet to the same pyrxd version. Downgrading is unsupported once 0.3.0 has written a coin_type-annotated wallet file.

Installation

pip install pyrxd

Requires Python 3.10 or newer.

Quick start

Generate a key and check a balance

import asyncio
from pyrxd.keys import PrivateKey
from pyrxd.network.electrumx import ElectrumXClient, script_hash_for_address

async def main():
    priv = PrivateKey()  # no-arg constructor generates a fresh key
    addr = priv.public_key().address()
    print(f"address: {addr}")

    sh = script_hash_for_address(addr)
    async with ElectrumXClient(["wss://electrumx.radiant4people.com:50022/"]) as client:
        confirmed, unconfirmed = await client.get_balance(sh)
        print(f"balance: {confirmed:,} photons confirmed, {unconfirmed:,} unconfirmed")

asyncio.run(main())

Send RXD

from pyrxd.keys import PrivateKey
from pyrxd.transaction.transaction import Transaction, TransactionInput, TransactionOutput
from pyrxd.script.type import P2PKH

priv = PrivateKey("L1aW4aubDFB7yfras2S1mN3bqg9nwySY8nkoLmJebSLD5BWv3ENZ")
# ... build transaction with inputs and outputs ...
# See examples/ for full flows.

From a BIP39 seed phrase

If you already have a 12/24-word mnemonic (e.g. created by pyrxd wallet new or restored from another Radiant wallet), HdWallet.from_mnemonic gives you a full HD wallet at the correct Radiant BIP44 path (m/44'/512'/<account>').

⚠️ Radiant's BIP44 coin type per SLIP-0044 is 512. Bitcoin's is 0. Many Radiant-native software wallets historically used coin type 0 (a copy from upstream Bitcoin code) and addresses derived that way are different from spec-correct addresses. Tangem (the hardware wallet with Radiant integration) correctly uses coin type 512. As of pyrxd 0.3, the default is coin type 512 to align with the spec and with Tangem.

Migrating from older pyrxd? Earlier versions used coin type 236 (which is BSV's, not Radiant's). To recover funds derived at the old path, set RXD_PY_SDK_BIP44_DERIVATION_PATH=m/44'/236'/0' before running any pyrxd command. Sweep funds to a new spec-correct address, then unset the env var.

from pyrxd.hd import HdWallet

wallet = HdWallet.from_mnemonic("word1 word2 ... word12")
addr = wallet.next_receive_address()
print(f"first receive address: {addr}")

For a one-off private key at a specific path (the equivalent of the short mnemonic + bip32utils snippet some users start from), use the lower-level helpers directly:

from pyrxd.hd import bip44_derive_xprv_from_mnemonic

# Default path is m/44'/512'/0' — the Radiant account 0 key (SLIP-0044).
xprv = bip44_derive_xprv_from_mnemonic("word1 word2 ... word12")
child = xprv.ckd(0).ckd(0)  # m/44'/512'/0'/0/0  (external chain, index 0)
priv = child.private_key()
print(f"WIF:     {priv.wif()}")
print(f"address: {priv.public_key().address()}")

See examples/mnemonic_to_key.py for a runnable version of both flows.

Mint a Glyph NFT

A Glyph mint is two transactions: a commit that locks a hash of the metadata, then a reveal that publishes the metadata and creates the token. GlyphMinter runs both — UTXO selection, commit sizing, the pre-broadcast fee guard, signing and confirmation polling included.

from pyrxd.glyph import GlyphMetadata, GlyphProtocol
from pyrxd.glyph.mint import GlyphMinter, JsonFilePendingStore

metadata = GlyphMetadata(
    protocol=[GlyphProtocol.NFT],
    name="My NFT",
    description="A demo non-fungible token.",
)
minter = GlyphMinter(client, wallet, JsonFilePendingStore("~/.pyrxd/pending-mints"))
result = await minter.mint_nft(metadata)
print(result.ref)  # the token's permanent identity: the commit outpoint

The store is a required argument, not an option. The commit output is a hashlock with no owner-only spend path, so losing the metadata bytes between the two phases makes it permanently unspendable — the store writes them to disk, and verifies the write, before the commit is broadcast. That is also what makes the mint resumable:

pending = await minter.commit_nft(metadata)   # persisted, then broadcast
...                                           # crash, reboot, next week
result = await minter.reveal_nft(store.load(pending.commit_txid))

Deploy a fungible token (premine)

metadata = GlyphMetadata(
    protocol=[GlyphProtocol.FT],
    name="My Token",
    ticker="MTK",
    description="A premine fungible token.",
)
result = await minter.deploy_ft(metadata, supply=1_000_000)

GlyphBuilder remains the lower-level API when you need to compose the transactions yourself (mutable NFTs, containers, WAVE names and dMint deploys have different reveal shapes and are built through it directly).

See examples/glyph_mint_demo.py for a complete end-to-end NFT mint, and examples/ft_deploy_premine.py for an FT premine deployment.

Command line

pip install pyrxd also installs a pyrxd CLI. The command surface is intentionally narrow — it covers wallet management and (in v0.3+) Glyph token operations, the things that don't have a clean equivalent in radiant-cli (the node wallet). For plain RXD sendtoaddress on a node, prefer radiant-cli.

# Create a fresh HD wallet. The mnemonic is shown ONCE — write it down.
pyrxd wallet new

# Show the next unused receive address.
pyrxd address

# Check balance via ElectrumX.
pyrxd balance --refresh

# Look up a deterministic index without scanning.
pyrxd address --index 5

# Quiet mode for scripting.
pyrxd --quiet balance --refresh

pyrxd <command> --help prints the full reference for any subcommand. JSON mode for scripting: pass --json (and --yes for any broadcasting operation).

Security: scripting wallet new with --json --yes

In --json --yes mode, pyrxd wallet new prints the mnemonic in the JSON payload on stdout — that's the only way scripted automation can capture a freshly-generated mnemonic. The user is responsible for ensuring the consumer of stdout is itself secure:

  • Never run pyrxd wallet new --json --yes | tee mnemonic.txt — that writes the mnemonic to disk unencrypted.
  • Never run it in a shell whose history is recorded with stdout — most shells don't capture stdout in history, but some configurations and tools (script, terminal recorders, CI log collectors) do.
  • Don't run it in a container where stdout is logged to a shared log aggregator — containerized stdout is captured by the orchestrator and ends up in centralized logging.

The interactive form (pyrxd wallet new without --json) shows the mnemonic in a clearly-flagged box and waits for the user to press Enter. Even then, terminal scrollback, tmux/screen buffers, and screen-sharing can expose the mnemonic — do not run wallet generation on a shared or recorded display.

Production architecture

If you're building a web app that interacts with Radiant in production, do not put private keys in your web tier. A web RCE in your app then becomes a wallet compromise.

The recommended pattern:

  1. Keep pyrxd as the cryptographic and protocol library — it's safe to import in any process that needs to read chain state.
  2. Run a separate signing service (a small HTTP service that wraps pyrxd) on a different process, ideally a different host, with the private key loaded only there.
  3. Have your web app talk to the signing service over an authenticated API (HMAC-signed requests, mutual TLS, or similar) for any operation that needs a signature.

This is the pattern used by major payment-rail SDKs (Stripe, Square, AWS) and is the correct shape for any application handling real funds.

Documentation

Hosted at mudwoodlabs.github.io/pyrxd (API reference + tutorials + how-to guides + concepts).

Other resources in this repo:

Contributing

See CONTRIBUTING.md for development setup, code style, and how to send a PR. We use the Developer Certificate of Origin for contributor sign-off — no CLA paperwork.

By contributing, you agree your contributions are licensed under Apache 2.0.

Security

Report vulnerabilities privately to security@mudwoodlabs.com. See SECURITY.md for the full policy and disclosure timeline.

License

Apache License 2.0 — see LICENSE and NOTICE.

Copyright 2026 Mudwood Labs.

Release files for pyrxd 0.14.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyrxd 0.14.0
File Size Uploaded
pyrxd-0.14.0.tar.gz 2.8 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyrxd 0.14.0
File Interpreter ABI Platform
pyrxd-0.14.0-py3-none-any.whl Python 3 none any Details

Total release size: 3.8 MB

Release files / pyrxd-0.14.0.tar.gz

Download URL pyrxd-0.14.0.tar.gz
Size 2.8 MB
Tags Source
SHA-256 checksum
How to use checksums
c53654637fdd2e3849c38892dd91fbd7374ac234daaf2613d37ecf826f90a208
BLAKE2b-256 checksum
How to use checksums
2eea983294d80dfdff359aee4c242526035ac04633589b83866efcb2e99c4bef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 11, 2026.

Transparency log

Release files / pyrxd-0.14.0-py3-none-any.whl

Download URL pyrxd-0.14.0-py3-none-any.whl
Size 1.0 MB
Tags Python 3
SHA-256 checksum
How to use checksums
857a172f98dfbbf1020c17f85e6b5cac76f8281edeadf25e950bb1fc2fab3abd
BLAKE2b-256 checksum
How to use checksums
af6adbafd3d6c6d323cfde7494bb7a129eedf6cde705ff54f4e061a4f86fe36a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 11, 2026.

Transparency log

Release history Release notifications | RSS feed

0.24.0

2 release files

0.21.0

2 release files

0.20.0

2 release files

0.19.0

2 release files

0.18.0

2 release files

0.17.0

2 release files

0.16.0

2 release files

0.15.0

2 release files

This release

0.14.0 This release

2 release files

0.13.0

2 release files

0.11.1

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page