Skip to main content

Official Python port of the @blockchain0x/x402 wire primitives + client + server adapters

Project description

blockchain0x-x402 (Python)

License: Apache-2.0 Python ≥ 3.9

Official Python port of @blockchain0x/x402. Ships the wire primitives + a 402-aware fetch wrapper. Sibling package to blockchain0x; install only when your service either issues x402-aware HTTP calls (a payer) or verifies inbound x402 payments (a recipient).

Pre-release: 0.0.1a0 ships the wire primitives + the X402Client 402-aware fetch wrapper + ASGI middleware (Starlette / FastAPI / Quart) + a Flask before_request hook.

Why a separate package

x402 is a separable concern from the rest of the Blockchain0x SDK:

  • A consumer who only verifies inbound webhooks does not need the x402 client stack.
  • A service that exposes paid HTTP routes does not need the webhook verifier bundled with it.

Keeping them as two pip-installable packages lets each downstream service depend only on what it actually uses.

Install

pip install blockchain0x-x402

For the payer path (X402Client) you also need the main SDK:

pip install blockchain0x blockchain0x-x402

For the recipient/verifier path you only need blockchain0x-x402.

Verify an inbound x402 payment (recipient)

from blockchain0x_x402 import parse_payment_header, X402WireError

def verify(request):
    raw = request.headers.get("X-Payment")
    try:
        payment = parse_payment_header(raw)
    except X402WireError as e:
        return JSONResponse({"code": e.code}, status_code=400)
    # payment.payment_request_id, payment.tx_hash, payment.network
    # ...

The verifier:

  • Accepts only exact-usdc:<base64> scheme; anything else rejects with header.unknown_scheme.
  • Validates txHash, payerAddress, amountUsdc, and network shape; any drift rejects with header.payload_malformed.
  • Lowercases hex fields so downstream comparisons against on-chain transaction logs are deterministic.

Issue x402-aware HTTP calls (payer)

import os
from blockchain0x import Client
from blockchain0x_x402 import X402Client

sdk = Client(api_key=os.environ["BLOCKCHAIN0X_API_KEY"])
x402 = X402Client(sdk=sdk, agent_id="agt_...")
response = x402.fetch("https://service-b.com/llm-query", method="POST")
response.raise_for_status()

The wrapper handles a 402 response transparently:

  1. Parses the 402 body and picks the requirement matching the SDK's network.
  2. Calls sdk.payments.create(...) to settle on-chain. The SDK auto-attaches an Idempotency-Key so a flaky retry does not double-spend.
  3. Polls sdk.transactions.get(payment_id) every 1s for up to 30s until the transaction confirms.
  4. Rebuilds the request with the X-Payment header and re-issues it once. The second 200 response is returned to the caller.

Failures surface as X402ClientError with stable codes:

  • no_matching_requirement - the 402 had no accepts entry for the SDK's network mode.
  • settlement_timeout - the on-chain payment did not confirm within the poll window.
  • chain_failed - the payment row flipped to failed status before confirming.

Expose a paid HTTP route (recipient, server-side)

Two ready-made adapters wrap the verifier into a framework-level gate so paid routes do not have to repeat the parse + settle dance themselves.

Starlette / FastAPI / any ASGI app

from starlette.applications import Starlette
from blockchain0x import Client
from blockchain0x_x402.server import X402Middleware, PricingEntry

sdk = Client(api_key=os.environ["BLOCKCHAIN0X_API_KEY"])

app = Starlette(routes=[...])
app.add_middleware(
    X402Middleware,
    sdk=sdk,
    pricing={
        "POST /llm-query": PricingEntry(
            amount_usdc="0.10",
            pay_to_address="0xabc...",
            payment_request_id="pr_demo",
        ),
    },
)

A miss in the pricing table is a no-op (the route is free). A hit with no valid X-Payment short-circuits the response with HTTP 402 and the canonical accepts[] body the payer needs. A hit with a valid payment attaches the parsed payload to scope["x402_payment"] for downstream handlers and lets the request proceed.

Flask

from flask import Flask, g
from blockchain0x import Client
from blockchain0x_x402.server import x402_before_request_factory, PricingEntry

app = Flask(__name__)
app.before_request(x402_before_request_factory(
    sdk=Client(api_key=os.environ["BLOCKCHAIN0X_API_KEY"]),
    pricing={
        "POST /llm-query": PricingEntry(
            amount_usdc="0.10",
            pay_to_address="0xabc...",
            payment_request_id="pr_demo",
        ),
    },
))

@app.post("/llm-query")
def handler():
    # g.x402_payment is the verified ExactUsdcPayment payload.
    ...

Both adapters call sdk.payment_requests.settle() once per request to anchor trust; the backend's settle route is the chain-of-custody boundary. The settle() impl may be sync OR async - the adapter awaits whichever shape it returns.

Wire-format cross-compatibility

The Python build_payment_header output is byte-for-byte identical to the Node SDK's. A Python payer can pay a Node server, a Node payer can pay a Python server - the canonical JSON shape is:

{
  "scheme": "exact-usdc",
  "version": 1,
  "paymentRequestId": "...",
  "txHash": "...",
  "payerAddress": "...",
  "amountUsdc": "...",
  "network": "..."
}

Keys are insertion-ordered; no whitespace between separators. The hex fields (txHash, payerAddress) are lowercased before encoding.

License

Apache-2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

blockchain0x_x402-0.0.1a1.tar.gz (26.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

blockchain0x_x402-0.0.1a1-py3-none-any.whl (25.1 kB view details)

Uploaded Python 3

File details

Details for the file blockchain0x_x402-0.0.1a1.tar.gz.

File metadata

  • Download URL: blockchain0x_x402-0.0.1a1.tar.gz
  • Upload date:
  • Size: 26.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for blockchain0x_x402-0.0.1a1.tar.gz
Algorithm Hash digest
SHA256 dfe26e6b85b02366c875dabfb24bbb5df5d507fc091800fd6364baddeeaf8897
MD5 eb8697d06510a195eb605b858f8f4fd6
BLAKE2b-256 c394984bb6a114c7966d399e5d72660112c1a8cc221c609f7c03e8c29f550ade

See more details on using hashes here.

Provenance

The following attestation bundles were made for blockchain0x_x402-0.0.1a1.tar.gz:

Publisher: publish.yml on tosh-labs/blockchain0x-x402-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file blockchain0x_x402-0.0.1a1-py3-none-any.whl.

File metadata

File hashes

Hashes for blockchain0x_x402-0.0.1a1-py3-none-any.whl
Algorithm Hash digest
SHA256 8cfb899824c2a902e12832b7d7ad11d1ebbac127319fc4aa4725188e92c806ef
MD5 fe3a5428bd4beed3f047c7d229ea0faa
BLAKE2b-256 0f939fa58bc9d8f628ba53ea1e2f9c8c3900164f68904b5420714868f47bc6ea

See more details on using hashes here.

Provenance

The following attestation bundles were made for blockchain0x_x402-0.0.1a1-py3-none-any.whl:

Publisher: publish.yml on tosh-labs/blockchain0x-x402-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page