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.
- package/LICENSE +21 -0
- package/README.md +112 -0
- package/index.ts +361 -0
- package/lib/mcp-servers.ts +14 -0
- package/lib/x402-fetch.ts +213 -0
- package/memory/algorand-plugin.md +82 -0
- package/openclaw.plugin.json +30 -0
- package/package.json +38 -0
- package/setup.ts +80 -0
- package/skills/algorand-development/SKILL.md +90 -0
- package/skills/algorand-development/references/build-smart-contracts-reference.md +79 -0
- package/skills/algorand-development/references/build-smart-contracts.md +52 -0
- package/skills/algorand-development/references/create-project-reference.md +86 -0
- package/skills/algorand-development/references/create-project.md +89 -0
- package/skills/algorand-development/references/implement-arc-standards-arc32-arc56.md +396 -0
- package/skills/algorand-development/references/implement-arc-standards-arc4.md +265 -0
- package/skills/algorand-development/references/implement-arc-standards.md +92 -0
- package/skills/algorand-development/references/search-algorand-examples-reference.md +119 -0
- package/skills/algorand-development/references/search-algorand-examples.md +89 -0
- package/skills/algorand-development/references/troubleshoot-errors-contract.md +373 -0
- package/skills/algorand-development/references/troubleshoot-errors-transaction.md +599 -0
- package/skills/algorand-development/references/troubleshoot-errors.md +105 -0
- package/skills/algorand-development/references/use-algokit-cli-reference.md +228 -0
- package/skills/algorand-development/references/use-algokit-cli.md +64 -0
- package/skills/algorand-interaction/SKILL.md +223 -0
- package/skills/algorand-interaction/references/algorand-mcp.md +743 -0
- package/skills/algorand-interaction/references/examples-algorand-mcp.md +647 -0
- package/skills/algorand-python/SKILL.md +95 -0
- package/skills/algorand-python/references/build-smart-contracts-decorators.md +413 -0
- package/skills/algorand-python/references/build-smart-contracts-reference.md +55 -0
- package/skills/algorand-python/references/build-smart-contracts-storage.md +452 -0
- package/skills/algorand-python/references/build-smart-contracts-transactions.md +445 -0
- package/skills/algorand-python/references/build-smart-contracts-types.md +438 -0
- package/skills/algorand-python/references/build-smart-contracts.md +82 -0
- package/skills/algorand-python/references/create-project-reference.md +55 -0
- package/skills/algorand-python/references/create-project.md +75 -0
- package/skills/algorand-python/references/implement-arc-standards-arc32-arc56.md +101 -0
- package/skills/algorand-python/references/implement-arc-standards-arc4.md +154 -0
- package/skills/algorand-python/references/implement-arc-standards.md +39 -0
- package/skills/algorand-python/references/troubleshoot-errors-contract.md +355 -0
- package/skills/algorand-python/references/troubleshoot-errors-transaction.md +430 -0
- package/skills/algorand-python/references/troubleshoot-errors.md +46 -0
- package/skills/algorand-python/references/use-algokit-utils-reference.md +350 -0
- package/skills/algorand-python/references/use-algokit-utils.md +76 -0
- package/skills/algorand-typescript/SKILL.md +131 -0
- package/skills/algorand-typescript/references/algorand-ts-migration-from-beta.md +448 -0
- package/skills/algorand-typescript/references/algorand-ts-migration-from-tealscript.md +487 -0
- package/skills/algorand-typescript/references/algorand-ts-migration.md +102 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-methods-and-abi.md +134 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-reference.md +58 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-storage.md +154 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-transactions.md +187 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-types-and-values.md +150 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax.md +84 -0
- package/skills/algorand-typescript/references/build-smart-contracts-reference.md +52 -0
- package/skills/algorand-typescript/references/build-smart-contracts.md +74 -0
- package/skills/algorand-typescript/references/call-smart-contracts-reference.md +237 -0
- package/skills/algorand-typescript/references/call-smart-contracts.md +183 -0
- package/skills/algorand-typescript/references/create-project-reference.md +53 -0
- package/skills/algorand-typescript/references/create-project.md +86 -0
- package/skills/algorand-typescript/references/deploy-react-frontend-examples.md +527 -0
- package/skills/algorand-typescript/references/deploy-react-frontend-reference.md +412 -0
- package/skills/algorand-typescript/references/deploy-react-frontend.md +239 -0
- package/skills/algorand-typescript/references/implement-arc-standards-arc32-arc56.md +73 -0
- package/skills/algorand-typescript/references/implement-arc-standards-arc4.md +126 -0
- package/skills/algorand-typescript/references/implement-arc-standards.md +44 -0
- package/skills/algorand-typescript/references/test-smart-contracts-examples.md +245 -0
- package/skills/algorand-typescript/references/test-smart-contracts-unit-tests.md +147 -0
- package/skills/algorand-typescript/references/test-smart-contracts.md +127 -0
- package/skills/algorand-typescript/references/troubleshoot-errors-contract.md +296 -0
- package/skills/algorand-typescript/references/troubleshoot-errors-transaction.md +438 -0
- package/skills/algorand-typescript/references/troubleshoot-errors.md +56 -0
- package/skills/algorand-typescript/references/use-algokit-utils-reference.md +342 -0
- package/skills/algorand-typescript/references/use-algokit-utils.md +74 -0
- package/skills/algorand-x402-python/SKILL.md +113 -0
- package/skills/algorand-x402-python/references/create-python-x402-client-examples.md +469 -0
- package/skills/algorand-x402-python/references/create-python-x402-client-reference.md +313 -0
- package/skills/algorand-x402-python/references/create-python-x402-client.md +207 -0
- package/skills/algorand-x402-python/references/create-python-x402-facilitator-examples.md +924 -0
- package/skills/algorand-x402-python/references/create-python-x402-facilitator-reference.md +629 -0
- package/skills/algorand-x402-python/references/create-python-x402-facilitator.md +408 -0
- package/skills/algorand-x402-python/references/create-python-x402-server-examples.md +703 -0
- package/skills/algorand-x402-python/references/create-python-x402-server-reference.md +303 -0
- package/skills/algorand-x402-python/references/create-python-x402-server.md +221 -0
- package/skills/algorand-x402-python/references/explain-algorand-x402-python-examples.md +605 -0
- package/skills/algorand-x402-python/references/explain-algorand-x402-python-reference.md +315 -0
- package/skills/algorand-x402-python/references/explain-algorand-x402-python.md +167 -0
- package/skills/algorand-x402-python/references/use-python-x402-core-avm-examples.md +554 -0
- package/skills/algorand-x402-python/references/use-python-x402-core-avm-reference.md +278 -0
- package/skills/algorand-x402-python/references/use-python-x402-core-avm.md +166 -0
- package/skills/algorand-x402-typescript/SKILL.md +129 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-client-examples.md +879 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-client-reference.md +371 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-client.md +236 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator-examples.md +875 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator-reference.md +461 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator.md +270 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs-examples.md +1181 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs-reference.md +360 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs.md +251 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall-examples.md +870 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall-reference.md +323 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall.md +281 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-server-examples.md +1135 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-server-reference.md +382 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-server.md +216 -0
- package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript-examples.md +616 -0
- package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript-reference.md +323 -0
- package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript.md +232 -0
- package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm-examples.md +1417 -0
- package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm-reference.md +504 -0
- package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm.md +158 -0
package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript-reference.md
ADDED
|
@@ -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)
|