primer-x402 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- primer_x402-0.4.0/PKG-INFO +287 -0
- primer_x402-0.4.0/README.md +239 -0
- primer_x402-0.4.0/primer_x402.egg-info/PKG-INFO +287 -0
- primer_x402-0.4.0/primer_x402.egg-info/SOURCES.txt +21 -0
- primer_x402-0.4.0/primer_x402.egg-info/dependency_links.txt +1 -0
- primer_x402-0.4.0/primer_x402.egg-info/requires.txt +27 -0
- primer_x402-0.4.0/primer_x402.egg-info/top_level.txt +1 -0
- primer_x402-0.4.0/pyproject.toml +96 -0
- primer_x402-0.4.0/setup.cfg +4 -0
- primer_x402-0.4.0/tests/test_payee.py +603 -0
- primer_x402-0.4.0/tests/test_payer.py +674 -0
- primer_x402-0.4.0/tests/test_signer.py +168 -0
- primer_x402-0.4.0/tests/test_testing.py +270 -0
- primer_x402-0.4.0/tests/test_utils.py +328 -0
- primer_x402-0.4.0/x402_python/__init__.py +51 -0
- primer_x402-0.4.0/x402_python/payee.py +750 -0
- primer_x402-0.4.0/x402_python/payer.py +969 -0
- primer_x402-0.4.0/x402_python/signer.py +190 -0
- primer_x402-0.4.0/x402_python/testing/__init__.py +39 -0
- primer_x402-0.4.0/x402_python/testing/fixtures.py +94 -0
- primer_x402-0.4.0/x402_python/testing/mock_facilitator.py +196 -0
- primer_x402-0.4.0/x402_python/testing/test_payment.py +121 -0
- primer_x402-0.4.0/x402_python/utils.py +574 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: primer-x402
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Python SDK for x402 payments - pay and charge for APIs with stablecoins
|
|
5
|
+
Author-email: Primer Systems <support@primer.systems>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://x402.org
|
|
8
|
+
Project-URL: Documentation, https://x402.org/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/Primer-Systems/x402
|
|
10
|
+
Project-URL: Issues, https://github.com/Primer-Systems/x402/issues
|
|
11
|
+
Keywords: x402,payments,crypto,usdc,stablecoin,ethereum,base,eip-3009,web3,ai-payments,micropayments,http-402,ai-agents
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
23
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
Requires-Dist: web3>=6.0.0
|
|
27
|
+
Requires-Dist: eth-account>=0.11.0
|
|
28
|
+
Requires-Dist: requests>=2.28.0
|
|
29
|
+
Provides-Extra: httpx
|
|
30
|
+
Requires-Dist: httpx>=0.24.0; extra == "httpx"
|
|
31
|
+
Provides-Extra: flask
|
|
32
|
+
Requires-Dist: flask>=2.0.0; extra == "flask"
|
|
33
|
+
Provides-Extra: fastapi
|
|
34
|
+
Requires-Dist: fastapi>=0.100.0; extra == "fastapi"
|
|
35
|
+
Requires-Dist: starlette>=0.27.0; extra == "fastapi"
|
|
36
|
+
Provides-Extra: all
|
|
37
|
+
Requires-Dist: httpx>=0.24.0; extra == "all"
|
|
38
|
+
Requires-Dist: flask>=2.0.0; extra == "all"
|
|
39
|
+
Requires-Dist: fastapi>=0.100.0; extra == "all"
|
|
40
|
+
Requires-Dist: starlette>=0.27.0; extra == "all"
|
|
41
|
+
Provides-Extra: dev
|
|
42
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
43
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
44
|
+
Requires-Dist: httpx>=0.24.0; extra == "dev"
|
|
45
|
+
Requires-Dist: flask>=2.0.0; extra == "dev"
|
|
46
|
+
Requires-Dist: fastapi>=0.100.0; extra == "dev"
|
|
47
|
+
Requires-Dist: starlette>=0.27.0; extra == "dev"
|
|
48
|
+
|
|
49
|
+
# x402-python
|
|
50
|
+
|
|
51
|
+
[](https://pypi.org/project/x402-python/)
|
|
52
|
+
[](https://pypi.org/project/x402-python/)
|
|
53
|
+
[](https://opensource.org/licenses/MIT)
|
|
54
|
+
|
|
55
|
+
Python SDK for x402 HTTP payments.
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
- **Multi-chain** - Base, Ethereum, Arbitrum, Optimism, Polygon
|
|
60
|
+
- **Gasless payments** - EIP-712 signatures, payers never pay gas
|
|
61
|
+
- **Any ERC-20 token** - USDC, EURC, or any token via Prism contract
|
|
62
|
+
- **Framework support** - Flask, FastAPI middleware
|
|
63
|
+
- **Built-in limits** - Automatic spend caps per request
|
|
64
|
+
- **Testing utilities** - Mock facilitator for integration tests
|
|
65
|
+
|
|
66
|
+
## Installation
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install x402-python
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
With optional dependencies:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install x402-python[flask] # Flask middleware
|
|
76
|
+
pip install x402-python[fastapi] # FastAPI middleware
|
|
77
|
+
pip install x402-python[httpx] # Async HTTP client
|
|
78
|
+
pip install x402-python[all] # All optional dependencies
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Payer (Client)
|
|
82
|
+
|
|
83
|
+
Wrap requests to automatically handle 402 responses:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
import os
|
|
87
|
+
from x402_python import create_signer, x402_requests
|
|
88
|
+
|
|
89
|
+
# Create a signer (use CAIP-2 network format)
|
|
90
|
+
signer = create_signer('eip155:8453', os.environ['PRIVATE_KEY'])
|
|
91
|
+
|
|
92
|
+
# Create a session that handles 402 payments
|
|
93
|
+
with x402_requests(signer, max_amount='1.00') as session:
|
|
94
|
+
response = session.get('https://example.com/api/paywall')
|
|
95
|
+
print(response.json())
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Options
|
|
99
|
+
|
|
100
|
+
| Option | Required | Description |
|
|
101
|
+
|--------|----------|-------------|
|
|
102
|
+
| `max_amount` | Yes | Maximum payment per request (e.g., '1.00') |
|
|
103
|
+
| `facilitator` | No | Custom facilitator URL |
|
|
104
|
+
| `verify` | No | Verify payment before sending (default: True) |
|
|
105
|
+
|
|
106
|
+
## Payee (Server)
|
|
107
|
+
|
|
108
|
+
Middleware for Flask and FastAPI:
|
|
109
|
+
|
|
110
|
+
### Flask
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from flask import Flask, jsonify
|
|
114
|
+
from x402_python import x402_flask
|
|
115
|
+
|
|
116
|
+
app = Flask(__name__)
|
|
117
|
+
|
|
118
|
+
# Protect routes with payment requirements
|
|
119
|
+
@app.before_request
|
|
120
|
+
@x402_flask('0xYourAddress', {
|
|
121
|
+
'/api/premium': {
|
|
122
|
+
'amount': '0.01',
|
|
123
|
+
'asset': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
124
|
+
'network': 'eip155:8453' # CAIP-2 format
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
def check_payment():
|
|
128
|
+
pass
|
|
129
|
+
|
|
130
|
+
@app.route('/api/premium')
|
|
131
|
+
def premium():
|
|
132
|
+
return jsonify({'data': 'premium content'})
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### FastAPI
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from fastapi import FastAPI
|
|
139
|
+
from x402_python import x402_fastapi
|
|
140
|
+
|
|
141
|
+
app = FastAPI()
|
|
142
|
+
|
|
143
|
+
app.add_middleware(x402_fastapi(
|
|
144
|
+
'0xYourAddress',
|
|
145
|
+
{
|
|
146
|
+
'/api/premium': {
|
|
147
|
+
'amount': '0.01',
|
|
148
|
+
'asset': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
149
|
+
'network': 'eip155:8453' # CAIP-2 format
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
))
|
|
153
|
+
|
|
154
|
+
@app.get('/api/premium')
|
|
155
|
+
async def premium():
|
|
156
|
+
return {'data': 'premium content'}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Token Approval
|
|
160
|
+
|
|
161
|
+
For standard ERC-20 tokens (not USDC/EURC), approve the *Prism* contract first:
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from x402_python import create_signer, approve_token
|
|
165
|
+
|
|
166
|
+
signer = create_signer('eip155:8453', os.environ['PRIVATE_KEY'])
|
|
167
|
+
receipt = approve_token(signer, '0xTokenAddress')
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Networks
|
|
171
|
+
|
|
172
|
+
Networks use [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) identifiers (e.g., `eip155:8453` for Base).
|
|
173
|
+
|
|
174
|
+
| Network (CAIP-2) | Chain ID | Legacy Name | Default Facilitator |
|
|
175
|
+
|------------------|----------|-------------|---------------------|
|
|
176
|
+
| eip155:8453 | 8453 | base | Primer |
|
|
177
|
+
| eip155:84532 | 84532 | base-sepolia | Primer |
|
|
178
|
+
| eip155:1 | 1 | ethereum | Custom required |
|
|
179
|
+
| eip155:11155111 | 11155111 | sepolia | Custom required |
|
|
180
|
+
| eip155:42161 | 42161 | arbitrum | Custom required |
|
|
181
|
+
| eip155:421614 | 421614 | arbitrum-sepolia | Custom required |
|
|
182
|
+
| eip155:10 | 10 | optimism | Custom required |
|
|
183
|
+
| eip155:11155420 | 11155420 | optimism-sepolia | Custom required |
|
|
184
|
+
| eip155:137 | 137 | polygon | Custom required |
|
|
185
|
+
| eip155:80002 | 80002 | polygon-amoy | Custom required |
|
|
186
|
+
|
|
187
|
+
> **Note:** Legacy network names (e.g., `'base'`) are still accepted for backward compatibility but CAIP-2 format is recommended.
|
|
188
|
+
|
|
189
|
+
### Custom Facilitator
|
|
190
|
+
|
|
191
|
+
For non-Base networks, you must provide your own facilitator:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
# Payee
|
|
195
|
+
@x402_flask('0xYourAddress', routes, facilitator='https://your-facilitator.com')
|
|
196
|
+
|
|
197
|
+
# Payer
|
|
198
|
+
session = x402_requests(signer, max_amount='1.00', facilitator='https://your-facilitator.com')
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Testing Your Integration
|
|
202
|
+
|
|
203
|
+
The SDK provides testing utilities to help you test your x402 integration without making real payments:
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
from x402_python.testing import (
|
|
207
|
+
create_mock_facilitator,
|
|
208
|
+
create_test_payment,
|
|
209
|
+
create_test_402_response,
|
|
210
|
+
TEST_ADDRESSES,
|
|
211
|
+
USDC_ADDRESSES
|
|
212
|
+
)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Testing a Payee (Server)
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
import pytest
|
|
219
|
+
from your_app import app
|
|
220
|
+
from x402_python.testing import create_mock_facilitator, create_test_payment
|
|
221
|
+
|
|
222
|
+
@pytest.fixture
|
|
223
|
+
def mock_facilitator():
|
|
224
|
+
mock = create_mock_facilitator(port=3001)
|
|
225
|
+
yield mock
|
|
226
|
+
mock.close()
|
|
227
|
+
|
|
228
|
+
def test_returns_402_when_no_payment(client):
|
|
229
|
+
response = client.get('/api/premium')
|
|
230
|
+
assert response.status_code == 402
|
|
231
|
+
|
|
232
|
+
def test_returns_200_with_valid_payment(client, mock_facilitator):
|
|
233
|
+
payment = create_test_payment(amount='10000') # 0.01 USDC
|
|
234
|
+
|
|
235
|
+
response = client.get(
|
|
236
|
+
'/api/premium',
|
|
237
|
+
headers={'X-PAYMENT': payment}
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
assert response.status_code == 200
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Mock Facilitator Options
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
# Auto-approve all payments (default)
|
|
247
|
+
mock = create_mock_facilitator(mode='approve')
|
|
248
|
+
|
|
249
|
+
# Reject all payments
|
|
250
|
+
mock = create_mock_facilitator(mode='reject')
|
|
251
|
+
|
|
252
|
+
# Custom logic
|
|
253
|
+
def my_handler(payload):
|
|
254
|
+
amount = payload.get('paymentRequirements', {}).get('maxAmountRequired')
|
|
255
|
+
if int(amount) > 1000000:
|
|
256
|
+
return {'success': False, 'error': 'Amount too high'}
|
|
257
|
+
return {'success': True, 'transaction': '0x' + 'f' * 64}
|
|
258
|
+
|
|
259
|
+
mock = create_mock_facilitator(mode='custom', handler=my_handler)
|
|
260
|
+
|
|
261
|
+
# Add artificial latency
|
|
262
|
+
mock = create_mock_facilitator(latency_ms=5000)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Debug Logging
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
import logging
|
|
269
|
+
logging.getLogger('x402').setLevel(logging.DEBUG)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Changelog
|
|
273
|
+
|
|
274
|
+
### v0.4.0
|
|
275
|
+
- **x402 v2 protocol**: Full upgrade to x402 v2 specification with `x402Version: 2`
|
|
276
|
+
- **CAIP-2 network identifiers**: All networks now use CAIP-2 format (e.g., `'eip155:8453'` instead of `'base'`)
|
|
277
|
+
- **Multi-chain support**: Base, Ethereum, Arbitrum, Optimism, and Polygon (mainnets + testnets)
|
|
278
|
+
- **Network utilities**: New functions `to_caip_network()`, `from_caip_network()`, `chain_id_to_caip()`, `caip_to_chain_id()`
|
|
279
|
+
- **Facilitator validation**: SDK requires custom facilitator for non-Base networks
|
|
280
|
+
- **Legacy compatibility**: Legacy network names still accepted as input but CAIP-2 is used internally
|
|
281
|
+
- **Payer**: `create_signer`, `x402_requests`, `x402_httpx`
|
|
282
|
+
- **Payee**: `x402_flask`, `x402_fastapi`, `x402_protect` middleware
|
|
283
|
+
- **Testing utilities**: `create_mock_facilitator`, `create_test_payment`, fixtures (updated to v2 format)
|
|
284
|
+
|
|
285
|
+
## License
|
|
286
|
+
|
|
287
|
+
MIT
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# x402-python
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/x402-python/)
|
|
4
|
+
[](https://pypi.org/project/x402-python/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
Python SDK for x402 HTTP payments.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Multi-chain** - Base, Ethereum, Arbitrum, Optimism, Polygon
|
|
12
|
+
- **Gasless payments** - EIP-712 signatures, payers never pay gas
|
|
13
|
+
- **Any ERC-20 token** - USDC, EURC, or any token via Prism contract
|
|
14
|
+
- **Framework support** - Flask, FastAPI middleware
|
|
15
|
+
- **Built-in limits** - Automatic spend caps per request
|
|
16
|
+
- **Testing utilities** - Mock facilitator for integration tests
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install x402-python
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
With optional dependencies:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install x402-python[flask] # Flask middleware
|
|
28
|
+
pip install x402-python[fastapi] # FastAPI middleware
|
|
29
|
+
pip install x402-python[httpx] # Async HTTP client
|
|
30
|
+
pip install x402-python[all] # All optional dependencies
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Payer (Client)
|
|
34
|
+
|
|
35
|
+
Wrap requests to automatically handle 402 responses:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
import os
|
|
39
|
+
from x402_python import create_signer, x402_requests
|
|
40
|
+
|
|
41
|
+
# Create a signer (use CAIP-2 network format)
|
|
42
|
+
signer = create_signer('eip155:8453', os.environ['PRIVATE_KEY'])
|
|
43
|
+
|
|
44
|
+
# Create a session that handles 402 payments
|
|
45
|
+
with x402_requests(signer, max_amount='1.00') as session:
|
|
46
|
+
response = session.get('https://example.com/api/paywall')
|
|
47
|
+
print(response.json())
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Options
|
|
51
|
+
|
|
52
|
+
| Option | Required | Description |
|
|
53
|
+
|--------|----------|-------------|
|
|
54
|
+
| `max_amount` | Yes | Maximum payment per request (e.g., '1.00') |
|
|
55
|
+
| `facilitator` | No | Custom facilitator URL |
|
|
56
|
+
| `verify` | No | Verify payment before sending (default: True) |
|
|
57
|
+
|
|
58
|
+
## Payee (Server)
|
|
59
|
+
|
|
60
|
+
Middleware for Flask and FastAPI:
|
|
61
|
+
|
|
62
|
+
### Flask
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from flask import Flask, jsonify
|
|
66
|
+
from x402_python import x402_flask
|
|
67
|
+
|
|
68
|
+
app = Flask(__name__)
|
|
69
|
+
|
|
70
|
+
# Protect routes with payment requirements
|
|
71
|
+
@app.before_request
|
|
72
|
+
@x402_flask('0xYourAddress', {
|
|
73
|
+
'/api/premium': {
|
|
74
|
+
'amount': '0.01',
|
|
75
|
+
'asset': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
76
|
+
'network': 'eip155:8453' # CAIP-2 format
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
def check_payment():
|
|
80
|
+
pass
|
|
81
|
+
|
|
82
|
+
@app.route('/api/premium')
|
|
83
|
+
def premium():
|
|
84
|
+
return jsonify({'data': 'premium content'})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### FastAPI
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from fastapi import FastAPI
|
|
91
|
+
from x402_python import x402_fastapi
|
|
92
|
+
|
|
93
|
+
app = FastAPI()
|
|
94
|
+
|
|
95
|
+
app.add_middleware(x402_fastapi(
|
|
96
|
+
'0xYourAddress',
|
|
97
|
+
{
|
|
98
|
+
'/api/premium': {
|
|
99
|
+
'amount': '0.01',
|
|
100
|
+
'asset': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
101
|
+
'network': 'eip155:8453' # CAIP-2 format
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
))
|
|
105
|
+
|
|
106
|
+
@app.get('/api/premium')
|
|
107
|
+
async def premium():
|
|
108
|
+
return {'data': 'premium content'}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Token Approval
|
|
112
|
+
|
|
113
|
+
For standard ERC-20 tokens (not USDC/EURC), approve the *Prism* contract first:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from x402_python import create_signer, approve_token
|
|
117
|
+
|
|
118
|
+
signer = create_signer('eip155:8453', os.environ['PRIVATE_KEY'])
|
|
119
|
+
receipt = approve_token(signer, '0xTokenAddress')
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Networks
|
|
123
|
+
|
|
124
|
+
Networks use [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) identifiers (e.g., `eip155:8453` for Base).
|
|
125
|
+
|
|
126
|
+
| Network (CAIP-2) | Chain ID | Legacy Name | Default Facilitator |
|
|
127
|
+
|------------------|----------|-------------|---------------------|
|
|
128
|
+
| eip155:8453 | 8453 | base | Primer |
|
|
129
|
+
| eip155:84532 | 84532 | base-sepolia | Primer |
|
|
130
|
+
| eip155:1 | 1 | ethereum | Custom required |
|
|
131
|
+
| eip155:11155111 | 11155111 | sepolia | Custom required |
|
|
132
|
+
| eip155:42161 | 42161 | arbitrum | Custom required |
|
|
133
|
+
| eip155:421614 | 421614 | arbitrum-sepolia | Custom required |
|
|
134
|
+
| eip155:10 | 10 | optimism | Custom required |
|
|
135
|
+
| eip155:11155420 | 11155420 | optimism-sepolia | Custom required |
|
|
136
|
+
| eip155:137 | 137 | polygon | Custom required |
|
|
137
|
+
| eip155:80002 | 80002 | polygon-amoy | Custom required |
|
|
138
|
+
|
|
139
|
+
> **Note:** Legacy network names (e.g., `'base'`) are still accepted for backward compatibility but CAIP-2 format is recommended.
|
|
140
|
+
|
|
141
|
+
### Custom Facilitator
|
|
142
|
+
|
|
143
|
+
For non-Base networks, you must provide your own facilitator:
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
# Payee
|
|
147
|
+
@x402_flask('0xYourAddress', routes, facilitator='https://your-facilitator.com')
|
|
148
|
+
|
|
149
|
+
# Payer
|
|
150
|
+
session = x402_requests(signer, max_amount='1.00', facilitator='https://your-facilitator.com')
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Testing Your Integration
|
|
154
|
+
|
|
155
|
+
The SDK provides testing utilities to help you test your x402 integration without making real payments:
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from x402_python.testing import (
|
|
159
|
+
create_mock_facilitator,
|
|
160
|
+
create_test_payment,
|
|
161
|
+
create_test_402_response,
|
|
162
|
+
TEST_ADDRESSES,
|
|
163
|
+
USDC_ADDRESSES
|
|
164
|
+
)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Testing a Payee (Server)
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
import pytest
|
|
171
|
+
from your_app import app
|
|
172
|
+
from x402_python.testing import create_mock_facilitator, create_test_payment
|
|
173
|
+
|
|
174
|
+
@pytest.fixture
|
|
175
|
+
def mock_facilitator():
|
|
176
|
+
mock = create_mock_facilitator(port=3001)
|
|
177
|
+
yield mock
|
|
178
|
+
mock.close()
|
|
179
|
+
|
|
180
|
+
def test_returns_402_when_no_payment(client):
|
|
181
|
+
response = client.get('/api/premium')
|
|
182
|
+
assert response.status_code == 402
|
|
183
|
+
|
|
184
|
+
def test_returns_200_with_valid_payment(client, mock_facilitator):
|
|
185
|
+
payment = create_test_payment(amount='10000') # 0.01 USDC
|
|
186
|
+
|
|
187
|
+
response = client.get(
|
|
188
|
+
'/api/premium',
|
|
189
|
+
headers={'X-PAYMENT': payment}
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
assert response.status_code == 200
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Mock Facilitator Options
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
# Auto-approve all payments (default)
|
|
199
|
+
mock = create_mock_facilitator(mode='approve')
|
|
200
|
+
|
|
201
|
+
# Reject all payments
|
|
202
|
+
mock = create_mock_facilitator(mode='reject')
|
|
203
|
+
|
|
204
|
+
# Custom logic
|
|
205
|
+
def my_handler(payload):
|
|
206
|
+
amount = payload.get('paymentRequirements', {}).get('maxAmountRequired')
|
|
207
|
+
if int(amount) > 1000000:
|
|
208
|
+
return {'success': False, 'error': 'Amount too high'}
|
|
209
|
+
return {'success': True, 'transaction': '0x' + 'f' * 64}
|
|
210
|
+
|
|
211
|
+
mock = create_mock_facilitator(mode='custom', handler=my_handler)
|
|
212
|
+
|
|
213
|
+
# Add artificial latency
|
|
214
|
+
mock = create_mock_facilitator(latency_ms=5000)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Debug Logging
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
import logging
|
|
221
|
+
logging.getLogger('x402').setLevel(logging.DEBUG)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Changelog
|
|
225
|
+
|
|
226
|
+
### v0.4.0
|
|
227
|
+
- **x402 v2 protocol**: Full upgrade to x402 v2 specification with `x402Version: 2`
|
|
228
|
+
- **CAIP-2 network identifiers**: All networks now use CAIP-2 format (e.g., `'eip155:8453'` instead of `'base'`)
|
|
229
|
+
- **Multi-chain support**: Base, Ethereum, Arbitrum, Optimism, and Polygon (mainnets + testnets)
|
|
230
|
+
- **Network utilities**: New functions `to_caip_network()`, `from_caip_network()`, `chain_id_to_caip()`, `caip_to_chain_id()`
|
|
231
|
+
- **Facilitator validation**: SDK requires custom facilitator for non-Base networks
|
|
232
|
+
- **Legacy compatibility**: Legacy network names still accepted as input but CAIP-2 is used internally
|
|
233
|
+
- **Payer**: `create_signer`, `x402_requests`, `x402_httpx`
|
|
234
|
+
- **Payee**: `x402_flask`, `x402_fastapi`, `x402_protect` middleware
|
|
235
|
+
- **Testing utilities**: `create_mock_facilitator`, `create_test_payment`, fixtures (updated to v2 format)
|
|
236
|
+
|
|
237
|
+
## License
|
|
238
|
+
|
|
239
|
+
MIT
|