xClaw02 - x402 payments SDK for OpenClaw agents. Pay and charge for APIs with stablecoins.
Project description
xClaw02
Python SDK for x402 HTTP payments by Primer. Built for OpenClaw 🦞
Easily add pay-per-request monetization to your Python APIs using the x402 protocol. Accept stablecoin payments (USDC, EURC) or any ERC-20 token with gasless transactions—payers never pay gas fees.
Quick Start (CLI)
# Create a new wallet
xclaw02 wallet create
# Check balance
xclaw02 wallet balance 0xYourAddress
# Probe a URL for x402 support
xclaw02 probe https://api.example.com/paid
# Set up for OpenClaw
xclaw02 openclaw init
Why x402?
- HTTP-native payments - Uses the standard HTTP 402 Payment Required status code
- Gasless for payers - Payments are authorized via EIP-712 signatures; facilitators handle gas
- Stablecoin support - Native support for USDC/EURC via EIP-3009
transferWithAuthorization - Any ERC-20 token - Support for other tokens via Primer's Prism settlement contract
- Multi-chain - Base, Ethereum, Arbitrum, Optimism, Polygon (mainnet + testnet)
- Framework integrations - Flask, FastAPI middleware included
- Testing utilities - Mock facilitator for integration testing
Installation
pip install xclaw02
With optional dependencies:
pip install xclaw02[flask] # Flask middleware
pip install xclaw02[fastapi] # FastAPI middleware
pip install xclaw02[httpx] # Async HTTP client
pip install xclaw02[all] # All optional dependencies
Quick Start
Payer (Client)
Wrap your HTTP client to automatically handle 402 responses:
import os
from xclaw02 import create_signer, x402_requests
# Create a signer with your wallet
signer = create_signer('eip155:8453', os.environ['PRIVATE_KEY'])
# Create a session that handles 402 payments automatically
with x402_requests(signer, max_amount='1.00') as session:
response = session.get('https://api.example.com/paid-endpoint')
print(response.json())
When the server returns 402 Payment Required, the SDK automatically:
- Parses the payment requirements from the response
- Creates a signed payment authorization (no gas required)
- Retries the request with the payment header
- Returns the successful response
Payee (Server)
Add payment requirements to your API routes:
from flask import Flask, jsonify
from xclaw02 import x402_flask
app = Flask(__name__)
@app.before_request
@x402_flask('0xYourWalletAddress', {
'/api/premium': {
'amount': '0.01', # $0.01 USDC
'asset': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', # USDC on Base
'network': 'eip155:8453' # Base mainnet
}
})
def require_payment():
pass
@app.route('/api/premium')
def premium_content():
return jsonify({'data': 'premium content'})
Token Types
EIP-3009 Tokens (USDC, EURC)
These tokens support gasless transfers natively via transferWithAuthorization. The payer signs an authorization, and the facilitator executes the transfer—payer pays zero gas.
Standard ERC-20 Tokens
For other ERC-20 tokens, Primer's Prism contract enables gasless payments:
- One-time approval - Approve the Prism contract to spend your tokens
- Gasless payments - Sign authorizations; Prism handles the transfers
from xclaw02 import create_signer, approve_token
signer = create_signer('eip155:8453', os.environ['PRIVATE_KEY'])
# One-time approval (this transaction requires gas)
receipt = approve_token(signer, '0xTokenAddress')
# Now you can make gasless payments with this token
Supported Networks
Networks use CAIP-2 identifiers.
| Network | CAIP-2 ID | Default Facilitator |
|---|---|---|
| Base | eip155:8453 |
Primer |
| Base Sepolia | eip155:84532 |
Primer |
| Ethereum | eip155:1 |
Custom required |
| Arbitrum | eip155:42161 |
Custom required |
| Optimism | eip155:10 |
Custom required |
| Polygon | eip155:137 |
Custom required |
Legacy network names (
'base','ethereum') are accepted for compatibility but CAIP-2 is recommended.
Custom Facilitator
For non-Base networks, provide your own facilitator:
# Payer
session = x402_requests(signer, max_amount='1.00', facilitator='https://your-facilitator.com')
# Payee
@x402_flask('0xAddress', routes, facilitator='https://your-facilitator.com')
FastAPI Example
from fastapi import FastAPI
from xclaw02 import x402_fastapi
app = FastAPI()
app.add_middleware(x402_fastapi(
'0xYourWalletAddress',
{
'/api/premium': {
'amount': '0.01',
'asset': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
'network': 'eip155:8453'
}
}
))
@app.get('/api/premium')
async def premium():
return {'data': 'premium content'}
Testing
The SDK includes utilities for testing your integration without real payments:
import pytest
from xclaw02.testing import create_mock_facilitator, create_test_payment
@pytest.fixture
def mock_facilitator():
mock = create_mock_facilitator(mode='approve')
yield mock
mock.close()
def test_paid_endpoint(client, mock_facilitator):
payment = create_test_payment(amount='10000') # 0.01 USDC
response = client.get(
'/api/premium',
headers={'X-PAYMENT': payment}
)
assert response.status_code == 200
Debug Logging
import logging
logging.getLogger('xclaw02').setLevel(logging.DEBUG)
CLI Reference
xclaw02 <command> [options]
| Command | Description |
|---|---|
wallet create |
Create a new wallet |
wallet balance <address> |
Check USDC/ETH balance |
wallet from-mnemonic |
Restore wallet from mnemonic |
probe <url> |
Check if URL supports x402 |
pay <url> |
Make a payment to a 402 endpoint |
pay <url> --dry-run |
Preview payment without paying |
networks |
List supported networks |
facilitator |
Show facilitator info |
openclaw init |
Set up x402 for OpenClaw |
openclaw status |
Check OpenClaw status |
Environment Variables
| Variable | Description |
|---|---|
XCLAW02_PRIVATE_KEY |
Wallet private key |
XCLAW02_NETWORK |
Default network (default: base) |
XCLAW02_MAX_AMOUNT |
Default max payment amount |
XCLAW02_FACILITATOR |
Facilitator URL override |
Examples
# Create wallet and save output
xclaw02 wallet create --json > wallet.json
# Check balance on Arbitrum
xclaw02 wallet balance 0x... --network arbitrum
# Preview payment (dry run)
xclaw02 pay https://api.example.com/data --dry-run
# Pay for an API
XCLAW02_PRIVATE_KEY=0x... xclaw02 pay https://api.example.com/data --max-amount 0.10
Wallet Utilities
from xclaw02 import create_wallet, get_balance, x402_probe
# Create wallet
wallet = create_wallet()
print(wallet.address, wallet.private_key, wallet.mnemonic)
# Check balance
balance = get_balance('0x...', 'base', 'USDC')
print(f"{balance.balance} {balance.token}")
# Probe URL
probe = x402_probe('https://api.example.com/paid')
if probe.supports_402:
print(probe.requirements)
Error Handling
from xclaw02 import X402Error, ErrorCodes
try:
response = session.get(url)
except X402Error as e:
if e.code == ErrorCodes.INSUFFICIENT_FUNDS:
print(f"Need more funds: {e.details}")
OpenClaw Integration
pip install xclaw02
xclaw02 openclaw init
Or install skill from ClawHub: clawhub install xclaw02
Changelog
v0.1.0
- Initial release
- CLI for wallet management, probing, and payments
- Flask and FastAPI middleware
- Testing utilities with mock facilitator
- OpenClaw skill integration
Links
License
MIT - Primer Systems
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xclaw02-0.1.0.tar.gz.
File metadata
- Download URL: xclaw02-0.1.0.tar.gz
- Upload date:
- Size: 47.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8215eff36037a3a0b7a48a8c802a83bd8a22baac823a3d0f0a4dd5b52ab60453
|
|
| MD5 |
783f930366ab5cc6e60a23e34da2b601
|
|
| BLAKE2b-256 |
7627c4fdfe481446de5b55dcfead2ce1511dc9de004a477142a35026e8efbef5
|
File details
Details for the file xclaw02-0.1.0-py3-none-any.whl.
File metadata
- Download URL: xclaw02-0.1.0-py3-none-any.whl
- Upload date:
- Size: 38.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7796dc9c0c4a4f5478720078c76c4ed6715adfee0d23cc238d4d8193201ae543
|
|
| MD5 |
8ec4f7fb324fe0652eb0f4f4a3218878
|
|
| BLAKE2b-256 |
9fc7d3e95cbab8d3b3eb9d533e142289e829458a4e15ede402cfc478fe54632d
|