Skip to main content

antd-py -- Python SDK for Autonomi

Python SDK for the antd daemon. Provides synchronous and asynchronous clients with both REST and gRPC transports.

Installation

# REST transport (recommended)
pip install antd[rest]

# gRPC transport
pip install antd[grpc]

# Both transports
pip install antd[all]

# From source (development)
pip install -e ".[all]"

Compatibility

This package talks to a running antd daemon; it does not join the network itself. Python 3.10+. Tested against antd 0.12.x; health() fields such as version/evm_network need antd 0.4.0 or newer. For a daemon-less client see the ant-sdk package (import ant_ffi). Not related to the Ant Design UI library.

Quick Start

from antd import AntdClient

client = AntdClient()  # REST transport, localhost:8082

# Health check
status = client.health()
print(f"{status.network} -- healthy: {status.ok}")

# Store and retrieve data
result = client.data_put_public(b"Hello, Autonomi!")
print(f"Address: {result.address}, chunks: {result.chunks_stored}")

data = client.data_get_public(result.address)
print(data.decode())  # "Hello, Autonomi!"

Transports

from antd import AntdClient, AsyncAntdClient

# REST (default)
client = AntdClient(transport="rest", base_url="http://localhost:8082", timeout=30)

# gRPC (wallet operations and payment_mode are available via REST only)
client = AntdClient(transport="grpc", target="localhost:50051")

# Async REST
aclient = AsyncAntdClient(transport="rest")
status = await aclient.health()
await aclient.close()

API Reference

Factory Functions

Function Description
AntdClient(transport="rest", **kwargs) Create a synchronous client
AsyncAntdClient(transport="rest", **kwargs) Create an asynchronous client

Client Methods

Health

Method Returns Description
health() HealthStatus Check daemon health — also surfaces antd version, EVM network, uptime, build commit, and payment contract addresses (antd ≥ 0.4.0)

Data

Method Returns Description
data_put_public(data, payment_mode=...) DataPutPublicResult Store public data — DataMap is stored on-network
data_get_public(address: str) bytes Retrieve public data by address
data_put(data, payment_mode=...) DataPutResult Store private (encrypted) data — DataMap returned to caller (NOT stored on-network)
data_get(data_map: str) bytes Retrieve private data using a caller-held DataMap
data_cost(data, payment_mode=...) UploadCostEstimate Estimate storage cost — size, chunks, gas, payment mode

Chunks

Method Returns Description
chunk_put(data: bytes) PutResult Store a raw chunk
chunk_get(address: str) bytes Retrieve a chunk

Files

Method Returns Description
file_put(path, payment_mode=...) FilePutResult Upload a file privately — DataMap returned to caller (NOT stored on-network)
file_get(data_map, dest_path) None Download a private file using a caller-held DataMap
file_put_public(path, payment_mode=...) FilePutPublicResult Upload a file publicly — DataMap is stored on-network
file_get_public(address, dest_path) None Download a public file by address
file_cost(path, is_public, payment_mode=...) UploadCostEstimate Estimate file cost — size, chunks, gas, payment mode

External Signer

Two-phase upload — daemon prepares the payment intent, caller signs + submits the payForQuotes tx, daemon finalizes once the chain confirms. See examples/07_external_signer.py + docs/external-signer-flow.md. A finalize that stores only some chunks raises PartialUploadError — see Partial uploads for how to finish the upload without paying twice.

Method Returns Description
prepare_upload(path, visibility=None) PrepareUploadResult Prepare a file upload for external signing
prepare_upload_public(path) PrepareUploadResult Convenience for prepare_upload(path, visibility="public")
prepare_data_upload(data, visibility=None) PrepareUploadResult Prepare a data upload for external signing
prepare_chunk_upload(data) PrepareChunkResult Prepare a single chunk for external-signer publish
finalize_upload(upload_id, tx_hashes) FinalizeUploadResult Submit a prepared upload after external payment. data_map_address populated when prepare used visibility="public". Raises PartialUploadError on a partial store
finalize_merkle_upload(upload_id, winner_pool_hash, store_data_map=False) FinalizeUploadResult Submit a prepared merkle-batch upload after selecting the winning pool. Raises PartialUploadError on a partial store
finalize_chunk_upload(upload_id, tx_hashes) str Submit a prepared chunk after external payment; returns the chunk address

Models

All models are frozen dataclasses (immutable).

Model Fields Description
HealthStatus ok, network, version, evm_network, uptime_seconds, build_commit, payment_token_address, payment_vault_address Health check result (diagnostic fields require antd ≥ 0.4.0)
PutResult cost, address Result of chunk_put only
DataPutResult data_map, chunks_stored, payment_mode_used Private data put — DataMap returned to caller
DataPutPublicResult address, chunks_stored, payment_mode_used Public data put — DataMap stored on-network
FilePutResult data_map, storage_cost_atto, gas_cost_wei, chunks_stored, payment_mode_used Private file put — DataMap returned to caller
FilePutPublicResult address, storage_cost_atto, gas_cost_wei, chunks_stored, payment_mode_used Public file put — DataMap stored on-network
UploadCostEstimate cost, file_size, chunk_count, estimated_gas_cost_wei, payment_mode Pre-upload cost breakdown

Error Handling

All errors inherit from AntdError:

from antd import AntdClient, AntdError, NotFoundError, PaymentError

client = AntdClient()

try:
    data = client.data_get_public("nonexistent_address")
except NotFoundError:
    print("Data not found on the network")
except PaymentError:
    print("Insufficient funds")
except AntdError as e:
    print(f"Error ({e.status_code}): {e}")
Exception HTTP gRPC Description
BadRequestError 400 INVALID_ARGUMENT Invalid request parameters
PaymentError 402 FAILED_PRECONDITION Wallet/payment issue
NotFoundError 404 NOT_FOUND Resource not found
AlreadyExistsError 409 ALREADY_EXISTS Resource already exists
ForkError 409 ABORTED (non-partial-upload) Version conflict
TooLargeError 413 RESOURCE_EXHAUSTED Payload too large
InternalError 500 INTERNAL Server error
NetworkError 502 UNAVAILABLE Network unreachable
PartialUploadError 502 (code: "PARTIAL_UPLOAD") ABORTED (message starts Partial upload:) Finalize stored some chunks, not all — subclass of NetworkError; carries chunks_stored, chunks_failed, total_chunks, retryable

Partial uploads

finalize_upload / finalize_merkle_upload can fail after the wallet has paid: some chunks store, others miss quorum after the daemon's own retries. That surfaces as PartialUploadError (a NetworkError subclass, so existing except NetworkError / except AntdError blocks still catch it). The on-chain payment persists and the stored chunks stay on the network. retryable and retention_known say how to finish (retryable implies retention_known):

  • retryable — the daemon kept the paid attempt (payment proofs + unstored chunks) under the same upload_id. Call the same finalize method again with the same arguments (the same upload_id and payment artefacts) to store the remainder against the same payment: no re-prepare, no second signature, no double payment. Bound the loop — a persistent failure raises again on every call, so cap the attempts and treat a chunks_failed that stops shrinking as stuck. The retained attempt expires with the daemon's pending-upload TTL (one hour). Sent by antd ≥ 0.14.0.
  • retention_known and not retryable — the daemon confirmed it kept nothing (e.g. a merkle finalize whose signer deliberately left some sub-batches unpaid). Re-prepare the same content: already-stored chunks are skipped, so the retry pays only for the remainder.
  • not retention_known — retention is unknown. The daemon may still hold the paid attempt: it records the resume handle before it returns the error. Stop automatic recovery, keep the upload_id and the original payment artefacts (tx_hashes / winner_pool_hash), and reconcile before re-preparing or paying again. Never pay again on this signal alone. Daemons older than 0.14.0 never send retryable, so their REST partial uploads read as unknown.

Over gRPC a partial upload used to raise ForkError; it now raises PartialUploadError. The daemon sends ABORTED only for PARTIAL_UPLOAD, so code that caught ForkError around a finalize should catch PartialUploadError.

Over REST the counts and flags come from the structured error body. Over gRPC a partial upload is an ABORTED status whose message starts with the daemon's fixed Partial upload: prefix, and the counts and flags are parsed from that message. An ABORTED that does not start with the prefix (including one that only embeds it, e.g. upstream error: Partial upload: ...) is not a partial upload and raises ForkError as before. Full contract: docs/external-signer-flow.md §6.

Malformed input is read conservatively and never escapes as a raw ValueError / TypeError / OverflowError:

  • REST. Each count must be a JSON integer from 0 to 2^64−1. A quoted number ("1"), bool, float (including Infinity), array, object, negative or larger value reads as 0. retryable is True only for the JSON literal true; "true", 1 and everything else read as False. retention_known is True only when retryable is a JSON bool (true or false); absent, null or any other type reads as unknown. Only a string code of exactly "PARTIAL_UPLOAD" selects PartialUploadError. A body that is not a JSON object, or has any other code, keeps the plain 502 → NetworkError mapping, as does a body Python cannot decode at all. A non-string error makes the raw response body the message.
  • gRPC. The message reads Partial upload: S/T chunks stored, F failed after retries: <reason> (<hint>). retention_known is True only when the message starts with that counts pattern, all three counts fit in a u64, and it ends with one of the daemon's two hints. A (paid attempt retained...) hint sets retryable. A (stored chunks persist; re-prepare the same content...) hint means the daemon confirmed nothing was retained; daemons older than 0.14.0 write only this one. A pattern miss or an out-of-range count reads the counts as 0 with both flags False. Readable counts with a missing, truncated or unrecognised hint keep the counts, but both flags stay False: retention is unknown, not "nothing retained".
import time
from antd import PartialUploadError

def finalize_with_retry(client, upload_id, tx_hashes, max_attempts=5):
    last_failed = None
    for attempt in range(1, max_attempts + 1):
        try:
            return client.finalize_upload(upload_id, tx_hashes)  # every chunk stored
        except PartialUploadError as e:
            if not e.retryable:
                # retention_known: the daemon kept nothing, so re-prepare.
                # Otherwise retention is unknown: stop, keep upload_id and
                # tx_hashes, and reconcile. Never pay again on this alone.
                raise
            stuck = last_failed is not None and e.chunks_failed >= last_failed
            if attempt == max_attempts or stuck:
                raise  # paid attempt still retained under upload_id: retry the same finalize later
            last_failed = e.chunks_failed
            time.sleep(2 * attempt)

Examples

Run examples from the examples/ directory:

# Requires antd daemon running on local testnet
python examples/01_connect.py      # Health check
python examples/02_data.py         # Store/retrieve data
python examples/03_chunks.py       # Raw chunks
python examples/04_files.py        # File upload/download
python examples/06_private_data.py # Private data with data maps
python examples/07_external_signer.py # External-signer file + chunk upload
python examples/08_grpc.py          # gRPC transport (requires antd[grpc])
python examples/08_grpc.py         # gRPC transport (instead of REST)

Or use the dev CLI:

ant dev example data
ant dev example all

Release files for antd 0.2.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 antd 0.2.0
File Size Uploaded
antd-0.2.0.tar.gz 43.6 kB Details

Built distribution (wheel)

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

Total release size: 109.2 kB

Release files / antd-0.2.0.tar.gz

Download URL antd-0.2.0.tar.gz
Size 43.6 kB
Tags Source
SHA-256 checksum
How to use checksums
3c964d86f0f6467db246c198fe167d1a7eb808ad8bfa7957dab3235244de18d1
BLAKE2b-256 checksum
How to use checksums
741c193d470e1d6b793f5bb3fbef8f67df4b75c89f853157aa3c742fa5e41cfd
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 Sep 25, 2026.

Transparency log

Release files / antd-0.2.0-py3-none-any.whl

Download URL antd-0.2.0-py3-none-any.whl
Size 65.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
208dc3121a2694b498f232bbc04f3ee43040e58ee58ebfe243e10221597cbb92
BLAKE2b-256 checksum
How to use checksums
b6f8b7ee7ddbf71ffcb79b17dd9213d608045a5d8b32e7364dd8e8c8383348ba
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 Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.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