forked from x402-foundation/x402
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdynamic_pay_to.py
More file actions
89 lines (63 loc) · 2.35 KB
/
Copy pathdynamic_pay_to.py
File metadata and controls
89 lines (63 loc) · 2.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
"""Dynamic pay-to routing example."""
import os
from dotenv import load_dotenv
from fastapi import FastAPI
from pydantic import BaseModel
from x402.http import FacilitatorConfig, HTTPFacilitatorClient, PaymentOption
from x402.http.middleware.fastapi import PaymentMiddlewareASGI
from x402.http.types import HTTPRequestContext, RouteConfig
from x402.mechanisms.evm.exact import ExactEvmServerScheme
from x402.schemas import Network
from x402.server import x402ResourceServer
load_dotenv()
# Config
EVM_ADDRESS = os.getenv("EVM_ADDRESS")
EVM_NETWORK: Network = "eip155:84532" # Base Sepolia
FACILITATOR_URL = os.getenv("FACILITATOR_URL", "https://x402.org/facilitator")
if not EVM_ADDRESS:
raise ValueError("Missing required EVM_ADDRESS environment variable")
# Address lookup for dynamic pay-to
ADDRESS_LOOKUP: dict[str, str] = {
"US": EVM_ADDRESS,
"UK": EVM_ADDRESS,
"CA": EVM_ADDRESS,
"AU": EVM_ADDRESS,
}
def get_dynamic_pay_to(context: HTTPRequestContext) -> str:
"""Get dynamic pay-to address based on country query parameter."""
country = context.adapter.get_query_param("country") or "US"
return ADDRESS_LOOKUP.get(country, EVM_ADDRESS)
class WeatherReport(BaseModel):
weather: str
temperature: int
class WeatherResponse(BaseModel):
report: WeatherReport
app = FastAPI()
facilitator = HTTPFacilitatorClient(FacilitatorConfig(url=FACILITATOR_URL))
server = x402ResourceServer(facilitator)
server.register(EVM_NETWORK, ExactEvmServerScheme())
# Register hooks to log selected payment option
async def after_verify(ctx):
print("\n=== Dynamic Pay-To - After verify ===")
print(f"Pay to: {ctx.requirements.pay_to}")
print(f"Payer: {ctx.result.payer}")
server.on_after_verify(after_verify)
routes = {
"GET /weather": RouteConfig(
accepts=[
PaymentOption(
scheme="exact",
pay_to=get_dynamic_pay_to,
price="$0.001",
network=EVM_NETWORK,
),
],
),
}
app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)
@app.get("/weather")
async def get_weather(city: str = "San Francisco", country: str = "US") -> WeatherResponse:
return WeatherResponse(report=WeatherReport(weather="sunny", temperature=70))
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=4021)