@goplausible/openclaw-algorand-plugin 0.5.0

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 (112) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +112 -0
  3. package/index.ts +361 -0
  4. package/lib/mcp-servers.ts +14 -0
  5. package/lib/x402-fetch.ts +213 -0
  6. package/memory/algorand-plugin.md +82 -0
  7. package/openclaw.plugin.json +30 -0
  8. package/package.json +41 -0
  9. package/setup.ts +80 -0
  10. package/skills/algorand-development/SKILL.md +90 -0
  11. package/skills/algorand-development/references/build-smart-contracts-reference.md +79 -0
  12. package/skills/algorand-development/references/build-smart-contracts.md +52 -0
  13. package/skills/algorand-development/references/create-project-reference.md +86 -0
  14. package/skills/algorand-development/references/create-project.md +89 -0
  15. package/skills/algorand-development/references/implement-arc-standards-arc32-arc56.md +396 -0
  16. package/skills/algorand-development/references/implement-arc-standards-arc4.md +265 -0
  17. package/skills/algorand-development/references/implement-arc-standards.md +92 -0
  18. package/skills/algorand-development/references/search-algorand-examples-reference.md +119 -0
  19. package/skills/algorand-development/references/search-algorand-examples.md +89 -0
  20. package/skills/algorand-development/references/troubleshoot-errors-contract.md +373 -0
  21. package/skills/algorand-development/references/troubleshoot-errors-transaction.md +599 -0
  22. package/skills/algorand-development/references/troubleshoot-errors.md +105 -0
  23. package/skills/algorand-development/references/use-algokit-cli-reference.md +228 -0
  24. package/skills/algorand-development/references/use-algokit-cli.md +64 -0
  25. package/skills/algorand-interaction/SKILL.md +223 -0
  26. package/skills/algorand-interaction/references/algorand-mcp.md +743 -0
  27. package/skills/algorand-interaction/references/examples-algorand-mcp.md +647 -0
  28. package/skills/algorand-python/SKILL.md +95 -0
  29. package/skills/algorand-python/references/build-smart-contracts-decorators.md +413 -0
  30. package/skills/algorand-python/references/build-smart-contracts-reference.md +55 -0
  31. package/skills/algorand-python/references/build-smart-contracts-storage.md +452 -0
  32. package/skills/algorand-python/references/build-smart-contracts-transactions.md +445 -0
  33. package/skills/algorand-python/references/build-smart-contracts-types.md +438 -0
  34. package/skills/algorand-python/references/build-smart-contracts.md +82 -0
  35. package/skills/algorand-python/references/create-project-reference.md +55 -0
  36. package/skills/algorand-python/references/create-project.md +75 -0
  37. package/skills/algorand-python/references/implement-arc-standards-arc32-arc56.md +101 -0
  38. package/skills/algorand-python/references/implement-arc-standards-arc4.md +154 -0
  39. package/skills/algorand-python/references/implement-arc-standards.md +39 -0
  40. package/skills/algorand-python/references/troubleshoot-errors-contract.md +355 -0
  41. package/skills/algorand-python/references/troubleshoot-errors-transaction.md +430 -0
  42. package/skills/algorand-python/references/troubleshoot-errors.md +46 -0
  43. package/skills/algorand-python/references/use-algokit-utils-reference.md +350 -0
  44. package/skills/algorand-python/references/use-algokit-utils.md +76 -0
  45. package/skills/algorand-typescript/SKILL.md +131 -0
  46. package/skills/algorand-typescript/references/algorand-ts-migration-from-beta.md +448 -0
  47. package/skills/algorand-typescript/references/algorand-ts-migration-from-tealscript.md +487 -0
  48. package/skills/algorand-typescript/references/algorand-ts-migration.md +102 -0
  49. package/skills/algorand-typescript/references/algorand-typescript-syntax-methods-and-abi.md +134 -0
  50. package/skills/algorand-typescript/references/algorand-typescript-syntax-reference.md +58 -0
  51. package/skills/algorand-typescript/references/algorand-typescript-syntax-storage.md +154 -0
  52. package/skills/algorand-typescript/references/algorand-typescript-syntax-transactions.md +187 -0
  53. package/skills/algorand-typescript/references/algorand-typescript-syntax-types-and-values.md +150 -0
  54. package/skills/algorand-typescript/references/algorand-typescript-syntax.md +84 -0
  55. package/skills/algorand-typescript/references/build-smart-contracts-reference.md +52 -0
  56. package/skills/algorand-typescript/references/build-smart-contracts.md +74 -0
  57. package/skills/algorand-typescript/references/call-smart-contracts-reference.md +237 -0
  58. package/skills/algorand-typescript/references/call-smart-contracts.md +183 -0
  59. package/skills/algorand-typescript/references/create-project-reference.md +53 -0
  60. package/skills/algorand-typescript/references/create-project.md +86 -0
  61. package/skills/algorand-typescript/references/deploy-react-frontend-examples.md +527 -0
  62. package/skills/algorand-typescript/references/deploy-react-frontend-reference.md +412 -0
  63. package/skills/algorand-typescript/references/deploy-react-frontend.md +239 -0
  64. package/skills/algorand-typescript/references/implement-arc-standards-arc32-arc56.md +73 -0
  65. package/skills/algorand-typescript/references/implement-arc-standards-arc4.md +126 -0
  66. package/skills/algorand-typescript/references/implement-arc-standards.md +44 -0
  67. package/skills/algorand-typescript/references/test-smart-contracts-examples.md +245 -0
  68. package/skills/algorand-typescript/references/test-smart-contracts-unit-tests.md +147 -0
  69. package/skills/algorand-typescript/references/test-smart-contracts.md +127 -0
  70. package/skills/algorand-typescript/references/troubleshoot-errors-contract.md +296 -0
  71. package/skills/algorand-typescript/references/troubleshoot-errors-transaction.md +438 -0
  72. package/skills/algorand-typescript/references/troubleshoot-errors.md +56 -0
  73. package/skills/algorand-typescript/references/use-algokit-utils-reference.md +342 -0
  74. package/skills/algorand-typescript/references/use-algokit-utils.md +74 -0
  75. package/skills/algorand-x402-python/SKILL.md +113 -0
  76. package/skills/algorand-x402-python/references/create-python-x402-client-examples.md +469 -0
  77. package/skills/algorand-x402-python/references/create-python-x402-client-reference.md +313 -0
  78. package/skills/algorand-x402-python/references/create-python-x402-client.md +207 -0
  79. package/skills/algorand-x402-python/references/create-python-x402-facilitator-examples.md +924 -0
  80. package/skills/algorand-x402-python/references/create-python-x402-facilitator-reference.md +629 -0
  81. package/skills/algorand-x402-python/references/create-python-x402-facilitator.md +408 -0
  82. package/skills/algorand-x402-python/references/create-python-x402-server-examples.md +703 -0
  83. package/skills/algorand-x402-python/references/create-python-x402-server-reference.md +303 -0
  84. package/skills/algorand-x402-python/references/create-python-x402-server.md +221 -0
  85. package/skills/algorand-x402-python/references/explain-algorand-x402-python-examples.md +605 -0
  86. package/skills/algorand-x402-python/references/explain-algorand-x402-python-reference.md +315 -0
  87. package/skills/algorand-x402-python/references/explain-algorand-x402-python.md +167 -0
  88. package/skills/algorand-x402-python/references/use-python-x402-core-avm-examples.md +554 -0
  89. package/skills/algorand-x402-python/references/use-python-x402-core-avm-reference.md +278 -0
  90. package/skills/algorand-x402-python/references/use-python-x402-core-avm.md +166 -0
  91. package/skills/algorand-x402-typescript/SKILL.md +129 -0
  92. package/skills/algorand-x402-typescript/references/create-typescript-x402-client-examples.md +879 -0
  93. package/skills/algorand-x402-typescript/references/create-typescript-x402-client-reference.md +371 -0
  94. package/skills/algorand-x402-typescript/references/create-typescript-x402-client.md +236 -0
  95. package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator-examples.md +875 -0
  96. package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator-reference.md +461 -0
  97. package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator.md +270 -0
  98. package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs-examples.md +1181 -0
  99. package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs-reference.md +360 -0
  100. package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs.md +251 -0
  101. package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall-examples.md +870 -0
  102. package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall-reference.md +323 -0
  103. package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall.md +281 -0
  104. package/skills/algorand-x402-typescript/references/create-typescript-x402-server-examples.md +1135 -0
  105. package/skills/algorand-x402-typescript/references/create-typescript-x402-server-reference.md +382 -0
  106. package/skills/algorand-x402-typescript/references/create-typescript-x402-server.md +216 -0
  107. package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript-examples.md +616 -0
  108. package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript-reference.md +323 -0
  109. package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript.md +232 -0
  110. package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm-examples.md +1417 -0
  111. package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm-reference.md +504 -0
  112. package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm.md +158 -0
@@ -0,0 +1,303 @@
1
+ # x402 Python Server Middleware Reference
2
+
3
+ Detailed API reference for FastAPI and Flask payment middleware in the `x402-avm` Python package.
4
+
5
+ ## FastAPI Middleware API
6
+
7
+ ### `payment_middleware(routes, server, ...)`
8
+
9
+ Creates an async middleware callable for FastAPI.
10
+
11
+ | Parameter | Type | Default | Description |
12
+ |-----------|------|---------|-------------|
13
+ | `routes` | `RoutesConfig` | required | Route configuration for protected endpoints |
14
+ | `server` | `x402ResourceServer` | required | Pre-configured async resource server |
15
+ | `paywall_config` | `PaywallConfig \| None` | `None` | Optional paywall UI configuration |
16
+ | `paywall_provider` | `PaywallProvider \| None` | `None` | Optional custom paywall provider |
17
+ | `sync_facilitator_on_start` | `bool` | `True` | Fetch facilitator support on first request |
18
+
19
+ **Returns**: Async middleware callable `(Request, call_next) -> Response`
20
+
21
+ **Usage**:
22
+ ```python
23
+ x402_mw = payment_middleware(routes=routes, server=server)
24
+
25
+ @app.middleware("http")
26
+ async def x402_middleware(request: Request, call_next):
27
+ return await x402_mw(request, call_next)
28
+ ```
29
+
30
+ ### `payment_middleware_from_config(routes, facilitator_client, ...)`
31
+
32
+ Creates middleware with an internally-created resource server.
33
+
34
+ | Parameter | Type | Default | Description |
35
+ |-----------|------|---------|-------------|
36
+ | `routes` | `RoutesConfig` | required | Route configuration |
37
+ | `facilitator_client` | `Any` | `None` | Facilitator client for payment processing |
38
+ | `schemes` | `list[dict] \| None` | `None` | Scheme registrations (`{"network": ..., "server": ...}`) |
39
+ | `paywall_config` | `PaywallConfig \| None` | `None` | Optional paywall config |
40
+ | `paywall_provider` | `PaywallProvider \| None` | `None` | Optional custom paywall |
41
+ | `sync_facilitator_on_start` | `bool` | `True` | Lazy initialization flag |
42
+
43
+ **Returns**: Async middleware callable `(Request, call_next) -> Response`
44
+
45
+ ### `PaymentMiddlewareASGI`
46
+
47
+ Starlette `BaseHTTPMiddleware` subclass. Accepts same parameters as `payment_middleware` via `app.add_middleware()`.
48
+
49
+ | Parameter | Type | Description |
50
+ |-----------|------|-------------|
51
+ | `app` | `ASGIApp` | Passed automatically by Starlette |
52
+ | `routes` | `RoutesConfig` | Route configuration |
53
+ | `server` | `x402ResourceServer` | Pre-configured server instance |
54
+ | `paywall_config` | `PaywallConfig \| None` | Optional paywall UI config |
55
+ | `paywall_provider` | `PaywallProvider \| None` | Optional custom paywall |
56
+
57
+ **Usage**:
58
+ ```python
59
+ app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)
60
+ ```
61
+
62
+ ### `FastAPIAdapter`
63
+
64
+ Implements the `HTTPAdapter` protocol for FastAPI/Starlette requests. Used internally.
65
+
66
+ | Method | Returns | Description |
67
+ |--------|---------|-------------|
68
+ | `get_header(name)` | `str \| None` | Case-insensitive header lookup |
69
+ | `get_method()` | `str` | HTTP method (GET, POST, etc.) |
70
+ | `get_path()` | `str` | Request path |
71
+ | `get_url()` | `str` | Full request URL |
72
+ | `get_accept_header()` | `str` | Accept header value |
73
+ | `get_user_agent()` | `str` | User-Agent header value |
74
+ | `get_query_params()` | `dict` | All query parameters |
75
+ | `get_query_param(name)` | `str \| None` | Single query parameter |
76
+ | `get_body()` | `None` | Returns None (body requires async access) |
77
+
78
+ ## Flask Middleware API
79
+
80
+ ### `PaymentMiddleware(app, routes, server, ...)`
81
+
82
+ The main WSGI middleware class. Replaces `app.wsgi_app` on initialization.
83
+
84
+ | Parameter | Type | Default | Description |
85
+ |-----------|------|---------|-------------|
86
+ | `app` | `Flask` | required | Flask application instance |
87
+ | `routes` | `RoutesConfig` | required | Route configuration for protected endpoints |
88
+ | `server` | `x402ResourceServerSync` | required | Pre-configured **sync** resource server |
89
+ | `paywall_config` | `PaywallConfig \| None` | `None` | Optional paywall UI configuration |
90
+ | `paywall_provider` | `PaywallProvider \| None` | `None` | Optional custom paywall provider |
91
+ | `sync_facilitator_on_start` | `bool` | `True` | Fetch facilitator support on first request |
92
+
93
+ **Side effect**: Replaces `app.wsgi_app` with the payment-checking WSGI middleware.
94
+
95
+ ### `payment_middleware(app, routes, server, ...)`
96
+
97
+ Factory function. Accepts same parameters as `PaymentMiddleware`, returns `PaymentMiddleware` instance.
98
+
99
+ | Parameter | Type | Default | Description |
100
+ |-----------|------|---------|-------------|
101
+ | `app` | `Flask` | required | Flask application instance |
102
+ | `routes` | `RoutesConfig` | required | Route configuration |
103
+ | `server` | `x402ResourceServerSync` | required | Pre-configured **sync** resource server |
104
+ | `paywall_config` | `PaywallConfig \| None` | `None` | Optional paywall config |
105
+ | `paywall_provider` | `PaywallProvider \| None` | `None` | Optional custom paywall |
106
+ | `sync_facilitator_on_start` | `bool` | `True` | Lazy initialization flag |
107
+
108
+ **Returns**: `PaymentMiddleware` instance.
109
+
110
+ ### `payment_middleware_from_config(app, routes, ...)`
111
+
112
+ Convenience function that creates the `x402ResourceServer` internally.
113
+
114
+ | Parameter | Type | Default | Description |
115
+ |-----------|------|---------|-------------|
116
+ | `app` | `Flask` | required | Flask application instance |
117
+ | `routes` | `RoutesConfig` | required | Route configuration |
118
+ | `facilitator_client` | `Any` | `None` | Facilitator client for payment processing |
119
+ | `schemes` | `list[dict] \| None` | `None` | Scheme registrations (`{"network": ..., "server": ...}`) |
120
+ | `paywall_config` | `PaywallConfig \| None` | `None` | Optional paywall config |
121
+ | `paywall_provider` | `PaywallProvider \| None` | `None` | Optional custom paywall |
122
+ | `sync_facilitator_on_start` | `bool` | `True` | Lazy initialization flag |
123
+
124
+ **Returns**: `PaymentMiddleware` instance.
125
+
126
+ ### `FlaskAdapter`
127
+
128
+ Implements the `HTTPAdapter` protocol for Flask requests. Used internally.
129
+
130
+ | Method | Returns | Description |
131
+ |--------|---------|-------------|
132
+ | `get_header(name)` | `str \| None` | Case-insensitive header lookup |
133
+ | `get_method()` | `str` | HTTP method (GET, POST, etc.) |
134
+ | `get_path()` | `str` | Request path |
135
+ | `get_url()` | `str` | Full request URL |
136
+ | `get_accept_header()` | `str` | Accept header value |
137
+ | `get_user_agent()` | `str` | User-Agent header value |
138
+ | `get_query_params()` | `dict` | All query parameters |
139
+ | `get_query_param(name)` | `str \| None` | Single query parameter |
140
+ | `get_body()` | `Any \| None` | Parsed JSON body (via `request.get_json(silent=True)`) |
141
+
142
+ ### `ResponseWrapper`
143
+
144
+ Internal class that captures and buffers the WSGI response for settlement processing.
145
+
146
+ | Method/Property | Description |
147
+ |-----------------|-------------|
148
+ | `status` | Captured HTTP status string |
149
+ | `status_code` | Parsed integer status code |
150
+ | `headers` | List of (name, value) header tuples |
151
+ | `add_header(name, value)` | Add a header to the response |
152
+ | `send_response(body_chunks)` | Send the buffered response to the client |
153
+
154
+ ## RouteConfig
155
+
156
+ Dataclass for route configuration.
157
+
158
+ ```python
159
+ from x402.http.types import RouteConfig
160
+
161
+ RouteConfig(
162
+ accepts=PaymentOption(...), # Required: single payment option
163
+ # or: accepts=[PaymentOption(...), PaymentOption(...)], # Multiple options
164
+ resource="https://api.example.com/api/weather", # Optional: resource URL
165
+ description="Weather data API", # Optional: description
166
+ mime_type="application/json", # Optional: response MIME type
167
+ )
168
+ ```
169
+
170
+ ### Route Key Format
171
+
172
+ Route keys follow the pattern `"METHOD /path"`:
173
+
174
+ | Pattern | Matches |
175
+ |---------|---------|
176
+ | `"GET /api/weather"` | Exactly `/api/weather` |
177
+ | `"GET /api/premium/*"` | `/api/premium/anything`, `/api/premium/a/b` |
178
+ | `"POST /api/generate"` | Exactly `POST /api/generate` |
179
+ | `"GET /api/data/*"` | Any GET under `/api/data/` |
180
+
181
+ ## PaymentOption
182
+
183
+ Dataclass for payment options.
184
+
185
+ ```python
186
+ from x402.http import PaymentOption
187
+
188
+ PaymentOption(
189
+ scheme="exact", # Payment scheme name
190
+ network="algorand:SGO...", # CAIP-2 network identifier
191
+ pay_to="ALGO_ADDRESS", # Recipient address
192
+ price="$0.01", # Auto-converted to AssetAmount
193
+ # or: price=AssetAmount(amount="10000", asset="10458941"),
194
+ )
195
+ ```
196
+
197
+ ## AssetAmount
198
+
199
+ Explicit asset amount specification.
200
+
201
+ ```python
202
+ from x402.schemas import AssetAmount
203
+
204
+ AssetAmount(
205
+ amount="10000", # Atomic units (string)
206
+ asset="10458941", # Asset identifier (ASA ID as string)
207
+ extra={"name": "USDC", "decimals": 6}, # Optional metadata
208
+ )
209
+ ```
210
+
211
+ ## Sync vs Async Comparison
212
+
213
+ | Component | Flask (Sync) | FastAPI (Async) |
214
+ |-----------|-------------|-----------------|
215
+ | Resource server | `x402ResourceServerSync` | `x402ResourceServer` |
216
+ | Facilitator client | `HTTPFacilitatorClientSync` | `HTTPFacilitatorClient` |
217
+ | Middleware class | `PaymentMiddleware` (WSGI) | `PaymentMiddlewareASGI` (ASGI) |
218
+ | Payment info storage | `flask.g.payment_payload` | `request.state.payment_payload` |
219
+ | HTTP server wrapper | `x402HTTPResourceServerSync` | `x402HTTPResourceServer` |
220
+ | Middleware invocation | `PaymentMiddleware(app, ...)` | `app.add_middleware(PaymentMiddlewareASGI, ...)` |
221
+ | Settlement | Synchronous (blocking) | `await` async settlement |
222
+
223
+ ## Middleware Flow
224
+
225
+ ### FastAPI (ASGI)
226
+
227
+ 1. Client sends request with `Payment-Signature` header
228
+ 2. Middleware checks if the route requires payment via `requires_payment(context)`
229
+ 3. On first protected request, facilitator support is synchronized (lazy init)
230
+ 4. `process_http_request(context)` verifies the payment:
231
+ - `"no-payment-required"` -- route not protected, passes through
232
+ - `"payment-error"` -- returns 402 response (JSON or HTML paywall)
233
+ - `"payment-verified"` -- stores on `request.state`, calls route handler
234
+ 5. If route handler returns a successful (2xx) response, settlement is processed
235
+ 6. Settlement headers are added to the response
236
+
237
+ ### Flask (WSGI)
238
+
239
+ 1. Client sends request with `Payment-Signature` header
240
+ 2. The WSGI middleware intercepts the request within a Flask request context
241
+ 3. Middleware checks if the route requires payment via `requires_payment(context)`
242
+ 4. On first protected request, facilitator support is synchronized (lazy init)
243
+ 5. `process_http_request(context)` verifies the payment **synchronously**:
244
+ - `"no-payment-required"` -- passes through to `original_wsgi`
245
+ - `"payment-error"` -- returns 402 response
246
+ - `"payment-verified"` -- stores on `flask.g`, calls original WSGI app
247
+ 6. Response is captured by `ResponseWrapper`, settlement is processed synchronously
248
+ 7. Settlement headers are added to the buffered response
249
+
250
+ ## Environment Variables
251
+
252
+ | Variable | Description | Default |
253
+ |----------|-------------|---------|
254
+ | `AVM_ADDRESS` | Algorand address to receive payments | Required |
255
+ | `FACILITATOR_URL` | URL of the x402 facilitator service | `https://x402.org/facilitator` |
256
+
257
+ ## Algorand-Specific Constants
258
+
259
+ | Constant | Value | Import |
260
+ |----------|-------|--------|
261
+ | `ALGORAND_TESTNET_CAIP2` | `"algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="` | `x402.mechanisms.avm` |
262
+ | `ALGORAND_MAINNET_CAIP2` | `"algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8="` | `x402.mechanisms.avm` |
263
+ | `USDC_TESTNET_ASA_ID` | `10458941` | `x402.mechanisms.avm` |
264
+ | `USDC_MAINNET_ASA_ID` | `31566704` | `x402.mechanisms.avm` |
265
+
266
+ ## CAIP-2 Network Identifiers
267
+
268
+ | Network | CAIP-2 Identifier |
269
+ |---------|-------------------|
270
+ | Algorand Mainnet | `algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=` |
271
+ | Algorand Testnet | `algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=` |
272
+ | Base Sepolia (EVM) | `eip155:84532` |
273
+ | Solana Devnet (SVM) | `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` |
274
+
275
+ ## Error Handling
276
+
277
+ ### Payment Errors (402 Responses)
278
+
279
+ When a client sends a request without a valid payment, the middleware returns a 402 response containing `PaymentRequirements` the client needs to fulfill.
280
+
281
+ ### Settlement Failures
282
+
283
+ If the route handler succeeds but settlement fails:
284
+
285
+ ```json
286
+ {
287
+ "error": "Settlement failed",
288
+ "details": "reason for failure"
289
+ }
290
+ ```
291
+
292
+ ### Unprotected Routes
293
+
294
+ Routes not listed in the `routes` configuration are served normally without any payment check.
295
+
296
+ ## External Resources
297
+
298
+ - [x402-avm on PyPI](https://pypi.org/project/x402-avm/)
299
+ - [x402-avm Examples Repository](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
300
+ - [x402 Algorand Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)
301
+ - [FastAPI Documentation](https://fastapi.tiangolo.com/)
302
+ - [Flask Documentation](https://flask.palletsprojects.com/)
303
+ - [Coinbase x402 Specification](https://github.com/coinbase/x402)
@@ -0,0 +1,221 @@
1
+ # Creating x402 Payment-Protected Servers in Python
2
+
3
+ Build FastAPI (async) or Flask (sync) servers that protect API endpoints behind Algorand USDC payments using x402 middleware.
4
+
5
+ ## Prerequisites
6
+
7
+ Before using this skill, ensure:
8
+
9
+ 1. **Python 3.10+** is installed
10
+ 2. **An Algorand address** to receive payments (the `payTo` address)
11
+ 3. **A facilitator URL** -- use `https://x402.org/facilitator` or run your own
12
+ 4. **Understanding of FastAPI or Flask** basics
13
+
14
+ ## Core Workflow: Middleware-Based Payment Protection
15
+
16
+ The middleware intercepts requests to protected routes, checks for payment headers, verifies payments through the facilitator, and settles on success.
17
+
18
+ ```
19
+ Client Request
20
+ |
21
+ v
22
+ x402 Middleware (checks route config)
23
+ |
24
+ +-- Not protected -> Pass through to handler
25
+ |
26
+ +-- Protected, no payment -> Return 402 with PaymentRequirements
27
+ |
28
+ +-- Protected, has payment -> Verify via Facilitator
29
+ |
30
+ +-- Invalid -> Return 402
31
+ |
32
+ +-- Valid -> Call handler, then settle payment
33
+ ```
34
+
35
+ ## How to Proceed
36
+
37
+ ### Step 1: Install Dependencies
38
+
39
+ For FastAPI (async):
40
+ ```bash
41
+ pip install "x402-avm[fastapi,avm]"
42
+ ```
43
+
44
+ For Flask (sync):
45
+ ```bash
46
+ pip install "x402-avm[flask,avm]"
47
+ ```
48
+
49
+ ### Step 2: Choose Your Framework Pattern
50
+
51
+ **FastAPI** uses async components:
52
+ - `x402ResourceServer` (async)
53
+ - `HTTPFacilitatorClient` (async)
54
+ - `PaymentMiddlewareASGI` or `payment_middleware`
55
+
56
+ **Flask** uses sync components:
57
+ - `x402ResourceServerSync` (sync)
58
+ - `HTTPFacilitatorClientSync` (sync)
59
+ - `PaymentMiddleware` or `payment_middleware`
60
+
61
+ ### Step 3: Set Up the Resource Server
62
+
63
+ Create a facilitator client, resource server, and register the AVM scheme:
64
+
65
+ **FastAPI:**
66
+ ```python
67
+ from x402.server import x402ResourceServer
68
+ from x402.http import HTTPFacilitatorClient, FacilitatorConfig
69
+ from x402.mechanisms.avm.exact import ExactAvmServerScheme
70
+
71
+ facilitator = HTTPFacilitatorClient(FacilitatorConfig(url="https://x402.org/facilitator"))
72
+ server = x402ResourceServer(facilitator)
73
+ server.register("algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", ExactAvmServerScheme())
74
+ ```
75
+
76
+ **Flask:**
77
+ ```python
78
+ from x402.server import x402ResourceServerSync
79
+ from x402.http import HTTPFacilitatorClientSync, FacilitatorConfig
80
+ from x402.mechanisms.avm.exact import ExactAvmServerScheme
81
+
82
+ facilitator = HTTPFacilitatorClientSync(FacilitatorConfig(url="https://x402.org/facilitator"))
83
+ server = x402ResourceServerSync(facilitator)
84
+ server.register("algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=", ExactAvmServerScheme())
85
+ ```
86
+
87
+ ### Step 4: Define Route Configurations
88
+
89
+ Routes map HTTP method + path patterns to payment requirements:
90
+
91
+ ```python
92
+ from x402.http import PaymentOption
93
+ from x402.http.types import RouteConfig
94
+
95
+ routes = {
96
+ "GET /api/weather": RouteConfig(
97
+ accepts=PaymentOption(
98
+ scheme="exact",
99
+ network="algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
100
+ pay_to="YOUR_ALGORAND_ADDRESS",
101
+ price="$0.01",
102
+ ),
103
+ ),
104
+ }
105
+ ```
106
+
107
+ ### Step 5: Apply Middleware
108
+
109
+ **FastAPI -- Option A (ASGI class, recommended):**
110
+ ```python
111
+ from x402.http.middleware.fastapi import PaymentMiddlewareASGI
112
+ app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)
113
+ ```
114
+
115
+ **FastAPI -- Option B (function-based):**
116
+ ```python
117
+ from x402.http.middleware.fastapi import payment_middleware
118
+ x402_mw = payment_middleware(routes=routes, server=server)
119
+
120
+ @app.middleware("http")
121
+ async def x402_middleware(request, call_next):
122
+ return await x402_mw(request, call_next)
123
+ ```
124
+
125
+ **Flask:**
126
+ ```python
127
+ from x402.http.middleware.flask import PaymentMiddleware
128
+ PaymentMiddleware(app, routes, server)
129
+ ```
130
+
131
+ ### Step 6: Define Route Handlers
132
+
133
+ Routes listed in the configuration require payment. Unlisted routes pass through freely.
134
+
135
+ **FastAPI:**
136
+ ```python
137
+ @app.get("/api/weather")
138
+ async def get_weather():
139
+ return {"temperature": 72, "unit": "F"}
140
+ ```
141
+
142
+ **Flask:**
143
+ ```python
144
+ @app.route("/api/weather")
145
+ def get_weather():
146
+ return {"temperature": 72, "unit": "F"}
147
+ ```
148
+
149
+ ## Important Rules / Guidelines
150
+
151
+ 1. **Match async/sync variants** -- FastAPI uses `x402ResourceServer` + `HTTPFacilitatorClient`, Flask uses `x402ResourceServerSync` + `HTTPFacilitatorClientSync`
152
+ 2. **Route format** -- Keys must be `"METHOD /path"` (e.g., `"GET /api/weather"`, `"POST /api/generate/*"`)
153
+ 3. **Wildcard paths** -- Use `/*` suffix to match all sub-paths (e.g., `"GET /api/premium/*"`)
154
+ 4. **Unlisted routes pass through** -- Only routes in the config require payment
155
+ 5. **Register scheme before middleware** -- Call `server.register(...)` before adding middleware
156
+ 6. **Price format** -- Use `"$0.01"` for auto-conversion or `AssetAmount(amount="10000", asset="10458941")` for explicit control
157
+ 7. **CAIP-2 network IDs** -- Use full CAIP-2 identifiers like `"algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="`
158
+
159
+ ## Pricing Options
160
+
161
+ ### Simple String Price
162
+
163
+ ```python
164
+ PaymentOption(
165
+ scheme="exact",
166
+ network="algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
167
+ pay_to="YOUR_ADDRESS",
168
+ price="$0.01", # Auto-converts to 10000 microUSDC
169
+ )
170
+ ```
171
+
172
+ ### Explicit AssetAmount
173
+
174
+ ```python
175
+ from x402.schemas import AssetAmount
176
+
177
+ PaymentOption(
178
+ scheme="exact",
179
+ network="algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
180
+ pay_to="YOUR_ADDRESS",
181
+ price=AssetAmount(
182
+ amount="50000", # 50000 microUSDC = $0.05
183
+ asset="10458941", # USDC ASA ID on testnet
184
+ extra={"name": "USDC", "decimals": 6},
185
+ ),
186
+ )
187
+ ```
188
+
189
+ ### Multi-Network (AVM + EVM + SVM)
190
+
191
+ ```python
192
+ routes = {
193
+ "GET /api/data/*": RouteConfig(
194
+ accepts=[
195
+ PaymentOption(scheme="exact", pay_to=AVM_ADDRESS, price="$0.01",
196
+ network="algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="),
197
+ PaymentOption(scheme="exact", pay_to=EVM_ADDRESS, price="$0.01",
198
+ network="eip155:84532"),
199
+ PaymentOption(scheme="exact", pay_to=SVM_ADDRESS, price="$0.01",
200
+ network="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"),
201
+ ],
202
+ ),
203
+ }
204
+ ```
205
+
206
+ ## Common Errors / Troubleshooting
207
+
208
+ | Error | Cause | Solution |
209
+ |-------|-------|----------|
210
+ | `TypeError: async` errors in Flask | Using async variants with Flask | Use `x402ResourceServerSync` and `HTTPFacilitatorClientSync` |
211
+ | 402 returned to all requests | Middleware applied but facilitator unreachable | Check `FACILITATOR_URL` and network connectivity |
212
+ | Route not protected | Path pattern mismatch | Verify route key format matches: `"GET /exact/path"` or `"GET /prefix/*"` |
213
+ | Settlement fails | Facilitator cannot reach Algorand network | Check facilitator logs and algod endpoint |
214
+ | `ImportError` on middleware | Missing extras | `pip install "x402-avm[fastapi,avm]"` or `"x402-avm[flask,avm]"` |
215
+
216
+ ## References / Further Reading
217
+
218
+ - [create-python-x402-server-reference.md](./create-python-x402-server-reference.md) - Detailed API reference for middleware
219
+ - [create-python-x402-server-examples.md](./create-python-x402-server-examples.md) - Complete code examples for FastAPI and Flask
220
+ - [x402-avm Examples Repository](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
221
+ - [x402 Algorand Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)