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,315 @@
1
+ # x402-avm Python Package Reference
2
+
3
+ Detailed reference for the `x402-avm` Python package covering package structure, extras, async/sync variants, signer protocols, registration functions, constants, utilities, and algosdk encoding.
4
+
5
+ ## Package Structure
6
+
7
+ The package is published on PyPI as `x402-avm` but all imports use the `x402` namespace:
8
+
9
+ ```
10
+ x402/
11
+ __init__.py # x402Client, x402ClientSync, x402Facilitator, etc.
12
+ server.py # x402ResourceServer, x402ResourceServerSync
13
+ schemas.py # AssetAmount, Network, PaymentRequirements, etc.
14
+ http/
15
+ __init__.py # HTTPFacilitatorClient, HTTPFacilitatorClientSync, PaymentOption, etc.
16
+ types.py # RouteConfig, RoutesConfig, FacilitatorConfig
17
+ clients/
18
+ __init__.py # Lazy imports for httpx/requests
19
+ httpx.py # x402HttpxClient, wrapHttpxWithPayment, etc.
20
+ requests.py # x402_requests, wrapRequestsWithPayment, etc.
21
+ middleware/
22
+ __init__.py # Lazy imports for fastapi/flask
23
+ fastapi.py # PaymentMiddlewareASGI, payment_middleware, etc.
24
+ flask.py # PaymentMiddleware, payment_middleware, etc.
25
+ mechanisms/
26
+ avm/
27
+ __init__.py # Re-exports constants
28
+ constants.py # Network IDs, USDC config, algod URLs
29
+ signer.py # ClientAvmSigner, FacilitatorAvmSigner Protocols
30
+ utils.py # Address validation, encoding, network utils
31
+ exact/
32
+ __init__.py # ExactAvmClientScheme, ExactAvmServerScheme, etc.
33
+ register.py # register_exact_avm_client, register_exact_avm_server, etc.
34
+ evm/ # EVM mechanism (same structure)
35
+ svm/ # SVM mechanism (same structure)
36
+ ```
37
+
38
+ ## Extras
39
+
40
+ | Extra | Installs | Use Case |
41
+ |-------|----------|----------|
42
+ | `[avm]` | `py-algorand-sdk>=2.0.0` | Algorand transaction signing |
43
+ | `[evm]` | `web3`, `eth-account` | Ethereum/EVM transaction signing |
44
+ | `[svm]` | `solders`, `solana-py` | Solana/SVM transaction signing |
45
+ | `[fastapi]` | `fastapi[standard]>=0.115.0`, `starlette>=0.27.0` | FastAPI async middleware |
46
+ | `[flask]` | `flask>=3.0.0` | Flask sync middleware |
47
+ | `[httpx]` | `httpx>=0.28.1` | Async HTTP client |
48
+ | `[requests]` | `requests>=2.31.0` | Sync HTTP client |
49
+ | `[mechanisms]` | All mechanism extras | All blockchain mechanisms |
50
+ | `[clients]` | `httpx`, `requests` | All HTTP clients |
51
+ | `[servers]` | `fastapi`, `flask` | All server frameworks |
52
+ | `[extensions]` | Extensions dependencies | Optional extensions |
53
+ | `[all]` | Everything | Full installation |
54
+
55
+ Installation examples:
56
+
57
+ ```bash
58
+ pip install "x402-avm[avm]"
59
+ pip install "x402-avm[fastapi,avm]"
60
+ pip install "x402-avm[flask,avm]"
61
+ pip install "x402-avm[httpx,avm]"
62
+ pip install "x402-avm[requests,avm]"
63
+ pip install "x402-avm[all]"
64
+ ```
65
+
66
+ ## Async vs Sync Component Table
67
+
68
+ | Component | Async (FastAPI/httpx) | Sync (Flask/requests) |
69
+ |-----------|----------------------|----------------------|
70
+ | x402 Client | `x402Client` | `x402ClientSync` |
71
+ | Resource Server | `x402ResourceServer` | `x402ResourceServerSync` |
72
+ | Facilitator Client | `HTTPFacilitatorClient` | `HTTPFacilitatorClientSync` |
73
+ | HTTP Resource Server | `x402HTTPResourceServer` | `x402HTTPResourceServerSync` |
74
+ | HTTP Client wrapper | `x402HTTPClient` | `x402HTTPClientSync` |
75
+ | Middleware (FastAPI) | `PaymentMiddlewareASGI` | N/A |
76
+ | Middleware (Flask) | N/A | `PaymentMiddleware` |
77
+ | HTTP Client (httpx) | `x402HttpxClient` | N/A |
78
+ | HTTP Client (requests) | N/A | `x402_requests` |
79
+ | Payment info storage | `request.state.payment_payload` | `flask.g.payment_payload` |
80
+
81
+ ## ClientAvmSigner Protocol
82
+
83
+ Defined in `x402.mechanisms.avm.signer`. Structural typing -- no inheritance required.
84
+
85
+ ```python
86
+ class ClientAvmSigner(Protocol):
87
+ @property
88
+ def address(self) -> str:
89
+ """58-character Algorand address."""
90
+ ...
91
+
92
+ def sign_transactions(
93
+ self,
94
+ unsigned_txns: list[bytes],
95
+ indexes_to_sign: list[int],
96
+ ) -> list[bytes | None]:
97
+ """Sign specified transactions in a group.
98
+
99
+ Args:
100
+ unsigned_txns: Raw msgpack-encoded unsigned transactions.
101
+ indexes_to_sign: Indexes this signer should sign.
102
+
103
+ Returns:
104
+ Parallel list: signed bytes at signed indexes, None elsewhere.
105
+ """
106
+ ...
107
+ ```
108
+
109
+ ### Implementation Notes
110
+
111
+ - `unsigned_txns` contains raw msgpack bytes, not base64 strings
112
+ - Convert at boundary: `base64.b64encode(txn_bytes).decode()` before `msgpack_decode`
113
+ - `Transaction.sign(key)` expects base64-encoded private key string
114
+ - Convert back: `base64.b64decode(msgpack_encode(signed))` to return raw bytes
115
+
116
+ ## FacilitatorAvmSigner Protocol
117
+
118
+ Defined in `x402.mechanisms.avm.signer`. Required for facilitator services.
119
+
120
+ ```python
121
+ class FacilitatorAvmSigner(Protocol):
122
+ def get_addresses(self) -> list[str]: ...
123
+ def sign_transaction(self, txn_bytes: bytes, fee_payer: str, network: str) -> bytes: ...
124
+ def sign_group(self, group_bytes: list[bytes], fee_payer: str, indexes_to_sign: list[int], network: str) -> list[bytes]: ...
125
+ def simulate_group(self, group_bytes: list[bytes], network: str) -> None: ...
126
+ def send_group(self, group_bytes: list[bytes], network: str) -> str: ...
127
+ def confirm_transaction(self, txid: str, network: str, rounds: int = 4) -> None: ...
128
+ ```
129
+
130
+ ### Implementation Patterns
131
+
132
+ | Method | Key Pattern |
133
+ |--------|-------------|
134
+ | `simulate_group` | Wrap unsigned `Transaction` with `SignedTransaction(txn, None)`, use `allow_empty_signatures=True` |
135
+ | `send_group` | Use `send_raw_transaction(base64.b64encode(b"".join(group_bytes)))` |
136
+ | `confirm_transaction` | Use `transaction.wait_for_confirmation(client, txid, rounds)` |
137
+
138
+ ## Registration Functions
139
+
140
+ ### `register_exact_avm_client(client, signer, networks=None, algod_url=None)`
141
+
142
+ Registers AVM payment scheme on an x402 client.
143
+
144
+ | Parameter | Type | Default | Description |
145
+ |-----------|------|---------|-------------|
146
+ | `client` | `x402Client \| x402ClientSync` | required | The x402 client instance |
147
+ | `signer` | `ClientAvmSigner` | required | Signer implementation |
148
+ | `networks` | `str \| list[str] \| None` | `None` | Specific networks; default registers `"algorand:*"` wildcard + V1 names |
149
+ | `algod_url` | `str \| None` | `None` | Custom algod endpoint |
150
+
151
+ ### `register_exact_avm_server(server)`
152
+
153
+ Registers AVM scheme on a resource server.
154
+
155
+ | Parameter | Type | Description |
156
+ |-----------|------|-------------|
157
+ | `server` | `x402ResourceServer \| x402ResourceServerSync` | The resource server |
158
+
159
+ ### `register_exact_avm_facilitator(facilitator, signer, networks)`
160
+
161
+ Registers AVM scheme on a facilitator.
162
+
163
+ | Parameter | Type | Description |
164
+ |-----------|------|-------------|
165
+ | `facilitator` | `x402Facilitator` | The facilitator instance |
166
+ | `signer` | `FacilitatorAvmSigner` | Facilitator signer implementation |
167
+ | `networks` | `list[str]` | CAIP-2 network identifiers to support |
168
+
169
+ ## Constants
170
+
171
+ Defined in `x402.mechanisms.avm.constants`:
172
+
173
+ ### Network Identifiers
174
+
175
+ | Constant | Value |
176
+ |----------|-------|
177
+ | `ALGORAND_MAINNET_CAIP2` | `"algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8="` |
178
+ | `ALGORAND_TESTNET_CAIP2` | `"algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="` |
179
+ | `SUPPORTED_NETWORKS` | `[MAINNET_CAIP2, TESTNET_CAIP2]` |
180
+ | `MAINNET_GENESIS_HASH` | `"wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8="` |
181
+ | `TESTNET_GENESIS_HASH` | `"SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="` |
182
+ | `V1_NETWORKS` | `["algorand-mainnet", "algorand-testnet"]` |
183
+
184
+ ### USDC Configuration
185
+
186
+ | Constant | Value |
187
+ |----------|-------|
188
+ | `USDC_MAINNET_ASA_ID` | `31566704` |
189
+ | `USDC_TESTNET_ASA_ID` | `10458941` |
190
+ | `DEFAULT_DECIMALS` | `6` |
191
+
192
+ ### Algod Endpoints
193
+
194
+ | Constant | Default Value |
195
+ |----------|---------------|
196
+ | `MAINNET_ALGOD_URL` | env `ALGOD_MAINNET_URL` or `"https://mainnet-api.algonode.cloud"` |
197
+ | `TESTNET_ALGOD_URL` | env `ALGOD_TESTNET_URL` or `"https://testnet-api.algonode.cloud"` |
198
+ | `FALLBACK_ALGOD_MAINNET` | `"https://mainnet-api.algonode.cloud"` |
199
+ | `FALLBACK_ALGOD_TESTNET` | `"https://testnet-api.algonode.cloud"` |
200
+
201
+ ### Transaction Limits
202
+
203
+ | Constant | Value |
204
+ |----------|-------|
205
+ | `MAX_GROUP_SIZE` | `16` |
206
+ | `MIN_TXN_FEE` | `1000` (microAlgos) |
207
+
208
+ ## Utility Functions
209
+
210
+ Defined in `x402.mechanisms.avm.utils`:
211
+
212
+ | Function | Signature | Returns |
213
+ |----------|-----------|---------|
214
+ | `is_valid_address(addr)` | `str -> bool` | Whether address is valid 58-char Algorand address |
215
+ | `to_atomic_amount(amount)` | `float -> int` | Decimal to atomic units (e.g., 1.50 -> 1500000) |
216
+ | `from_atomic_amount(amount)` | `int -> float` | Atomic units to decimal (e.g., 1500000 -> 1.5) |
217
+ | `decode_transaction_bytes(raw)` | `bytes -> DecodedTransactionInfo` | Decoded transaction details |
218
+ | `decode_base64_transaction(b64)` | `str -> DecodedTransactionInfo` | Decode from base64 string |
219
+ | `decode_payment_group(group, index)` | `list[str], int -> PaymentGroupInfo` | Full group analysis |
220
+ | `encode_transaction_group(txns)` | `list[bytes] -> list[str]` | Encode raw bytes to base64 strings |
221
+ | `normalize_network(network)` | `str -> str` | Normalize V1 name to CAIP-2 |
222
+ | `is_valid_network(network)` | `str -> bool` | Check if network is recognized |
223
+ | `get_network_config(network)` | `str -> dict` | Full config for network |
224
+ | `get_usdc_asa_id(network)` | `str -> int` | USDC ASA ID for network |
225
+ | `get_genesis_hash(network)` | `str -> str` | Genesis hash for network |
226
+ | `network_from_genesis_hash(hash)` | `str -> str` | CAIP-2 from genesis hash |
227
+ | `validate_no_security_risks(info)` | `DecodedTransactionInfo -> str \| None` | Error code or None |
228
+ | `validate_fee_payer_transaction(info, addr)` | `DecodedTransactionInfo, str -> str \| None` | Error code or None |
229
+ | `is_blocked_transaction_type(type)` | `str -> bool` | Whether type is blocked (e.g., keyreg) |
230
+
231
+ ## algosdk Encoding Notes (v2.11.1)
232
+
233
+ The Python `algosdk` has different encoding conventions than TypeScript algosdk:
234
+
235
+ | Operation | Python algosdk | TypeScript algosdk |
236
+ |-----------|---------------|-------------------|
237
+ | `msgpack_decode(s)` | Expects **base64 string** | N/A (uses `decodeUnsignedTransaction(Uint8Array)`) |
238
+ | `msgpack_encode(obj)` | Returns **base64 string** | N/A (uses `txn.toByte()` returning `Uint8Array`) |
239
+ | `Transaction.sign(key)` | Expects **base64 string** key | `signTransaction(txn, Uint8Array)` |
240
+ | SDK protocol | Passes **raw msgpack bytes** | Passes **raw `Uint8Array`** |
241
+
242
+ Boundary conversions:
243
+
244
+ ```python
245
+ # Raw bytes -> algosdk object
246
+ txn_obj = encoding.msgpack_decode(base64.b64encode(raw_bytes).decode("utf-8"))
247
+
248
+ # algosdk object -> raw bytes
249
+ raw_bytes = base64.b64decode(encoding.msgpack_encode(txn_obj))
250
+ ```
251
+
252
+ ## Environment Variables
253
+
254
+ | Variable | Description | Default |
255
+ |----------|-------------|---------|
256
+ | `AVM_PRIVATE_KEY` | Base64-encoded 64-byte key (32-byte seed + 32-byte pubkey) | Required |
257
+ | `ALGOD_MAINNET_URL` | Custom algod mainnet endpoint | `https://mainnet-api.algonode.cloud` |
258
+ | `ALGOD_TESTNET_URL` | Custom algod testnet endpoint | `https://testnet-api.algonode.cloud` |
259
+ | `INDEXER_MAINNET_URL` | Custom indexer mainnet endpoint | `https://mainnet-idx.algonode.cloud` |
260
+ | `INDEXER_TESTNET_URL` | Custom indexer testnet endpoint | `https://testnet-idx.algonode.cloud` |
261
+ | `ALGOD_SERVER` | Algod URL for facilitator examples | N/A |
262
+ | `ALGOD_TOKEN` | Algod token for facilitator examples | N/A |
263
+
264
+ ### Private Key Format
265
+
266
+ The `AVM_PRIVATE_KEY` is a Base64-encoded 64-byte key:
267
+ - First 32 bytes: Ed25519 seed (private key)
268
+ - Last 32 bytes: Ed25519 public key
269
+ - Address derivation: `encoding.encode_address(secret_key[32:])`
270
+
271
+ ## Payment Flow
272
+
273
+ ```
274
+ Client -> Resource Server -> Facilitator -> Algorand Network
275
+ | | | |
276
+ | 1. GET | | |
277
+ |--------->| | |
278
+ | 2. 402 | | |
279
+ |<---------| | |
280
+ | 3. Build | | |
281
+ | payload| | |
282
+ | 4. GET + | | |
283
+ | PAYMENT- | | |
284
+ | SIGNATURE| | |
285
+ |--------->| 5. verify() | |
286
+ | |----------------->| 6. simulate |
287
+ | | |--------------->|
288
+ | | |<---------------|
289
+ | |<-----------------| |
290
+ | | 7. settle() | |
291
+ | |----------------->| 8. sign + send |
292
+ | | |--------------->|
293
+ | | |<---------------|
294
+ | |<-----------------| 9. txId |
295
+ | 10. 200 | | |
296
+ |<---------| | |
297
+ ```
298
+
299
+ ## Testing Notes
300
+
301
+ - Use Algorand TestNet for development with free test ALGO from the [Algorand Faucet](https://bank.testnet.algorand.network/)
302
+ - USDC on TestNet uses ASA ID `10458941` -- ensure receiver has opted in
303
+ - Simulation (`simulate_group`) validates transactions without submitting
304
+ - Algorand has instant finality -- once confirmed, transactions are permanent
305
+ - AlgoNode public endpoints require no authentication token
306
+
307
+ ## External Resources
308
+
309
+ - [x402-avm on PyPI](https://pypi.org/project/x402-avm/)
310
+ - [x402-avm GitHub Repository](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/)
311
+ - [x402-avm Examples](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
312
+ - [x402 Algorand Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)
313
+ - [Algorand Developer Portal](https://dev.algorand.co/)
314
+ - [py-algorand-sdk Documentation](https://py-algorand-sdk.readthedocs.io/)
315
+ - [Coinbase x402 Specification](https://github.com/coinbase/x402)
@@ -0,0 +1,167 @@
1
+ # x402-avm Python Package for Algorand
2
+
3
+ The `x402-avm` Python package provides Algorand (AVM) payment protocol support through a modular extras system, Protocol-based signer interfaces, and async/sync variants for every component.
4
+
5
+ ## Prerequisites
6
+
7
+ Before using this skill, ensure:
8
+
9
+ 1. **Python 3.10+** is installed
10
+ 2. **pip** is available for package installation
11
+ 3. **Understanding of x402 protocol** -- client sends request, gets 402, creates payment, retries with payment header
12
+
13
+ ## Core Concept: Extras-Based Installation
14
+
15
+ The `x402-avm` package uses pip extras to install only what you need. The package name on PyPI is `x402-avm` but all imports use `from x402...` (not `from x402_avm...`).
16
+
17
+ ```bash
18
+ # Minimal AVM support
19
+ pip install "x402-avm[avm]"
20
+
21
+ # Server frameworks
22
+ pip install "x402-avm[fastapi,avm]"
23
+ pip install "x402-avm[flask,avm]"
24
+
25
+ # HTTP clients
26
+ pip install "x402-avm[httpx,avm]"
27
+ pip install "x402-avm[requests,avm]"
28
+
29
+ # Everything
30
+ pip install "x402-avm[all]"
31
+ ```
32
+
33
+ ## Core Workflow: Signer Protocol Pattern
34
+
35
+ The key insight is that x402 defines **Protocol classes** (structural typing) for signers. Your implementation does not need to inherit -- it just needs matching methods.
36
+
37
+ ```
38
+ Private Key (env var)
39
+ |
40
+ v
41
+ Signer Implementation (satisfies Protocol)
42
+ |
43
+ v
44
+ register_exact_avm_client(x402_client, signer)
45
+ |
46
+ v
47
+ HTTP Client (httpx or requests) handles 402 automatically
48
+ ```
49
+
50
+ ## How to Proceed
51
+
52
+ ### Step 1: Choose Your Extras
53
+
54
+ | Use Case | Install Command |
55
+ |----------|----------------|
56
+ | Client with httpx (async) | `pip install "x402-avm[httpx,avm]"` |
57
+ | Client with requests (sync) | `pip install "x402-avm[requests,avm]"` |
58
+ | Server with FastAPI (async) | `pip install "x402-avm[fastapi,avm]"` |
59
+ | Server with Flask (sync) | `pip install "x402-avm[flask,avm]"` |
60
+ | Facilitator service | `pip install "x402-avm[fastapi,avm]"` or `"x402-avm[flask,avm]"` |
61
+ | Full installation | `pip install "x402-avm[all]"` |
62
+
63
+ ### Step 2: Understand Async vs Sync Variants
64
+
65
+ Every core class has both async and sync variants. Using the wrong variant causes runtime errors.
66
+
67
+ | Component | Async (FastAPI/httpx) | Sync (Flask/requests) |
68
+ |-----------|----------------------|----------------------|
69
+ | x402 Client | `x402Client` | `x402ClientSync` |
70
+ | Resource Server | `x402ResourceServer` | `x402ResourceServerSync` |
71
+ | Facilitator Client | `HTTPFacilitatorClient` | `HTTPFacilitatorClientSync` |
72
+ | HTTP Resource Server | `x402HTTPResourceServer` | `x402HTTPResourceServerSync` |
73
+
74
+ ### Step 3: Implement a Signer
75
+
76
+ For clients, implement `ClientAvmSigner`:
77
+
78
+ ```python
79
+ from x402.mechanisms.avm.signer import ClientAvmSigner
80
+
81
+ # Protocol -- just match this shape:
82
+ class ClientAvmSigner(Protocol):
83
+ @property
84
+ def address(self) -> str: ...
85
+ def sign_transactions(self, unsigned_txns: list[bytes], indexes_to_sign: list[int]) -> list[bytes | None]: ...
86
+ ```
87
+
88
+ For facilitators, implement `FacilitatorAvmSigner`:
89
+
90
+ ```python
91
+ from x402.mechanisms.avm.signer import FacilitatorAvmSigner
92
+
93
+ # Protocol -- match this shape:
94
+ class FacilitatorAvmSigner(Protocol):
95
+ def get_addresses(self) -> list[str]: ...
96
+ def sign_transaction(self, txn_bytes: bytes, fee_payer: str, network: str) -> bytes: ...
97
+ def sign_group(self, group_bytes: list[bytes], fee_payer: str, indexes_to_sign: list[int], network: str) -> list[bytes]: ...
98
+ def simulate_group(self, group_bytes: list[bytes], network: str) -> None: ...
99
+ def send_group(self, group_bytes: list[bytes], network: str) -> str: ...
100
+ def confirm_transaction(self, txid: str, network: str, rounds: int = 4) -> None: ...
101
+ ```
102
+
103
+ ### Step 4: Handle algosdk Encoding Boundaries
104
+
105
+ This is the most common source of bugs. The x402 SDK passes **raw msgpack bytes** between methods, but Python algosdk (v2.11.1) works with **base64 strings**:
106
+
107
+ | Operation | Python algosdk Expects/Returns |
108
+ |-----------|-------------------------------|
109
+ | `msgpack_decode(s)` | Expects **base64 string** |
110
+ | `msgpack_encode(obj)` | Returns **base64 string** |
111
+ | `Transaction.sign(key)` | Expects **base64 string** key |
112
+
113
+ Boundary conversion:
114
+
115
+ ```python
116
+ import base64
117
+ from algosdk import encoding
118
+
119
+ # Raw bytes -> algosdk object (DECODE)
120
+ b64_string = base64.b64encode(raw_bytes).decode("utf-8")
121
+ txn_obj = encoding.msgpack_decode(b64_string)
122
+
123
+ # algosdk object -> raw bytes (ENCODE)
124
+ b64_string = encoding.msgpack_encode(txn_obj)
125
+ raw_bytes = base64.b64decode(b64_string)
126
+ ```
127
+
128
+ ### Step 5: Register and Use
129
+
130
+ ```python
131
+ from x402 import x402Client
132
+ from x402.mechanisms.avm.exact import register_exact_avm_client
133
+
134
+ signer = MyClientSigner(os.environ["AVM_PRIVATE_KEY"])
135
+ client = x402Client()
136
+ register_exact_avm_client(client, signer)
137
+ # Now use with httpx or requests client wrappers
138
+ ```
139
+
140
+ ## Important Rules / Guidelines
141
+
142
+ 1. **Always use base64 boundaries** -- `msgpack_decode` expects base64 string, not raw bytes
143
+ 2. **Match async/sync variants** -- FastAPI uses `x402Client`, Flask uses `x402ClientSync`
144
+ 3. **Private key format** -- `AVM_PRIVATE_KEY` is Base64-encoded 64 bytes (32-byte seed + 32-byte pubkey)
145
+ 4. **Address derivation** -- `encode_address(secret_key[32:])` extracts address from public key portion
146
+ 5. **Import as x402** -- install as `x402-avm` but import as `from x402...`
147
+ 6. **Protocol typing** -- no inheritance needed, just match the method signatures
148
+
149
+ ## Common Errors / Troubleshooting
150
+
151
+ | Error | Cause | Solution |
152
+ |-------|-------|----------|
153
+ | `TypeError: a bytes-like object is required` | Passed raw bytes to `msgpack_decode` | Convert to base64 string first: `base64.b64encode(raw).decode()` |
154
+ | `TypeError: expected str, got bytes` | `msgpack_encode` returns base64 string, not bytes | Use `base64.b64decode(result)` to get raw bytes |
155
+ | `Invalid key length: expected 64` | Wrong key format | Ensure `AVM_PRIVATE_KEY` is Base64-encoded 64-byte key |
156
+ | `TypeError: x402HTTPAdapter requires sync client` | Used `x402Client` with requests | Use `x402ClientSync` for requests (sync) |
157
+ | `ImportError: AVM mechanism requires...` | Missing `py-algorand-sdk` | `pip install "x402-avm[avm]"` |
158
+ | `ModuleNotFoundError: x402_avm` | Wrong import name | Import as `from x402...` not `from x402_avm...` |
159
+ | `Simulation failed: ...` | Transaction group invalid | Check group ID assignment, fee calculations, asset opt-in |
160
+
161
+ ## References / Further Reading
162
+
163
+ - [explain-algorand-x402-python-reference.md](./explain-algorand-x402-python-reference.md) - Detailed API reference for all Python components
164
+ - [explain-algorand-x402-python-examples.md](./explain-algorand-x402-python-examples.md) - Complete code examples
165
+ - [x402-avm on PyPI](https://pypi.org/project/x402-avm/)
166
+ - [x402-avm Examples Repository](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
167
+ - [x402 Algorand Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)