waveledger-sdk — Python client
Official Python SDK for the WaveLedger
post-quantum chain. One Client class for every messenger surface
(auth, chat, wallet, explorer, playground, admin) plus an iterator
over the SSE event stream. Ships with the Fourier compiler
vendored in-process so contracts compile locally without a network
round-trip.
Install
pip install waveledger-sdk
The PyPI distribution is waveledger-sdk; the importable module is
waveledger, so your code stays from waveledger import Client. The
only runtime dependency is requests.
From the WaveLedger source tree:
pip install -e clients/python
Quickstart
from waveledger import Client
c = Client("https://api.waveledger.net")
# Sign up with an invite (instant approval + 100 testnet WAVE)
c.signup("alice", invite_code="WAVE-ABC123")
# Post a chat message — real on-chain ML-DSA-87 tx
c.send_message("hello world")
# Send WAVE to another address
c.wallet_send(to="34378b1ba5be9d0999acd60be3a8a1f1", amount=1.0)
# Subscribe to every block as it lands
for ev in c.subscribe(types=["block"]):
b = ev["block"]
print(f"block {b['height']} from {b['miner'][:16]}")
API surface
# Auth / session
c.signup(name, invite_code=None)
c.login(name, token)
c.me()
c.logout()
# Chat
c.send_message(text)
c.messages(limit=50)
# Wallet
c.wallet()
c.wallet_send(to=..., amount=..., memo=None)
c.wallet_export(passphrase=...)
c.wallet_import(name=..., encrypted=..., passphrase=...)
# Explorer (public, no auth)
c.explorer.stats()
c.explorer.blocks(limit=25, offset=0)
c.explorer.block(height)
c.explorer.tx(tx_id)
c.explorer.address(address)
# Playground (Fourier)
c.playground.compile(source) # server-side
c.playground.compile_local(source) # in-process — no network call
c.playground.deploy(source)
c.playground.call(contract=..., method=..., args=[...])
c.playground.receipt(tx_id)
c.playground.contracts()
# SSE event stream — block / tx / message / receipt
for ev in c.subscribe(types=None, address=None):
handle(ev)
# Admin (HTTP Basic — pass admin=(user, password) at construction)
ac = Client("https://api.waveledger.net",
admin=("admin", "PASSWORD"))
ac.admin.pending()
ac.admin.approve(name)
ac.admin.block(name, reason=None)
ac.admin.unblock(name)
ac.admin.invite_create(max_uses=25)
ac.admin.invite_revoke(code)
ac.admin.invites_list()
ac.admin.token_create(label=..., name=..., scope="playground")
ac.admin.tokens_list()
ac.admin.token_revoke(token="wlg_...")
API token auth
For CI pipelines and unattended use, an administrator mints a Bearer token bound to an approved user. The token's user owns any contracts deployed or called through it; that user's wallet pays the fees.
# Operator (one-off): mint a token bound to ci-bot.
admin = Client("https://api.waveledger.net",
admin=("admin", "PASSWORD"))
admin.admin.approve("ci-bot")
out = admin.admin.token_create(label="release-pipeline",
name="ci-bot",
scope="playground")
print(out["token"]) # wlg_… — save this once; not recoverable
# Pipeline: use the token, no signup/login required.
c = Client("https://api.waveledger.net", api_token="wlg_…")
c.playground.deploy(source)
Tokens are stored as their SHA3-256 hash. The raw value is returned exactly once; revocation is the only recovery for a lost or leaked token.
Local Fourier compile
The package vendors the Fourier compiler. compile_local() runs
in-process and returns the same shape as the server compile:
out = c.playground.compile_local("""
contract Counter {
storage value: uint @ 0;
pub fn inc() -> uint { value = value + 1; return value; }
}
""")
print(out["bytecode_size"], out["abi"]["contract"])
The vendored compiler is pinned with the SDK release, so a given
waveledger-sdk version produces byte-identical bytecode regardless
of when or where it runs. Lex / parse / codegen / ABI errors raise
ValidationError with payload={"phase": "compile", "error": ...},
matching the server's 400 response shape.
Filtering the event stream
# Block events only
for ev in c.subscribe(types=["block"]):
print(ev["block"]["height"])
# Everything that touches one address
for ev in c.subscribe(address="34378b1ba5be9d0999acd60be3a8a1f1"):
print(ev["type"], ev)
# Both filters AND'd
for ev in c.subscribe(types=["tx", "receipt"],
address="34378b1ba5be9d0999acd60be3a8a1f1"):
print(ev)
Filtering is server-side, so the client pays no bandwidth or CPU cost for events outside the filter.
Errors
from waveledger import (
AuthError, NotFoundError, RateLimitedError,
ValidationError, ServerError, WaveLedgerError,
)
| HTTP | Exception |
|---|---|
| 400 | ValidationError |
| 401 / 403 | AuthError |
| 404 | NotFoundError |
| 429 | RateLimitedError |
| 5xx | ServerError |
| anything else | WaveLedgerError |
Each exception carries .status (int) and .payload (decoded JSON if
any).
Security notes
- The SDK emits a
UserWarningat construction time ifapi_tokenoradmin=is configured against a non-loopbackhttp://URL. Loopback hosts (localhost,127.0.0.1,::1) stay quiet — that is normal local development. - Bearer tokens and admin credentials are sent on a per-request basis;
requestsstrips theAuthorizationheader on cross-origin redirects so a redirect to a different host does not leak the credential. - Wallet backups are AES-256-GCM with Argon2id KDF (server-side); the
SDK never sees the user's passphrase except as a value passed
through to
/api/wallet/export.
Self-hosted nodes
c = Client("http://localhost:8081")
The messenger serves on 8081 by default (node.py --messenger-port).
Tests
cd clients/python
python3 -m pytest tests/ -q
The suite uses a mock requests.Session plus the vendored Fourier
compiler — no network, no fixtures, no extra test deps.
Versioning
Pre-1.0. Method names and response shapes track the REST API. Latest
release: waveledger-sdk 0.2.0.
Metadata
Release files for waveledger-sdk 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| waveledger_sdk-0.2.0.tar.gz | 51.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| waveledger_sdk-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 101.1 kB
Release files / waveledger_sdk-0.2.0.tar.gz
| Download URL | waveledger_sdk-0.2.0.tar.gz |
|---|---|
| Size | 51.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
32f69bc2d6e4308d5316bd888b7b9626b697e42d2a4be04235b84ef53c3956ef
|
|
BLAKE2b-256 checksum How to use checksums |
d2e873dcb85b48838ed77c2d9cb85b6e1984741624546e0eb3037a89669babe8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.2
|
Release files / waveledger_sdk-0.2.0-py3-none-any.whl
| Download URL | waveledger_sdk-0.2.0-py3-none-any.whl |
|---|---|
| Size | 49.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0b1b11a985777cf4e64145bdf78277c05ed5485399ffa8795479de2a77a0f8fe
|
|
BLAKE2b-256 checksum How to use checksums |
e9bfee4daa3ffea8fa88615613f0d7554e1718f6169f28ded806ca55c281f015
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.2
|