Metadata-Version: 2.4
Name: subetha
Version: 0.2.0
Summary: Pay for x402 (HTTP 402) APIs privately over SubEtha's zERC20 rail — Python payer client
Project-URL: Homepage, https://github.com/peaceandwhisky/SubEtha
Project-URL: Repository, https://github.com/peaceandwhisky/SubEtha
Project-URL: Issues, https://github.com/peaceandwhisky/SubEtha/issues
Project-URL: Changelog, https://github.com/peaceandwhisky/SubEtha/blob/main/python/CHANGELOG.md
Project-URL: Documentation, https://github.com/peaceandwhisky/SubEtha/blob/main/docs/PROTOCOL.md
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: ai-agents,http-402,payments,privacy,x402,zerc20
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Security :: Cryptography
Requires-Python: >=3.11
Requires-Dist: eth-account>=0.13
Requires-Dist: eth-utils>=5
Requires-Dist: httpx>=0.27
Description-Content-Type: text/markdown

# subetha (Python) — private x402 payments for Python agents

Pay for x402 (HTTP 402) paywalled APIs over SubEtha's zERC20 rail so that **no on-chain
trail links the payer to the payee**: the burn itself is public (amounts stay
transparent), but nothing on-chain connects it to the provider's treasury. This is the
Python counterpart of the TypeScript agent tools
([docs/AGENT-TOOLS.md](https://github.com/peaceandwhisky/SubEtha/blob/main/docs/AGENT-TOOLS.md)):
the same wire protocol
([docs/PROTOCOL.md](https://github.com/peaceandwhisky/SubEtha/blob/main/docs/PROTOCOL.md) —
this package is a reference implementation written against that spec), the same
spending-policy semantics.

## Status

**Experimental (0.x).** The API may change in breaking ways between 0.x minor
releases while integrations (agent frameworks, plugins) shape it. If you depend on
this package, **pin a minor**: `subetha>=0.1,<0.2`. Stability will be declared at
1.0. Changes are recorded in
[CHANGELOG.md](https://github.com/peaceandwhisky/SubEtha/blob/main/python/CHANGELOG.md).

## Scope

This package is the **payer side only**: decode a 402 offer, decide under an
operator-configured spending policy, sign, pay, report. That is a deliberate,
stable boundary — it is also what the API-stability promise will cover at 1.0.

The provider, facilitator, and settlement layers are TypeScript and live in the
[same repository](https://github.com/peaceandwhisky/SubEtha); there is no plan to
port them. Paying touches no zk code and no BUSL code: this package depends only on
`httpx` and `eth-account`.

## Install

```bash
pip install subetha
```

For development (from a repository checkout):

```bash
uv pip install -e python/          # from the repository root
# or: pip install -e python/
```

Dependencies: `httpx`, `eth-account` (no web3.py). Python ≥ 3.11.

## Use

```python
from subetha import SubethaClient, SpendingPolicy

client = SubethaClient(
    private_key="0x…",                    # the paying account (permit: only signs, no gas)
    rpc_url="http://127.0.0.1:8545",
    mode="permit",                         # gasless (default); or "self-transfer"
    policy=SpendingPolicy(
        allowed_hosts=["127.0.0.1"],       # first line of defense — keep it tight
        max_per_payment=100_000,           # token base units
        max_total=5_000_000,
    ),
    approve_above=10_000,                                  # optional human-in-the-loop
    approve_payment=lambda info: ask_human(info),          # True = approve
)

q = client.quote("http://127.0.0.1:4031/api/complete", method="POST", body='{"prompt":"hi"}')
print(q.offer.quoted, q.offer.fee, q.offer.approval_required)

r = client.pay("http://127.0.0.1:4031/api/complete", method="POST", body='{"prompt":"hi"}')
print(r.status, r.payment.amount, r.resource)

print(client.report())                     # totals / payments / attempts (incl. approvals)
```

`SubethaClient.from_env()` reads the same `SUBETHA_*` variables as the TypeScript tools
(`SUBETHA_PAYER_PK`, `SUBETHA_RPC_URL`, `SUBETHA_MODE`, `SUBETHA_ALLOWED_HOSTS`,
`SUBETHA_ALLOWED_NETWORK`, `SUBETHA_ALLOWED_TOKEN`, `SUBETHA_MAX_PER_PAYMENT`,
`SUBETHA_MAX_TOTAL`, `SUBETHA_APPROVE_ABOVE`, `SUBETHA_APPROVAL_TIMEOUT_MS`,
`SUBETHA_TIMEOUT_MS`).

### Semantics you can rely on

- **Policy before money**: host allowlist before any request; per-payment / total caps
  and network/token pins at offer selection. Refusals raise `SubethaError` with the
  reason; nothing is paid.
- **Approval**: payments quoted above `approve_above` call `approve_payment` (bounded by
  `approval_timeout_s`, default 120 s). Decline / timeout / a raising callback / no
  callback ⇒ refused. The approval is bound to the exact offer.
- **Accounting at the point of no return**: a self-transfer burn is counted the moment it
  lands; a permit reservation is released only when settle is definitively rejected.
- **One payment at a time**; errors are redacted (the key never appears in messages).
- `mode="permit"` fail-fasts when the offer lacks the gasless path — it never silently
  degrades to a gas-paying transfer.

## Key management & safety

This client signs with a raw private key. Treat that as the threat model:

- **At runtime the key exists decrypted in process memory.** Encrypted config or
  secret stores protect the key *at rest* — anything that can read your agent
  process (or its crash dumps) can read the key. Plan accordingly.
- **Use a dedicated hot wallet.** Fund the paying account with small amounts, top it
  up as needed, and keep it separate from any treasury or personal wallet. If it
  leaks, the loss is bounded by the balance and your `max_total`.
- **The spending policy is the operator's, not the agent's.** Allowlist, caps, and
  `approve_above` are configuration the human sets; agents cannot raise their own
  limits. Keep `allowed_hosts` as tight as your deployment allows.
- **Redaction is scoped.** This package keeps the key out of its own errors and
  reports; whatever *you* log around it (request dumps, env printouts) is your
  responsibility.
- Report vulnerabilities privately via
  [GitHub Security Advisories](https://github.com/peaceandwhisky/SubEtha/security/advisories)
  (see [SECURITY.md](https://github.com/peaceandwhisky/SubEtha/blob/main/SECURITY.md)).

## LangChain (Python) example

No extra dependency in this package — wrap the client yourself:

```python
from langchain_core.tools import tool
from subetha import SubethaClient, SubethaError

client = SubethaClient.from_env()

@tool
def subetha_x402_pay(url: str, method: str = "GET", body: str | None = None) -> str:
    """Pay for an x402 resource privately under the configured spending policy."""
    try:
        r = client.pay(url, method=method, body=body)
        return f"HTTP {r.status}; paid {r.payment.amount if r.payment else 0}; {r.resource[:2000]}"
    except SubethaError as e:
        return f"ERROR: {e}"   # let the agent read the refusal instead of crashing
```

## Tests

```bash
uv run --project python pytest python/tests -q          # unit (no chain needed)
# cross-language live e2e (real stack + the TypeScript provider/facilitator):
PERMIT_BURNER_ADDRESS=0x… pnpm --filter @subetha/demo-official exec tsx ../../python/scripts/live-e2e.ts
```

## License

Apache-2.0 (this package). Note that operating a SubEtha facilitator commercially / in
production requires a separate use grant from the zERC20 team — see the License section
of the [repository README](https://github.com/peaceandwhisky/SubEtha#license).
