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 +38 -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,408 @@
1
+ # Creating Python x402 Facilitator Services and Bazaar Discovery
2
+
3
+ Build FastAPI-based facilitator services that verify and settle x402 payments on-chain for Algorand (AVM), with optional multi-network support for EVM and SVM. Includes Bazaar discovery extension for automatic cataloging and indexing of payment-gated APIs.
4
+
5
+ ## Prerequisites
6
+
7
+ Before using this skill, ensure:
8
+
9
+ 1. **Python 3.10+** is installed
10
+ 2. **x402-avm package** is available: `pip install "x402-avm[avm,fastapi]"`
11
+ 3. **Algorand private key** is available as a Base64-encoded 64-byte key (32-byte seed + 32-byte pubkey) in `AVM_PRIVATE_KEY` environment variable
12
+ 4. **Algod node access** via AlgoNode (default) or custom node via `ALGOD_SERVER` / `ALGOD_TOKEN`
13
+
14
+ ## Core Workflow: Facilitator Payment Lifecycle
15
+
16
+ The facilitator sits between the resource server and the blockchain, handling payment verification and settlement:
17
+
18
+ ```
19
+ Resource Server Facilitator Blockchain
20
+ | | |
21
+ |--- /verify (payload) ---->| |
22
+ | |-- simulate_group() -------->|
23
+ | |<-- simulation result -------|
24
+ |<-- {isValid: true} -------| |
25
+ | | |
26
+ |--- /settle (payload) ---->| |
27
+ | |-- sign_group() ------------>|
28
+ | |-- send_group() ------------>|
29
+ | |<-- txid --------------------|
30
+ | |-- confirm_transaction() --->|
31
+ |<-- {success, txid} -------| |
32
+ ```
33
+
34
+ ## How to Proceed
35
+
36
+ ### Step 1: Install Dependencies
37
+
38
+ ```bash
39
+ pip install "x402-avm[avm,fastapi]"
40
+ ```
41
+
42
+ This installs `py-algorand-sdk` (algosdk), FastAPI, uvicorn, and the x402-avm SDK.
43
+
44
+ ### Step 2: Implement FacilitatorAvmSigner
45
+
46
+ The `FacilitatorAvmSigner` protocol defines six methods. Implement all of them using `algosdk`:
47
+
48
+ ```python
49
+ import os
50
+ import base64
51
+ from algosdk import encoding, transaction
52
+ from algosdk.v2client import algod
53
+ from x402.mechanisms.avm.constants import NETWORK_CONFIGS
54
+
55
+
56
+ class AlgorandFacilitatorSigner:
57
+ def __init__(self, private_key_b64: str, algod_url: str = "", algod_token: str = ""):
58
+ self._secret_key = base64.b64decode(private_key_b64)
59
+ self._address = encoding.encode_address(self._secret_key[32:])
60
+ self._signing_key = base64.b64encode(self._secret_key).decode()
61
+ self._clients: dict[str, algod.AlgodClient] = {}
62
+ if algod_url:
63
+ self._default_client = algod.AlgodClient(algod_token, algod_url)
64
+ else:
65
+ self._default_client = None
66
+
67
+ def _get_client(self, network: str) -> algod.AlgodClient:
68
+ if network not in self._clients:
69
+ if self._default_client:
70
+ self._clients[network] = self._default_client
71
+ else:
72
+ config = NETWORK_CONFIGS.get(network, {})
73
+ url = config.get("algod_url", "https://testnet-api.algonode.cloud")
74
+ self._clients[network] = algod.AlgodClient("", url)
75
+ return self._clients[network]
76
+
77
+ def get_addresses(self) -> list[str]:
78
+ return [self._address]
79
+
80
+ def sign_transaction(self, txn_bytes: bytes, fee_payer: str, network: str) -> bytes:
81
+ b64 = base64.b64encode(txn_bytes).decode("utf-8")
82
+ txn_obj = encoding.msgpack_decode(b64)
83
+ signed = txn_obj.sign(self._signing_key)
84
+ return base64.b64decode(encoding.msgpack_encode(signed))
85
+
86
+ def sign_group(self, group_bytes, fee_payer, indexes_to_sign, network):
87
+ result = list(group_bytes)
88
+ for i in indexes_to_sign:
89
+ result[i] = self.sign_transaction(group_bytes[i], fee_payer, network)
90
+ return result
91
+
92
+ def simulate_group(self, group_bytes, network):
93
+ client = self._get_client(network)
94
+ stxns = []
95
+ for txn_bytes in group_bytes:
96
+ b64 = base64.b64encode(txn_bytes).decode("utf-8")
97
+ obj = encoding.msgpack_decode(b64)
98
+ if isinstance(obj, transaction.SignedTransaction):
99
+ stxns.append(obj)
100
+ else:
101
+ stxns.append(transaction.SignedTransaction(obj, None))
102
+ req = transaction.SimulateRequest(
103
+ txn_groups=[transaction.SimulateRequestTransactionGroup(txns=stxns)],
104
+ allow_empty_signatures=True,
105
+ )
106
+ result = client.simulate_raw_transactions(req)
107
+ for group in result.get("txn-groups", []):
108
+ if group.get("failure-message"):
109
+ raise Exception(f"Simulation failed: {group['failure-message']}")
110
+
111
+ def send_group(self, group_bytes, network):
112
+ client = self._get_client(network)
113
+ return client.send_raw_transaction(base64.b64encode(b"".join(group_bytes)))
114
+
115
+ def confirm_transaction(self, txid, network, rounds=4):
116
+ client = self._get_client(network)
117
+ transaction.wait_for_confirmation(client, txid, rounds)
118
+ ```
119
+
120
+ ### Step 3: Register the Signer with x402Facilitator
121
+
122
+ ```python
123
+ from x402 import x402Facilitator
124
+ from x402.mechanisms.avm.exact import register_exact_avm_facilitator
125
+ from x402.mechanisms.avm import ALGORAND_TESTNET_CAIP2, ALGORAND_MAINNET_CAIP2
126
+
127
+ signer = AlgorandFacilitatorSigner(
128
+ private_key_b64=os.environ["AVM_PRIVATE_KEY"],
129
+ algod_url=os.environ.get("ALGOD_SERVER", ""),
130
+ algod_token=os.environ.get("ALGOD_TOKEN", ""),
131
+ )
132
+
133
+ facilitator = x402Facilitator()
134
+ register_exact_avm_facilitator(
135
+ facilitator,
136
+ signer,
137
+ networks=[ALGORAND_TESTNET_CAIP2, ALGORAND_MAINNET_CAIP2],
138
+ )
139
+ ```
140
+
141
+ ### Step 4: Create FastAPI Endpoints
142
+
143
+ ```python
144
+ from fastapi import FastAPI, Request
145
+ from fastapi.responses import JSONResponse
146
+
147
+ app = FastAPI(title="x402-avm Facilitator Service")
148
+
149
+ @app.get("/supported")
150
+ async def supported():
151
+ return facilitator.get_supported_networks()
152
+
153
+ @app.post("/verify")
154
+ async def verify(request: Request):
155
+ body = await request.json()
156
+ try:
157
+ result = await facilitator.verify(
158
+ body["paymentPayload"], body["paymentRequirements"]
159
+ )
160
+ return result
161
+ except Exception as e:
162
+ return JSONResponse(status_code=400, content={"error": str(e)})
163
+
164
+ @app.post("/settle")
165
+ async def settle(request: Request):
166
+ body = await request.json()
167
+ try:
168
+ result = await facilitator.settle(
169
+ body["paymentPayload"], body["paymentRequirements"]
170
+ )
171
+ return result
172
+ except Exception as e:
173
+ return JSONResponse(status_code=400, content={"error": str(e)})
174
+ ```
175
+
176
+ ### Step 5: Run the Service
177
+
178
+ ```bash
179
+ AVM_PRIVATE_KEY="your-base64-key" uvicorn facilitator_service:app --port 4000
180
+ ```
181
+
182
+ ## Important Rules / Guidelines
183
+
184
+ 1. **algosdk encoding boundaries** -- `msgpack_decode()` expects a base64 string, not raw bytes. Always convert: `base64.b64encode(raw_bytes).decode("utf-8")` before decoding. `msgpack_encode()` returns a base64 string; convert back with `base64.b64decode()`.
185
+ 2. **Private key format** -- `Transaction.sign()` expects a base64-encoded string of the 64-byte key, not raw bytes.
186
+ 3. **send_group pattern** -- Use `send_raw_transaction(base64.b64encode(b"".join(group_bytes)))` to avoid unnecessary decode/re-encode overhead.
187
+ 4. **simulate_group pattern** -- Wrap unsigned transactions with `SignedTransaction(txn, None)` and use `allow_empty_signatures=True`.
188
+ 5. **Address derivation** -- Use `encoding.encode_address(secret_key[32:])` to derive the address from the 64-byte key.
189
+ 6. **First-class AVM** -- Register AVM unconditionally, never behind `if (env.AVM_*)` guards.
190
+ 7. **Network constants** -- Import `ALGORAND_TESTNET_CAIP2` and `ALGORAND_MAINNET_CAIP2` from the SDK; do not hardcode genesis hashes in application code.
191
+
192
+ ## Lifecycle Hooks
193
+
194
+ The `x402Facilitator` supports lifecycle hooks for custom logic:
195
+
196
+ | Hook | When Called | Use Case |
197
+ |------|-----------|----------|
198
+ | `on_before_verify` | Before payment verification | Logging, rate limiting |
199
+ | `on_after_verify` | After verification completes | Analytics, caching |
200
+ | `on_before_settle` | Before settlement submission | Final validation |
201
+ | `on_after_settle` | After settlement completes | Notification, receipts |
202
+
203
+ ## Common Errors / Troubleshooting
204
+
205
+ | Error | Cause | Solution |
206
+ |-------|-------|----------|
207
+ | `msgpack_decode expects string` | Passing raw bytes to `msgpack_decode` | Wrap with `base64.b64encode(raw).decode()` |
208
+ | `Invalid key length` | Wrong private key format | Ensure `AVM_PRIVATE_KEY` is base64-encoded 64 bytes |
209
+ | `Simulation failed` | Transaction would fail on-chain | Check balances, asset opt-in, fee amounts |
210
+ | `send_raw_transaction expects bytes-like` | Wrong argument type | Use `base64.b64encode(b"".join(group_bytes))` |
211
+ | `Transaction not confirmed` | Node timeout or network issue | Increase `rounds` parameter or check node connectivity |
212
+ | `send_transactions asserts NOT Transaction` | Passing unsigned `Transaction` to `send_transactions` | Use `send_raw_transaction` instead |
213
+
214
+ ---
215
+
216
+ ## Bazaar Discovery Extension
217
+
218
+ Bazaar is a resource discovery protocol built into x402. It allows payment-gated APIs to advertise:
219
+
220
+ - **What they accept as input** -- query parameters for GET/HEAD/DELETE, or request body schemas for POST/PUT/PATCH
221
+ - **What they return as output** -- the shape, type, and examples of the response data
222
+
223
+ This metadata enables facilitators to automatically catalog and index x402-enabled resources, so clients can discover APIs by their capabilities rather than just by URL. It is a machine-readable menu for paid APIs.
224
+
225
+ ```
226
+ Resource Server (declares) Facilitator (catalogs) Client (discovers)
227
+ +---------------------------+ +----------------------+ +-------------------+
228
+ | RouteConfig + extensions: | | extract_discovery_ | | with_bazaar() |
229
+ | **declare_discovery_ | ---> | info() | ---> | .list_resources()|
230
+ | extension(...) | | validate_discovery_ | | |
231
+ +---------------------------+ | extension() | +-------------------+
232
+ +----------------------+
233
+ ```
234
+
235
+ ### Bazaar Prerequisites
236
+
237
+ 1. **x402-avm with extensions** is available: `pip install "x402-avm[extensions,avm]"`
238
+ 2. **Web framework** installed: `pip install "x402-avm[extensions,avm,fastapi]"` or `[...,flask]`
239
+
240
+ The `extensions` extra installs `jsonschema>=4.0.0` for schema validation.
241
+
242
+ ### Step 6: Declare Discovery Extensions on Routes
243
+
244
+ Use `declare_discovery_extension()` on your route configurations to describe what each endpoint accepts and returns.
245
+
246
+ **For GET endpoints (query parameters):**
247
+
248
+ ```python
249
+ from x402.extensions.bazaar import declare_discovery_extension, OutputConfig
250
+
251
+ discovery = declare_discovery_extension(
252
+ input={"city": "San Francisco"},
253
+ input_schema={
254
+ "properties": {
255
+ "city": {"type": "string", "description": "City name"},
256
+ },
257
+ "required": ["city"],
258
+ },
259
+ output=OutputConfig(
260
+ example={"weather": "sunny", "temperature": 70},
261
+ schema={
262
+ "properties": {
263
+ "weather": {"type": "string"},
264
+ "temperature": {"type": "number"},
265
+ },
266
+ "required": ["weather", "temperature"],
267
+ },
268
+ ),
269
+ )
270
+ ```
271
+
272
+ **For POST endpoints (JSON body):**
273
+
274
+ ```python
275
+ discovery = declare_discovery_extension(
276
+ input={"prompt": "Tell me about Algorand", "max_tokens": 100},
277
+ input_schema={
278
+ "properties": {
279
+ "prompt": {"type": "string"},
280
+ "max_tokens": {"type": "integer"},
281
+ },
282
+ "required": ["prompt"],
283
+ },
284
+ body_type="json",
285
+ output=OutputConfig(
286
+ example={"text": "Algorand is a...", "tokens_used": 42},
287
+ ),
288
+ )
289
+ ```
290
+
291
+ ### Step 7: Add Extensions to Route Configuration
292
+
293
+ Spread the discovery dict into your route's `extensions` field:
294
+
295
+ ```python
296
+ from x402.http import PaymentOption
297
+ from x402.http.types import RouteConfig
298
+ from x402.schemas import Network
299
+
300
+ AVM_NETWORK: Network = "algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="
301
+
302
+ routes = {
303
+ "GET /weather": RouteConfig(
304
+ accepts=[
305
+ PaymentOption(
306
+ scheme="exact",
307
+ pay_to=AVM_ADDRESS,
308
+ price="$0.001",
309
+ network=AVM_NETWORK,
310
+ ),
311
+ ],
312
+ description="Weather report",
313
+ mime_type="application/json",
314
+ extensions={
315
+ **declare_discovery_extension(
316
+ input={"city": "San Francisco"},
317
+ input_schema={
318
+ "properties": {"city": {"type": "string"}},
319
+ "required": ["city"],
320
+ },
321
+ output=OutputConfig(
322
+ example={"weather": "sunny", "temperature": 70},
323
+ ),
324
+ )
325
+ },
326
+ ),
327
+ }
328
+ ```
329
+
330
+ ### Step 8: Register Bazaar Extension on Server
331
+
332
+ ```python
333
+ from x402.server import x402ResourceServer
334
+ from x402.http import FacilitatorConfig, HTTPFacilitatorClient
335
+ from x402.extensions.bazaar import bazaar_resource_server_extension
336
+ from x402.mechanisms.avm.exact import ExactAvmServerScheme
337
+
338
+ facilitator = HTTPFacilitatorClient(FacilitatorConfig(url="https://x402.org/facilitator"))
339
+ server = x402ResourceServer(facilitator)
340
+ server.register(AVM_NETWORK, ExactAvmServerScheme())
341
+ server.register_extension(bazaar_resource_server_extension)
342
+ ```
343
+
344
+ ### Step 9: Extract and Validate on Facilitator Side
345
+
346
+ ```python
347
+ from x402.extensions.bazaar import extract_discovery_info, validate_discovery_extension
348
+
349
+ # Extract discovery info from a payment request
350
+ discovered = extract_discovery_info(
351
+ payment_payload=payment_payload,
352
+ payment_requirements=payment_requirements,
353
+ validate=True,
354
+ )
355
+
356
+ if discovered:
357
+ print(f"URL: {discovered.resource_url}")
358
+ print(f"Method: {discovered.method}")
359
+ print(f"Description: {discovered.description}")
360
+ ```
361
+
362
+ ### Step 10: Apply Payment Middleware with Bazaar
363
+
364
+ **FastAPI:**
365
+
366
+ ```python
367
+ from fastapi import FastAPI
368
+ from x402.http.middleware.fastapi import PaymentMiddlewareASGI
369
+
370
+ app = FastAPI()
371
+ app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)
372
+ ```
373
+
374
+ **Flask:**
375
+
376
+ ```python
377
+ from flask import Flask
378
+ from x402.http.middleware.flask import payment_middleware
379
+
380
+ app = Flask(__name__)
381
+ payment_middleware(app, routes=routes, server=server)
382
+ ```
383
+
384
+ ### Bazaar Rules / Guidelines
385
+
386
+ 1. **Discovery is chain-agnostic** -- The same Bazaar metadata applies regardless of which payment network (AVM, EVM, SVM) the client uses.
387
+ 2. **Extensions spread into routes** -- Use `**declare_discovery_extension(...)` to merge the `{"bazaar": {...}}` dict into the route's `extensions` dict.
388
+ 3. **body_type determines input type** -- `None` (default) creates a query extension (GET/HEAD/DELETE). `"json"` creates a body extension (POST/PUT/PATCH).
389
+ 4. **Server extension is required** -- Register `bazaar_resource_server_extension` on the server to enrich declarations with HTTP method at runtime.
390
+ 5. **Validation uses jsonschema** -- The `[extensions]` extra installs jsonschema. Validation checks that `info` data conforms to its `schema`.
391
+
392
+ ### Bazaar Common Errors
393
+
394
+ | Error | Cause | Solution |
395
+ |-------|-------|----------|
396
+ | `ImportError: jsonschema` | Missing `[extensions]` extra | Install with `pip install "x402-avm[extensions]"` |
397
+ | `KeyError: 'bazaar'` | Extension not declared on route | Add `**declare_discovery_extension(...)` to route config `extensions` |
398
+ | `ValidationResult.valid is False` | Extension info does not match schema | Check that example data matches the declared input/output schema |
399
+ | `discovered is None` | No Bazaar extension in the payment request | Ensure both server-side declaration and extension registration are in place |
400
+ | `body_type not set for POST` | POST route treated as query extension | Add `body_type="json"` to `declare_discovery_extension()` |
401
+
402
+ ## References / Further Reading
403
+
404
+ - [create-python-x402-facilitator-reference.md](./create-python-x402-facilitator-reference.md) -- Detailed API reference for FacilitatorAvmSigner protocol and Bazaar extension
405
+ - [create-python-x402-facilitator-examples.md](./create-python-x402-facilitator-examples.md) -- Complete code examples (including Bazaar discovery)
406
+ - [Facilitator Example](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/python/facilitator)
407
+ - [Extensions Examples](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
408
+ - [x402-avm AVM Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)