og-test-x402 0.0.5__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.
Files changed (40) hide show
  1. og_test_x402-0.0.5/.gitignore +9 -0
  2. og_test_x402-0.0.5/.python-version +1 -0
  3. og_test_x402-0.0.5/PKG-INFO +236 -0
  4. og_test_x402-0.0.5/README.md +217 -0
  5. og_test_x402-0.0.5/pyproject.toml +45 -0
  6. og_test_x402-0.0.5/src/x402/__init__.py +2 -0
  7. og_test_x402-0.0.5/src/x402/chains.py +62 -0
  8. og_test_x402-0.0.5/src/x402/clients/__init__.py +20 -0
  9. og_test_x402-0.0.5/src/x402/clients/base.py +199 -0
  10. og_test_x402-0.0.5/src/x402/clients/httpx.py +136 -0
  11. og_test_x402-0.0.5/src/x402/clients/requests.py +145 -0
  12. og_test_x402-0.0.5/src/x402/common.py +114 -0
  13. og_test_x402-0.0.5/src/x402/encoding.py +28 -0
  14. og_test_x402-0.0.5/src/x402/exact.py +130 -0
  15. og_test_x402-0.0.5/src/x402/facilitator.py +139 -0
  16. og_test_x402-0.0.5/src/x402/fastapi/__init__.py +0 -0
  17. og_test_x402-0.0.5/src/x402/fastapi/middleware.py +219 -0
  18. og_test_x402-0.0.5/src/x402/flask/__init__.py +0 -0
  19. og_test_x402-0.0.5/src/x402/flask/middleware.py +322 -0
  20. og_test_x402-0.0.5/src/x402/networks.py +10 -0
  21. og_test_x402-0.0.5/src/x402/path.py +43 -0
  22. og_test_x402-0.0.5/src/x402/paywall.py +119 -0
  23. og_test_x402-0.0.5/src/x402/py.typed +0 -0
  24. og_test_x402-0.0.5/src/x402/static/paywall.html +1355 -0
  25. og_test_x402-0.0.5/src/x402/template.py +1 -0
  26. og_test_x402-0.0.5/src/x402/types.py +287 -0
  27. og_test_x402-0.0.5/tests/clients/__init__.py +0 -0
  28. og_test_x402-0.0.5/tests/clients/test_base.py +194 -0
  29. og_test_x402-0.0.5/tests/clients/test_httpx.py +239 -0
  30. og_test_x402-0.0.5/tests/clients/test_requests.py +310 -0
  31. og_test_x402-0.0.5/tests/fastapi_tests/__init__.py +0 -0
  32. og_test_x402-0.0.5/tests/fastapi_tests/test_middleware.py +531 -0
  33. og_test_x402-0.0.5/tests/flask_tests/__init__.py +0 -0
  34. og_test_x402-0.0.5/tests/flask_tests/test_middleware.py +360 -0
  35. og_test_x402-0.0.5/tests/test_common.py +175 -0
  36. og_test_x402-0.0.5/tests/test_encoding.py +81 -0
  37. og_test_x402-0.0.5/tests/test_exact.py +198 -0
  38. og_test_x402-0.0.5/tests/test_paywall.py +262 -0
  39. og_test_x402-0.0.5/tests/test_types.py +162 -0
  40. og_test_x402-0.0.5/uv.lock +2084 -0
@@ -0,0 +1,9 @@
1
+ .env
2
+ node_modules/
3
+ dist/
4
+ .turbo/
5
+ .next/
6
+ proxy
7
+ .env
8
+ __pycache__/
9
+ **/.DS_Store
@@ -0,0 +1 @@
1
+ 3.10
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.4
2
+ Name: og-test-x402
3
+ Version: 0.0.5
4
+ Summary: x402: An internet native payments protocol
5
+ Author-email: erik <erik.reppel@coinbase.com>
6
+ License: Apache-2.0
7
+ Keywords: cdp,crypto,payments,sdk,web3,x402
8
+ Requires-Python: >=3.10
9
+ Requires-Dist: eth-account>=0.13.7
10
+ Requires-Dist: eth-typing>=4.0.0
11
+ Requires-Dist: eth-utils>=3.0.0
12
+ Requires-Dist: fastapi[standard]>=0.115.12
13
+ Requires-Dist: flask>=3.0.0
14
+ Requires-Dist: pydantic-settings>=2.2.1
15
+ Requires-Dist: pydantic>=2.10.3
16
+ Requires-Dist: python-dotenv>=1.0.1
17
+ Requires-Dist: web3>=6.0.0
18
+ Description-Content-Type: text/markdown
19
+
20
+ # x402 Python
21
+
22
+ Python package for the x402 payments protocol.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pip install x402
28
+ ```
29
+
30
+ ## Overview
31
+
32
+ The x402 package provides the core building blocks for implementing the x402 Payment Protocol in Python. It's designed to be used by:
33
+
34
+ - FastAPI middleware for accepting payments
35
+ - Flask middleware for accepting payments
36
+ - httpx client for paying resources
37
+ - requests client for paying resources
38
+
39
+ ## FastAPI Integration
40
+
41
+ The simplest way to add x402 payment protection to your FastAPI application:
42
+
43
+ ```py
44
+ from fastapi import FastAPI
45
+ from x402.fastapi.middleware import require_payment
46
+
47
+ app = FastAPI()
48
+ app.middleware("http")(
49
+ require_payment(price="0.01", pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C")
50
+ )
51
+
52
+ @app.get("/")
53
+ async def root():
54
+ return {"message": "Hello World"}
55
+ ```
56
+
57
+ To protect specific routes:
58
+
59
+ ```py
60
+ app.middleware("http")(
61
+ require_payment(price="0.01",
62
+ pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C"),
63
+ path="/foo" # <-- this can also be a list ex: ["/foo", "/bar"]
64
+ )
65
+ ```
66
+
67
+ ## Flask Integration
68
+
69
+ The simplest way to add x402 payment protection to your Flask application:
70
+
71
+ ```py
72
+ from flask import Flask
73
+ from x402.flask.middleware import PaymentMiddleware
74
+
75
+ app = Flask(__name__)
76
+
77
+ # Initialize payment middleware
78
+ payment_middleware = PaymentMiddleware(app)
79
+
80
+ # Add payment protection for all routes
81
+ payment_middleware.add(
82
+ price="$0.01",
83
+ pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
84
+ )
85
+
86
+ @app.route("/")
87
+ def root():
88
+ return {"message": "Hello World"}
89
+ ```
90
+
91
+ To protect specific routes:
92
+
93
+ ```py
94
+ # Protect specific endpoint
95
+ payment_middleware.add(
96
+ path="/foo",
97
+ price="$0.001",
98
+ pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
99
+ )
100
+ ```
101
+
102
+ ## Client Integration
103
+
104
+ ### Simple Usage
105
+
106
+ #### Httpx Client
107
+ ```py
108
+ from eth_account import Account
109
+ from x402.clients.httpx import x402HttpxClient
110
+
111
+ # Initialize account
112
+ account = Account.from_key("your_private_key")
113
+
114
+ # Create client and make request
115
+ async with x402HttpxClient(account=account, base_url="https://api.example.com") as client:
116
+ response = await client.get("/protected-endpoint")
117
+ print(await response.aread())
118
+ ```
119
+
120
+ #### Requests Session Client
121
+ ```py
122
+ from eth_account import Account
123
+ from x402.clients.requests import x402_requests
124
+
125
+ # Initialize account
126
+ account = Account.from_key("your_private_key")
127
+
128
+ # Create session and make request
129
+ session = x402_requests(account)
130
+ response = session.get("https://api.example.com/protected-endpoint")
131
+ print(response.content)
132
+ ```
133
+
134
+ ### Advanced Usage
135
+
136
+ #### Httpx Extensible Example
137
+ ```py
138
+ import httpx
139
+ from eth_account import Account
140
+ from x402.clients.httpx import x402_payment_hooks
141
+
142
+ # Initialize account
143
+ account = Account.from_key("your_private_key")
144
+
145
+ # Create httpx client with x402 payment hooks
146
+ async with httpx.AsyncClient(base_url="https://api.example.com") as client:
147
+ # Add payment hooks directly to client
148
+ client.event_hooks = x402_payment_hooks(account)
149
+
150
+ # Make request - payment handling is automatic
151
+ response = await client.get("/protected-endpoint")
152
+ print(await response.aread())
153
+ ```
154
+
155
+ #### Requests Session Extensible Example
156
+ ```py
157
+ import requests
158
+ from eth_account import Account
159
+ from x402.clients.requests import x402_http_adapter
160
+
161
+ # Initialize account
162
+ account = Account.from_key("your_private_key")
163
+
164
+ # Create session and mount the x402 adapter
165
+ session = requests.Session()
166
+ adapter = x402_http_adapter(account)
167
+
168
+ # Mount the adapter for both HTTP and HTTPS
169
+ session.mount("http://", adapter)
170
+ session.mount("https://", adapter)
171
+
172
+ # Make request - payment handling is automatic
173
+ response = session.get("https://api.example.com/protected-endpoint")
174
+ print(response.content)
175
+ ```
176
+
177
+ ## Manual Server Integration
178
+
179
+ If you're not using the FastAPI middleware, you can implement the x402 protocol manually. Here's what you'll need to handle:
180
+
181
+ 1. Return 402 error responses with the appropriate response body
182
+ 2. Use the facilitator to validate payments
183
+ 3. Use the facilitator to settle payments
184
+ 4. Return the appropriate response header to the caller
185
+
186
+ Here's an example of manual integration:
187
+
188
+ ```py
189
+ from typing import Annotated
190
+ from fastapi import FastAPI, Request
191
+ from x402.types import PaymentRequiredResponse, PaymentRequirements
192
+ from x402.encoding import safe_base64_decode
193
+
194
+ payment_requirements = PaymentRequirements(...)
195
+ facilitator = FacilitatorClient(facilitator_url)
196
+
197
+ @app.get("/foo")
198
+ async def foo(req: request: Request):
199
+ payment_required = PaymentRequiredResponse(
200
+ x402_version: 1,
201
+ accepts=[payment_requirements],
202
+ error="",
203
+ )
204
+ payment_header = req.headers.get("X-PAYMENT", "")
205
+
206
+ if payment_header == "":
207
+ payment_required.error = "X-PAYMENT header not set"
208
+ return JSONResponse(
209
+ content=payment_required.model_dump(by_alias=True),
210
+ status_code=402,
211
+ )
212
+
213
+ payment = PaymentPayload(**json.loads(safe_base64_decode(payment_header)))
214
+
215
+ verify_response = await facilitator.verify(payment, payment_requirements)
216
+ if not verify_response.is_valid:
217
+ payment_required.error = "Invalid payment"
218
+ return JSONResponse(
219
+ content=payment_required.model_dump(by_alias=True),
220
+ status_code=402,
221
+ )
222
+
223
+ settle_response = await facilitator.settle(payment, payment_requirements)
224
+ if settle_response.success:
225
+ response.headers["X-PAYMENT-RESPONSE"] = base64.b64encode(
226
+ settle_response.model_dump_json().encode("utf-8")
227
+ ).decode("utf-8")
228
+ else:
229
+ payment_required.error = "Settle failed: " + settle_response.error
230
+ return JSONResponse(
231
+ content=payment_required.model_dump(by_alias=True),
232
+ status_code=402,
233
+ )
234
+ ```
235
+
236
+ For more examples and advanced usage patterns, check out our [examples directory](https://github.com/coinbase/x402/tree/main/examples/python).
@@ -0,0 +1,217 @@
1
+ # x402 Python
2
+
3
+ Python package for the x402 payments protocol.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install x402
9
+ ```
10
+
11
+ ## Overview
12
+
13
+ The x402 package provides the core building blocks for implementing the x402 Payment Protocol in Python. It's designed to be used by:
14
+
15
+ - FastAPI middleware for accepting payments
16
+ - Flask middleware for accepting payments
17
+ - httpx client for paying resources
18
+ - requests client for paying resources
19
+
20
+ ## FastAPI Integration
21
+
22
+ The simplest way to add x402 payment protection to your FastAPI application:
23
+
24
+ ```py
25
+ from fastapi import FastAPI
26
+ from x402.fastapi.middleware import require_payment
27
+
28
+ app = FastAPI()
29
+ app.middleware("http")(
30
+ require_payment(price="0.01", pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C")
31
+ )
32
+
33
+ @app.get("/")
34
+ async def root():
35
+ return {"message": "Hello World"}
36
+ ```
37
+
38
+ To protect specific routes:
39
+
40
+ ```py
41
+ app.middleware("http")(
42
+ require_payment(price="0.01",
43
+ pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C"),
44
+ path="/foo" # <-- this can also be a list ex: ["/foo", "/bar"]
45
+ )
46
+ ```
47
+
48
+ ## Flask Integration
49
+
50
+ The simplest way to add x402 payment protection to your Flask application:
51
+
52
+ ```py
53
+ from flask import Flask
54
+ from x402.flask.middleware import PaymentMiddleware
55
+
56
+ app = Flask(__name__)
57
+
58
+ # Initialize payment middleware
59
+ payment_middleware = PaymentMiddleware(app)
60
+
61
+ # Add payment protection for all routes
62
+ payment_middleware.add(
63
+ price="$0.01",
64
+ pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
65
+ )
66
+
67
+ @app.route("/")
68
+ def root():
69
+ return {"message": "Hello World"}
70
+ ```
71
+
72
+ To protect specific routes:
73
+
74
+ ```py
75
+ # Protect specific endpoint
76
+ payment_middleware.add(
77
+ path="/foo",
78
+ price="$0.001",
79
+ pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
80
+ )
81
+ ```
82
+
83
+ ## Client Integration
84
+
85
+ ### Simple Usage
86
+
87
+ #### Httpx Client
88
+ ```py
89
+ from eth_account import Account
90
+ from x402.clients.httpx import x402HttpxClient
91
+
92
+ # Initialize account
93
+ account = Account.from_key("your_private_key")
94
+
95
+ # Create client and make request
96
+ async with x402HttpxClient(account=account, base_url="https://api.example.com") as client:
97
+ response = await client.get("/protected-endpoint")
98
+ print(await response.aread())
99
+ ```
100
+
101
+ #### Requests Session Client
102
+ ```py
103
+ from eth_account import Account
104
+ from x402.clients.requests import x402_requests
105
+
106
+ # Initialize account
107
+ account = Account.from_key("your_private_key")
108
+
109
+ # Create session and make request
110
+ session = x402_requests(account)
111
+ response = session.get("https://api.example.com/protected-endpoint")
112
+ print(response.content)
113
+ ```
114
+
115
+ ### Advanced Usage
116
+
117
+ #### Httpx Extensible Example
118
+ ```py
119
+ import httpx
120
+ from eth_account import Account
121
+ from x402.clients.httpx import x402_payment_hooks
122
+
123
+ # Initialize account
124
+ account = Account.from_key("your_private_key")
125
+
126
+ # Create httpx client with x402 payment hooks
127
+ async with httpx.AsyncClient(base_url="https://api.example.com") as client:
128
+ # Add payment hooks directly to client
129
+ client.event_hooks = x402_payment_hooks(account)
130
+
131
+ # Make request - payment handling is automatic
132
+ response = await client.get("/protected-endpoint")
133
+ print(await response.aread())
134
+ ```
135
+
136
+ #### Requests Session Extensible Example
137
+ ```py
138
+ import requests
139
+ from eth_account import Account
140
+ from x402.clients.requests import x402_http_adapter
141
+
142
+ # Initialize account
143
+ account = Account.from_key("your_private_key")
144
+
145
+ # Create session and mount the x402 adapter
146
+ session = requests.Session()
147
+ adapter = x402_http_adapter(account)
148
+
149
+ # Mount the adapter for both HTTP and HTTPS
150
+ session.mount("http://", adapter)
151
+ session.mount("https://", adapter)
152
+
153
+ # Make request - payment handling is automatic
154
+ response = session.get("https://api.example.com/protected-endpoint")
155
+ print(response.content)
156
+ ```
157
+
158
+ ## Manual Server Integration
159
+
160
+ If you're not using the FastAPI middleware, you can implement the x402 protocol manually. Here's what you'll need to handle:
161
+
162
+ 1. Return 402 error responses with the appropriate response body
163
+ 2. Use the facilitator to validate payments
164
+ 3. Use the facilitator to settle payments
165
+ 4. Return the appropriate response header to the caller
166
+
167
+ Here's an example of manual integration:
168
+
169
+ ```py
170
+ from typing import Annotated
171
+ from fastapi import FastAPI, Request
172
+ from x402.types import PaymentRequiredResponse, PaymentRequirements
173
+ from x402.encoding import safe_base64_decode
174
+
175
+ payment_requirements = PaymentRequirements(...)
176
+ facilitator = FacilitatorClient(facilitator_url)
177
+
178
+ @app.get("/foo")
179
+ async def foo(req: request: Request):
180
+ payment_required = PaymentRequiredResponse(
181
+ x402_version: 1,
182
+ accepts=[payment_requirements],
183
+ error="",
184
+ )
185
+ payment_header = req.headers.get("X-PAYMENT", "")
186
+
187
+ if payment_header == "":
188
+ payment_required.error = "X-PAYMENT header not set"
189
+ return JSONResponse(
190
+ content=payment_required.model_dump(by_alias=True),
191
+ status_code=402,
192
+ )
193
+
194
+ payment = PaymentPayload(**json.loads(safe_base64_decode(payment_header)))
195
+
196
+ verify_response = await facilitator.verify(payment, payment_requirements)
197
+ if not verify_response.is_valid:
198
+ payment_required.error = "Invalid payment"
199
+ return JSONResponse(
200
+ content=payment_required.model_dump(by_alias=True),
201
+ status_code=402,
202
+ )
203
+
204
+ settle_response = await facilitator.settle(payment, payment_requirements)
205
+ if settle_response.success:
206
+ response.headers["X-PAYMENT-RESPONSE"] = base64.b64encode(
207
+ settle_response.model_dump_json().encode("utf-8")
208
+ ).decode("utf-8")
209
+ else:
210
+ payment_required.error = "Settle failed: " + settle_response.error
211
+ return JSONResponse(
212
+ content=payment_required.model_dump(by_alias=True),
213
+ status_code=402,
214
+ )
215
+ ```
216
+
217
+ For more examples and advanced usage patterns, check out our [examples directory](https://github.com/coinbase/x402/tree/main/examples/python).
@@ -0,0 +1,45 @@
1
+ [project]
2
+ name = "og-test-x402"
3
+ version = "0.0.5"
4
+ description = "x402: An internet native payments protocol"
5
+ readme = "README.md"
6
+ license = { text = "Apache-2.0" }
7
+ authors = [
8
+ { name = "erik", email = "erik.reppel@coinbase.com" }
9
+ ]
10
+ requires-python = ">=3.10"
11
+ keywords = ["x402", "sdk", "crypto", "cdp", "payments", "web3"]
12
+ dependencies = [
13
+ "eth-account>=0.13.7",
14
+ "eth-typing>=4.0.0",
15
+ "eth-utils>=3.0.0",
16
+ "fastapi[standard]>=0.115.12",
17
+ "flask>=3.0.0",
18
+ "pydantic>=2.10.3",
19
+ "pydantic-settings>=2.2.1",
20
+ "python-dotenv>=1.0.1",
21
+ "web3>=6.0.0",
22
+ ]
23
+
24
+ [project.scripts]
25
+
26
+
27
+ [build-system]
28
+ requires = ["hatchling"]
29
+ build-backend = "hatchling.build"
30
+
31
+ [dependency-groups]
32
+ dev = [
33
+ "pytest>=8.3.5",
34
+ "pytest-asyncio>=1.0.0",
35
+ "ruff>=0.11.9",
36
+ ]
37
+
38
+ [tool.pytest.ini_options]
39
+ asyncio_mode = "auto"
40
+
41
+ [tool.hatch.build.targets.wheel]
42
+ packages = ["src/x402"]
43
+
44
+ [tool.hatch.metadata]
45
+ allow-direct-references = true
@@ -0,0 +1,2 @@
1
+ def hello() -> str:
2
+ return "Hello from x402!"
@@ -0,0 +1,62 @@
1
+ NETWORK_TO_ID = {
2
+ "og-devnet": "10744",
3
+ }
4
+
5
+
6
+ def get_chain_id(network: str) -> str:
7
+ """Get the chain ID for a given network
8
+ Supports string encoded chain IDs and human readable networks
9
+ """
10
+ try:
11
+ int(network)
12
+ return network
13
+ except ValueError:
14
+ pass
15
+ if network not in NETWORK_TO_ID:
16
+ raise ValueError(f"Unsupported network: {network}")
17
+ return NETWORK_TO_ID[network]
18
+
19
+
20
+ KNOWN_TOKENS = {
21
+ "10744": [
22
+ {
23
+ "human_name": "ousdc",
24
+ "address": "0x48515A4b24f17cadcD6109a9D85a57ba55a619a6",
25
+ "name": "OUSDC",
26
+ "decimals": 6,
27
+ "version": "2",
28
+ }
29
+ ],
30
+ }
31
+
32
+
33
+ def get_token_name(chain_id: str, address: str) -> str:
34
+ """Get the token name for a given chain and address"""
35
+ for token in KNOWN_TOKENS[chain_id]:
36
+ if token["address"] == address:
37
+ return token["name"]
38
+ raise ValueError(f"Token not found for chain {chain_id} and address {address}")
39
+
40
+
41
+ def get_token_version(chain_id: str, address: str) -> str:
42
+ """Get the token version for a given chain and address"""
43
+ for token in KNOWN_TOKENS[chain_id]:
44
+ if token["address"] == address:
45
+ return token["version"]
46
+ raise ValueError(f"Token not found for chain {chain_id} and address {address}")
47
+
48
+
49
+ def get_token_decimals(chain_id: str, address: str) -> int:
50
+ """Get the token decimals for a given chain and address"""
51
+ for token in KNOWN_TOKENS[chain_id]:
52
+ if token["address"] == address:
53
+ return token["decimals"]
54
+ raise ValueError(f"Token not found for chain {chain_id} and address {address}")
55
+
56
+
57
+ def get_default_token_address(chain_id: str, token_type: str = "usdc") -> str:
58
+ """Get the default token address for a given chain and token type"""
59
+ for token in KNOWN_TOKENS[chain_id]:
60
+ if token["human_name"] == token_type:
61
+ return token["address"]
62
+ raise ValueError(f"Token type '{token_type}' not found for chain {chain_id}")
@@ -0,0 +1,20 @@
1
+ from x402.clients.base import x402Client, decode_x_payment_response
2
+ from x402.clients.httpx import (
3
+ x402_payment_hooks,
4
+ x402HttpxClient,
5
+ )
6
+ from x402.clients.requests import (
7
+ x402HTTPAdapter,
8
+ x402_http_adapter,
9
+ x402_requests,
10
+ )
11
+
12
+ __all__ = [
13
+ "x402Client",
14
+ "decode_x_payment_response",
15
+ "x402_payment_hooks",
16
+ "x402HttpxClient",
17
+ "x402HTTPAdapter",
18
+ "x402_http_adapter",
19
+ "x402_requests",
20
+ ]