Skip to content

Tosh-Labs/blockchain0x-python

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

blockchain0x (Python SDK)

Official Python SDK for Blockchain0x - the non-custodial AI-agent wallet platform on Base.

Pre-release: 0.0.1a0 ships the operational essentials - HTTP transport, apiKeys resource, and webhooks.verify. The full surface (every resource + x402 client + async client) lands in the 21.3 Phase C follow-up rows.

Install

pip install blockchain0x

Requires Python 3.9 or newer.

Quick start

from blockchain0x import Client

client = Client(api_key="sk_test_...")
for key in client.api_keys.list()["data"]:
    print(key["id"], key["prefix"])

The client pins the network from the api-key prefix (sk_test_* → testnet, sk_live_* → mainnet). Override with Client(api_key=..., network="mainnet") when you need both modes in one process (mixed-mode tests).

Verify webhook signatures

This is the single most important utility this SDK ships - drop it into the top of your webhook handler BEFORE touching the body.

from blockchain0x import webhooks

# In your Flask / FastAPI / Django handler:
def receive_webhook(req, raw_body, secret):
    result = webhooks.verify(headers=req.headers, raw_body=raw_body, secret=secret)
    if not result.ok:
        return {"code": result.code}, 400
    # result.event_type / result.event_id / result.delivery_id populated
    process_event(raw_body, result.event_type)

The verifier:

  • Reads X-Blockchain0x-Signature in either t=<ts>,v1=<hex> or bare-hex form (some load balancers strip commas).
  • Falls back to X-Blockchain0x-Timestamp when the signature is bare.
  • Rejects with webhook.timestamp_outside_window when drift exceeds 300s (5-minute replay window; matches the worker).
  • Constant-time compares via hmac.compare_digest.

For exception-based flows pass raise_on_fail=True:

try:
    webhooks.verify(headers=req.headers, raw_body=raw_body, secret=secret, raise_on_fail=True)
except WebhookSignatureError as e:
    return {"code": e.code}, 400

Errors

Two classes:

  • Blockchain0xError - base class; every SDK error inherits.
  • ApiKeyError - subclass for HTTP 401 / 403 envelopes whose error.code starts with apikey. (e.g. apikey.scope_insufficient, apikey.wallet_not_assigned).

Always branch on .code, never regex-match .message:

from blockchain0x import ApiKeyError

try:
    client.api_keys.list()
except ApiKeyError as e:
    if e.code == "apikey.scope_insufficient":
        # mint a fresh key with more scope
        ...

Workspace keys (sub-plan 21.3)

Two key shapes exist (see docs/concept-api-key-types.md for the full decision tree):

  • Wallet-only: bound to ONE agent via agent_id. The right shape for an autonomous AI agent that IS one wallet.
  • Workspace: for human operators that can carry workspace-level scopes AND assignments to N specific wallets.

The Python SDK forwards both shapes through the same client.api_keys resource; the body shape decides the flavor on the server. Once the create surface lands beyond the C-2 scaffold:

key = client.api_keys.create(
    label="Treasury daily reconciliation",
    workspace_scopes=["read_workspace"],
    wallet_assignments=[
        {"agentId": "agt_trading", "scopes": ["read_wallet_metadata"]},
        {"agentId": "agt_settlement", "scopes": ["read_wallet_metadata"]},
    ],
    expires_in_days=30,
)
print(key["secret"])  # shown ONCE

Server-side RBAC: the minter cannot grant a scope they do not have themselves. Over-grants reject with apikey.role_insufficient_for_grants - catch ApiKeyError and branch on e.code.

Cascade behaviour: when an assigned wallet is soft-deleted, the assignment row is removed. If the key has zero workspace scopes AND no remaining assignments, it auto-revokes with apikey.no_grants_remaining. Mint a fresh key.

x402 (Phase C-7)

The sibling package blockchain0x-x402 (Python port of @blockchain0x/x402) will ship the x402 client + FastAPI / Starlette / Flask adapters in sub-plan 21.3 row C-7. The wire format is identical across languages so a Python service can accept payments from a Node client and vice-versa.

Retry behaviour

The transport retries on 429 and 5xx with exponential backoff (0.5s → 1s → 2s → ... → 30s cap). Retry-After is honoured when the server sends it. Network errors (timeout, connection drop) get the same retry budget.

POST / PATCH / DELETE requests carry an Idempotency-Key header

  • the SDK mints a uuid4 if you do not supply one. Pass idempotency_key="..." to thread a stable key across SDK retries OR across processes (e.g. cron jobs that hash their input deterministically).

Codegen

Type-only DTOs are generated from apps/backend/openapi/openapi.yaml via datamodel-code-generator. Transport, retry, error mapping, and the webhook verifier stay handwritten - see codegen/README.md for the decision rationale.

Source-of-truth + distribution

Source-of-truth: this directory in Tosh-Labs/blockchain0x-app under packages/sdk-python/.

Public mirror: Tosh-Labs/blockchain0x-python (receives merges from this directory on each push to dev).

Distribution: pypi via Trusted Publisher OIDC.

License

Apache-2.0.

Packages

 
 
 

Contributors

Languages