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
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
# @x402-avm/core and @x402-avm/avm Reference
|
|
2
|
+
|
|
3
|
+
Detailed API reference for the x402-avm TypeScript SDK packages.
|
|
4
|
+
|
|
5
|
+
## Dependencies
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@x402-avm/core": "latest",
|
|
11
|
+
"@x402-avm/avm": "latest",
|
|
12
|
+
"algosdk": "^3.0.0"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
For browser wallet integration:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@txnlab/use-wallet": "^4.0.0",
|
|
23
|
+
"@txnlab/use-wallet-react": "^4.0.0"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Package Exports: @x402-avm/core
|
|
29
|
+
|
|
30
|
+
| Import Path | Exports |
|
|
31
|
+
|-------------|---------|
|
|
32
|
+
| `@x402-avm/core/client` | `x402Client`, `PaymentPolicy` |
|
|
33
|
+
| `@x402-avm/core/server` | `x402ResourceServer`, `x402HTTPResourceServer`, `HTTPFacilitatorClient`, `ResourceConfig`, `RouteConfig` |
|
|
34
|
+
| `@x402-avm/core/facilitator` | `x402Facilitator` |
|
|
35
|
+
| `@x402-avm/core/http` | HTTP utilities and header parsing |
|
|
36
|
+
| `@x402-avm/core/types` | `PaymentRequirements`, `PaymentRequirementsV1`, `PaymentPayload`, `PaymentRequired`, `Network` |
|
|
37
|
+
|
|
38
|
+
## Package Exports: @x402-avm/avm
|
|
39
|
+
|
|
40
|
+
| Import Path | Exports |
|
|
41
|
+
|-------------|---------|
|
|
42
|
+
| `@x402-avm/avm` | All constants, types, and utilities |
|
|
43
|
+
| `@x402-avm/avm/exact/client` | `registerExactAvmScheme` (client variant) |
|
|
44
|
+
| `@x402-avm/avm/exact/server` | `registerExactAvmScheme` (server variant) |
|
|
45
|
+
| `@x402-avm/avm/exact/facilitator` | `registerExactAvmScheme` (facilitator variant) |
|
|
46
|
+
|
|
47
|
+
## x402Client
|
|
48
|
+
|
|
49
|
+
The client automatically handles HTTP 402 responses by creating payment payloads and retrying.
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { x402Client } from "@x402-avm/core/client";
|
|
53
|
+
|
|
54
|
+
const client = new x402Client({
|
|
55
|
+
schemes: [], // Populated via registerExactAvmScheme
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Methods
|
|
60
|
+
|
|
61
|
+
| Method | Signature | Description |
|
|
62
|
+
|--------|-----------|-------------|
|
|
63
|
+
| `fetch` | `(url: string, init?: RequestInit) => Promise<Response>` | Fetch with automatic 402 handling |
|
|
64
|
+
| `registerPolicy` | `(policy: PaymentPolicy) => void` | Add a payment filtering policy |
|
|
65
|
+
|
|
66
|
+
### Lifecycle
|
|
67
|
+
|
|
68
|
+
1. Client sends request to resource URL
|
|
69
|
+
2. Server responds with `402 Payment Required` + `PaymentRequired` body
|
|
70
|
+
3. Client selects a matching `PaymentRequirements` (filtered by policies)
|
|
71
|
+
4. Registered scheme creates and signs payment
|
|
72
|
+
5. Client retries with `PAYMENT-SIGNATURE` header containing signed payload
|
|
73
|
+
|
|
74
|
+
## PaymentPolicy
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
type PaymentPolicy = (
|
|
78
|
+
version: number,
|
|
79
|
+
requirements: PaymentRequirements[],
|
|
80
|
+
) => PaymentRequirements[];
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Policies receive the full list of `PaymentRequirements` from the 402 response and return a filtered subset. If the filtered list is empty, the client cannot pay.
|
|
84
|
+
|
|
85
|
+
## x402ResourceServer
|
|
86
|
+
|
|
87
|
+
Transport-agnostic server that creates 402 responses and processes payments.
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { x402ResourceServer } from "@x402-avm/core/server";
|
|
91
|
+
|
|
92
|
+
const server = new x402ResourceServer(facilitatorClient);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Methods
|
|
96
|
+
|
|
97
|
+
| Method | Signature | Description |
|
|
98
|
+
|--------|-----------|-------------|
|
|
99
|
+
| `createPaymentRequired` | `(resource, configs[]) => PaymentRequired` | Create a 402 response body |
|
|
100
|
+
| `processPayment` | `(xPaymentHeader, config) => Promise<ProcessResult>` | Verify and settle a payment |
|
|
101
|
+
|
|
102
|
+
## x402HTTPResourceServer
|
|
103
|
+
|
|
104
|
+
Adds HTTP route matching on top of `x402ResourceServer`.
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { x402HTTPResourceServer } from "@x402-avm/core/server";
|
|
108
|
+
|
|
109
|
+
const httpServer = new x402HTTPResourceServer(facilitatorClient, { routes });
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Methods
|
|
113
|
+
|
|
114
|
+
| Method | Signature | Description |
|
|
115
|
+
|--------|-----------|-------------|
|
|
116
|
+
| `processRequest` | `(context) => Promise<{ status, body }>` | Process an HTTP request with route matching |
|
|
117
|
+
| `onProtectedRequest` | `(callback) => void` | Register a hook for protected requests |
|
|
118
|
+
| `resourceServer` | Property | Access the underlying `x402ResourceServer` |
|
|
119
|
+
|
|
120
|
+
### Route Configuration
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
interface RouteConfig {
|
|
124
|
+
path: string; // Route pattern (supports * wildcard)
|
|
125
|
+
config: ResourceConfig;
|
|
126
|
+
description?: string;
|
|
127
|
+
mimeType?: string;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
interface ResourceConfig {
|
|
131
|
+
scheme: "exact";
|
|
132
|
+
payTo: string;
|
|
133
|
+
price: {
|
|
134
|
+
asset: string;
|
|
135
|
+
amount: string;
|
|
136
|
+
extra?: { name: string; decimals: number };
|
|
137
|
+
};
|
|
138
|
+
network: string;
|
|
139
|
+
maxTimeoutSeconds: number;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## HTTPFacilitatorClient
|
|
144
|
+
|
|
145
|
+
Communicates with a remote facilitator service over HTTP.
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import { HTTPFacilitatorClient } from "@x402-avm/core/server";
|
|
149
|
+
|
|
150
|
+
const client = new HTTPFacilitatorClient({
|
|
151
|
+
url: string;
|
|
152
|
+
headers?: Record<string, string>;
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Methods
|
|
157
|
+
|
|
158
|
+
| Method | Signature | Description |
|
|
159
|
+
|--------|-----------|-------------|
|
|
160
|
+
| `supported` | `() => Promise<{ networks }>` | Get supported networks |
|
|
161
|
+
| `verify` | `(payload) => Promise<VerifyResult>` | Verify a payment |
|
|
162
|
+
| `settle` | `(payload) => Promise<SettleResult>` | Settle a payment on-chain |
|
|
163
|
+
|
|
164
|
+
## x402Facilitator
|
|
165
|
+
|
|
166
|
+
Local facilitator that verifies and settles payments directly.
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { x402Facilitator } from "@x402-avm/core/facilitator";
|
|
170
|
+
|
|
171
|
+
const facilitator = new x402Facilitator();
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Methods
|
|
175
|
+
|
|
176
|
+
| Method | Signature | Description |
|
|
177
|
+
|--------|-----------|-------------|
|
|
178
|
+
| `verify` | `(payload, requirements) => Promise<VerifyResult>` | Verify payment signature and amounts |
|
|
179
|
+
| `settle` | `(payload, requirements) => Promise<SettleResult>` | Sign fee payer txn and submit group |
|
|
180
|
+
| `getSupportedNetworks` | `() => SupportedNetworks` | Get registered networks |
|
|
181
|
+
|
|
182
|
+
## registerExactAvmScheme
|
|
183
|
+
|
|
184
|
+
Three variants exist for client, server, and facilitator.
|
|
185
|
+
|
|
186
|
+
### Client Registration
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
import { registerExactAvmScheme } from "@x402-avm/avm/exact/client";
|
|
190
|
+
|
|
191
|
+
registerExactAvmScheme(client, {
|
|
192
|
+
signer: ClientAvmSigner; // Required: signer implementation
|
|
193
|
+
algodConfig?: { // Optional: Algod configuration
|
|
194
|
+
algodUrl?: string;
|
|
195
|
+
};
|
|
196
|
+
networks?: string[]; // Optional: restrict to specific networks
|
|
197
|
+
policies?: PaymentPolicy[]; // Optional: payment policies
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Server Registration
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { registerExactAvmScheme } from "@x402-avm/avm/exact/server";
|
|
205
|
+
|
|
206
|
+
registerExactAvmScheme(server, {
|
|
207
|
+
networks?: string[]; // Optional: restrict to specific networks
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Default: registers for all Algorand networks (algorand:*)
|
|
211
|
+
registerExactAvmScheme(server);
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Facilitator Registration
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { registerExactAvmScheme } from "@x402-avm/avm/exact/facilitator";
|
|
218
|
+
|
|
219
|
+
registerExactAvmScheme(facilitator, {
|
|
220
|
+
signer: FacilitatorAvmSigner; // Required: facilitator signer
|
|
221
|
+
networks: string | string[]; // Required: supported network(s)
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## ClientAvmSigner Interface
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
interface ClientAvmSigner {
|
|
229
|
+
address: string;
|
|
230
|
+
signTransactions(
|
|
231
|
+
txns: Uint8Array[],
|
|
232
|
+
indexesToSign?: number[],
|
|
233
|
+
): Promise<(Uint8Array | null)[]>;
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Compatible with `@txnlab/use-wallet`'s `signTransactions` function. The `indexesToSign` parameter allows selective signing in atomic groups (e.g., sign only the payment transaction, leave the fee payer unsigned for the facilitator).
|
|
238
|
+
|
|
239
|
+
## FacilitatorAvmSigner Interface
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
interface FacilitatorAvmSigner {
|
|
243
|
+
getAddresses(): readonly string[];
|
|
244
|
+
signTransaction(txn: Uint8Array, senderAddress: string): Promise<Uint8Array>;
|
|
245
|
+
getAlgodClient(network: Network): unknown;
|
|
246
|
+
simulateTransactions(txns: Uint8Array[], network: Network): Promise<unknown>;
|
|
247
|
+
sendTransactions(signedTxns: Uint8Array[], network: Network): Promise<string>;
|
|
248
|
+
waitForConfirmation(txId: string, network: Network, waitRounds?: number): Promise<unknown>;
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Method Details
|
|
253
|
+
|
|
254
|
+
| Method | Purpose |
|
|
255
|
+
|--------|---------|
|
|
256
|
+
| `getAddresses` | Returns fee payer addresses managed by this facilitator |
|
|
257
|
+
| `signTransaction` | Signs a single unsigned transaction (fee payer txn) |
|
|
258
|
+
| `getAlgodClient` | Returns an Algod client for the given network |
|
|
259
|
+
| `simulateTransactions` | Simulates an atomic group to validate before submission |
|
|
260
|
+
| `sendTransactions` | Submits signed transaction group to the network |
|
|
261
|
+
| `waitForConfirmation` | Waits for on-chain confirmation of a transaction |
|
|
262
|
+
|
|
263
|
+
## Type Guard
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
import { isAvmSignerWallet } from "@x402-avm/avm";
|
|
267
|
+
|
|
268
|
+
// Returns true if the object has { address: string, signTransactions: Function }
|
|
269
|
+
isAvmSignerWallet(wallet): wallet is ClientAvmSigner;
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Constants
|
|
273
|
+
|
|
274
|
+
### Network Identifiers
|
|
275
|
+
|
|
276
|
+
| Constant | Value |
|
|
277
|
+
|----------|-------|
|
|
278
|
+
| `ALGORAND_MAINNET_CAIP2` | `"algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8="` |
|
|
279
|
+
| `ALGORAND_TESTNET_CAIP2` | `"algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="` |
|
|
280
|
+
| `CAIP2_NETWORKS` | `[ALGORAND_MAINNET_CAIP2, ALGORAND_TESTNET_CAIP2]` |
|
|
281
|
+
| `ALGORAND_MAINNET_GENESIS_HASH` | `"wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8="` |
|
|
282
|
+
| `ALGORAND_TESTNET_GENESIS_HASH` | `"SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="` |
|
|
283
|
+
| `V1_ALGORAND_MAINNET` | `"algorand-mainnet"` |
|
|
284
|
+
| `V1_ALGORAND_TESTNET` | `"algorand-testnet"` |
|
|
285
|
+
| `V1_NETWORKS` | `["algorand-mainnet", "algorand-testnet"]` |
|
|
286
|
+
|
|
287
|
+
### V1/V2 Mapping
|
|
288
|
+
|
|
289
|
+
| Constant | Type | Description |
|
|
290
|
+
|----------|------|-------------|
|
|
291
|
+
| `V1_TO_CAIP2` | `Record<string, string>` | V1 name to CAIP-2 |
|
|
292
|
+
| `CAIP2_TO_V1` | `Record<string, string>` | CAIP-2 to V1 name |
|
|
293
|
+
|
|
294
|
+
### USDC Configuration
|
|
295
|
+
|
|
296
|
+
| Constant | Value |
|
|
297
|
+
|----------|-------|
|
|
298
|
+
| `USDC_MAINNET_ASA_ID` | `"31566704"` |
|
|
299
|
+
| `USDC_TESTNET_ASA_ID` | `"10458941"` |
|
|
300
|
+
| `USDC_DECIMALS` | `6` |
|
|
301
|
+
| `USDC_CONFIG` | `Record<network, { asaId, name, decimals }>` |
|
|
302
|
+
|
|
303
|
+
### Algod Endpoints
|
|
304
|
+
|
|
305
|
+
| Constant | Value |
|
|
306
|
+
|----------|-------|
|
|
307
|
+
| `DEFAULT_ALGOD_MAINNET` | env `ALGOD_MAINNET_URL` or `"https://mainnet-api.algonode.cloud"` |
|
|
308
|
+
| `DEFAULT_ALGOD_TESTNET` | env `ALGOD_TESTNET_URL` or `"https://testnet-api.algonode.cloud"` |
|
|
309
|
+
| `NETWORK_TO_ALGOD` | `Record<network, url>` |
|
|
310
|
+
| `FALLBACK_ALGOD_MAINNET` | `"https://mainnet-api.algonode.cloud"` |
|
|
311
|
+
| `FALLBACK_ALGOD_TESTNET` | `"https://testnet-api.algonode.cloud"` |
|
|
312
|
+
|
|
313
|
+
### Transaction Limits
|
|
314
|
+
|
|
315
|
+
| Constant | Value | Description |
|
|
316
|
+
|----------|-------|-------------|
|
|
317
|
+
| `MAX_ATOMIC_GROUP_SIZE` | `16` | Max transactions per atomic group |
|
|
318
|
+
| `MIN_TXN_FEE` | `1000` | Minimum transaction fee (microAlgos) |
|
|
319
|
+
| `MAX_REASONABLE_FEE` | `10_000_000` | 10 ALGO sanity check |
|
|
320
|
+
|
|
321
|
+
### Address Validation
|
|
322
|
+
|
|
323
|
+
| Constant | Value |
|
|
324
|
+
|----------|-------|
|
|
325
|
+
| `ALGORAND_ADDRESS_REGEX` | `/^[A-Z2-7]{58}$/` |
|
|
326
|
+
| `ALGORAND_ADDRESS_LENGTH` | `58` |
|
|
327
|
+
|
|
328
|
+
## Utility Functions
|
|
329
|
+
|
|
330
|
+
### Address Validation
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
isValidAlgorandAddress(address: string): boolean
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Full validation including format check and algosdk checksum verification.
|
|
337
|
+
|
|
338
|
+
### Amount Conversion
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
convertToTokenAmount(amount: string, decimals: number): string
|
|
342
|
+
convertFromTokenAmount(amount: string, decimals: number): string
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Convert between human-readable decimal amounts and atomic integer units.
|
|
346
|
+
|
|
347
|
+
### Transaction Encoding/Decoding
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
encodeTransaction(txnBytes: Uint8Array): string // Uint8Array -> base64
|
|
351
|
+
decodeTransaction(base64Str: string): Uint8Array // base64 -> Uint8Array
|
|
352
|
+
decodeSignedTransaction(base64Str: string): SignedTransaction
|
|
353
|
+
decodeUnsignedTransaction(base64Str: string): Transaction
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Network Utilities
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
getNetworkFromCaip2(caip2: string): "testnet" | "mainnet" | null
|
|
360
|
+
isAlgorandNetwork(network: string): boolean // Recognizes both V1 and CAIP-2
|
|
361
|
+
isTestnetNetwork(network: string): boolean
|
|
362
|
+
v1ToCaip2(v1Name: string): string
|
|
363
|
+
caip2ToV1(caip2: string): string
|
|
364
|
+
createAlgodClient(network: string, url?: string, token?: string): Algodv2
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Transaction Inspection
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
getSenderFromTransaction(txnBytes: Uint8Array, isSigned: boolean): string
|
|
371
|
+
getTransactionId(txnBytes: Uint8Array): string
|
|
372
|
+
hasSignature(txnBytes: Uint8Array): boolean
|
|
373
|
+
getGenesisHashFromTransaction(txnBytes: Uint8Array): string
|
|
374
|
+
validateGroupId(txnBytesArray: Uint8Array[]): boolean
|
|
375
|
+
assignGroupId(txns: Transaction[]): Transaction[]
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Type Definitions
|
|
379
|
+
|
|
380
|
+
### PaymentRequirements (V2)
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
interface PaymentRequirements {
|
|
384
|
+
scheme: "exact";
|
|
385
|
+
network: string; // CAIP-2 identifier
|
|
386
|
+
maxAmountRequired: string; // Atomic units as string
|
|
387
|
+
resource: string; // URL of the resource
|
|
388
|
+
description: string;
|
|
389
|
+
mimeType: string;
|
|
390
|
+
payTo: string; // Receiver address
|
|
391
|
+
maxTimeoutSeconds: number;
|
|
392
|
+
asset: string; // ASA ID ("0" for native ALGO)
|
|
393
|
+
outputSchema: unknown;
|
|
394
|
+
extra?: {
|
|
395
|
+
name: string; // Token name (e.g., "USDC")
|
|
396
|
+
decimals: number; // Token decimals (e.g., 6)
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### PaymentPayload
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
interface PaymentPayload {
|
|
405
|
+
x402Version: 2;
|
|
406
|
+
scheme: "exact";
|
|
407
|
+
network: string;
|
|
408
|
+
payload: {
|
|
409
|
+
paymentGroup: string[]; // base64-encoded msgpack transaction bytes
|
|
410
|
+
paymentIndex: number; // Index of the payment transaction
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### PaymentRequired
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
interface PaymentRequired {
|
|
419
|
+
x402Version: 2;
|
|
420
|
+
resource: {
|
|
421
|
+
url: string;
|
|
422
|
+
description: string;
|
|
423
|
+
mimeType: string;
|
|
424
|
+
};
|
|
425
|
+
accepts: PaymentRequirements[];
|
|
426
|
+
error: string;
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
## Fee Abstraction Flow
|
|
431
|
+
|
|
432
|
+
Fee abstraction uses Algorand atomic transaction groups and pooled fees:
|
|
433
|
+
|
|
434
|
+
1. **Client** creates a 2-transaction atomic group:
|
|
435
|
+
- Transaction 0: USDC/ALGO transfer from client to resource owner (fee = 0)
|
|
436
|
+
- Transaction 1: Self-payment by fee payer address (fee covers both transactions)
|
|
437
|
+
2. **Client** signs only Transaction 0 (their payment)
|
|
438
|
+
3. **Client** sends both transactions in `paymentGroup` array
|
|
439
|
+
4. **Facilitator** validates the fee payer transaction:
|
|
440
|
+
- Must be a self-payment (from == to)
|
|
441
|
+
- Amount must be 0
|
|
442
|
+
- No rekey, close-to, or other dangerous operations
|
|
443
|
+
- Fee must be within `MAX_REASONABLE_FEE`
|
|
444
|
+
5. **Facilitator** signs Transaction 1 and submits the atomic group
|
|
445
|
+
6. **Atomic execution** ensures all-or-nothing on-chain
|
|
446
|
+
|
|
447
|
+
### Security Guarantees
|
|
448
|
+
|
|
449
|
+
- Fee payer transaction validated for safety (no value extraction)
|
|
450
|
+
- Atomic group ensures both transactions succeed or both fail
|
|
451
|
+
- Maximum fee cap prevents excessive fee draining
|
|
452
|
+
- Group ID consistency validated before submission
|
|
453
|
+
|
|
454
|
+
## Environment Variables
|
|
455
|
+
|
|
456
|
+
| Variable | Description | Default |
|
|
457
|
+
|----------|-------------|---------|
|
|
458
|
+
| `AVM_PRIVATE_KEY` | Base64-encoded 64-byte key | Required for signing |
|
|
459
|
+
| `ALGOD_MAINNET_URL` | Custom mainnet Algod URL | `https://mainnet-api.algonode.cloud` |
|
|
460
|
+
| `ALGOD_TESTNET_URL` | Custom testnet Algod URL | `https://testnet-api.algonode.cloud` |
|
|
461
|
+
| `FACILITATOR_URL` | Facilitator service URL | Varies |
|
|
462
|
+
| `FACILITATOR_API_KEY` | Facilitator auth token | Optional |
|
|
463
|
+
|
|
464
|
+
## Private Key Format
|
|
465
|
+
|
|
466
|
+
The `AVM_PRIVATE_KEY` is a Base64-encoded 64-byte key:
|
|
467
|
+
- Bytes 0-31: Ed25519 seed (private key)
|
|
468
|
+
- Bytes 32-63: Ed25519 public key
|
|
469
|
+
- Address derivation: `algosdk.encodeAddress(secretKey.slice(32))`
|
|
470
|
+
|
|
471
|
+
## Testing
|
|
472
|
+
|
|
473
|
+
Use Algorand TestNet for development:
|
|
474
|
+
|
|
475
|
+
1. Get testnet ALGO from the [Algorand Dispenser](https://bank.testnet.algorand.network/)
|
|
476
|
+
2. Opt in to USDC TestNet ASA (ID: 10458941)
|
|
477
|
+
3. Get testnet USDC from [TestNet USDC Dispenser](https://asset-dispenser.testnet.algorand.network/)
|
|
478
|
+
4. Use `ALGORAND_TESTNET_CAIP2` as the network identifier
|
|
479
|
+
|
|
480
|
+
## Import Summary
|
|
481
|
+
|
|
482
|
+
| Component | TypeScript Import |
|
|
483
|
+
|-----------|-------------------|
|
|
484
|
+
| Client | `x402Client` from `@x402-avm/core/client` |
|
|
485
|
+
| Resource Server | `x402ResourceServer` from `@x402-avm/core/server` |
|
|
486
|
+
| HTTP Resource Server | `x402HTTPResourceServer` from `@x402-avm/core/server` |
|
|
487
|
+
| Facilitator | `x402Facilitator` from `@x402-avm/core/facilitator` |
|
|
488
|
+
| Facilitator Client | `HTTPFacilitatorClient` from `@x402-avm/core/server` |
|
|
489
|
+
| AVM Registration (Client) | `registerExactAvmScheme` from `@x402-avm/avm/exact/client` |
|
|
490
|
+
| AVM Registration (Server) | `registerExactAvmScheme` from `@x402-avm/avm/exact/server` |
|
|
491
|
+
| AVM Registration (Facilitator) | `registerExactAvmScheme` from `@x402-avm/avm/exact/facilitator` |
|
|
492
|
+
| Types | `@x402-avm/core/types` |
|
|
493
|
+
| Constants | `@x402-avm/avm` |
|
|
494
|
+
| Signer Interfaces | `ClientAvmSigner`, `FacilitatorAvmSigner` from `@x402-avm/avm` |
|
|
495
|
+
| Type Guard | `isAvmSignerWallet` from `@x402-avm/avm` |
|
|
496
|
+
|
|
497
|
+
## External Links
|
|
498
|
+
|
|
499
|
+
- [x402-avm Examples Repository](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
|
|
500
|
+
- [x402-avm Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)
|
|
501
|
+
- [algosdk TypeScript Documentation](https://algorand.github.io/js-algorand-sdk/)
|
|
502
|
+
- [CAIP-2 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md)
|
|
503
|
+
- [Algorand Atomic Transfers](https://developer.algorand.org/docs/get-details/atomic_transfers/)
|
|
504
|
+
- [@txnlab/use-wallet Documentation](https://txnlab.gitbook.io/use-wallet)
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Using @x402-avm/core and @x402-avm/avm Packages
|
|
2
|
+
|
|
3
|
+
Build custom x402 payment integrations on Algorand using the core TypeScript SDK packages directly. These packages provide the client, resource server, and facilitator primitives for the HTTP 402 payment protocol.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Before using this skill, ensure:
|
|
8
|
+
|
|
9
|
+
1. **Node.js 18+** is installed
|
|
10
|
+
2. **TypeScript project** is set up
|
|
11
|
+
3. **Algorand account** is available (for signing transactions)
|
|
12
|
+
4. **algosdk** is installed as a peer dependency
|
|
13
|
+
|
|
14
|
+
## Core Workflow: The x402 Payment Flow
|
|
15
|
+
|
|
16
|
+
The x402 protocol follows a standard HTTP 402 flow across three participants:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Client Resource Server Facilitator
|
|
20
|
+
| | |
|
|
21
|
+
|-- GET /resource ----------->| |
|
|
22
|
+
|<-- 402 PaymentRequired -----| |
|
|
23
|
+
| | |
|
|
24
|
+
| (sign payment txns) | |
|
|
25
|
+
| | |
|
|
26
|
+
|-- GET /resource ----------->| |
|
|
27
|
+
| PAYMENT-SIGNATURE: <pay> |-- verify(payload) ------->|
|
|
28
|
+
| |<-- { isValid: true } -----|
|
|
29
|
+
|<-- 200 OK + content --------| |
|
|
30
|
+
| |-- settle(payload) ------->|
|
|
31
|
+
| |<-- { txId: "..." } -------|
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## How to Proceed
|
|
35
|
+
|
|
36
|
+
### Step 1: Install Dependencies
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install @x402-avm/core @x402-avm/avm algosdk
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Step 2: Create a Client
|
|
43
|
+
|
|
44
|
+
The `x402Client` automatically handles 402 responses by creating and signing payments, then retrying the request with the `PAYMENT-SIGNATURE` header.
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { x402Client } from "@x402-avm/core/client";
|
|
48
|
+
import { registerExactAvmScheme } from "@x402-avm/avm/exact/client";
|
|
49
|
+
import type { ClientAvmSigner } from "@x402-avm/avm";
|
|
50
|
+
import algosdk from "algosdk";
|
|
51
|
+
|
|
52
|
+
const secretKey = Buffer.from(process.env.AVM_PRIVATE_KEY!, "base64");
|
|
53
|
+
const address = algosdk.encodeAddress(secretKey.slice(32));
|
|
54
|
+
|
|
55
|
+
const signer: ClientAvmSigner = {
|
|
56
|
+
address,
|
|
57
|
+
signTransactions: async (txns, indexesToSign) => {
|
|
58
|
+
return txns.map((txn, i) => {
|
|
59
|
+
if (indexesToSign && !indexesToSign.includes(i)) return null;
|
|
60
|
+
const decoded = algosdk.decodeUnsignedTransaction(txn);
|
|
61
|
+
return algosdk.signTransaction(decoded, secretKey).blob;
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const client = new x402Client({ schemes: [] });
|
|
67
|
+
registerExactAvmScheme(client, { signer });
|
|
68
|
+
|
|
69
|
+
const response = await client.fetch("https://api.example.com/premium/data");
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Step 3: Create a Resource Server
|
|
73
|
+
|
|
74
|
+
The `x402ResourceServer` is transport-agnostic. Use it with Express, Fastify, Hono, or any framework.
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { x402ResourceServer, HTTPFacilitatorClient } from "@x402-avm/core/server";
|
|
78
|
+
import { registerExactAvmScheme } from "@x402-avm/avm/exact/server";
|
|
79
|
+
import { ALGORAND_TESTNET_CAIP2, USDC_TESTNET_ASA_ID } from "@x402-avm/avm";
|
|
80
|
+
|
|
81
|
+
const facilitatorClient = new HTTPFacilitatorClient({
|
|
82
|
+
url: "https://facilitator.example.com",
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const server = new x402ResourceServer(facilitatorClient);
|
|
86
|
+
registerExactAvmScheme(server);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Step 4: Create a Facilitator
|
|
90
|
+
|
|
91
|
+
The `x402Facilitator` verifies payment signatures and settles transactions on-chain.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { x402Facilitator } from "@x402-avm/core/facilitator";
|
|
95
|
+
import { registerExactAvmScheme } from "@x402-avm/avm/exact/facilitator";
|
|
96
|
+
import type { FacilitatorAvmSigner } from "@x402-avm/avm";
|
|
97
|
+
|
|
98
|
+
const facilitator = new x402Facilitator();
|
|
99
|
+
registerExactAvmScheme(facilitator, {
|
|
100
|
+
signer: myFacilitatorSigner,
|
|
101
|
+
networks: ALGORAND_TESTNET_CAIP2,
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Step 5: Implement AVM Signers
|
|
106
|
+
|
|
107
|
+
Two signer interfaces exist:
|
|
108
|
+
|
|
109
|
+
- **ClientAvmSigner**: For clients paying for resources. Compatible with `@txnlab/use-wallet`.
|
|
110
|
+
- **FacilitatorAvmSigner**: For facilitators verifying and settling payments. Manages Algod clients, simulation, and submission.
|
|
111
|
+
|
|
112
|
+
### Step 6: Apply Payment Policies (Optional)
|
|
113
|
+
|
|
114
|
+
Policies filter payment requirements before the client selects one.
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { PaymentPolicy } from "@x402-avm/core/client";
|
|
118
|
+
import { ALGORAND_TESTNET_CAIP2 } from "@x402-avm/avm";
|
|
119
|
+
|
|
120
|
+
const preferTestnet: PaymentPolicy = (version, requirements) => {
|
|
121
|
+
return requirements.filter(r => r.network === ALGORAND_TESTNET_CAIP2);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
registerExactAvmScheme(client, {
|
|
125
|
+
signer,
|
|
126
|
+
policies: [preferTestnet],
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Important Rules / Guidelines
|
|
131
|
+
|
|
132
|
+
1. **Always register the AVM scheme** before using client, server, or facilitator -- call `registerExactAvmScheme()` after construction
|
|
133
|
+
2. **Use CAIP-2 network identifiers** in SDK code -- import `ALGORAND_TESTNET_CAIP2` / `ALGORAND_MAINNET_CAIP2` from `@x402-avm/avm`
|
|
134
|
+
3. **Signer separation** -- Protocol interfaces live in the SDK (`@x402-avm/avm`), implementations using `algosdk` live in your application code
|
|
135
|
+
4. **TypeScript algosdk uses raw Uint8Array** -- No base64 conversion needed (unlike the Python SDK)
|
|
136
|
+
5. **Fee abstraction is automatic** -- When `PaymentRequirements` include a `feePayer`, the scheme creates a 2-transaction atomic group automatically
|
|
137
|
+
6. **Private key format** -- `AVM_PRIVATE_KEY` is Base64-encoded 64-byte key (32-byte seed + 32-byte pubkey), address derived from `secretKey.slice(32)`
|
|
138
|
+
7. **Transaction groups** -- All x402-avm payments use Algorand atomic transaction groups; the `paymentGroup` array in the payload contains base64-encoded msgpack transaction bytes
|
|
139
|
+
|
|
140
|
+
## Common Errors / Troubleshooting
|
|
141
|
+
|
|
142
|
+
| Error | Cause | Solution |
|
|
143
|
+
|-------|-------|----------|
|
|
144
|
+
| `No scheme registered for network` | AVM scheme not registered | Call `registerExactAvmScheme()` on the client/server/facilitator |
|
|
145
|
+
| `Invalid key length: expected 64` | Wrong private key format | Ensure `AVM_PRIVATE_KEY` is Base64 of 64-byte key |
|
|
146
|
+
| `Simulation failed` | Transaction would fail on-chain | Check sender balance, USDC opt-in, correct receiver |
|
|
147
|
+
| `signer not found for address` | Address mismatch | Verify signer address matches the account paying |
|
|
148
|
+
| `Group ID mismatch` | Inconsistent atomic group | Use `algosdk.assignGroupID()` before encoding |
|
|
149
|
+
| `Fee too high` | Fee exceeds MAX_REASONABLE_FEE | Check fee calculation; max is 10 ALGO |
|
|
150
|
+
| `No payment requirements matched` | Policies filtered all options | Review policy logic; ensure at least one requirement passes |
|
|
151
|
+
| `Transaction rejected` | User cancelled in wallet | Handle rejection gracefully in UI |
|
|
152
|
+
|
|
153
|
+
## References / Further Reading
|
|
154
|
+
|
|
155
|
+
- [use-typescript-x402-core-avm-reference.md](./use-typescript-x402-core-avm-reference.md) - Full API reference for @x402-avm/core and @x402-avm/avm
|
|
156
|
+
- [use-typescript-x402-core-avm-examples.md](./use-typescript-x402-core-avm-examples.md) - Complete code examples
|
|
157
|
+
- [x402-avm Examples Repository](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
|
|
158
|
+
- [x402-avm Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)
|