# Python SDK The Python SDK provides both async QUIC transport and synchronous Rust FFI backends. Location: `sdks/python/` ## Installation ```sh pip install quicprochat ``` ## Transport Backends ### Async QUIC (pure Python) Uses [aioquic](https://github.com/aiortc/aioquic) for native QUIC transport with the v2 protobuf wire format. No Rust build required. ```python import asyncio from quicprochat import QpqClient, ConnectOptions async def main(): client = await QpqClient.connect(ConnectOptions( addr="127.0.0.1:5001", ca_cert_path="ca.pem", )) health = await client.health() print(f"Server: {health.status}") # OPAQUE auth (requires external OPAQUE library) resp = await client.login_start("alice", opaque_request) token = await client.login_finish("alice", finalization, identity_key) # Messaging key, proof = await client.resolve_user("bob") seq, proof = await client.send(key, b"hello") messages = await client.receive_wait(my_key, timeout_ms=5000) await client.close() asyncio.run(main()) ``` ### Rust FFI (synchronous) Wraps `libquicprochat_ffi` via CFFI for full Rust crypto stack at native speed. ```sh cargo build --release -p quicprochat-ffi ``` ```python from quicprochat import QpqClient, ConnectOptions client = QpqClient.connect_ffi(ConnectOptions( addr="127.0.0.1:5001", ca_cert_path="ca.pem", )) client.ffi_login("alice", "password123") client.ffi_send("bob", b"hello") messages = client.ffi_receive(timeout_ms=5000) client.close_sync() ``` ## Async API (QUIC) | Method | Description | |---|---| | `QpqClient.connect(opts)` | Connect via QUIC | | `client.health()` | Health check | | `client.register_start(username, request)` | OPAQUE register start | | `client.register_finish(username, upload, key)` | OPAQUE register finish | | `client.login_start(username, request)` | OPAQUE login start | | `client.login_finish(username, finalization, key)` | OPAQUE login finish | | `client.resolve_user(username)` | Look up identity key | | `client.resolve_identity(key)` | Reverse look up username | | `client.create_channel(peer_key)` | Create DM channel | | `client.send(recipient_key, payload)` | Send message | | `client.receive(recipient_key)` | Fetch messages | | `client.receive_wait(recipient_key, timeout_ms=5000)` | Long-poll | | `client.ack(recipient_key, seq_up_to)` | Acknowledge messages | | `client.upload_key_package(key, package)` | Upload MLS key package | | `client.fetch_key_package(key)` | Fetch MLS key package | | `client.upload_hybrid_key(key, hybrid_pk)` | Upload hybrid key | | `client.fetch_hybrid_key(key)` | Fetch hybrid key | | `client.delete_account()` | Delete account | | `client.close()` | Disconnect (async) | ## FFI API (synchronous) | Method | Description | |---|---| | `QpqClient.connect_ffi(opts)` | Connect via Rust FFI | | `client.ffi_login(username, password)` | Full OPAQUE login | | `client.ffi_send(recipient, message)` | Send by username | | `client.ffi_receive(timeout_ms=5000)` | Receive messages | | `client.close_sync()` | Disconnect (sync) | ## Exceptions | Exception | Description | |---|---| | `QpqError` | Base exception for all SDK errors | | `AuthError` | OPAQUE authentication failed | | `TimeoutError` | Operation timed out | | `ConnectionError` | Server connection failure | ## Structure | File | Purpose | |---|---| | `quicprochat/client.py` | High-level client API | | `quicprochat/transport.py` | QUIC transport (aioquic) | | `quicprochat/ffi.py` | Rust FFI transport (CFFI) | | `quicprochat/proto.py` | Protobuf encode/decode | | `quicprochat/wire.py` | v2 wire format framing | | `quicprochat/types.py` | Data types and exceptions |