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,629 @@
1
+ # Python x402 Facilitator and Bazaar Discovery Reference
2
+
3
+ Detailed API reference for building x402 facilitator services in Python with Algorand (AVM) support, including Bazaar discovery extension.
4
+
5
+ ## FacilitatorAvmSigner Protocol
6
+
7
+ The `FacilitatorAvmSigner` is a Python Protocol class (structural typing -- no inheritance required). Any class implementing all six methods satisfies the protocol.
8
+
9
+ **Import:**
10
+ ```python
11
+ from x402.mechanisms.avm.signer import FacilitatorAvmSigner
12
+ ```
13
+
14
+ ### Method: `get_addresses()`
15
+
16
+ ```python
17
+ def get_addresses(self) -> list[str]:
18
+ ```
19
+
20
+ Returns all managed fee payer addresses. The facilitator uses these addresses to identify which transactions it is responsible for signing in an atomic group.
21
+
22
+ - **Returns:** List of 58-character Algorand addresses
23
+ - **Typical implementation:** Returns a single-element list with the facilitator's address
24
+
25
+ ### Method: `sign_transaction()`
26
+
27
+ ```python
28
+ def sign_transaction(
29
+ self, txn_bytes: bytes, fee_payer: str, network: str,
30
+ ) -> bytes:
31
+ ```
32
+
33
+ Signs a single transaction with the fee payer's private key.
34
+
35
+ - **Parameters:**
36
+ - `txn_bytes` -- Raw msgpack-encoded unsigned transaction bytes
37
+ - `fee_payer` -- 58-character Algorand address of the fee payer
38
+ - `network` -- CAIP-2 network identifier (e.g., `"algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="`)
39
+ - **Returns:** Raw msgpack-encoded signed transaction bytes
40
+ - **Encoding note:** Must convert `txn_bytes` to base64 before calling `msgpack_decode()`, then convert `msgpack_encode()` result back from base64
41
+
42
+ ### Method: `sign_group()`
43
+
44
+ ```python
45
+ def sign_group(
46
+ self,
47
+ group_bytes: list[bytes],
48
+ fee_payer: str,
49
+ indexes_to_sign: list[int],
50
+ network: str,
51
+ ) -> list[bytes]:
52
+ ```
53
+
54
+ Signs specified transactions in an atomic group.
55
+
56
+ - **Parameters:**
57
+ - `group_bytes` -- List of raw msgpack-encoded transaction bytes (mix of signed and unsigned)
58
+ - `fee_payer` -- 58-character Algorand address
59
+ - `indexes_to_sign` -- Indexes of transactions this facilitator should sign
60
+ - `network` -- CAIP-2 network identifier
61
+ - **Returns:** Updated list with signed bytes at specified indexes, unchanged bytes elsewhere
62
+ - **Typical pattern:** Delegates to `sign_transaction()` for each index
63
+
64
+ ### Method: `simulate_group()`
65
+
66
+ ```python
67
+ def simulate_group(
68
+ self, group_bytes: list[bytes], network: str,
69
+ ) -> None:
70
+ ```
71
+
72
+ Simulates a transaction group to verify it would succeed on-chain. Raises an exception if simulation fails.
73
+
74
+ - **Parameters:**
75
+ - `group_bytes` -- List of raw msgpack-encoded transaction bytes
76
+ - `network` -- CAIP-2 network identifier
77
+ - **Returns:** None (raises on failure)
78
+ - **Key pattern:** Wrap unsigned `Transaction` objects with `SignedTransaction(txn, None)` and set `allow_empty_signatures=True`
79
+ - **Checks:** Iterates `txn-groups` in simulation result for `failure-message`
80
+
81
+ ### Method: `send_group()`
82
+
83
+ ```python
84
+ def send_group(
85
+ self, group_bytes: list[bytes], network: str,
86
+ ) -> str:
87
+ ```
88
+
89
+ Sends a fully signed transaction group to the network.
90
+
91
+ - **Parameters:**
92
+ - `group_bytes` -- List of raw msgpack-encoded signed transaction bytes
93
+ - `network` -- CAIP-2 network identifier
94
+ - **Returns:** Transaction ID string
95
+ - **Key pattern:** Use `send_raw_transaction(base64.b64encode(b"".join(group_bytes)))` to concatenate and send all transactions efficiently
96
+ - **Important:** Do NOT use `send_transactions()` which asserts inputs are NOT `Transaction` type
97
+
98
+ ### Method: `confirm_transaction()`
99
+
100
+ ```python
101
+ def confirm_transaction(
102
+ self, txid: str, network: str, rounds: int = 4,
103
+ ) -> None:
104
+ ```
105
+
106
+ Waits for transaction confirmation on the blockchain.
107
+
108
+ - **Parameters:**
109
+ - `txid` -- Transaction ID returned by `send_group()`
110
+ - `network` -- CAIP-2 network identifier
111
+ - `rounds` -- Maximum number of rounds to wait (default: 4)
112
+ - **Returns:** None (raises on timeout)
113
+ - **Note:** Algorand has instant finality; once confirmed, the transaction is permanent
114
+
115
+ ---
116
+
117
+ ## register_exact_avm_facilitator
118
+
119
+ ```python
120
+ from x402.mechanisms.avm.exact import register_exact_avm_facilitator
121
+
122
+ register_exact_avm_facilitator(
123
+ facilitator: x402Facilitator,
124
+ signer: FacilitatorAvmSigner,
125
+ networks: list[str] = None,
126
+ )
127
+ ```
128
+
129
+ Registers the AVM exact payment scheme on a facilitator instance.
130
+
131
+ - **Parameters:**
132
+ - `facilitator` -- An `x402Facilitator` instance
133
+ - `signer` -- Any object implementing the `FacilitatorAvmSigner` protocol
134
+ - `networks` -- List of CAIP-2 network identifiers to register for. Defaults to `[ALGORAND_TESTNET_CAIP2, ALGORAND_MAINNET_CAIP2]`
135
+
136
+ ---
137
+
138
+ ## ExactAvmFacilitatorScheme
139
+
140
+ The scheme class registered by `register_exact_avm_facilitator`. It handles:
141
+
142
+ - **Verification:** Decodes the payment group, validates transaction structure, simulates on-chain
143
+ - **Settlement:** Signs the fee payer transaction, sends the atomic group, confirms on-chain
144
+ - **Security validation:** Checks for rekey attacks, close-to exploits, blocked transaction types
145
+
146
+ ---
147
+
148
+ ## Multi-Network Facilitator (EVM + SVM + AVM)
149
+
150
+ A facilitator can support multiple blockchain networks simultaneously:
151
+
152
+ ```python
153
+ from x402 import x402Facilitator
154
+
155
+ # EVM registration
156
+ from x402.mechanisms.evm.exact import register_exact_evm_facilitator
157
+ # SVM registration
158
+ from x402.mechanisms.svm.exact import register_exact_svm_facilitator
159
+ # AVM registration
160
+ from x402.mechanisms.avm.exact import register_exact_avm_facilitator
161
+
162
+ facilitator = x402Facilitator()
163
+
164
+ # Register all networks
165
+ register_exact_evm_facilitator(facilitator, evm_signer)
166
+ register_exact_svm_facilitator(facilitator, svm_signer)
167
+ register_exact_avm_facilitator(facilitator, avm_signer, networks=[ALGORAND_TESTNET_CAIP2])
168
+ ```
169
+
170
+ **Signer types by network:**
171
+
172
+ | Network | Signer Type | Import |
173
+ |---------|------------|--------|
174
+ | EVM | `FacilitatorWeb3Signer` | `from x402.mechanisms.evm.signer import FacilitatorWeb3Signer` |
175
+ | SVM | `FacilitatorKeypairSigner` | `from x402.mechanisms.svm.signer import FacilitatorKeypairSigner` |
176
+ | AVM | `FacilitatorAvmSigner` | `from x402.mechanisms.avm.signer import FacilitatorAvmSigner` |
177
+
178
+ ---
179
+
180
+ ## Facilitator Lifecycle Hooks
181
+
182
+ | Hook | Signature | Description |
183
+ |------|-----------|-------------|
184
+ | `on_before_verify` | `(payload, requirements) -> None` | Called before payment verification |
185
+ | `on_after_verify` | `(payload, requirements, result) -> None` | Called after verification completes |
186
+ | `on_before_settle` | `(payload, requirements) -> None` | Called before settlement submission |
187
+ | `on_after_settle` | `(payload, requirements, result) -> None` | Called after settlement completes |
188
+
189
+ ---
190
+
191
+ ## Environment Variables
192
+
193
+ | Variable | Required | Description | Default |
194
+ |----------|----------|-------------|---------|
195
+ | `AVM_PRIVATE_KEY` | Yes | Base64-encoded 64-byte key (32-byte seed + 32-byte pubkey) | -- |
196
+ | `ALGOD_SERVER` | No | Custom Algod node URL | AlgoNode public endpoint |
197
+ | `ALGOD_TOKEN` | No | Algod API token | `""` |
198
+ | `ALGOD_MAINNET_URL` | No | Mainnet Algod URL | `https://mainnet-api.algonode.cloud` |
199
+ | `ALGOD_TESTNET_URL` | No | Testnet Algod URL | `https://testnet-api.algonode.cloud` |
200
+
201
+ ---
202
+
203
+ ## algosdk Encoding Reference (v2.11.1)
204
+
205
+ The Python `algosdk` has different encoding conventions than the TypeScript version. This is the most common source of bugs:
206
+
207
+ | Operation | Python algosdk | TypeScript algosdk |
208
+ |-----------|---------------|-------------------|
209
+ | `msgpack_decode(s)` | Expects **base64 string** | N/A (uses `decodeUnsignedTransaction(Uint8Array)`) |
210
+ | `msgpack_encode(obj)` | Returns **base64 string** | N/A (uses `txn.toByte()` returning `Uint8Array`) |
211
+ | `Transaction.sign(key)` | Expects **base64 string** key | `signTransaction(txn, Uint8Array)` |
212
+ | SDK protocol | Passes **raw msgpack bytes** | Passes **raw `Uint8Array`** |
213
+
214
+ **Boundary conversion patterns:**
215
+
216
+ ```python
217
+ import base64
218
+ from algosdk import encoding
219
+
220
+ # Raw bytes -> algosdk object (DECODE)
221
+ raw_bytes: bytes = ...
222
+ b64_string = base64.b64encode(raw_bytes).decode("utf-8")
223
+ txn_obj = encoding.msgpack_decode(b64_string)
224
+
225
+ # algosdk object -> raw bytes (ENCODE)
226
+ b64_string = encoding.msgpack_encode(txn_obj)
227
+ raw_bytes = base64.b64decode(b64_string)
228
+ ```
229
+
230
+ ---
231
+
232
+ ## API Endpoints
233
+
234
+ A standard x402 facilitator exposes three endpoints:
235
+
236
+ | Endpoint | Method | Description | Request Body |
237
+ |----------|--------|-------------|-------------|
238
+ | `/supported` | GET | List supported networks | -- |
239
+ | `/verify` | POST | Verify a payment payload | `{paymentPayload, paymentRequirements}` |
240
+ | `/settle` | POST | Settle a verified payment | `{paymentPayload, paymentRequirements}` |
241
+
242
+ ---
243
+
244
+ ## Installation Commands
245
+
246
+ ```bash
247
+ # Minimal facilitator
248
+ pip install "x402-avm[avm,fastapi]"
249
+
250
+ # With uvicorn for production
251
+ pip install "x402-avm[avm,fastapi]" uvicorn
252
+
253
+ # Multi-chain facilitator (EVM + SVM + AVM)
254
+ pip install "x402-avm[all,fastapi]"
255
+
256
+ # Everything
257
+ pip install "x402-avm[all]"
258
+ ```
259
+
260
+ ---
261
+
262
+ ## Testing
263
+
264
+ ```bash
265
+ # Start the facilitator
266
+ AVM_PRIVATE_KEY="your-key" uvicorn facilitator_service:app --port 4000
267
+
268
+ # Check supported networks
269
+ curl http://localhost:4000/supported
270
+
271
+ # Verify a payment (with actual payload)
272
+ curl -X POST http://localhost:4000/verify \
273
+ -H "Content-Type: application/json" \
274
+ -d '{"paymentPayload": {...}, "paymentRequirements": {...}}'
275
+ ```
276
+
277
+ ---
278
+
279
+ ---
280
+
281
+ ## Bazaar Extension API
282
+
283
+ ### declare_discovery_extension()
284
+
285
+ ```python
286
+ from x402.extensions.bazaar import declare_discovery_extension
287
+ ```
288
+
289
+ Creates a discovery extension dict for route configuration.
290
+
291
+ **Signature:**
292
+ ```python
293
+ def declare_discovery_extension(
294
+ input: dict,
295
+ input_schema: dict,
296
+ body_type: str | None = None,
297
+ output: OutputConfig | None = None,
298
+ ) -> dict:
299
+ ```
300
+
301
+ **Parameters:**
302
+
303
+ | Parameter | Type | Required | Description |
304
+ |-----------|------|----------|-------------|
305
+ | `input` | `dict` | Yes | Example values for query parameters or request body |
306
+ | `input_schema` | `dict` | Yes | JSON Schema describing the expected input |
307
+ | `body_type` | `str` or `None` | No | `None` for query (GET), `"json"` / `"form-data"` / `"text"` for body (POST) |
308
+ | `output` | `OutputConfig` or `None` | No | Output configuration with example and optional schema |
309
+
310
+ **Returns:** `{"bazaar": {"info": {...}, "schema": {...}}}`
311
+
312
+ **body_type values:**
313
+
314
+ | Value | HTTP Methods | Description |
315
+ |-------|-------------|-------------|
316
+ | `None` (default) | GET, HEAD, DELETE | Query parameter extension |
317
+ | `"json"` | POST, PUT, PATCH | JSON body extension |
318
+ | `"form-data"` | POST, PUT, PATCH | Form-data body extension |
319
+ | `"text"` | POST, PUT, PATCH | Plain text body extension |
320
+
321
+ ---
322
+
323
+ ### extract_discovery_info()
324
+
325
+ ```python
326
+ from x402.extensions.bazaar import extract_discovery_info
327
+ ```
328
+
329
+ Extracts discovery info from a payment request. Handles both v2 (extensions in PaymentPayload) and v1 (output_schema in PaymentRequirements) formats.
330
+
331
+ **Signature:**
332
+ ```python
333
+ def extract_discovery_info(
334
+ payment_payload: PaymentPayload | dict,
335
+ payment_requirements: PaymentRequirements | dict,
336
+ validate: bool = True,
337
+ ) -> DiscoveredResource | None:
338
+ ```
339
+
340
+ **Parameters:**
341
+
342
+ | Parameter | Type | Required | Description |
343
+ |-----------|------|----------|-------------|
344
+ | `payment_payload` | `PaymentPayload` or `dict` | Yes | The payment payload from the client |
345
+ | `payment_requirements` | `PaymentRequirements` or `dict` | Yes | The payment requirements from the server |
346
+ | `validate` | `bool` | No | Validate v2 extensions before extracting (default: `True`) |
347
+
348
+ **Returns:** `DiscoveredResource` or `None` if no Bazaar extension found
349
+
350
+ ---
351
+
352
+ ### extract_discovery_info_from_extension()
353
+
354
+ ```python
355
+ from x402.extensions.bazaar import extract_discovery_info_from_extension
356
+ ```
357
+
358
+ Extracts discovery info from an extension object directly.
359
+
360
+ **Signature:**
361
+ ```python
362
+ def extract_discovery_info_from_extension(
363
+ extension: dict | DiscoveryExtension,
364
+ validate: bool = True,
365
+ ) -> DiscoveryInfo:
366
+ ```
367
+
368
+ **Parameters:**
369
+
370
+ | Parameter | Type | Required | Description |
371
+ |-----------|------|----------|-------------|
372
+ | `extension` | `dict` or `DiscoveryExtension` | Yes | Extension with `"info"` and `"schema"` keys |
373
+ | `validate` | `bool` | No | Raises `ValueError` if validation fails (default: `True`) |
374
+
375
+ **Returns:** `QueryDiscoveryInfo` or `BodyDiscoveryInfo`
376
+
377
+ ---
378
+
379
+ ### validate_discovery_extension()
380
+
381
+ ```python
382
+ from x402.extensions.bazaar import validate_discovery_extension
383
+ ```
384
+
385
+ Validates that an extension's `info` data conforms to its `schema`.
386
+
387
+ **Signature:**
388
+ ```python
389
+ def validate_discovery_extension(
390
+ extension: dict | DiscoveryExtension,
391
+ ) -> ValidationResult:
392
+ ```
393
+
394
+ **Parameters:**
395
+
396
+ | Parameter | Type | Required | Description |
397
+ |-----------|------|----------|-------------|
398
+ | `extension` | `dict` or `DiscoveryExtension` | Yes | Extension to validate |
399
+
400
+ **Returns:** `ValidationResult` with `valid: bool` and `errors: list[str]`
401
+
402
+ ---
403
+
404
+ ### validate_and_extract()
405
+
406
+ ```python
407
+ from x402.extensions.bazaar import validate_and_extract
408
+ ```
409
+
410
+ Validates and extracts discovery info in one step.
411
+
412
+ **Signature:**
413
+ ```python
414
+ def validate_and_extract(
415
+ extension: dict | DiscoveryExtension,
416
+ ) -> ValidationExtractResult:
417
+ ```
418
+
419
+ **Returns:** Object with `valid: bool`, `errors: list[str]`, and `info: DiscoveryInfo | None`
420
+
421
+ ---
422
+
423
+ ### bazaar_resource_server_extension
424
+
425
+ ```python
426
+ from x402.extensions.bazaar import bazaar_resource_server_extension
427
+ ```
428
+
429
+ A server-side extension that enriches discovery declarations with HTTP method information at runtime. Must be registered on an `x402ResourceServer` or `x402ResourceServerSync` instance.
430
+
431
+ **Usage:**
432
+ ```python
433
+ server.register_extension(bazaar_resource_server_extension)
434
+ ```
435
+
436
+ **What it does at runtime:**
437
+ 1. Intercepts the declaration enrichment step when an HTTP request arrives for a payment-protected route with a `"bazaar"` extension
438
+ 2. Reads the HTTP method from the transport context (e.g., `request.method`)
439
+ 3. Injects the method into `info.input.method` and updates the schema
440
+ 4. The enriched extension is included in the 402 Payment Required response
441
+
442
+ ---
443
+
444
+ ### with_bazaar()
445
+
446
+ ```python
447
+ from x402.extensions.bazaar import with_bazaar
448
+ ```
449
+
450
+ Extends a facilitator client with discovery query capabilities.
451
+
452
+ **Signature:**
453
+ ```python
454
+ def with_bazaar(
455
+ client: HTTPFacilitatorClient,
456
+ ) -> BazaarExtendedClient:
457
+ ```
458
+
459
+ **Returns:** Extended client with `client.extensions.discovery.list_resources()` method. All original facilitator client methods are delegated transparently.
460
+
461
+ ---
462
+
463
+ ### OutputConfig
464
+
465
+ ```python
466
+ from x402.extensions.bazaar import OutputConfig
467
+ ```
468
+
469
+ Configuration for the output portion of a discovery extension.
470
+
471
+ **Fields:**
472
+
473
+ | Field | Type | Required | Description |
474
+ |-------|------|----------|-------------|
475
+ | `example` | `dict` | Yes | Example response value |
476
+ | `schema` | `dict` or `None` | No | JSON Schema for the response |
477
+
478
+ ---
479
+
480
+ ## Bazaar Data Types
481
+
482
+ ### DiscoveredResource
483
+
484
+ ```python
485
+ @dataclass
486
+ class DiscoveredResource:
487
+ resource_url: str # Normalized URL (no query/hash)
488
+ method: str # HTTP method (GET, POST, etc.)
489
+ x402_version: int # 1 or 2
490
+ discovery_info: DiscoveryInfo # QueryDiscoveryInfo or BodyDiscoveryInfo
491
+ description: str | None # From resource info or requirements
492
+ mime_type: str | None # From resource info or requirements
493
+ ```
494
+
495
+ ### DiscoveryInfo (Union Type)
496
+
497
+ ```python
498
+ DiscoveryInfo = QueryDiscoveryInfo | BodyDiscoveryInfo
499
+ ```
500
+
501
+ ### ValidationResult
502
+
503
+ ```python
504
+ @dataclass
505
+ class ValidationResult:
506
+ valid: bool
507
+ errors: list[str] # Empty when valid
508
+ ```
509
+
510
+ ---
511
+
512
+ ## Bazaar Pydantic Models (from `x402.extensions.bazaar.types`)
513
+
514
+ | Type | Fields | Description |
515
+ |------|--------|-------------|
516
+ | `QueryInput` | `type`, `method`, `query_params`, `headers` | Input spec for GET/HEAD/DELETE |
517
+ | `BodyInput` | `type`, `method`, `body_type`, `body`, `query_params`, `headers` | Input spec for POST/PUT/PATCH |
518
+ | `OutputInfo` | `type`, `format`, `example` | Output specification |
519
+ | `QueryDiscoveryInfo` | `input: QueryInput`, `output: OutputInfo` | Discovery info for query methods |
520
+ | `BodyDiscoveryInfo` | `input: BodyInput`, `output: OutputInfo` | Discovery info for body methods |
521
+ | `QueryDiscoveryExtension` | `info: QueryDiscoveryInfo`, `schema_: dict` | Full extension with schema (query) |
522
+ | `BodyDiscoveryExtension` | `info: BodyDiscoveryInfo`, `schema_: dict` | Full extension with schema (body) |
523
+
524
+ ### Bazaar Union Types
525
+
526
+ | Name | Members | Description |
527
+ |------|---------|-------------|
528
+ | `DiscoveryInfo` | `QueryDiscoveryInfo \| BodyDiscoveryInfo` | Any discovery info |
529
+ | `DiscoveryExtension` | `QueryDiscoveryExtension \| BodyDiscoveryExtension` | Any extension |
530
+
531
+ ---
532
+
533
+ ## Bazaar Type Constants and Literals
534
+
535
+ | Name | Value | Description |
536
+ |------|-------|-------------|
537
+ | `BAZAAR` | `"bazaar"` | Extension key identifier in route configs |
538
+
539
+ | Literal Type | Values | Description |
540
+ |-------------|--------|-------------|
541
+ | `QueryParamMethods` | `"GET"`, `"HEAD"`, `"DELETE"` | HTTP methods using query parameters |
542
+ | `BodyMethods` | `"POST"`, `"PUT"`, `"PATCH"` | HTTP methods using request bodies |
543
+ | `BodyType` | `"json"`, `"form-data"`, `"text"` | Content types for body requests |
544
+
545
+ ---
546
+
547
+ ## Bazaar Config Dataclasses
548
+
549
+ | Type | Fields | Description |
550
+ |------|--------|-------------|
551
+ | `OutputConfig` | `example`, `schema` | Configure output for `declare_discovery_extension` |
552
+ | `DeclareQueryDiscoveryConfig` | `input`, `input_schema`, `output` | Config for query discovery |
553
+ | `DeclareBodyDiscoveryConfig` | `input`, `input_schema`, `body_type`, `output` | Config for body discovery |
554
+
555
+ ---
556
+
557
+ ## Bazaar Client Types (from `x402.extensions.bazaar.facilitator_client`)
558
+
559
+ | Type | Description |
560
+ |------|-------------|
561
+ | `ListDiscoveryResourcesParams` | Params for `list_resources()`: `type`, `limit`, `offset` |
562
+ | `DiscoveryResource` | A discovered resource: `url`, `type`, `metadata` |
563
+ | `DiscoveryResourcesResponse` | Response: `resources`, `total`, `limit`, `offset` |
564
+ | `BazaarDiscoveryExtension` | Discovery query class with `list_resources()` method |
565
+ | `BazaarClientExtension` | Container with `.discovery` attribute |
566
+ | `BazaarExtendedClient` | Extended client with `.extensions` attribute |
567
+
568
+ ---
569
+
570
+ ## Bazaar Helper Functions (from `x402.extensions.bazaar.types`)
571
+
572
+ | Function | Import | Description |
573
+ |----------|--------|-------------|
574
+ | `parse_discovery_extension(data)` | `from x402.extensions.bazaar.types import parse_discovery_extension` | Parse raw dict into typed extension |
575
+ | `parse_discovery_info(data)` | `from x402.extensions.bazaar.types import parse_discovery_info` | Parse raw dict into typed info |
576
+ | `is_query_method(method)` | `from x402.extensions.bazaar.types import is_query_method` | Check if method is GET/HEAD/DELETE |
577
+ | `is_body_method(method)` | `from x402.extensions.bazaar.types import is_body_method` | Check if method is POST/PUT/PATCH |
578
+
579
+ ---
580
+
581
+ ## Bazaar Functions Summary Table
582
+
583
+ | Function | Import | Description |
584
+ |----------|--------|-------------|
585
+ | `declare_discovery_extension` | `from x402.extensions.bazaar import ...` | Create discovery extension dict for route config |
586
+ | `validate_discovery_extension` | `from x402.extensions.bazaar import ...` | Validate extension info against its schema |
587
+ | `extract_discovery_info` | `from x402.extensions.bazaar import ...` | Extract discovery info from payment request (v1 + v2) |
588
+ | `extract_discovery_info_from_extension` | `from x402.extensions.bazaar import ...` | Extract info from extension object directly |
589
+ | `validate_and_extract` | `from x402.extensions.bazaar import ...` | Validate and extract in one step |
590
+ | `with_bazaar` | `from x402.extensions.bazaar import ...` | Extend facilitator client with discovery queries |
591
+ | `parse_discovery_extension` | `from x402.extensions.bazaar.types import ...` | Parse raw dict into typed extension |
592
+ | `parse_discovery_info` | `from x402.extensions.bazaar.types import ...` | Parse raw dict into typed info |
593
+ | `is_query_method` | `from x402.extensions.bazaar.types import ...` | Check if method is GET/HEAD/DELETE |
594
+ | `is_body_method` | `from x402.extensions.bazaar.types import ...` | Check if method is POST/PUT/PATCH |
595
+
596
+ ---
597
+
598
+ ## Bazaar Installation Commands
599
+
600
+ ```bash
601
+ # Extensions only
602
+ pip install "x402-avm[extensions]"
603
+
604
+ # Extensions + Algorand support
605
+ pip install "x402-avm[extensions,avm]"
606
+
607
+ # Extensions + Algorand + FastAPI
608
+ pip install "x402-avm[extensions,avm,fastapi]"
609
+
610
+ # Extensions + Algorand + Flask
611
+ pip install "x402-avm[extensions,avm,flask]"
612
+
613
+ # Everything
614
+ pip install "x402-avm[all]"
615
+ ```
616
+
617
+ The `[extensions]` extra adds one dependency: `jsonschema>=4.0.0`.
618
+
619
+ ---
620
+
621
+ ## External Resources
622
+
623
+ - [Facilitator Example Source](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/python/facilitator)
624
+ - [Extensions Examples](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
625
+ - [x402-avm AVM Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)
626
+ - [algosdk Python Reference](https://py-algorand-sdk.readthedocs.io/)
627
+ - [Algorand Developer Portal](https://developer.algorand.org/)
628
+ - [JSON Schema Specification](https://json-schema.org/)
629
+ - [CAIP-2 Chain ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md)