@goplausible/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 +41 -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,360 @@
|
|
|
1
|
+
# @x402-avm/next Reference
|
|
2
|
+
|
|
3
|
+
Detailed API reference for the x402-avm Next.js integration package.
|
|
4
|
+
|
|
5
|
+
## Dependencies
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@x402-avm/next": "latest",
|
|
11
|
+
"@x402-avm/core": "latest",
|
|
12
|
+
"@x402-avm/avm": "latest",
|
|
13
|
+
"next": ">=14.0.0"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
For paywall UI:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@x402-avm/paywall": "latest"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Package Exports: @x402-avm/next
|
|
29
|
+
|
|
30
|
+
| Export | Description |
|
|
31
|
+
|--------|-------------|
|
|
32
|
+
| `paymentProxyFromConfig` | Create proxy with auto-configured resource server |
|
|
33
|
+
| `paymentProxy` | Create proxy with pre-configured resource server |
|
|
34
|
+
| `paymentProxyFromHTTPServer` | Create proxy from an `x402HTTPResourceServer` |
|
|
35
|
+
| `withX402` | Wrap a route handler with payment protection |
|
|
36
|
+
| `withX402FromHTTPServer` | Wrap a route handler using an `x402HTTPResourceServer` |
|
|
37
|
+
| `x402ResourceServer` | Re-export from `@x402-avm/core/server` |
|
|
38
|
+
| `x402HTTPResourceServer` | Re-export from `@x402-avm/core/server` |
|
|
39
|
+
|
|
40
|
+
## paymentProxyFromConfig
|
|
41
|
+
|
|
42
|
+
The simplest proxy setup. Creates the `x402ResourceServer` internally.
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
function paymentProxyFromConfig(
|
|
46
|
+
routes: Record<string, RouteDefinition>,
|
|
47
|
+
facilitatorClient: HTTPFacilitatorClient,
|
|
48
|
+
paywallConfig?: PaywallConfig,
|
|
49
|
+
): (request: NextRequest) => Promise<NextResponse>;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Parameters
|
|
53
|
+
|
|
54
|
+
| Parameter | Type | Description |
|
|
55
|
+
|-----------|------|-------------|
|
|
56
|
+
| `routes` | `Record<string, RouteDefinition>` | Route pattern to payment config mapping |
|
|
57
|
+
| `facilitatorClient` | `HTTPFacilitatorClient` | Client for communicating with facilitator |
|
|
58
|
+
| `paywallConfig` | `PaywallConfig` (optional) | Configuration for browser paywall UI |
|
|
59
|
+
|
|
60
|
+
### Route Pattern Format
|
|
61
|
+
|
|
62
|
+
Route patterns follow the format `"METHOD /path/pattern"`:
|
|
63
|
+
|
|
64
|
+
| Pattern | Matches |
|
|
65
|
+
|---------|---------|
|
|
66
|
+
| `"GET /api/weather"` | Exact match: `GET /api/weather` |
|
|
67
|
+
| `"GET /api/premium/*"` | Wildcard: `GET /api/premium/data`, `GET /api/premium/stats` |
|
|
68
|
+
| `"POST /api/generate"` | Exact match: `POST /api/generate` |
|
|
69
|
+
| `"GET /api/users/:id"` | Parameter: `GET /api/users/123` |
|
|
70
|
+
|
|
71
|
+
## paymentProxy
|
|
72
|
+
|
|
73
|
+
Create proxy with a pre-configured `x402ResourceServer`.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
function paymentProxy(
|
|
77
|
+
routes: Record<string, RouteDefinition>,
|
|
78
|
+
server: x402ResourceServer,
|
|
79
|
+
paywallConfig?: PaywallConfig,
|
|
80
|
+
): (request: NextRequest) => Promise<NextResponse>;
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Parameters
|
|
84
|
+
|
|
85
|
+
| Parameter | Type | Description |
|
|
86
|
+
|-----------|------|-------------|
|
|
87
|
+
| `routes` | `Record<string, RouteDefinition>` | Route pattern to payment config mapping |
|
|
88
|
+
| `server` | `x402ResourceServer` | Pre-configured resource server with registered schemes |
|
|
89
|
+
| `paywallConfig` | `PaywallConfig` (optional) | Configuration for browser paywall UI |
|
|
90
|
+
|
|
91
|
+
## paymentProxyFromHTTPServer
|
|
92
|
+
|
|
93
|
+
Most advanced proxy variant. Uses an `x402HTTPResourceServer` for HTTP-level hooks.
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
function paymentProxyFromHTTPServer(
|
|
97
|
+
httpServer: x402HTTPResourceServer,
|
|
98
|
+
): (request: NextRequest) => Promise<NextResponse>;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Parameters
|
|
102
|
+
|
|
103
|
+
| Parameter | Type | Description |
|
|
104
|
+
|-----------|------|-------------|
|
|
105
|
+
| `httpServer` | `x402HTTPResourceServer` | HTTP server with routes and hooks configured |
|
|
106
|
+
|
|
107
|
+
## withX402
|
|
108
|
+
|
|
109
|
+
Wrap an individual route handler with payment protection.
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
function withX402(
|
|
113
|
+
handler: (request: NextRequest) => Promise<NextResponse>,
|
|
114
|
+
routeConfig: RouteDefinition,
|
|
115
|
+
server: x402ResourceServer,
|
|
116
|
+
): (request: NextRequest) => Promise<NextResponse>;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Parameters
|
|
120
|
+
|
|
121
|
+
| Parameter | Type | Description |
|
|
122
|
+
|-----------|------|-------------|
|
|
123
|
+
| `handler` | `(request: NextRequest) => Promise<NextResponse>` | The route handler to protect |
|
|
124
|
+
| `routeConfig` | `RouteDefinition` | Payment configuration for this route |
|
|
125
|
+
| `server` | `x402ResourceServer` | Pre-configured resource server |
|
|
126
|
+
|
|
127
|
+
### Settlement Behavior
|
|
128
|
+
|
|
129
|
+
- Payment is verified **before** the handler executes
|
|
130
|
+
- Payment is settled **only if** the handler returns a response with status < 400
|
|
131
|
+
- If the handler returns 4xx or 5xx, payment is **not settled** (user is not charged)
|
|
132
|
+
|
|
133
|
+
## withX402FromHTTPServer
|
|
134
|
+
|
|
135
|
+
Wrap a route handler using an `x402HTTPResourceServer` with hooks.
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
function withX402FromHTTPServer(
|
|
139
|
+
handler: (request: NextRequest) => Promise<NextResponse>,
|
|
140
|
+
httpServer: x402HTTPResourceServer,
|
|
141
|
+
): (request: NextRequest) => Promise<NextResponse>;
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Parameters
|
|
145
|
+
|
|
146
|
+
| Parameter | Type | Description |
|
|
147
|
+
|-----------|------|-------------|
|
|
148
|
+
| `handler` | `(request: NextRequest) => Promise<NextResponse>` | The route handler to protect |
|
|
149
|
+
| `httpServer` | `x402HTTPResourceServer` | HTTP server with hooks configured |
|
|
150
|
+
|
|
151
|
+
## RouteDefinition
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
interface RouteDefinition {
|
|
155
|
+
accepts: AcceptsConfig | AcceptsConfig[];
|
|
156
|
+
description?: string;
|
|
157
|
+
mimeType?: string;
|
|
158
|
+
customPaywallHtml?: string;
|
|
159
|
+
unpaidResponseBody?: (context: RequestContext) => {
|
|
160
|
+
contentType: string;
|
|
161
|
+
body: unknown;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### AcceptsConfig
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
interface AcceptsConfig {
|
|
170
|
+
scheme: "exact";
|
|
171
|
+
network: string; // CAIP-2 identifier
|
|
172
|
+
payTo: string; // Algorand address (58 chars)
|
|
173
|
+
price: string; // Dollar amount, e.g., "$0.01", "$1.00"
|
|
174
|
+
extra?: {
|
|
175
|
+
asset?: string; // ASA ID for token payments
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Price Format
|
|
181
|
+
|
|
182
|
+
The `price` field uses dollar notation:
|
|
183
|
+
|
|
184
|
+
| Price | Atomic Units (6 decimals) |
|
|
185
|
+
|-------|--------------------------|
|
|
186
|
+
| `"$0.01"` | `10000` |
|
|
187
|
+
| `"$0.10"` | `100000` |
|
|
188
|
+
| `"$1.00"` | `1000000` |
|
|
189
|
+
| `"$5.00"` | `5000000` |
|
|
190
|
+
|
|
191
|
+
## PaywallConfig
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
interface PaywallConfig {
|
|
195
|
+
title?: string;
|
|
196
|
+
description?: string;
|
|
197
|
+
logoUrl?: string;
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Used by the proxy pattern to render a browser-friendly paywall page when the request's `Accept` header includes `text/html`.
|
|
202
|
+
|
|
203
|
+
## x402HTTPResourceServer Hooks
|
|
204
|
+
|
|
205
|
+
### onProtectedRequest
|
|
206
|
+
|
|
207
|
+
Register a hook that runs before payment processing.
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
httpServer.onProtectedRequest(async (context, routeConfig) => {
|
|
211
|
+
// Return { grantAccess: true } to skip payment
|
|
212
|
+
// Return { abort: true, reason: string } to reject the request
|
|
213
|
+
// Return undefined to continue to payment flow
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Hook Return Values
|
|
218
|
+
|
|
219
|
+
| Return | Effect |
|
|
220
|
+
|--------|--------|
|
|
221
|
+
| `{ grantAccess: true }` | Skip payment, forward request to handler |
|
|
222
|
+
| `{ abort: true, reason: string }` | Reject request immediately |
|
|
223
|
+
| `undefined` | Continue to standard payment flow |
|
|
224
|
+
|
|
225
|
+
## Middleware Configuration
|
|
226
|
+
|
|
227
|
+
### middleware.ts Placement
|
|
228
|
+
|
|
229
|
+
The `middleware.ts` file must be at the project root (next to `app/`):
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
my-project/
|
|
233
|
+
middleware.ts <-- here
|
|
234
|
+
app/
|
|
235
|
+
page.tsx
|
|
236
|
+
api/
|
|
237
|
+
...
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Matcher Configuration
|
|
241
|
+
|
|
242
|
+
Always specify which routes the middleware should intercept:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
export const config = {
|
|
246
|
+
matcher: "/api/:path*", // All API routes
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// Or specific routes:
|
|
250
|
+
export const config = {
|
|
251
|
+
matcher: [
|
|
252
|
+
"/api/weather/:path*",
|
|
253
|
+
"/api/premium/:path*",
|
|
254
|
+
"/premium-article",
|
|
255
|
+
],
|
|
256
|
+
};
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Matcher Patterns
|
|
260
|
+
|
|
261
|
+
| Pattern | Matches |
|
|
262
|
+
|---------|---------|
|
|
263
|
+
| `"/api/:path*"` | All routes under `/api/` |
|
|
264
|
+
| `"/api/weather/:path*"` | All routes under `/api/weather/` |
|
|
265
|
+
| `"/premium-article"` | Exact path `/premium-article` |
|
|
266
|
+
| `["/api/*", "/premium/*"]` | Multiple patterns |
|
|
267
|
+
|
|
268
|
+
## Proxy Pattern vs. withX402 Comparison
|
|
269
|
+
|
|
270
|
+
| Feature | Proxy (middleware.ts) | withX402 (route.ts) |
|
|
271
|
+
|---------|----------------------|---------------------|
|
|
272
|
+
| File location | `middleware.ts` at root | Each `route.ts` file |
|
|
273
|
+
| Route config | Centralized in one place | Per-route, distributed |
|
|
274
|
+
| Settlement timing | On proxy forward | After handler success (status < 400) |
|
|
275
|
+
| Error handling | Proxy-level | Handler-level (no charge on 5xx) |
|
|
276
|
+
| Handler modification | None required | Must wrap each exported function |
|
|
277
|
+
| Multi-method support | Via `"GET /path"`, `"POST /path"` | Wrap `GET`, `POST`, `PUT` individually |
|
|
278
|
+
| HTTP hooks | Via `paymentProxyFromHTTPServer` | Via `withX402FromHTTPServer` |
|
|
279
|
+
| Paywall support | Built-in with `paywallConfig` | Manual |
|
|
280
|
+
| Best for | Multiple routes, same config | Per-route control, safe settlement |
|
|
281
|
+
|
|
282
|
+
## Proxy Pattern Variants
|
|
283
|
+
|
|
284
|
+
| Function | Server Creation | Hooks | Use Case |
|
|
285
|
+
|----------|----------------|-------|----------|
|
|
286
|
+
| `paymentProxyFromConfig` | Automatic | No | Simplest setup |
|
|
287
|
+
| `paymentProxy` | Manual | No | Custom server config |
|
|
288
|
+
| `paymentProxyFromHTTPServer` | Manual | Yes | Auth bypass, rate limiting |
|
|
289
|
+
|
|
290
|
+
## withX402 Pattern Variants
|
|
291
|
+
|
|
292
|
+
| Function | Server Type | Hooks | Use Case |
|
|
293
|
+
|----------|-------------|-------|----------|
|
|
294
|
+
| `withX402` | `x402ResourceServer` | No | Simple per-route protection |
|
|
295
|
+
| `withX402FromHTTPServer` | `x402HTTPResourceServer` | Yes | Per-route with hooks |
|
|
296
|
+
|
|
297
|
+
## Environment Variables
|
|
298
|
+
|
|
299
|
+
| Variable | Description | Default | Required |
|
|
300
|
+
|----------|-------------|---------|----------|
|
|
301
|
+
| `PAY_TO` | Algorand address to receive payments | None | Yes |
|
|
302
|
+
| `FACILITATOR_URL` | URL of the facilitator server | `https://x402.org/facilitator` | No |
|
|
303
|
+
| `ALGOD_SERVER` | Algorand node URL | `https://testnet-api.algonode.cloud` | No |
|
|
304
|
+
| `ALGOD_TOKEN` | Algorand node API token | `""` | No |
|
|
305
|
+
|
|
306
|
+
## CAIP-2 Network Identifiers
|
|
307
|
+
|
|
308
|
+
| Network | Constant | Value |
|
|
309
|
+
|---------|----------|-------|
|
|
310
|
+
| Algorand Testnet | `ALGORAND_TESTNET_CAIP2` | `"algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI="` |
|
|
311
|
+
| Algorand Mainnet | `ALGORAND_MAINNET_CAIP2` | `"algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8="` |
|
|
312
|
+
|
|
313
|
+
## USDC ASA IDs
|
|
314
|
+
|
|
315
|
+
| Network | Constant | Value |
|
|
316
|
+
|---------|----------|-------|
|
|
317
|
+
| Testnet | `USDC_TESTNET_ASA_ID` | `"10458941"` |
|
|
318
|
+
| Mainnet | `USDC_MAINNET_ASA_ID` | `"31566704"` |
|
|
319
|
+
|
|
320
|
+
## Shared Config Pattern
|
|
321
|
+
|
|
322
|
+
For projects using the `withX402` pattern across multiple routes, create a shared config module:
|
|
323
|
+
|
|
324
|
+
```
|
|
325
|
+
lib/
|
|
326
|
+
x402.ts <-- shared x402Server, PAY_TO, NETWORK
|
|
327
|
+
app/
|
|
328
|
+
api/
|
|
329
|
+
weather/route.ts <-- imports from @/lib/x402
|
|
330
|
+
premium/route.ts <-- imports from @/lib/x402
|
|
331
|
+
generate/route.ts <-- imports from @/lib/x402
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
The shared module creates and configures the `x402ResourceServer` once, and exports it along with common constants.
|
|
335
|
+
|
|
336
|
+
## Testing
|
|
337
|
+
|
|
338
|
+
1. Start with Algorand TestNet (`ALGORAND_TESTNET_CAIP2`)
|
|
339
|
+
2. Set `PAY_TO` to a testnet address
|
|
340
|
+
3. Fund the test client address with testnet ALGO and USDC (ASA 10458941)
|
|
341
|
+
4. Use the [Algorand Dispenser](https://bank.testnet.algorand.network/) for testnet ALGO
|
|
342
|
+
5. Test 402 responses by hitting protected routes without the `PAYMENT-SIGNATURE` header
|
|
343
|
+
6. Test payment flow using `x402Client` from `@x402-avm/core/client`
|
|
344
|
+
|
|
345
|
+
## Key Considerations
|
|
346
|
+
|
|
347
|
+
- **Settlement safety**: Use `withX402` when you need guaranteed settlement only on success (e.g., AI generation that can fail)
|
|
348
|
+
- **Centralized config**: Use the proxy pattern when many routes share the same pricing structure
|
|
349
|
+
- **HTML pages**: Set `mimeType: "text/html"` for page routes to enable paywall rendering
|
|
350
|
+
- **Free routes**: Either exclude from the middleware matcher or do not wrap with `withX402`
|
|
351
|
+
- **Cross-chain**: Multiple `accepts` entries allow clients to pay on different networks
|
|
352
|
+
- **Dynamic pricing**: Route config can include callback functions for dynamic price computation
|
|
353
|
+
|
|
354
|
+
## External Links
|
|
355
|
+
|
|
356
|
+
- [x402-avm Next.js Examples](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
|
|
357
|
+
- [x402-avm Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)
|
|
358
|
+
- [Next.js Middleware Documentation](https://nextjs.org/docs/app/building-your-application/routing/middleware)
|
|
359
|
+
- [Next.js App Router](https://nextjs.org/docs/app/building-your-application/routing)
|
|
360
|
+
- [@x402-avm/core Reference](./use-typescript-x402-core-avm-reference.md)
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# Creating Next.js Apps with x402 Payment Protection
|
|
2
|
+
|
|
3
|
+
Build fullstack Next.js applications with HTTP 402 payment-gated routes using Algorand blockchain payments. Two patterns are available: the Proxy Pattern for middleware-level protection and the Route Handler Wrapper for per-endpoint control.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Before using this skill, ensure:
|
|
8
|
+
|
|
9
|
+
1. **Next.js 14+ App Router** project is set up
|
|
10
|
+
2. **Node.js 18+** is installed
|
|
11
|
+
3. **Algorand address** to receive payments (`PAY_TO`)
|
|
12
|
+
4. **Facilitator URL** is available (default: `https://x402.org/facilitator`)
|
|
13
|
+
|
|
14
|
+
## Core Workflow: Two Integration Patterns
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
Pattern 1: Proxy (middleware.ts) Pattern 2: withX402 (route.ts)
|
|
18
|
+
|
|
19
|
+
Request Request
|
|
20
|
+
| |
|
|
21
|
+
v v
|
|
22
|
+
middleware.ts route.ts
|
|
23
|
+
| |
|
|
24
|
+
paymentProxy / paymentProxyFromConfig withX402(handler, config, server)
|
|
25
|
+
| |
|
|
26
|
+
Has PAYMENT-SIGNATURE? -No-> 402 Has PAYMENT-SIGNATURE? -No-> 402
|
|
27
|
+
| |
|
|
28
|
+
Yes Yes
|
|
29
|
+
| |
|
|
30
|
+
Verify via facilitator Verify via facilitator
|
|
31
|
+
| |
|
|
32
|
+
Forward to route handler Execute handler
|
|
33
|
+
| |
|
|
34
|
+
Return response If status < 400: settle payment
|
|
35
|
+
|
|
|
36
|
+
Return response
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## How to Proceed
|
|
40
|
+
|
|
41
|
+
### Step 1: Install Dependencies
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install @x402-avm/next @x402-avm/avm @x402-avm/core
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For paywall UI support:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm install @x402-avm/next @x402-avm/avm @x402-avm/core @x402-avm/paywall
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Step 2: Set Up Environment Variables
|
|
54
|
+
|
|
55
|
+
Create `.env.local`:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
PAY_TO=ALGORAND_ADDRESS_HERE_58_CHARS
|
|
59
|
+
FACILITATOR_URL=https://x402.org/facilitator
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Step 3: Choose Your Pattern
|
|
63
|
+
|
|
64
|
+
#### Option A: Proxy Pattern (Recommended for Multi-Route APIs)
|
|
65
|
+
|
|
66
|
+
Create `middleware.ts` at your project root:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { NextRequest } from "next/server";
|
|
70
|
+
import { paymentProxyFromConfig } from "@x402-avm/next";
|
|
71
|
+
import { HTTPFacilitatorClient } from "@x402-avm/core/server";
|
|
72
|
+
import { ALGORAND_TESTNET_CAIP2 } from "@x402-avm/avm";
|
|
73
|
+
|
|
74
|
+
const PAY_TO = process.env.PAY_TO!;
|
|
75
|
+
|
|
76
|
+
const routes = {
|
|
77
|
+
"GET /api/weather": {
|
|
78
|
+
accepts: {
|
|
79
|
+
scheme: "exact",
|
|
80
|
+
network: ALGORAND_TESTNET_CAIP2,
|
|
81
|
+
payTo: PAY_TO,
|
|
82
|
+
price: "$0.01",
|
|
83
|
+
},
|
|
84
|
+
description: "Weather data",
|
|
85
|
+
},
|
|
86
|
+
"GET /api/premium/*": {
|
|
87
|
+
accepts: {
|
|
88
|
+
scheme: "exact",
|
|
89
|
+
network: ALGORAND_TESTNET_CAIP2,
|
|
90
|
+
payTo: PAY_TO,
|
|
91
|
+
price: "$0.10",
|
|
92
|
+
},
|
|
93
|
+
description: "Premium API endpoints",
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const facilitatorClient = new HTTPFacilitatorClient();
|
|
98
|
+
const proxy = paymentProxyFromConfig(routes, facilitatorClient);
|
|
99
|
+
|
|
100
|
+
export async function middleware(request: NextRequest) {
|
|
101
|
+
return proxy(request);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const config = {
|
|
105
|
+
matcher: "/api/:path*",
|
|
106
|
+
};
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Route handlers remain unchanged -- no wrapping needed:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// app/api/weather/route.ts
|
|
113
|
+
import { NextResponse } from "next/server";
|
|
114
|
+
|
|
115
|
+
export async function GET() {
|
|
116
|
+
return NextResponse.json({ temperature: 72, condition: "sunny" });
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### Option B: Route Handler Wrapper (Recommended for Per-Endpoint Control)
|
|
121
|
+
|
|
122
|
+
Create a shared config module:
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// lib/x402.ts
|
|
126
|
+
import { x402ResourceServer } from "@x402-avm/next";
|
|
127
|
+
import { registerExactAvmScheme } from "@x402-avm/avm/exact/server";
|
|
128
|
+
import { HTTPFacilitatorClient } from "@x402-avm/core/server";
|
|
129
|
+
import { ALGORAND_TESTNET_CAIP2 } from "@x402-avm/avm";
|
|
130
|
+
|
|
131
|
+
export const PAY_TO = process.env.PAY_TO!;
|
|
132
|
+
export const NETWORK = ALGORAND_TESTNET_CAIP2;
|
|
133
|
+
|
|
134
|
+
const facilitatorClient = new HTTPFacilitatorClient({
|
|
135
|
+
url: process.env.FACILITATOR_URL || "https://x402.org/facilitator",
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
export const x402Server = new x402ResourceServer(facilitatorClient);
|
|
139
|
+
registerExactAvmScheme(x402Server);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Wrap individual route handlers:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// app/api/weather/route.ts
|
|
146
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
147
|
+
import { withX402 } from "@x402-avm/next";
|
|
148
|
+
import { x402Server, PAY_TO, NETWORK } from "@/lib/x402";
|
|
149
|
+
|
|
150
|
+
const handler = async (request: NextRequest) => {
|
|
151
|
+
return NextResponse.json({ temperature: 72, condition: "sunny" });
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export const GET = withX402(handler, {
|
|
155
|
+
accepts: {
|
|
156
|
+
scheme: "exact",
|
|
157
|
+
network: NETWORK,
|
|
158
|
+
payTo: PAY_TO,
|
|
159
|
+
price: "$0.01",
|
|
160
|
+
},
|
|
161
|
+
description: "Weather data",
|
|
162
|
+
}, x402Server);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Step 4: Add Free Routes (Optional)
|
|
166
|
+
|
|
167
|
+
Routes not matched by the middleware matcher or not wrapped with `withX402` are free:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
// app/api/health/route.ts -- not wrapped, always free
|
|
171
|
+
import { NextResponse } from "next/server";
|
|
172
|
+
|
|
173
|
+
export async function GET() {
|
|
174
|
+
return NextResponse.json({ status: "healthy" });
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Step 5: Add Multi-Network Support (Optional)
|
|
179
|
+
|
|
180
|
+
Accept payments on both testnet and mainnet:
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import {
|
|
184
|
+
ALGORAND_TESTNET_CAIP2,
|
|
185
|
+
ALGORAND_MAINNET_CAIP2,
|
|
186
|
+
} from "@x402-avm/avm";
|
|
187
|
+
|
|
188
|
+
const routes = {
|
|
189
|
+
"GET /api/data": {
|
|
190
|
+
accepts: [
|
|
191
|
+
{
|
|
192
|
+
scheme: "exact",
|
|
193
|
+
network: ALGORAND_TESTNET_CAIP2,
|
|
194
|
+
payTo: "YOUR_TESTNET_ADDRESS",
|
|
195
|
+
price: "$0.01",
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
scheme: "exact",
|
|
199
|
+
network: ALGORAND_MAINNET_CAIP2,
|
|
200
|
+
payTo: "YOUR_MAINNET_ADDRESS",
|
|
201
|
+
price: "$0.01",
|
|
202
|
+
},
|
|
203
|
+
],
|
|
204
|
+
description: "Data endpoint (testnet or mainnet)",
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Important Rules / Guidelines
|
|
210
|
+
|
|
211
|
+
1. **Proxy settles on forward, withX402 settles after success** -- The proxy pattern settles payment when forwarding the request. The `withX402` pattern only settles when the handler returns status < 400, protecting against paying for failed requests.
|
|
212
|
+
2. **middleware.ts must be at the project root** -- Next.js only loads middleware from the root `middleware.ts` file
|
|
213
|
+
3. **Use the `matcher` config** -- Always specify which routes the middleware should intercept to avoid processing static files and other non-API routes
|
|
214
|
+
4. **Route patterns use `*` wildcard** -- `"GET /api/premium/*"` matches all sub-paths under `/api/premium/`
|
|
215
|
+
5. **Share server instances** -- Create `lib/x402.ts` with shared `x402Server` and `PAY_TO` to avoid duplicating setup across route files
|
|
216
|
+
6. **Register the AVM scheme** -- Call `registerExactAvmScheme()` on the server before use
|
|
217
|
+
7. **Price uses dollar notation** -- Use `"$0.01"` format for human-readable pricing; the SDK converts to atomic units
|
|
218
|
+
8. **Free routes** -- Either exclude them from the middleware matcher or do not wrap them with `withX402`
|
|
219
|
+
|
|
220
|
+
## Pattern Comparison
|
|
221
|
+
|
|
222
|
+
| Criteria | Proxy (middleware.ts) | withX402 (route.ts) |
|
|
223
|
+
|----------|----------------------|---------------------|
|
|
224
|
+
| Setup complexity | Single file | Per-route setup |
|
|
225
|
+
| Route configuration | Centralized | Distributed |
|
|
226
|
+
| Settlement guarantee | Settles on proxy forward | Settles after handler success |
|
|
227
|
+
| Error handling | Proxy-level | Handler-level |
|
|
228
|
+
| Handler changes | None required | Wrap each export |
|
|
229
|
+
| Multiple methods | Via route patterns | Per-method wrapping |
|
|
230
|
+
| Best for | Multi-route APIs | Individual endpoints |
|
|
231
|
+
|
|
232
|
+
## Common Errors / Troubleshooting
|
|
233
|
+
|
|
234
|
+
| Error | Cause | Solution |
|
|
235
|
+
|-------|-------|----------|
|
|
236
|
+
| Middleware not running | `middleware.ts` not at project root | Move to project root directory |
|
|
237
|
+
| Static files returning 402 | Matcher too broad | Restrict `matcher` to `/api/:path*` or specific paths |
|
|
238
|
+
| `PAY_TO` undefined | Missing env variable | Add `PAY_TO` to `.env.local` |
|
|
239
|
+
| `No scheme registered` | Missing AVM scheme registration | Call `registerExactAvmScheme(server)` |
|
|
240
|
+
| Payment settled on 500 error | Using proxy pattern | Switch to `withX402` for endpoints that can fail |
|
|
241
|
+
| Route not matched | Wrong route pattern | Verify pattern matches Next.js route structure |
|
|
242
|
+
| Cross-origin issues | CORS not configured | Add CORS headers in middleware or `next.config.js` |
|
|
243
|
+
| `FACILITATOR_URL` not set | Missing facilitator config | Set `FACILITATOR_URL` env variable or use default |
|
|
244
|
+
|
|
245
|
+
## References / Further Reading
|
|
246
|
+
|
|
247
|
+
- [create-typescript-x402-nextjs-reference.md](./create-typescript-x402-nextjs-reference.md) - Full API reference for @x402-avm/next
|
|
248
|
+
- [create-typescript-x402-nextjs-examples.md](./create-typescript-x402-nextjs-examples.md) - Complete code examples
|
|
249
|
+
- [x402-avm Next.js Examples](https://github.com/GoPlausible/x402-avm/tree/branch-v2-algorand-publish/examples/)
|
|
250
|
+
- [x402-avm Documentation](https://github.com/GoPlausible/.github/blob/main/profile/algorand-x402-documentation/)
|
|
251
|
+
- [Next.js Middleware Documentation](https://nextjs.org/docs/app/building-your-application/routing/middleware)
|