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,371 @@
1
+ # x402 HTTP Client Reference
2
+
3
+ Detailed API reference for `@x402-avm/fetch`, `@x402-avm/axios`, and `@x402-avm/avm` client packages.
4
+
5
+ ## Package: @x402-avm/fetch
6
+
7
+ ### Installation
8
+
9
+ ```bash
10
+ npm install @x402-avm/fetch @x402-avm/avm algosdk
11
+ ```
12
+
13
+ ### Exports
14
+
15
+ | Export | Type | Description |
16
+ |--------|------|-------------|
17
+ | `wrapFetchWithPayment` | Function | Wraps fetch with automatic 402 payment handling |
18
+ | `wrapFetchWithPaymentFromConfig` | Function | Config-based variant of the above |
19
+ | `x402Client` | Class | Core client for managing payment schemes |
20
+ | `x402HTTPClient` | Class | HTTP-level payment client |
21
+ | `decodePaymentResponseHeader` | Function | Decodes the PAYMENT-RESPONSE header |
22
+ | `PaymentPolicy` | Type | Policy function type for filtering requirements |
23
+ | `SchemeRegistration` | Type | Scheme registration configuration |
24
+ | `x402ClientConfig` | Type | Configuration object type |
25
+ | `PaymentRequired` | Type | 402 response structure |
26
+ | `PaymentRequirements` | Type | Individual payment requirement |
27
+ | `PaymentPayload` | Type | Signed payment payload |
28
+ | `Network` | Type | Network identifier string type |
29
+ | `SchemeNetworkClient` | Type | Client-side scheme interface |
30
+
31
+ ### wrapFetchWithPayment
32
+
33
+ Wraps a standard `fetch` function with automatic 402 payment handling.
34
+
35
+ ```typescript
36
+ function wrapFetchWithPayment(
37
+ fetch: typeof globalThis.fetch,
38
+ client: x402Client | x402HTTPClient,
39
+ ): (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
40
+ ```
41
+
42
+ **Flow:**
43
+ 1. Makes the initial HTTP request normally
44
+ 2. If the server responds with 402, parses payment requirements from the response
45
+ 3. Selects a suitable payment method based on registered schemes
46
+ 4. Creates a payment payload by signing a transaction group
47
+ 5. Retries the request with the `PAYMENT-SIGNATURE` header
48
+ 6. If the response is anything other than 402, returns it as-is
49
+
50
+ ### wrapFetchWithPaymentFromConfig
51
+
52
+ Config-based variant that creates the `x402Client` internally.
53
+
54
+ ```typescript
55
+ function wrapFetchWithPaymentFromConfig(
56
+ fetch: typeof globalThis.fetch,
57
+ config: x402ClientConfig,
58
+ ): (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
59
+ ```
60
+
61
+ ### x402ClientConfig
62
+
63
+ ```typescript
64
+ interface x402ClientConfig {
65
+ schemes: Array<{
66
+ network: string; // CAIP-2 identifier or wildcard ("algorand:*")
67
+ client: SchemeNetworkClient;
68
+ }>;
69
+ policies?: PaymentPolicy[];
70
+ }
71
+ ```
72
+
73
+ ### PaymentPolicy
74
+
75
+ ```typescript
76
+ type PaymentPolicy = (
77
+ version: number,
78
+ requirements: PaymentRequirements[],
79
+ ) => PaymentRequirements[];
80
+ ```
81
+
82
+ Policies are applied in registration order. Each policy receives the remaining requirements and returns a filtered/transformed list.
83
+
84
+ ### decodePaymentResponseHeader
85
+
86
+ ```typescript
87
+ function decodePaymentResponseHeader(header: string): any;
88
+ ```
89
+
90
+ Decodes the `PAYMENT-RESPONSE` header returned by the server after settlement.
91
+
92
+ ---
93
+
94
+ ## Package: @x402-avm/axios
95
+
96
+ ### Installation
97
+
98
+ ```bash
99
+ npm install @x402-avm/axios @x402-avm/avm algosdk axios
100
+ ```
101
+
102
+ ### Exports
103
+
104
+ | Export | Type | Description |
105
+ |--------|------|-------------|
106
+ | `wrapAxiosWithPayment` | Function | Wraps Axios instance with 402 payment interceptor |
107
+ | `wrapAxiosWithPaymentFromConfig` | Function | Config-based variant of the above |
108
+ | `x402Client` | Class | Core client for managing payment schemes |
109
+ | `x402HTTPClient` | Class | HTTP-level payment client |
110
+ | `decodePaymentResponseHeader` | Function | Decodes the PAYMENT-RESPONSE header |
111
+ | `PaymentPolicy` | Type | Policy function type for filtering requirements |
112
+ | `SchemeRegistration` | Type | Scheme registration configuration |
113
+ | `x402ClientConfig` | Type | Configuration object type |
114
+ | `PaymentRequired` | Type | 402 response structure |
115
+ | `PaymentRequirements` | Type | Individual payment requirement |
116
+ | `PaymentPayload` | Type | Signed payment payload |
117
+ | `Network` | Type | Network identifier string type |
118
+ | `SchemeNetworkClient` | Type | Client-side scheme interface |
119
+
120
+ ### wrapAxiosWithPayment
121
+
122
+ Adds a response interceptor that handles 402 responses by signing and submitting payment transactions.
123
+
124
+ ```typescript
125
+ function wrapAxiosWithPayment(
126
+ axiosInstance: AxiosInstance,
127
+ client: x402Client | x402HTTPClient,
128
+ ): AxiosInstance;
129
+ ```
130
+
131
+ Returns the same Axios instance (mutated with the interceptor). The interceptor:
132
+ - Catches 402 responses
133
+ - Parses payment requirements (headers for V2, body for V1)
134
+ - Creates payment payload via `x402Client`
135
+ - Marks the request with `__is402Retry = true` to prevent infinite loops
136
+ - Retries with `PAYMENT-SIGNATURE` header
137
+
138
+ ### wrapAxiosWithPaymentFromConfig
139
+
140
+ ```typescript
141
+ function wrapAxiosWithPaymentFromConfig(
142
+ axiosInstance: AxiosInstance,
143
+ config: x402ClientConfig,
144
+ ): AxiosInstance;
145
+ ```
146
+
147
+ ### Interceptor Behavior
148
+
149
+ ```
150
+ Client Request --> Axios sends request --> Server Response
151
+ |
152
+ Status != 402 -------> Return response normally
153
+ Status == 402 -------> Already retried? --> Reject
154
+ |
155
+ Parse PaymentRequired
156
+ Create payment payload
157
+ Retry with PAYMENT-SIGNATURE
158
+ Return retried response
159
+ ```
160
+
161
+ Key details:
162
+ - **Single retry**: Only retries once per 402
163
+ - **Request mutation**: Modifies original config and retries via `axiosInstance.request()`
164
+ - **Concurrent requests**: Each 402 is handled independently
165
+ - **Interceptor order**: Payment interceptor should be added last
166
+
167
+ ---
168
+
169
+ ## Package: @x402-avm/avm
170
+
171
+ ### Installation
172
+
173
+ ```bash
174
+ npm install @x402-avm/avm algosdk
175
+ ```
176
+
177
+ ### Exports
178
+
179
+ | Export | Type | Description |
180
+ |--------|------|-------------|
181
+ | `ExactAvmScheme` | Class | Algorand exact payment scheme (client) |
182
+ | `ClientAvmSigner` | Interface | Signer interface for client wallets |
183
+ | `ClientAvmConfig` | Interface | Algod client configuration |
184
+ | `ALGORAND_TESTNET_CAIP2` | Constant | `"algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="` |
185
+ | `ALGORAND_MAINNET_CAIP2` | Constant | `"algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8="` |
186
+ | `isAvmSignerWallet` | Function | Type guard for ClientAvmSigner |
187
+
188
+ ### ClientAvmSigner Interface
189
+
190
+ The interface that bridges wallets (browser or server) to the x402 payment system.
191
+
192
+ ```typescript
193
+ interface ClientAvmSigner {
194
+ /** The Algorand address of the payer */
195
+ address: string;
196
+
197
+ /**
198
+ * Sign one or more transactions in a group.
199
+ * @param txns - Array of unsigned transaction bytes (msgpack)
200
+ * @param indexesToSign - Optional indices of transactions to sign.
201
+ * If omitted, sign all transactions.
202
+ * @returns Array where signed transactions contain the signed blob,
203
+ * and skipped transactions are null
204
+ */
205
+ signTransactions(
206
+ txns: Uint8Array[],
207
+ indexesToSign?: number[],
208
+ ): Promise<(Uint8Array | null)[]>;
209
+ }
210
+ ```
211
+
212
+ ### Subpath: @x402-avm/avm/exact/client
213
+
214
+ | Export | Type | Description |
215
+ |--------|------|-------------|
216
+ | `registerExactAvmScheme` | Function | Registers AVM schemes (V1 + V2) to an x402Client |
217
+ | `AvmClientConfig` | Interface | Configuration for AVM client registration |
218
+
219
+ ### registerExactAvmScheme
220
+
221
+ ```typescript
222
+ function registerExactAvmScheme(
223
+ client: x402Client,
224
+ config: AvmClientConfig,
225
+ ): void;
226
+ ```
227
+
228
+ ### AvmClientConfig
229
+
230
+ ```typescript
231
+ interface AvmClientConfig {
232
+ /** The client signer implementation */
233
+ signer: ClientAvmSigner;
234
+
235
+ /** Optional Algod configuration */
236
+ algodConfig?: {
237
+ /** Algod URL (defaults to AlgoNode testnet/mainnet) */
238
+ algodUrl?: string;
239
+ /** Algod API token */
240
+ algodToken?: string;
241
+ /** Pre-configured Algodv2 client */
242
+ algodClient?: algosdk.Algodv2;
243
+ };
244
+
245
+ /** Optional: restrict to specific networks */
246
+ networks?: string[];
247
+ }
248
+ ```
249
+
250
+ ---
251
+
252
+ ## x402Client Class
253
+
254
+ ### Constructor
255
+
256
+ ```typescript
257
+ const client = new x402Client(selector?: PaymentRequirementsSelector);
258
+ ```
259
+
260
+ Optional `selector` overrides default selection logic for choosing among payment requirements.
261
+
262
+ ### Methods
263
+
264
+ | Method | Signature | Description |
265
+ |--------|-----------|-------------|
266
+ | `registerPolicy` | `(policy: PaymentPolicy) => x402Client` | Register a payment policy (chainable) |
267
+ | `onBeforePaymentCreation` | `(hook: BeforePaymentHook) => void` | Register pre-payment hook |
268
+ | `onAfterPaymentCreation` | `(hook: AfterPaymentHook) => void` | Register post-payment hook |
269
+ | `onPaymentCreationFailure` | `(hook: PaymentFailureHook) => void` | Register failure hook |
270
+
271
+ ### Lifecycle Hooks
272
+
273
+ **BeforePaymentCreation:**
274
+ ```typescript
275
+ client.onBeforePaymentCreation(async (context) => {
276
+ // context.selectedRequirements - the chosen payment requirements
277
+ // context.paymentRequired - full 402 response
278
+ // Return { abort: true, reason: "..." } to cancel payment
279
+ });
280
+ ```
281
+
282
+ **AfterPaymentCreation:**
283
+ ```typescript
284
+ client.onAfterPaymentCreation(async (context) => {
285
+ // context.paymentPayload - the signed payload
286
+ // context.paymentRequired - full 402 response
287
+ });
288
+ ```
289
+
290
+ **PaymentCreationFailure:**
291
+ ```typescript
292
+ client.onPaymentCreationFailure(async (context) => {
293
+ // context.error - the error that occurred
294
+ // Return { recovered: true, payload: ... } to provide fallback
295
+ });
296
+ ```
297
+
298
+ ---
299
+
300
+ ## Environment Variables
301
+
302
+ | Variable | Description | Format |
303
+ |----------|-------------|--------|
304
+ | `AVM_PRIVATE_KEY` | Algorand private key | Base64-encoded 64-byte key (32-byte seed + 32-byte pubkey) |
305
+ | `ALGOD_TESTNET_URL` | Custom Algod testnet URL | URL string (default: `https://testnet-api.algonode.cloud`) |
306
+ | `ALGOD_MAINNET_URL` | Custom Algod mainnet URL | URL string (default: `https://mainnet-api.algonode.cloud`) |
307
+
308
+ ---
309
+
310
+ ## Network Constants
311
+
312
+ | Constant | Value |
313
+ |----------|-------|
314
+ | `ALGORAND_TESTNET_CAIP2` | `"algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="` |
315
+ | `ALGORAND_MAINNET_CAIP2` | `"algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8="` |
316
+ | `V1_ALGORAND_TESTNET` | `"algorand-testnet"` |
317
+ | `V1_ALGORAND_MAINNET` | `"algorand-mainnet"` |
318
+
319
+ ---
320
+
321
+ ## Testing
322
+
323
+ ### Unit Testing a Client
324
+
325
+ ```typescript
326
+ import { x402Client } from "@x402-avm/fetch";
327
+ import { registerExactAvmScheme } from "@x402-avm/avm/exact/client";
328
+
329
+ // Create a mock signer for testing
330
+ const mockSigner = {
331
+ address: "TEST_ADDRESS_58_CHARS_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
332
+ signTransactions: async (txns: Uint8Array[], indexesToSign?: number[]) => {
333
+ return txns.map((_, i) => {
334
+ if (indexesToSign && !indexesToSign.includes(i)) return null;
335
+ return new Uint8Array([0x80]); // mock signed bytes
336
+ });
337
+ },
338
+ };
339
+
340
+ const client = new x402Client();
341
+ registerExactAvmScheme(client, { signer: mockSigner });
342
+ ```
343
+
344
+ ### Integration Testing with Real Transactions
345
+
346
+ ```bash
347
+ # Set up environment
348
+ export AVM_PRIVATE_KEY="your-base64-key-here"
349
+
350
+ # Run with tsx
351
+ npx tsx client-test.ts https://api.example.com/paid-endpoint
352
+ ```
353
+
354
+ ---
355
+
356
+ ## Important Notes
357
+
358
+ - `AVM_PRIVATE_KEY` is a Base64-encoded 64-byte key. The first 32 bytes are the seed, the last 32 bytes are the public key.
359
+ - Address derivation always uses `algosdk.encodeAddress(secretKey.slice(32))` -- the public key portion.
360
+ - The `algorand:*` wildcard in config-based setups matches any Algorand network (testnet or mainnet).
361
+ - Policies are composable and applied in order. An empty result from any policy means no payment options are available.
362
+ - The Axios interceptor modifies the instance in place and returns it. Do not create a new instance after wrapping.
363
+
364
+ ---
365
+
366
+ ## External Resources
367
+
368
+ - [x402-avm Examples Repository](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
369
+ - [x402-avm Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)
370
+ - [@txnlab/use-wallet Documentation](https://txnlab.gitbook.io/use-wallet)
371
+ - [algosdk TypeScript Reference](https://algorand.github.io/js-algorand-sdk/)
@@ -0,0 +1,236 @@
1
+ # Creating x402 HTTP Clients (Fetch and Axios)
2
+
3
+ Build HTTP clients that automatically detect `402 Payment Required` responses, sign Algorand transactions, and retry requests with payment proof -- all transparently.
4
+
5
+ ## Prerequisites
6
+
7
+ Before using this skill, ensure:
8
+
9
+ 1. **Node.js or browser environment** with TypeScript support
10
+ 2. **An Algorand wallet or private key** for signing payment transactions
11
+ 3. **USDC balance** on the target network (testnet or mainnet) in the payer's account
12
+
13
+ ## Core Workflow: The 402 Payment Flow
14
+
15
+ The key insight is that `wrapFetchWithPayment` and `wrapAxiosWithPayment` intercept 402 responses, sign a transaction group, and retry the original request with the payment header -- all automatically:
16
+
17
+ ```
18
+ Client Request (GET /api/premium)
19
+ |
20
+ v
21
+ Server Response
22
+ |
23
+ +-- Status != 402 --> Return response as-is
24
+ |
25
+ +-- Status == 402 -->
26
+ |
27
+ +-- Parse PaymentRequired (headers V2 / body V1)
28
+ +-- Select scheme via registered x402Client
29
+ +-- Build atomic transaction group
30
+ +-- Sign with ClientAvmSigner (wallet or private key)
31
+ +-- Encode PAYMENT-SIGNATURE header
32
+ +-- Retry original request with payment header
33
+ |
34
+ v
35
+ Return retried response
36
+ ```
37
+
38
+ ## How to Proceed
39
+
40
+ ### Step 1: Install Dependencies
41
+
42
+ For Fetch-based clients:
43
+ ```bash
44
+ npm install @x402-avm/fetch @x402-avm/avm algosdk
45
+ ```
46
+
47
+ For Axios-based clients:
48
+ ```bash
49
+ npm install @x402-avm/axios @x402-avm/avm algosdk axios
50
+ ```
51
+
52
+ ### Step 2: Implement a ClientAvmSigner
53
+
54
+ The `ClientAvmSigner` interface is what bridges your wallet or private key to the x402 payment system.
55
+
56
+ **Interface:**
57
+ ```typescript
58
+ interface ClientAvmSigner {
59
+ address: string;
60
+ signTransactions(
61
+ txns: Uint8Array[],
62
+ indexesToSign?: number[],
63
+ ): Promise<(Uint8Array | null)[]>;
64
+ }
65
+ ```
66
+
67
+ **For Node.js (private key):**
68
+ ```typescript
69
+ import algosdk from "algosdk";
70
+
71
+ const secretKey = Buffer.from(process.env.AVM_PRIVATE_KEY!, "base64");
72
+ const address = algosdk.encodeAddress(secretKey.slice(32));
73
+
74
+ const signer = {
75
+ address,
76
+ signTransactions: async (txns: Uint8Array[], indexesToSign?: number[]) => {
77
+ return txns.map((txn, i) => {
78
+ if (indexesToSign && !indexesToSign.includes(i)) return null;
79
+ const decoded = algosdk.decodeUnsignedTransaction(txn);
80
+ const signed = algosdk.signTransaction(decoded, secretKey);
81
+ return signed.blob;
82
+ });
83
+ },
84
+ };
85
+ ```
86
+
87
+ **For Browser (@txnlab/use-wallet):**
88
+ ```typescript
89
+ import { useWallet } from "@txnlab/use-wallet-react";
90
+ import type { ClientAvmSigner } from "@x402-avm/avm";
91
+
92
+ function useAvmSigner(): ClientAvmSigner | null {
93
+ const { activeAccount, signTransactions } = useWallet();
94
+ if (!activeAccount) return null;
95
+ return {
96
+ address: activeAccount.address,
97
+ signTransactions: async (txns: Uint8Array[], indexesToSign?: number[]) => {
98
+ return signTransactions(txns, indexesToSign);
99
+ },
100
+ };
101
+ }
102
+ ```
103
+
104
+ ### Step 3: Create and Configure the x402Client
105
+
106
+ ```typescript
107
+ import { x402Client } from "@x402-avm/fetch"; // or "@x402-avm/axios"
108
+ import { registerExactAvmScheme } from "@x402-avm/avm/exact/client";
109
+
110
+ const client = new x402Client();
111
+ registerExactAvmScheme(client, { signer });
112
+ ```
113
+
114
+ ### Step 4: Wrap Fetch or Axios
115
+
116
+ **Fetch:**
117
+ ```typescript
118
+ import { wrapFetchWithPayment } from "@x402-avm/fetch";
119
+
120
+ const fetchWithPay = wrapFetchWithPayment(fetch, client);
121
+ const response = await fetchWithPay("https://api.example.com/premium-data");
122
+ ```
123
+
124
+ **Axios:**
125
+ ```typescript
126
+ import axios from "axios";
127
+ import { wrapAxiosWithPayment } from "@x402-avm/axios";
128
+
129
+ const api = wrapAxiosWithPayment(axios.create(), client);
130
+ const response = await api.get("https://api.example.com/premium-data");
131
+ ```
132
+
133
+ ### Step 5: Add Payment Policies (Optional)
134
+
135
+ Policies filter payment requirements before selection. They are applied in order:
136
+
137
+ ```typescript
138
+ import type { PaymentPolicy } from "@x402-avm/fetch";
139
+
140
+ const maxAmount: PaymentPolicy = (version, reqs) => {
141
+ return reqs.filter((r) => BigInt(r.amount ?? "0") <= BigInt("5000000"));
142
+ };
143
+
144
+ const preferAlgorand: PaymentPolicy = (version, reqs) => {
145
+ const algoReqs = reqs.filter((r) => r.network.startsWith("algorand:"));
146
+ return algoReqs.length > 0 ? algoReqs : reqs;
147
+ };
148
+
149
+ client.registerPolicy(preferAlgorand).registerPolicy(maxAmount);
150
+ ```
151
+
152
+ ### Step 6: Add Lifecycle Hooks (Optional)
153
+
154
+ Monitor and control the payment lifecycle:
155
+
156
+ ```typescript
157
+ client.onBeforePaymentCreation(async ({ selectedRequirements }) => {
158
+ const amountUSDC = Number(selectedRequirements.amount) / 1_000_000;
159
+ console.log(`Paying $${amountUSDC.toFixed(6)} USDC`);
160
+ if (amountUSDC > 10) {
161
+ return { abort: true, reason: "Amount exceeds $10 limit" };
162
+ }
163
+ });
164
+
165
+ client.onAfterPaymentCreation(async () => {
166
+ console.log("Payment signed successfully");
167
+ });
168
+
169
+ client.onPaymentCreationFailure(async ({ error }) => {
170
+ console.error("Payment failed:", error.message);
171
+ });
172
+ ```
173
+
174
+ ## Important Rules / Guidelines
175
+
176
+ 1. **Always register a scheme before wrapping** -- `registerExactAvmScheme(client, { signer })` must be called before `wrapFetchWithPayment` or `wrapAxiosWithPayment`
177
+ 2. **AVM_PRIVATE_KEY format** -- Base64-encoded 64-byte key (32-byte seed + 32-byte public key)
178
+ 3. **Address derivation** -- Always use `algosdk.encodeAddress(secretKey.slice(32))`, never the first 32 bytes
179
+ 4. **Single retry** -- The wrapper retries exactly once after 402. If the retry also returns 402, the error is propagated
180
+ 5. **Interceptor order for Axios** -- Add your own interceptors first, then call `wrapAxiosWithPayment` last
181
+ 6. **Config-based alternative** -- Use `wrapFetchWithPaymentFromConfig` / `wrapAxiosWithPaymentFromConfig` for declarative setup without manual `x402Client` construction
182
+ 7. **Wildcard networks** -- Use `"algorand:*"` in config-based setups to match any Algorand network
183
+
184
+ ## Config-Based Setup (Alternative)
185
+
186
+ Instead of creating an `x402Client` manually, use the config-based approach:
187
+
188
+ ```typescript
189
+ import { wrapFetchWithPaymentFromConfig, type x402ClientConfig } from "@x402-avm/fetch";
190
+ import { ExactAvmScheme } from "@x402-avm/avm";
191
+
192
+ const config: x402ClientConfig = {
193
+ schemes: [
194
+ {
195
+ network: "algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
196
+ client: new ExactAvmScheme(signer),
197
+ },
198
+ ],
199
+ policies: [maxAmount],
200
+ };
201
+
202
+ const fetchWithPay = wrapFetchWithPaymentFromConfig(fetch, config);
203
+ ```
204
+
205
+ ## Common Errors / Troubleshooting
206
+
207
+ | Error | Cause | Solution |
208
+ |-------|-------|----------|
209
+ | `Failed to parse payment requirements` | Server returned 402 with invalid body | Check server is running x402-compatible middleware |
210
+ | `Failed to create payment payload` | Insufficient balance or wrong network | Ensure USDC balance on the correct network |
211
+ | `Payment already attempted` | Server returned 402 after payment was sent | Payment was rejected; check facilitator logs |
212
+ | `No network/scheme registered` | Server requires an unregistered network | Register the needed scheme with `registerExactAvmScheme` |
213
+ | `Payment creation aborted` | A `beforePaymentCreation` hook returned abort | Review hook logic; check amount limits |
214
+ | `All payment requirements were filtered out` | Policies removed all options | Relax policies or register additional schemes |
215
+ | `No client registered for x402 version: 2` | No schemes registered at all | Call `registerExactAvmScheme(client, { signer })` |
216
+
217
+ ## Reading Payment Receipts
218
+
219
+ After a successful paid request, check the response header:
220
+
221
+ ```typescript
222
+ import { decodePaymentResponseHeader } from "@x402-avm/fetch";
223
+
224
+ const paymentResponseHeader = response.headers.get("PAYMENT-RESPONSE");
225
+ if (paymentResponseHeader) {
226
+ const receipt = decodePaymentResponseHeader(paymentResponseHeader);
227
+ console.log("Transaction settled:", receipt);
228
+ }
229
+ ```
230
+
231
+ ## References / Further Reading
232
+
233
+ - [create-typescript-x402-client-reference.md](./create-typescript-x402-client-reference.md) - Detailed API reference
234
+ - [create-typescript-x402-client-examples.md](./create-typescript-x402-client-examples.md) - Complete code examples
235
+ - [x402-avm Fetch Examples](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
236
+ - [x402-avm Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)