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,323 @@
1
+ # x402-avm TypeScript Reference
2
+
3
+ ## Package Ecosystem
4
+
5
+ ### @x402-avm/core
6
+
7
+ The core package provides protocol-agnostic base classes and types.
8
+
9
+ **Key Exports:**
10
+
11
+ | Export | Path | Description |
12
+ |--------|------|-------------|
13
+ | `x402Client` | `@x402-avm/core/client` | Base client that handles 402 responses and payment |
14
+ | `x402ResourceServer` | `@x402-avm/core/server` | Transport-agnostic resource server |
15
+ | `x402HTTPResourceServer` | `@x402-avm/core/server` | HTTP-aware resource server with route configuration |
16
+ | `HTTPFacilitatorClient` | `@x402-avm/core/server` | HTTP client for communicating with a remote facilitator |
17
+ | `x402Facilitator` | `@x402-avm/core/facilitator` | Base facilitator for verifying and settling payments |
18
+ | `PaymentRequirements` | `@x402-avm/core/types` | Type: what payment a server accepts |
19
+ | `PaymentPayload` | `@x402-avm/core/types` | Type: what the client sends in PAYMENT-SIGNATURE header |
20
+ | `PaymentRequired` | `@x402-avm/core/types` | Type: 402 response body |
21
+ | `Network` | `@x402-avm/core/types` | Type: CAIP-2 network identifier string |
22
+ | `PaymentPolicy` | `@x402-avm/core/client` | Type: filter function for payment requirements |
23
+
24
+ ### @x402-avm/avm
25
+
26
+ The AVM mechanism package provides Algorand-specific signer interfaces, constants, utilities, and scheme registration.
27
+
28
+ **Signer Interfaces:**
29
+
30
+ | Interface | Description |
31
+ |-----------|-------------|
32
+ | `ClientAvmSigner` | Client-side signer with `address` and `signTransactions()` |
33
+ | `FacilitatorAvmSigner` | Facilitator signer with `getAddresses()`, `signTransaction()`, `getAlgodClient()`, `simulateTransactions()`, `sendTransactions()`, `waitForConfirmation()` |
34
+
35
+ **Registration Functions (from subpaths):**
36
+
37
+ | Function | Import Path | Arguments |
38
+ |----------|-------------|-----------|
39
+ | `registerExactAvmScheme` | `@x402-avm/avm/exact/client` | `(client, { signer, algodConfig?, networks?, policies? })` |
40
+ | `registerExactAvmScheme` | `@x402-avm/avm/exact/server` | `(server, { networks? }?)` |
41
+ | `registerExactAvmScheme` | `@x402-avm/avm/exact/facilitator` | `(facilitator, { signer, networks })` |
42
+
43
+ **Constants:**
44
+
45
+ | Constant | Value | Description |
46
+ |----------|-------|-------------|
47
+ | `ALGORAND_TESTNET_CAIP2` | `"algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="` | Testnet CAIP-2 |
48
+ | `ALGORAND_MAINNET_CAIP2` | `"algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8="` | Mainnet CAIP-2 |
49
+ | `CAIP2_NETWORKS` | Array of both | All supported CAIP-2 networks |
50
+ | `ALGORAND_TESTNET_GENESIS_HASH` | `"SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="` | Testnet genesis hash |
51
+ | `ALGORAND_MAINNET_GENESIS_HASH` | `"wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8="` | Mainnet genesis hash |
52
+ | `V1_ALGORAND_TESTNET` | `"algorand-testnet"` | V1 testnet identifier |
53
+ | `V1_ALGORAND_MAINNET` | `"algorand-mainnet"` | V1 mainnet identifier |
54
+ | `V1_TO_CAIP2` | `Record<string, string>` | V1 to CAIP-2 mapping |
55
+ | `CAIP2_TO_V1` | `Record<string, string>` | CAIP-2 to V1 mapping |
56
+ | `USDC_TESTNET_ASA_ID` | `"10458941"` | USDC ASA ID on testnet |
57
+ | `USDC_MAINNET_ASA_ID` | `"31566704"` | USDC ASA ID on mainnet |
58
+ | `USDC_DECIMALS` | `6` | USDC decimal places |
59
+ | `USDC_CONFIG` | `Record<network, config>` | USDC config per network |
60
+ | `DEFAULT_ALGOD_TESTNET` | Env or `"https://testnet-api.algonode.cloud"` | Testnet Algod URL |
61
+ | `DEFAULT_ALGOD_MAINNET` | Env or `"https://mainnet-api.algonode.cloud"` | Mainnet Algod URL |
62
+ | `MIN_TXN_FEE` | `1000` | Minimum transaction fee (microAlgos) |
63
+ | `MAX_ATOMIC_GROUP_SIZE` | `16` | Maximum group size |
64
+ | `MAX_REASONABLE_FEE` | `10_000_000` | Fee safety cap (microAlgos) |
65
+ | `ALGORAND_ADDRESS_LENGTH` | `58` | Address character length |
66
+ | `ALGORAND_ADDRESS_REGEX` | `/^[A-Z2-7]{58}$/` | Address format regex |
67
+
68
+ **Utility Functions:**
69
+
70
+ | Function | Signature | Description |
71
+ |----------|-----------|-------------|
72
+ | `isValidAlgorandAddress` | `(addr: string) => boolean` | Full address validation (format + checksum) |
73
+ | `convertToTokenAmount` | `(amount: string, decimals: number) => string` | Decimal to atomic units |
74
+ | `convertFromTokenAmount` | `(amount: string, decimals: number) => string` | Atomic units to decimal |
75
+ | `encodeTransaction` | `(bytes: Uint8Array) => string` | Uint8Array to base64 |
76
+ | `decodeTransaction` | `(b64: string) => Uint8Array` | Base64 to Uint8Array |
77
+ | `decodeSignedTransaction` | `(b64: string) => SignedTransaction` | Decode signed txn from base64 |
78
+ | `decodeUnsignedTransaction` | `(b64: string) => Transaction` | Decode unsigned txn from base64 |
79
+ | `getNetworkFromCaip2` | `(caip2: string) => "testnet" \| "mainnet" \| null` | Extract network type |
80
+ | `isAlgorandNetwork` | `(network: string) => boolean` | Check if Algorand network |
81
+ | `isTestnetNetwork` | `(network: string) => boolean` | Check if testnet |
82
+ | `v1ToCaip2` | `(v1: string) => string` | Convert V1 to CAIP-2 |
83
+ | `caip2ToV1` | `(caip2: string) => string` | Convert CAIP-2 to V1 |
84
+ | `createAlgodClient` | `(network, url?, token?) => Algodv2` | Create Algod client |
85
+ | `getSenderFromTransaction` | `(bytes, isSigned) => string` | Extract sender address |
86
+ | `getTransactionId` | `(bytes) => string` | Get transaction ID |
87
+ | `hasSignature` | `(bytes) => boolean` | Check if transaction is signed |
88
+ | `validateGroupId` | `(txnBytes[]) => boolean` | Validate consistent group ID |
89
+ | `assignGroupId` | `(txns[]) => Transaction[]` | Assign group ID to transactions |
90
+ | `isAvmSignerWallet` | `(wallet: unknown) => wallet is ClientAvmSigner` | Type guard for ClientAvmSigner |
91
+
92
+ ### @x402-avm/express
93
+
94
+ Express.js middleware for payment-gated routes.
95
+
96
+ | Export | Description |
97
+ |--------|-------------|
98
+ | `paymentMiddleware(routes, server, paywallConfig?, paywall?)` | Middleware with pre-configured x402ResourceServer |
99
+ | `paymentMiddlewareFromConfig(routes, facilitatorClient, schemes?, paywallConfig?, paywall?)` | Auto-creates server internally |
100
+ | `paymentMiddlewareFromHTTPServer(httpServer)` | Uses x402HTTPResourceServer with hooks |
101
+
102
+ ### @x402-avm/hono
103
+
104
+ Hono middleware for payment-gated routes. Same API as Express but returns Hono `MiddlewareHandler`.
105
+
106
+ | Export | Description |
107
+ |--------|-------------|
108
+ | `paymentMiddleware(routes, server, paywallConfig?, paywall?)` | Middleware with pre-configured x402ResourceServer |
109
+ | `paymentMiddlewareFromConfig(routes, facilitatorClient, schemes?, paywallConfig?, paywall?, syncOnStart?)` | Auto-creates server internally |
110
+ | `paymentMiddlewareFromHTTPServer(httpServer)` | Uses x402HTTPResourceServer with hooks |
111
+
112
+ ### @x402-avm/next
113
+
114
+ Next.js middleware for payment-gated routes.
115
+
116
+ ### @x402-avm/fetch
117
+
118
+ Fetch API wrapper that automatically handles 402 responses.
119
+
120
+ | Export | Description |
121
+ |--------|-------------|
122
+ | `wrapFetch(client)` | Returns a fetch-like function with 402 handling |
123
+
124
+ ### @x402-avm/axios
125
+
126
+ Axios interceptor that automatically handles 402 responses.
127
+
128
+ | Export | Description |
129
+ |--------|-------------|
130
+ | `wrapAxios(client)` | Returns an axios instance with 402 handling |
131
+
132
+ ### @x402-avm/paywall
133
+
134
+ Browser paywall UI component shown when a user visits a protected route in a browser.
135
+
136
+ ### @x402-avm/extensions
137
+
138
+ Protocol extensions (bazaar marketplace, custom schemes).
139
+
140
+ ## ClientAvmSigner Interface (Detailed)
141
+
142
+ ```typescript
143
+ interface ClientAvmSigner {
144
+ /**
145
+ * The 58-character Algorand address of the signer.
146
+ * Used to identify which transactions belong to this signer.
147
+ */
148
+ address: string;
149
+
150
+ /**
151
+ * Sign one or more transactions from an atomic group.
152
+ *
153
+ * @param txns - Array of unsigned transactions as raw msgpack Uint8Array bytes.
154
+ * Each element is a complete unsigned transaction.
155
+ * @param indexesToSign - Optional array of zero-based indexes indicating which
156
+ * transactions this signer should sign. If not provided,
157
+ * the signer should sign all transactions.
158
+ * @returns Array of the same length as txns. Each element is either:
159
+ * - Uint8Array: the signed transaction bytes (for indexes that were signed)
160
+ * - null: for indexes that were not signed (e.g., fee payer txn)
161
+ */
162
+ signTransactions(
163
+ txns: Uint8Array[],
164
+ indexesToSign?: number[],
165
+ ): Promise<(Uint8Array | null)[]>;
166
+ }
167
+ ```
168
+
169
+ **Compatibility:** This interface matches `@txnlab/use-wallet`'s `signTransactions` function signature, allowing direct bridging from wallet to signer.
170
+
171
+ ## FacilitatorAvmSigner Interface (Detailed)
172
+
173
+ ```typescript
174
+ interface FacilitatorAvmSigner {
175
+ /**
176
+ * Get all Algorand addresses this facilitator manages.
177
+ * These are the fee payer addresses used for fee abstraction.
178
+ * Only transactions from these addresses will be signed by the facilitator.
179
+ */
180
+ getAddresses(): readonly string[];
181
+
182
+ /**
183
+ * Sign a single unsigned transaction.
184
+ *
185
+ * @param txn - Raw msgpack bytes of the unsigned transaction
186
+ * @param senderAddress - The Algorand address of the transaction sender
187
+ * @returns Raw msgpack bytes of the signed transaction
188
+ */
189
+ signTransaction(txn: Uint8Array, senderAddress: string): Promise<Uint8Array>;
190
+
191
+ /**
192
+ * Get an Algod client for the specified network.
193
+ * Used for fetching transaction parameters and other on-chain queries.
194
+ *
195
+ * @param network - CAIP-2 network identifier
196
+ * @returns algosdk.Algodv2 instance (typed as unknown to avoid algosdk dependency in types)
197
+ */
198
+ getAlgodClient(network: Network): unknown;
199
+
200
+ /**
201
+ * Simulate a transaction group before submission.
202
+ * Must use allowEmptySignatures: true for unsigned fee payer transactions.
203
+ *
204
+ * @param txns - Array of transaction bytes (mix of signed and unsigned)
205
+ * @param network - CAIP-2 network identifier
206
+ * @returns Simulation result from the Algod API
207
+ */
208
+ simulateTransactions(txns: Uint8Array[], network: Network): Promise<unknown>;
209
+
210
+ /**
211
+ * Submit fully signed transactions to the Algorand network.
212
+ * All transactions in the group must be signed at this point.
213
+ *
214
+ * @param signedTxns - Array of signed transaction bytes
215
+ * @param network - CAIP-2 network identifier
216
+ * @returns Transaction ID of the submitted group
217
+ */
218
+ sendTransactions(signedTxns: Uint8Array[], network: Network): Promise<string>;
219
+
220
+ /**
221
+ * Wait for a transaction to be confirmed on-chain.
222
+ *
223
+ * @param txId - Transaction ID to wait for
224
+ * @param network - CAIP-2 network identifier
225
+ * @param waitRounds - Number of rounds to wait (default: 4)
226
+ * @returns Confirmation result
227
+ */
228
+ waitForConfirmation(
229
+ txId: string,
230
+ network: Network,
231
+ waitRounds?: number,
232
+ ): Promise<unknown>;
233
+ }
234
+ ```
235
+
236
+ ## Route Configuration Types
237
+
238
+ ```typescript
239
+ // RoutesConfig: maps "METHOD /path" to RouteConfig
240
+ type RoutesConfig = Record<string, RouteConfig>;
241
+
242
+ interface RouteConfig {
243
+ accepts: PaymentOption | PaymentOption[];
244
+ resource?: string;
245
+ description?: string;
246
+ mimeType?: string;
247
+ customPaywallHtml?: string;
248
+ unpaidResponseBody?: (context: any) => { contentType: string; body: any };
249
+ extensions?: Record<string, unknown>;
250
+ }
251
+
252
+ interface PaymentOption {
253
+ scheme: string; // "exact"
254
+ payTo: string; // Algorand address (58 chars)
255
+ price: Price; // "$0.01" or DynamicPrice function
256
+ network: string; // CAIP-2 identifier
257
+ maxTimeoutSeconds?: number;
258
+ extra?: Record<string, unknown>;
259
+ }
260
+ ```
261
+
262
+ ## Testing Notes
263
+
264
+ ### Running a Local Stack
265
+
266
+ 1. Start facilitator on port 4020 with `AVM_PRIVATE_KEY` env var
267
+ 2. Start resource server on port 4021 with `FACILITATOR_URL=http://localhost:4020`
268
+ 3. Run client with `AVM_PRIVATE_KEY` and `RESOURCE_SERVER_URL=http://localhost:4021`
269
+
270
+ ### Using the Online Facilitator
271
+
272
+ Set `FACILITATOR_URL=https://facilitator.goplausible.xyz` in the resource server to avoid running a local facilitator.
273
+
274
+ ### Algorand Testnet Resources
275
+
276
+ - Fund accounts: [Algorand Testnet Dispenser](https://bank.testnet.algorand.network/)
277
+ - Explorer: [Allo Explorer Testnet](https://testnet.explorer.perawallet.app/)
278
+ - Algod: `https://testnet-api.algonode.cloud`
279
+ - USDC ASA ID: `10458941`
280
+
281
+ ## Design Considerations
282
+
283
+ ### Why Signer Separation?
284
+
285
+ The SDK defines interfaces (`ClientAvmSigner`, `FacilitatorAvmSigner`) but never imports `algosdk`. This means:
286
+
287
+ - The SDK core has zero `algosdk` dependency
288
+ - Any wallet library can provide signers (Pera, Defly, Kibisis, etc.)
289
+ - Server-side code can use `algosdk` directly
290
+ - The `@txnlab/use-wallet` ecosystem works out of the box
291
+
292
+ ### Why Raw Bytes?
293
+
294
+ The SDK passes `Uint8Array` between all methods. This:
295
+
296
+ - Matches `@txnlab/use-wallet`'s `signTransactions` signature
297
+ - Avoids double-encoding/decoding
298
+ - Keeps the protocol layer independent of `algosdk` types
299
+ - Base64 encoding only happens at the HTTP boundary (PAYMENT-SIGNATURE header)
300
+
301
+ ### Why Unconditional Registration?
302
+
303
+ AVM scheme registration is never conditional on environment variables. This ensures:
304
+
305
+ - AVM is always available as a payment option
306
+ - No silent failures when env vars are missing
307
+ - Parity with EVM and SVM treatment
308
+
309
+ ## External Resources
310
+
311
+ - [@x402-avm/core on npm](https://www.npmjs.com/package/@x402-avm/core)
312
+ - [@x402-avm/avm on npm](https://www.npmjs.com/package/@x402-avm/avm)
313
+ - [@x402-avm/express on npm](https://www.npmjs.com/package/@x402-avm/express)
314
+ - [@x402-avm/hono on npm](https://www.npmjs.com/package/@x402-avm/hono)
315
+ - [@x402-avm/next on npm](https://www.npmjs.com/package/@x402-avm/next)
316
+ - [@x402-avm/fetch on npm](https://www.npmjs.com/package/@x402-avm/fetch)
317
+ - [@x402-avm/axios on npm](https://www.npmjs.com/package/@x402-avm/axios)
318
+ - [@x402-avm/paywall on npm](https://www.npmjs.com/package/@x402-avm/paywall)
319
+ - [@x402-avm/extensions on npm](https://www.npmjs.com/package/@x402-avm/extensions)
320
+ - [GoPlausible x402-avm Examples](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
321
+ - [GoPlausible x402-avm Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)
322
+ - [@txnlab/use-wallet](https://github.com/TxnLab/use-wallet)
323
+ - [algosdk TypeScript](https://github.com/algorand/js-algorand-sdk)
@@ -0,0 +1,232 @@
1
+ # x402-avm for TypeScript Developers
2
+
3
+ Understand the @x402-avm/* TypeScript package ecosystem, signer interfaces, registration patterns, and how to integrate Algorand payments into TypeScript applications.
4
+
5
+ ## Prerequisites
6
+
7
+ Before using x402-avm in TypeScript:
8
+
9
+ 1. **Node.js 18+** or a modern browser runtime
10
+ 2. **TypeScript 5+** recommended (JavaScript also works)
11
+ 3. **npm or yarn** for package management
12
+ 4. **algosdk** -- the Algorand JavaScript SDK (peer dependency for signer implementations)
13
+
14
+ ## Core Workflow: Register, Configure, Use
15
+
16
+ Every x402-avm TypeScript application follows the same pattern:
17
+
18
+ ```
19
+ 1. Create component instance (client/server/facilitator)
20
+ 2. Register AVM scheme via registerExactAvmScheme()
21
+ 3. Use the component (fetch, middleware, verify/settle)
22
+ ```
23
+
24
+ The `registerExactAvmScheme` function is the bridge between the generic x402 core and Algorand-specific logic.
25
+
26
+ ## How to Proceed
27
+
28
+ ### Step 1: Install Packages
29
+
30
+ The package ecosystem is modular. Install only what you need:
31
+
32
+ ```bash
33
+ # Core + AVM mechanism (always needed)
34
+ npm install @x402-avm/core @x402-avm/avm algosdk
35
+
36
+ # For a client application (pick one)
37
+ npm install @x402-avm/fetch # Fetch API wrapper
38
+ npm install @x402-avm/axios # Axios interceptor
39
+
40
+ # For a server application (pick one)
41
+ npm install @x402-avm/express # Express.js middleware
42
+ npm install @x402-avm/hono # Hono middleware
43
+ npm install @x402-avm/next # Next.js middleware
44
+
45
+ # For browser wallet integration
46
+ npm install @txnlab/use-wallet
47
+
48
+ # Optional
49
+ npm install @x402-avm/paywall # Browser paywall UI
50
+ npm install @x402-avm/extensions # Protocol extensions
51
+ ```
52
+
53
+ ### Step 2: Understand the Package Structure
54
+
55
+ | Package | Role | Key Exports |
56
+ |---------|------|-------------|
57
+ | `@x402-avm/core` | Base protocol | `x402Client`, `x402ResourceServer`, `x402Facilitator`, `HTTPFacilitatorClient` |
58
+ | `@x402-avm/avm` | AVM mechanism | `ClientAvmSigner`, `FacilitatorAvmSigner`, constants, utilities |
59
+ | `@x402-avm/express` | Express middleware | `paymentMiddleware`, `paymentMiddlewareFromConfig` |
60
+ | `@x402-avm/hono` | Hono middleware | `paymentMiddleware`, `paymentMiddlewareFromConfig` |
61
+ | `@x402-avm/next` | Next.js middleware | `paymentMiddleware` |
62
+ | `@x402-avm/fetch` | Fetch client | `wrapFetch` |
63
+ | `@x402-avm/axios` | Axios client | `wrapAxios` |
64
+ | `@x402-avm/paywall` | Paywall UI | `PaywallProvider` |
65
+ | `@x402-avm/extensions` | Extensions | Bazaar, custom schemes |
66
+
67
+ ### Step 3: Implement a Signer
68
+
69
+ The signer is the only component that touches `algosdk` directly. The SDK defines the interface; you provide the implementation.
70
+
71
+ **For clients (browser with wallet):**
72
+ ```typescript
73
+ import type { ClientAvmSigner } from "@x402-avm/avm";
74
+ import { useWallet } from "@txnlab/use-wallet";
75
+
76
+ const { activeAccount, signTransactions } = useWallet();
77
+
78
+ const signer: ClientAvmSigner = {
79
+ address: activeAccount.address,
80
+ signTransactions: async (txns, indexesToSign) => {
81
+ return signTransactions(txns, indexesToSign);
82
+ },
83
+ };
84
+ ```
85
+
86
+ **For clients (server-side with private key):**
87
+ ```typescript
88
+ import type { ClientAvmSigner } from "@x402-avm/avm";
89
+ import algosdk from "algosdk";
90
+
91
+ const secretKey = Buffer.from(process.env.AVM_PRIVATE_KEY!, "base64");
92
+ const address = algosdk.encodeAddress(secretKey.slice(32));
93
+
94
+ const signer: ClientAvmSigner = {
95
+ address,
96
+ signTransactions: async (txns, indexesToSign) => {
97
+ return txns.map((txn, i) => {
98
+ if (indexesToSign && !indexesToSign.includes(i)) return null;
99
+ const decoded = algosdk.decodeUnsignedTransaction(txn);
100
+ return algosdk.signTransaction(decoded, secretKey).blob;
101
+ });
102
+ },
103
+ };
104
+ ```
105
+
106
+ **For facilitators:**
107
+ ```typescript
108
+ import type { FacilitatorAvmSigner } from "@x402-avm/avm";
109
+ import algosdk from "algosdk";
110
+
111
+ const secretKey = Buffer.from(process.env.AVM_PRIVATE_KEY!, "base64");
112
+ const address = algosdk.encodeAddress(secretKey.slice(32));
113
+ const algodClient = new algosdk.Algodv2("", "https://testnet-api.algonode.cloud", "");
114
+
115
+ const signer: FacilitatorAvmSigner = {
116
+ getAddresses: () => [address],
117
+ signTransaction: async (txn, _addr) => {
118
+ const decoded = algosdk.decodeUnsignedTransaction(txn);
119
+ return algosdk.signTransaction(decoded, secretKey).blob;
120
+ },
121
+ getAlgodClient: () => algodClient,
122
+ simulateTransactions: async (txns) => { /* ... */ },
123
+ sendTransactions: async (signedTxns) => { /* ... */ },
124
+ waitForConfirmation: async (txId, _net, rounds) => { /* ... */ },
125
+ };
126
+ ```
127
+
128
+ ### Step 4: Register the AVM Scheme
129
+
130
+ Registration connects the AVM mechanism to the core component. Each role has its own registration function from a different subpath:
131
+
132
+ ```typescript
133
+ // Client
134
+ import { registerExactAvmScheme } from "@x402-avm/avm/exact/client";
135
+ registerExactAvmScheme(client, { signer });
136
+
137
+ // Server
138
+ import { registerExactAvmScheme } from "@x402-avm/avm/exact/server";
139
+ registerExactAvmScheme(server);
140
+
141
+ // Facilitator
142
+ import { registerExactAvmScheme } from "@x402-avm/avm/exact/facilitator";
143
+ registerExactAvmScheme(facilitator, { signer, networks: ALGORAND_TESTNET_CAIP2 });
144
+ ```
145
+
146
+ ### Step 5: Use Constants and Utilities
147
+
148
+ ```typescript
149
+ import {
150
+ ALGORAND_TESTNET_CAIP2,
151
+ ALGORAND_MAINNET_CAIP2,
152
+ USDC_TESTNET_ASA_ID,
153
+ USDC_MAINNET_ASA_ID,
154
+ isAlgorandNetwork,
155
+ isValidAlgorandAddress,
156
+ convertToTokenAmount,
157
+ createAlgodClient,
158
+ } from "@x402-avm/avm";
159
+ ```
160
+
161
+ ## Signer Interfaces
162
+
163
+ ### ClientAvmSigner
164
+
165
+ ```typescript
166
+ interface ClientAvmSigner {
167
+ address: string;
168
+ signTransactions(
169
+ txns: Uint8Array[],
170
+ indexesToSign?: number[],
171
+ ): Promise<(Uint8Array | null)[]>;
172
+ }
173
+ ```
174
+
175
+ - `address`: The 58-character Algorand address of the payer
176
+ - `signTransactions`: Signs one or more transactions. Returns `null` for transactions the client should not sign (e.g., fee payer transactions)
177
+ - `txns`: Array of unsigned transactions as raw msgpack `Uint8Array`
178
+ - `indexesToSign`: Optional array of indexes to sign. If not provided, sign all
179
+
180
+ This interface is directly compatible with `@txnlab/use-wallet`'s `signTransactions`.
181
+
182
+ ### FacilitatorAvmSigner
183
+
184
+ ```typescript
185
+ interface FacilitatorAvmSigner {
186
+ getAddresses(): readonly string[];
187
+ signTransaction(txn: Uint8Array, senderAddress: string): Promise<Uint8Array>;
188
+ getAlgodClient(network: Network): unknown;
189
+ simulateTransactions(txns: Uint8Array[], network: Network): Promise<unknown>;
190
+ sendTransactions(signedTxns: Uint8Array[], network: Network): Promise<string>;
191
+ waitForConfirmation(txId: string, network: Network, waitRounds?: number): Promise<unknown>;
192
+ }
193
+ ```
194
+
195
+ - `getAddresses`: Returns all fee payer addresses the facilitator manages
196
+ - `signTransaction`: Signs a single transaction for the given sender address
197
+ - `getAlgodClient`: Returns an Algod client for the specified network
198
+ - `simulateTransactions`: Simulates a transaction group before submission
199
+ - `sendTransactions`: Submits signed transactions to the network, returns txId
200
+ - `waitForConfirmation`: Waits for transaction confirmation
201
+
202
+ ## Important Rules / Guidelines
203
+
204
+ 1. **Import paths matter** -- `registerExactAvmScheme` comes from different subpaths for client, server, and facilitator
205
+ 2. **Signer is the boundary** -- only signer implementations import `algosdk`. The SDK core never touches `algosdk` directly
206
+ 3. **Raw bytes everywhere** -- the SDK passes `Uint8Array` msgpack bytes. No base64 conversion needed within the SDK (unlike Python)
207
+ 4. **Registration is unconditional** -- never wrap `registerExactAvmScheme()` in `if (env.AVM_*)` checks
208
+ 5. **Type imports** -- use `import type { ... }` for interfaces to avoid bundling issues
209
+ 6. **Network constants** -- always import `ALGORAND_TESTNET_CAIP2` / `ALGORAND_MAINNET_CAIP2` from `@x402-avm/avm` in SDK code
210
+
211
+ ## Common Errors / Troubleshooting
212
+
213
+ | Error | Cause | Solution |
214
+ |-------|-------|----------|
215
+ | `Cannot find module '@x402-avm/avm/exact/client'` | Package not installed or wrong version | Run `npm install @x402-avm/avm` |
216
+ | `signTransactions is not a function` | Signer object missing method | Ensure signer implements `ClientAvmSigner` interface |
217
+ | `Invalid key length: expected 64` | Wrong private key format | Key must be 64 bytes Base64-encoded |
218
+ | `No scheme registered for network` | AVM scheme not registered | Call `registerExactAvmScheme()` before use |
219
+ | `getAddresses is not a function` | Wrong signer type | Use `FacilitatorAvmSigner` for facilitators, `ClientAvmSigner` for clients |
220
+ | `Simulation failed` | Transaction would fail on-chain | Check balances, ASA opt-in, correct network |
221
+ | `global is not defined` | algosdk references `global` in browser | Add `define: { global: 'globalThis' }` to vite.config.ts |
222
+ | Type errors in wallet integration | `@txnlab/use-wallet` version mismatch | Ensure compatible version of `@txnlab/use-wallet` |
223
+
224
+ ## References / Further Reading
225
+
226
+ - [explain-algorand-x402-typescript-reference.md](./explain-algorand-x402-typescript-reference.md) - Detailed package API reference
227
+ - [explain-algorand-x402-typescript-examples.md](./explain-algorand-x402-typescript-examples.md) - Complete TypeScript code examples
228
+ - [@x402-avm/core on npm](https://www.npmjs.com/package/@x402-avm/core)
229
+ - [@x402-avm/avm on npm](https://www.npmjs.com/package/@x402-avm/avm)
230
+ - [GoPlausible x402-avm Examples](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
231
+ - [GoPlausible x402-avm Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)
232
+ - [@txnlab/use-wallet Documentation](https://txnlab.gitbook.io/use-wallet)