Metadata-Version: 2.4
Name: waveledger-sdk
Version: 0.1.0
Summary: Official Python client for the WaveLedger post-quantum testnet.
Author: Fermi
License: MIT
Project-URL: Homepage, https://docs.waveledger.net/sdk/python/
Project-URL: Documentation, https://docs.waveledger.net
Project-URL: Source, https://github.com/DosseyRichards/Fermi-Mining-ASIC-Software
Keywords: waveledger,blockchain,post-quantum,fermi
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Distributed Computing
Classifier: License :: OSI Approved :: MIT License
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28
Dynamic: license-file

# waveledger — Python client

Official Python client for the [WaveLedger](https://docs.waveledger.net)
post-quantum testnet. One class for every messenger surface (auth,
chat, wallet, explorer, playground, admin) plus an iterator over the
SSE event stream.

## Install

```bash
pip install waveledger-sdk
```

The PyPI distribution is `waveledger-sdk`; the importable module is
`waveledger` (so your code stays `from waveledger import Client`).

From the WaveLedger source tree:

```bash
pip install -e clients/python
```

Or vendor `clients/python/waveledger/` into your project — it's
pure-Python with one dep (`requests`).

## Quickstart

```python
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 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]}")
```

## Surfaces

The `Client` exposes everything as either a method or a sub-surface:

```python
c.signup(...)           c.login(...)            c.me()
c.send_message(...)     c.messages()
c.wallet()              c.wallet_send(...)      c.wallet_export(...)
c.subscribe(...)        # SSE: block / tx / message / receipt events

c.explorer.stats()
c.explorer.blocks(limit=25, offset=0)
c.explorer.block(height)
c.explorer.tx(tx_id)
c.explorer.address(address)

c.playground.compile(source)
c.playground.deploy(source)
c.playground.call(contract=..., method=..., args=[...])
c.playground.receipt(tx_id)
c.playground.contracts()

# Admin endpoints — pass HTTP Basic at construction time
ac = Client("https://api.waveledger.net", admin=("admin", "PASSWORD"))
ac.admin.pending()
ac.admin.approve("alice")
ac.admin.block("spammer", reason="abuse")
ac.admin.unblock("spammer")
ac.admin.invite_create(max_uses=10)
```

## Filtering the event stream

```python
# Block events only
for ev in c.subscribe(types=["block"]): ...

# Everything that touches one address
for ev in c.subscribe(address="34378b1ba5be9d0999acd60be3a8a1f1"): ...

# Both
for ev in c.subscribe(types=["tx", "receipt"],
                       address="34378b1ba5be9d0999acd60be3a8a1f1"): ...
```

Filtering happens **server-side**, so the client pays no bandwidth or
CPU cost for events it doesn't care about.

## Errors

Every HTTP error maps to a specific exception class:

```python
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` (the server's
JSON response if any).

## Self-hosted nodes

Point the client at your own node:

```python
c = Client("http://localhost:8081")
```

The messenger serves on `8081` by default
(`node.py --messenger-port`).

## Tests

```bash
cd clients/python
python3 -m pytest tests/ -q
```

The test suite uses a `MockSession` that captures every HTTP call —
no network, no fixtures, no external test deps.

## Versioning

Pre-1.0. Method names and response shapes track the REST API, which
is itself under active development on testnet. See
[CHANGELOG](https://docs.waveledger.net) on the docs site.
