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.
@@ -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
+ [![PyPI version](https://img.shields.io/pypi/v/x402-python.svg)](https://pypi.org/project/x402-python/)
52
+ [![Python](https://img.shields.io/pypi/pyversions/x402-python.svg)](https://pypi.org/project/x402-python/)
53
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
+ [![PyPI version](https://img.shields.io/pypi/v/x402-python.svg)](https://pypi.org/project/x402-python/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/x402-python.svg)](https://pypi.org/project/x402-python/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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