Metadata-Version: 2.4
Name: ant-sdk
Version: 0.0.9
Summary: Autonomi FFI — direct-network, daemon-less client for Python (UniFFI bindings)
License: MIT OR Apache-2.0
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# Autonomi FFI — Python bindings

Direct-network, **daemon-less** Autonomi client for Python, generated by
[UniFFI](https://mozilla.github.io/uniffi-rs/) from the `ant-ffi` Rust crate —
the same compiled library that backs the Swift and Kotlin mobile SDKs. Unlike
[`antd`](../../antd-py) (which talks to a running antd daemon over REST/gRPC),
this embeds the network client in-process, exactly like the mobile bindings.

Async `Client` methods are real `async def` — they run on Rust's tokio runtime
and bridge to asyncio, so `await client.data_put_public(...)` works from plain
asyncio with no extra event-loop setup.

> **Package name.** The distribution is `ant-sdk` (matches this repo) — a
> working title, distribution name only: the *import* name is `ant_ffi`,
> fixed by the UniFFI crate namespace (`pip install ant-sdk`, then
> `import ant_ffi`). If a product-level rename happens, the PyPI project
> will be deleted and recreated under the new name. Track: V2-880.

## Layout

```
python/
├── ant_ffi/
│   ├── __init__.py         # re-exports the generated surface
│   ├── ant_ffi.py          # generated by uniffi-bindgen (do not edit)
│   └── libant_ffi.dylib    # bundled native lib (per-platform; not committed)
├── examples/
│   └── upload_download_demo.py
├── tests/
│   └── test_smoke.py       # offline: import + version + address derivation
├── pyproject.toml
└── README.md
```

The generated `ant_ffi.py` and the bundled native library are build outputs —
regenerate them with `ffi/scripts/build.sh` (which now includes a Python step).

## Build the bindings

```bash
cd ffi/rust && cargo build --release -p ant-ffi
./target/release/uniffi-bindgen generate \
    --library target/release/libant_ffi.dylib \
    --language python --out-dir ../python/ant_ffi/
cp target/release/libant_ffi.dylib ../python/ant_ffi/   # or .so / .dll
```

(`ffi/scripts/build.sh` does all of the above alongside the C#/Kotlin/Swift steps.)

## Build & check a wheel

This is a **wheel-only** distribution. `sdist` is deliberately blocked — a
source tarball would embed this host's native library under a platform-neutral
name — and the wheel build refuses to run unless the generated module and
native library are staged (otherwise the wheel would install cleanly and fail
on first import). Build and verify with:

```bash
cd ffi/python && python3 -m build --wheel
../scripts/check-python-wheel.sh   # installs into a throwaway venv + imports
```

## Smoke test (offline, no network)

```bash
cd ffi/python && python3 tests/test_smoke.py
```

## Upload/download demo (needs a devnet)

Start a local devnet (writes `~/.ant-dev/devnet-manifest.json`):

```bash
cd ant-node && cargo run --release --bin ant-devnet -- \
    --preset small --enable-evm --manifest ~/.ant-dev/devnet-manifest.json
```

Then run the round-trip demo — connect from the manifest, upload a file (the
manifest wallet pays inside ant-core), download it back, verify byte-identical:

```bash
cd ffi/python && python3 examples/upload_download_demo.py
```

## Progress callbacks & threading

`_with_progress` / `download_*_to_file` methods take a `ProgressListener`
(subclass it, implement `on_progress`). **Callbacks arrive on a Rust/tokio
worker thread, not the asyncio event loop.** asyncio is not thread-safe, so to
touch event-loop state from a callback, hop back with
`loop.call_soon_threadsafe(...)`. Keep callbacks quick — events flow through a
bounded channel and a slow callback backpressures the transfer.
