# x402-stacks

Python SDK for the [x402 payment protocol](https://www.x402.org/) on Stacks blockchain.

Turn any API into a pay-per-use service using HTTP 402. Clients pay automatically, servers gate endpoints with middleware — no Stripe, no subscriptions, just crypto micropayments.

## Installation

```bash
pip install x402-stacks
```

With optional HTTP framework support:

```bash
pip install x402-stacks[httpx]      # httpx client
pip install x402-stacks[requests]   # requests client
pip install x402-stacks[fastapi]    # FastAPI/Starlette middleware
pip install x402-stacks[flask]      # Flask middleware
pip install x402-stacks[all]        # everything
```

## Quick Start: Client (Pays Automatically)

```python
from x402_stacks import private_key_to_account
from x402_stacks.http.client_httpx import create_payment_client_sync

account = private_key_to_account("your-private-key-hex", "testnet")

with create_payment_client_sync(account, timeout=60) as client:
    response = client.get("https://api.example.com/premium-data")
    print(response.json())  # Payment happens automatically on 402
```

## Quick Start: Server (Requires Payment)

### FastAPI

```python
from fastapi import FastAPI, Request
from x402_stacks.http.middleware_fastapi import (
    PaymentMiddleware, PaymentMiddlewareConfig, get_payment,
)

app = FastAPI()

config = PaymentMiddlewareConfig(
    network="testnet",
    amount="1000",  # 0.001 STX in microSTX
    pay_to="ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM",
    description="Premium weather data",
    facilitator_url="https://facilitator.stacksx402.com",
)

app.add_middleware(PaymentMiddleware, config=config)

@app.get("/weather")
async def weather(request: Request):
    payment = get_payment(request)
    return {"temperature": 72, "conditions": "sunny"}
```

### Flask

```python
from flask import Flask, jsonify
from x402_stacks.http.middleware_flask import (
    PaymentMiddlewareConfig, payment_middleware, get_payment,
)

app = Flask(__name__)

config = PaymentMiddlewareConfig(
    network="testnet",
    amount="1000",
    pay_to="ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM",
    facilitator_url="https://facilitator.stacksx402.com",
)

app.before_request(payment_middleware(config))

@app.route("/weather")
def weather():
    payment = get_payment()
    return jsonify({"temperature": 72, "conditions": "sunny"})
```

## How It Works

```
1. Client  →  GET /api/data           →  Server
2. Server  →  402 + payment-required   →  Client
3. Client signs STX transaction (not broadcast)
4. Client  →  GET + payment-signature  →  Server
5. Server  →  Facilitator settles tx   →  Blockchain
6. Server  →  200 + data               →  Client
```

The client never broadcasts directly — a facilitator service handles settlement.

## Wallet Setup

### Load Existing Wallet

```python
from x402_stacks import private_key_to_account

account = private_key_to_account("your-private-key-hex", "testnet")
print(account.address)  # ST...
```

### Generate New Wallet

```python
from x402_stacks import generate_keypair

keypair = generate_keypair("testnet")
print(keypair["private_key"])  # Save this to .env
print(keypair["address"])      # Fund via testnet faucet
```

Fund testnet wallets at: https://explorer.stacks.co/sandbox/faucet?chain=testnet

## Supported Tokens

| Token | Type | Usage |
|-------|------|-------|
| **STX** | Native | Default, no extra config |
| **sBTC** | SIP-010 | Set `asset` to contract address |
| **USDCx** | SIP-010 | Set `asset` to contract address |

## API Reference

### Client Functions

| Function | Purpose |
|----------|---------|
| `private_key_to_account(key, network)` | Create account from private key |
| `generate_keypair(network)` | Generate new wallet |
| `create_payment_client_sync(account)` | httpx client with auto-pay |
| `create_payment_client(account)` | Async httpx client with auto-pay |
| `create_payment_session(account)` | requests session with auto-pay |

### Server Middleware

| Class/Function | Framework |
|----------------|-----------|
| `PaymentMiddleware` | FastAPI/Starlette |
| `payment_middleware(config)` | Flask |
| `payment_required(config)` | FastAPI dependency injection |

### Utilities

| Function | Purpose |
|----------|---------|
| `stx_to_micro_stx(amount)` | Convert STX to microSTX |
| `micro_stx_to_stx(amount)` | Convert microSTX to STX |
| `is_valid_stacks_address(addr)` | Validate address format |
| `network_to_caip2(network)` | Convert to CAIP-2 format |

## Environment Variables

```bash
# Client
PRIVATE_KEY=your-private-key-hex

# Server
SERVER_PAY_TO=ST1...
FACILITATOR_URL=https://facilitator.stacksx402.com
NETWORK=testnet
```

## Requirements

- Python >= 3.10
- Core: `pydantic`, `coincurve`
- HTTP clients/middleware are optional extras

## License

MIT
