agentic-x402 0.3.6 → 0.3.8
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/SKILL.md +1 -1
- package/openclaw.plugin.json +2 -3
- package/package.json +1 -2
- package/scripts/plugin/tools.ts +50 -43
- package/scripts/plugin/types.ts +14 -5
- package/skills/x402/SKILL.md +0 -486
package/SKILL.md
CHANGED
|
@@ -4,7 +4,7 @@ description: Make x402 payments to access gated APIs and content. Fetch paid res
|
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: Requires Node.js 20+, network access to x402 facilitators and EVM chains
|
|
6
6
|
homepage: https://www.npmjs.com/package/agentic-x402
|
|
7
|
-
metadata: {"author": "monemetrics", "version": "0.3.
|
|
7
|
+
metadata: {"author": "monemetrics", "version": "0.3.7", "openclaw": {"requires": {"bins": ["x402"], "env": ["EVM_PRIVATE_KEY"]}, "primaryEnv": "EVM_PRIVATE_KEY", "install": [{"id": "node", "kind": "node", "package": "agentic-x402", "bins": ["x402"], "label": "Install agentic-x402 (npm)"}], "plugin": true}}
|
|
8
8
|
allowed-tools: Bash(x402:*) Bash(npm:*) Read
|
|
9
9
|
---
|
|
10
10
|
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "agentic-x402",
|
|
3
3
|
"name": "x402 Payments",
|
|
4
|
-
"version": "0.3.
|
|
5
|
-
"description": "Agent
|
|
6
|
-
"skills": ["./skills/x402"],
|
|
4
|
+
"version": "0.3.8",
|
|
5
|
+
"description": "Agent plugin for x402 payments — pay for and sell gated content with background payment watching",
|
|
7
6
|
"configSchema": {
|
|
8
7
|
"type": "object",
|
|
9
8
|
"properties": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-x402",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"description": "Agent skill for x402 payments - pay for and sell gated content",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"files": [
|
|
13
13
|
"bin/",
|
|
14
14
|
"scripts/",
|
|
15
|
-
"skills/",
|
|
16
15
|
"config/example.env",
|
|
17
16
|
"openclaw.plugin.json",
|
|
18
17
|
"README.md",
|
package/scripts/plugin/tools.ts
CHANGED
|
@@ -4,20 +4,28 @@
|
|
|
4
4
|
import type { PluginTool } from './types.js';
|
|
5
5
|
import type { PaymentWatcher } from './watcher.js';
|
|
6
6
|
|
|
7
|
+
/** Helper to wrap a result as OpenClaw tool response */
|
|
8
|
+
function json(payload: unknown) {
|
|
9
|
+
return {
|
|
10
|
+
content: [{ type: 'text' as const, text: JSON.stringify(payload, null, 2) }],
|
|
11
|
+
details: payload,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
7
15
|
export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
8
16
|
return [
|
|
9
17
|
// 1. x402_balance
|
|
10
18
|
{
|
|
11
19
|
name: 'x402_balance',
|
|
12
20
|
description: 'Check wallet USDC and ETH balances on Base',
|
|
13
|
-
|
|
14
|
-
async execute() {
|
|
21
|
+
parameters: { type: 'object', properties: {} },
|
|
22
|
+
async execute(_toolCallId, _params) {
|
|
15
23
|
const { getClient, getWalletAddress, getUsdcBalance, getEthBalance } = await import('../core/client.js');
|
|
16
24
|
const client = getClient();
|
|
17
25
|
const address = getWalletAddress();
|
|
18
26
|
const [usdc, eth] = await Promise.all([getUsdcBalance(), getEthBalance()]);
|
|
19
27
|
|
|
20
|
-
return {
|
|
28
|
+
return json({
|
|
21
29
|
address,
|
|
22
30
|
network: client.config.network,
|
|
23
31
|
chainId: client.config.chainId,
|
|
@@ -25,7 +33,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
25
33
|
usdc: { raw: usdc.raw.toString(), formatted: usdc.formatted },
|
|
26
34
|
eth: { raw: eth.raw.toString(), formatted: eth.formatted },
|
|
27
35
|
},
|
|
28
|
-
};
|
|
36
|
+
});
|
|
29
37
|
},
|
|
30
38
|
},
|
|
31
39
|
|
|
@@ -33,7 +41,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
33
41
|
{
|
|
34
42
|
name: 'x402_pay',
|
|
35
43
|
description: 'Pay for an x402-gated resource. Returns the response body after payment.',
|
|
36
|
-
|
|
44
|
+
parameters: {
|
|
37
45
|
type: 'object',
|
|
38
46
|
properties: {
|
|
39
47
|
url: { type: 'string', description: 'URL of the x402-gated resource' },
|
|
@@ -44,7 +52,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
44
52
|
},
|
|
45
53
|
required: ['url'],
|
|
46
54
|
},
|
|
47
|
-
async execute(params) {
|
|
55
|
+
async execute(_toolCallId, params) {
|
|
48
56
|
const url = params.url as string;
|
|
49
57
|
const method = (params.method as string) || 'GET';
|
|
50
58
|
const body = params.body as string | undefined;
|
|
@@ -65,7 +73,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
65
73
|
const responseBody = contentType?.includes('json')
|
|
66
74
|
? await probe.json()
|
|
67
75
|
: await probe.text();
|
|
68
|
-
return { paid: false, status: probe.status, response: responseBody };
|
|
76
|
+
return json({ paid: false, status: probe.status, response: responseBody });
|
|
69
77
|
}
|
|
70
78
|
|
|
71
79
|
// Parse payment info
|
|
@@ -84,18 +92,18 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
84
92
|
const effectiveMax = maxPaymentUsd ?? client.config.maxPaymentUsd;
|
|
85
93
|
|
|
86
94
|
if (priceNum > effectiveMax) {
|
|
87
|
-
return { paid: false, error: `Price $${priceNum} exceeds max $${effectiveMax}`, paymentInfo };
|
|
95
|
+
return json({ paid: false, error: `Price $${priceNum} exceeds max $${effectiveMax}`, paymentInfo });
|
|
88
96
|
}
|
|
89
97
|
|
|
90
98
|
if (dryRun) {
|
|
91
|
-
return { paid: false, dryRun: true, price: priceNum, paymentInfo };
|
|
99
|
+
return json({ paid: false, dryRun: true, price: priceNum, paymentInfo });
|
|
92
100
|
}
|
|
93
101
|
|
|
94
102
|
// Execute payment
|
|
95
103
|
const response = await client.fetchWithPayment(url, { method, body, headers });
|
|
96
104
|
|
|
97
105
|
if (!response.ok) {
|
|
98
|
-
return { paid: false, error: `${response.status} ${response.statusText}` };
|
|
106
|
+
return json({ paid: false, error: `${response.status} ${response.statusText}` });
|
|
99
107
|
}
|
|
100
108
|
|
|
101
109
|
const contentType = response.headers.get('content-type');
|
|
@@ -112,7 +120,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
112
120
|
} catch { /* */ }
|
|
113
121
|
}
|
|
114
122
|
|
|
115
|
-
return { paid: true, price: priceNum, transactionHash: txHash, response: responseBody };
|
|
123
|
+
return json({ paid: true, price: priceNum, transactionHash: txHash, response: responseBody });
|
|
116
124
|
},
|
|
117
125
|
},
|
|
118
126
|
|
|
@@ -120,7 +128,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
120
128
|
{
|
|
121
129
|
name: 'x402_fetch',
|
|
122
130
|
description: 'Fetch a URL with automatic x402 payment handling. Simpler than x402_pay — just returns the content.',
|
|
123
|
-
|
|
131
|
+
parameters: {
|
|
124
132
|
type: 'object',
|
|
125
133
|
properties: {
|
|
126
134
|
url: { type: 'string', description: 'URL to fetch' },
|
|
@@ -129,7 +137,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
129
137
|
},
|
|
130
138
|
required: ['url'],
|
|
131
139
|
},
|
|
132
|
-
async execute(params) {
|
|
140
|
+
async execute(_toolCallId, params) {
|
|
133
141
|
const url = params.url as string;
|
|
134
142
|
const method = (params.method as string) || 'GET';
|
|
135
143
|
const body = params.body as string | undefined;
|
|
@@ -143,7 +151,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
143
151
|
const response = await client.fetchWithPayment(url, { method, body, headers });
|
|
144
152
|
|
|
145
153
|
if (!response.ok) {
|
|
146
|
-
return { success: false, status: response.status, error: response.statusText };
|
|
154
|
+
return json({ success: false, status: response.status, error: response.statusText });
|
|
147
155
|
}
|
|
148
156
|
|
|
149
157
|
const contentType = response.headers.get('content-type');
|
|
@@ -151,7 +159,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
151
159
|
? await response.json()
|
|
152
160
|
: await response.text();
|
|
153
161
|
|
|
154
|
-
return { success: true, status: response.status, response: responseBody };
|
|
162
|
+
return json({ success: true, status: response.status, response: responseBody });
|
|
155
163
|
},
|
|
156
164
|
},
|
|
157
165
|
|
|
@@ -159,7 +167,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
159
167
|
{
|
|
160
168
|
name: 'x402_create_link',
|
|
161
169
|
description: 'Create a payment link via 21.cash to sell gated content',
|
|
162
|
-
|
|
170
|
+
parameters: {
|
|
163
171
|
type: 'object',
|
|
164
172
|
properties: {
|
|
165
173
|
name: { type: 'string', description: 'Name of the payment link' },
|
|
@@ -171,7 +179,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
171
179
|
},
|
|
172
180
|
required: ['name', 'price'],
|
|
173
181
|
},
|
|
174
|
-
async execute(params) {
|
|
182
|
+
async execute(_toolCallId, params) {
|
|
175
183
|
const name = params.name as string;
|
|
176
184
|
const price = params.price as string;
|
|
177
185
|
const gatedUrl = params.url as string | undefined;
|
|
@@ -180,7 +188,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
180
188
|
const webhookUrl = params.webhookUrl as string | undefined;
|
|
181
189
|
|
|
182
190
|
if (!gatedUrl && !gatedText) {
|
|
183
|
-
return { success: false, error: 'Either url or text is required' };
|
|
191
|
+
return json({ success: false, error: 'Either url or text is required' });
|
|
184
192
|
}
|
|
185
193
|
|
|
186
194
|
const { getClient, getWalletAddress } = await import('../core/client.js');
|
|
@@ -210,10 +218,10 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
210
218
|
|
|
211
219
|
const data = await response.json();
|
|
212
220
|
if (!response.ok || !(data as Record<string, unknown>).success) {
|
|
213
|
-
return { success: false, error: (data as Record<string, unknown>).error ?? 'Unknown error' };
|
|
221
|
+
return json({ success: false, error: (data as Record<string, unknown>).error ?? 'Unknown error' });
|
|
214
222
|
}
|
|
215
223
|
|
|
216
|
-
return data;
|
|
224
|
+
return json(data);
|
|
217
225
|
},
|
|
218
226
|
},
|
|
219
227
|
|
|
@@ -221,14 +229,14 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
221
229
|
{
|
|
222
230
|
name: 'x402_link_info',
|
|
223
231
|
description: 'Get details about a payment link by router address',
|
|
224
|
-
|
|
232
|
+
parameters: {
|
|
225
233
|
type: 'object',
|
|
226
234
|
properties: {
|
|
227
235
|
routerAddress: { type: 'string', description: 'Router contract address or payment URL' },
|
|
228
236
|
},
|
|
229
237
|
required: ['routerAddress'],
|
|
230
238
|
},
|
|
231
|
-
async execute(params) {
|
|
239
|
+
async execute(_toolCallId, params) {
|
|
232
240
|
let routerAddress = params.routerAddress as string;
|
|
233
241
|
|
|
234
242
|
// Extract address from URL if needed
|
|
@@ -239,7 +247,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
239
247
|
}
|
|
240
248
|
|
|
241
249
|
if (!routerAddress.startsWith('0x') || routerAddress.length !== 42) {
|
|
242
|
-
return { success: false, error: 'Invalid router address' };
|
|
250
|
+
return json({ success: false, error: 'Invalid router address' });
|
|
243
251
|
}
|
|
244
252
|
|
|
245
253
|
const { getConfig } = await import('../core/config.js');
|
|
@@ -250,10 +258,10 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
250
258
|
const data = await response.json();
|
|
251
259
|
|
|
252
260
|
if (!response.ok || !(data as Record<string, unknown>).success) {
|
|
253
|
-
return { success: false, error: (data as Record<string, unknown>).error ?? 'Link not found' };
|
|
261
|
+
return json({ success: false, error: (data as Record<string, unknown>).error ?? 'Link not found' });
|
|
254
262
|
}
|
|
255
263
|
|
|
256
|
-
return data;
|
|
264
|
+
return json(data);
|
|
257
265
|
},
|
|
258
266
|
},
|
|
259
267
|
|
|
@@ -261,14 +269,13 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
261
269
|
{
|
|
262
270
|
name: 'x402_routers',
|
|
263
271
|
description: 'List payment routers where your wallet is a beneficiary',
|
|
264
|
-
|
|
272
|
+
parameters: {
|
|
265
273
|
type: 'object',
|
|
266
274
|
properties: {
|
|
267
275
|
withBalances: { type: 'boolean', description: 'Fetch on-chain USDC balance for each router' },
|
|
268
276
|
},
|
|
269
|
-
required: [],
|
|
270
277
|
},
|
|
271
|
-
async execute(params) {
|
|
278
|
+
async execute(_toolCallId, params) {
|
|
272
279
|
const withBalances = params.withBalances as boolean | undefined;
|
|
273
280
|
|
|
274
281
|
const { getWalletAddress } = await import('../core/client.js');
|
|
@@ -282,13 +289,13 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
282
289
|
const data = await response.json() as { success: boolean; links?: Array<Record<string, unknown>>; error?: string };
|
|
283
290
|
|
|
284
291
|
if (!response.ok || !data.success) {
|
|
285
|
-
return { success: false, error: data.error ?? 'Failed to fetch routers' };
|
|
292
|
+
return json({ success: false, error: data.error ?? 'Failed to fetch routers' });
|
|
286
293
|
}
|
|
287
294
|
|
|
288
295
|
const links = data.links ?? [];
|
|
289
296
|
|
|
290
297
|
if (!withBalances) {
|
|
291
|
-
return {
|
|
298
|
+
return json({
|
|
292
299
|
success: true,
|
|
293
300
|
address,
|
|
294
301
|
routers: links.map((l) => ({
|
|
@@ -298,7 +305,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
298
305
|
sharePercent: l.beneficiary_percentage,
|
|
299
306
|
createdAt: l.created_at,
|
|
300
307
|
})),
|
|
301
|
-
};
|
|
308
|
+
});
|
|
302
309
|
}
|
|
303
310
|
|
|
304
311
|
// Fetch balances
|
|
@@ -340,7 +347,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
340
347
|
};
|
|
341
348
|
}));
|
|
342
349
|
|
|
343
|
-
return { success: true, address, routers };
|
|
350
|
+
return json({ success: true, address, routers });
|
|
344
351
|
},
|
|
345
352
|
},
|
|
346
353
|
|
|
@@ -348,7 +355,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
348
355
|
{
|
|
349
356
|
name: 'x402_distribute',
|
|
350
357
|
description: 'Distribute (withdraw) USDC from a PaymentRouter contract',
|
|
351
|
-
|
|
358
|
+
parameters: {
|
|
352
359
|
type: 'object',
|
|
353
360
|
properties: {
|
|
354
361
|
routerAddress: { type: 'string', description: 'PaymentRouter contract address' },
|
|
@@ -356,12 +363,12 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
356
363
|
},
|
|
357
364
|
required: ['routerAddress'],
|
|
358
365
|
},
|
|
359
|
-
async execute(params) {
|
|
366
|
+
async execute(_toolCallId, params) {
|
|
360
367
|
const routerAddress = params.routerAddress as string;
|
|
361
368
|
const specifiedAmount = params.amount as string | undefined;
|
|
362
369
|
|
|
363
370
|
if (!routerAddress.startsWith('0x') || routerAddress.length !== 42) {
|
|
364
|
-
return { success: false, error: 'Invalid router address' };
|
|
371
|
+
return json({ success: false, error: 'Invalid router address' });
|
|
365
372
|
}
|
|
366
373
|
|
|
367
374
|
const { getClient } = await import('../core/client.js');
|
|
@@ -400,17 +407,17 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
400
407
|
});
|
|
401
408
|
|
|
402
409
|
if (routerBalance === 0n) {
|
|
403
|
-
return { success: false, error: 'Router has no USDC balance to distribute' };
|
|
410
|
+
return json({ success: false, error: 'Router has no USDC balance to distribute' });
|
|
404
411
|
}
|
|
405
412
|
|
|
406
413
|
let distributeAmount: bigint;
|
|
407
414
|
if (specifiedAmount) {
|
|
408
415
|
distributeAmount = parseUnits(specifiedAmount, 6);
|
|
409
416
|
if (distributeAmount > routerBalance) {
|
|
410
|
-
return {
|
|
417
|
+
return json({
|
|
411
418
|
success: false,
|
|
412
419
|
error: `Requested ${specifiedAmount} USDC exceeds balance ${formatUnits(routerBalance, 6)} USDC`,
|
|
413
|
-
};
|
|
420
|
+
});
|
|
414
421
|
}
|
|
415
422
|
} else {
|
|
416
423
|
distributeAmount = routerBalance;
|
|
@@ -426,7 +433,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
426
433
|
|
|
427
434
|
const receipt = await client.publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
428
435
|
|
|
429
|
-
return {
|
|
436
|
+
return json({
|
|
430
437
|
success: receipt.status === 'success',
|
|
431
438
|
routerAddress,
|
|
432
439
|
amount: formatUnits(distributeAmount, 6),
|
|
@@ -434,7 +441,7 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
434
441
|
transactionHash: txHash,
|
|
435
442
|
blockNumber: receipt.blockNumber.toString(),
|
|
436
443
|
status: receipt.status,
|
|
437
|
-
};
|
|
444
|
+
});
|
|
438
445
|
},
|
|
439
446
|
},
|
|
440
447
|
|
|
@@ -442,12 +449,12 @@ export function createTools(watcher: PaymentWatcher | null): PluginTool[] {
|
|
|
442
449
|
{
|
|
443
450
|
name: 'x402_watcher_status',
|
|
444
451
|
description: 'Get the status of the background payment watcher (tracked routers, payments detected)',
|
|
445
|
-
|
|
452
|
+
parameters: { type: 'object', properties: {} },
|
|
446
453
|
async execute() {
|
|
447
454
|
if (!watcher) {
|
|
448
|
-
return { running: false, error: 'Watcher is not enabled' };
|
|
455
|
+
return json({ running: false, error: 'Watcher is not enabled' });
|
|
449
456
|
}
|
|
450
|
-
return watcher.getStatus();
|
|
457
|
+
return json(watcher.getStatus());
|
|
451
458
|
},
|
|
452
459
|
},
|
|
453
460
|
];
|
package/scripts/plugin/types.ts
CHANGED
|
@@ -15,24 +15,33 @@ export interface PluginService {
|
|
|
15
15
|
stop(): Promise<void>;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
/** JSON Schema for tool
|
|
19
|
-
export interface
|
|
18
|
+
/** JSON Schema for tool parameters */
|
|
19
|
+
export interface ToolParameters {
|
|
20
20
|
type: 'object';
|
|
21
21
|
properties: Record<string, {
|
|
22
22
|
type: string;
|
|
23
|
-
description
|
|
23
|
+
description?: string;
|
|
24
24
|
enum?: string[];
|
|
25
25
|
default?: unknown;
|
|
26
26
|
}>;
|
|
27
27
|
required?: string[];
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/** Tool result content block */
|
|
31
|
+
export interface ToolResultContent {
|
|
32
|
+
type: 'text';
|
|
33
|
+
text: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
30
36
|
/** An agent tool registered by a plugin */
|
|
31
37
|
export interface PluginTool {
|
|
32
38
|
name: string;
|
|
33
39
|
description: string;
|
|
34
|
-
|
|
35
|
-
execute(params: Record<string, unknown>): Promise<
|
|
40
|
+
parameters: ToolParameters;
|
|
41
|
+
execute(toolCallId: string, params: Record<string, unknown>): Promise<{
|
|
42
|
+
content: ToolResultContent[];
|
|
43
|
+
details?: unknown;
|
|
44
|
+
}>;
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
/** Commander.js-style program for CLI registration */
|
package/skills/x402/SKILL.md
DELETED
|
@@ -1,486 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: x402
|
|
3
|
-
description: Make x402 payments to access gated APIs and content. Fetch paid resources, check wallet balance, create payment links, monitor routers for incoming payments, and distribute funds. Use when encountering 402 Payment Required responses or when the user wants to pay for web resources with crypto. Also available as an OpenClaw plugin with background payment watching and 8 agent tools.
|
|
4
|
-
license: MIT
|
|
5
|
-
compatibility: Requires Node.js 20+, network access to x402 facilitators and EVM chains
|
|
6
|
-
homepage: https://www.npmjs.com/package/agentic-x402
|
|
7
|
-
metadata: {"author": "monemetrics", "version": "0.3.6", "openclaw": {"requires": {"bins": ["x402"], "env": ["EVM_PRIVATE_KEY"]}, "primaryEnv": "EVM_PRIVATE_KEY", "install": [{"id": "node", "kind": "node", "package": "agentic-x402", "bins": ["x402"], "label": "Install agentic-x402 (npm)"}], "plugin": true}}
|
|
8
|
-
allowed-tools: Bash(x402:*) Bash(npm:*) Read
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# x402 Agent Skill
|
|
12
|
-
|
|
13
|
-
Pay for x402-gated APIs and content using USDC on Base. This skill enables agents to autonomously make crypto payments when accessing paid web resources.
|
|
14
|
-
|
|
15
|
-
## Quick Reference
|
|
16
|
-
|
|
17
|
-
| Command | Description |
|
|
18
|
-
|---------|-------------|
|
|
19
|
-
| `x402 setup` | Create or configure wallet |
|
|
20
|
-
| `x402 balance` | Check USDC and ETH balances |
|
|
21
|
-
| `x402 pay <url>` | Pay for a gated resource |
|
|
22
|
-
| `x402 fetch <url>` | Fetch with auto-payment |
|
|
23
|
-
| `x402 create-link` | Create payment link (seller) |
|
|
24
|
-
| `x402 link-info <addr>` | Get payment link details |
|
|
25
|
-
| `x402 routers` | List routers where your wallet is a beneficiary |
|
|
26
|
-
| `x402 distribute <addr>` | Distribute USDC from a PaymentRouter |
|
|
27
|
-
|
|
28
|
-
## OpenClaw Plugin
|
|
29
|
-
|
|
30
|
-
When installed as an OpenClaw plugin, agentic-x402 provides **8 agent tools** and a **background payment watcher** — no CLI required.
|
|
31
|
-
|
|
32
|
-
### Install as Plugin
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
openclaw plugins install agentic-x402
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### Agent Tools
|
|
39
|
-
|
|
40
|
-
When running inside OpenClaw, the agent can call these tools directly (no shell commands needed):
|
|
41
|
-
|
|
42
|
-
| Tool | Description |
|
|
43
|
-
|------|-------------|
|
|
44
|
-
| `x402_balance` | Check wallet USDC + ETH balances |
|
|
45
|
-
| `x402_pay` | Pay for x402-gated resource (supports dry-run) |
|
|
46
|
-
| `x402_fetch` | Fetch URL with automatic payment |
|
|
47
|
-
| `x402_create_link` | Create payment link via 21.cash |
|
|
48
|
-
| `x402_link_info` | Get link details by router address |
|
|
49
|
-
| `x402_routers` | List beneficiary routers (optional balances) |
|
|
50
|
-
| `x402_distribute` | Distribute USDC from a router |
|
|
51
|
-
| `x402_watcher_status` | Get watcher state (tracked routers, payments detected) |
|
|
52
|
-
|
|
53
|
-
All tools return structured JSON. Parameters use camelCase (e.g., `routerAddress`, `maxPaymentUsd`, `withBalances`).
|
|
54
|
-
|
|
55
|
-
### Background Payment Watcher
|
|
56
|
-
|
|
57
|
-
The plugin includes a background service that monitors your payment routers for incoming USDC:
|
|
58
|
-
|
|
59
|
-
- Fetches your routers from the 21.cash API
|
|
60
|
-
- Polls USDC `balanceOf` for each router onchain (free view call, no gas)
|
|
61
|
-
- Detects balance increases and triggers a hook at `/hooks/agent` with payment details
|
|
62
|
-
- Configurable poll interval (default 30s)
|
|
63
|
-
- First poll seeds state without triggering notifications (no false positives on restart)
|
|
64
|
-
|
|
65
|
-
When a payment is detected, the watcher sends a hook with:
|
|
66
|
-
```json
|
|
67
|
-
{
|
|
68
|
-
"name": "x402-payment",
|
|
69
|
-
"wakeMode": "now",
|
|
70
|
-
"data": {
|
|
71
|
-
"routerAddress": "0x...",
|
|
72
|
-
"routerName": "My Link",
|
|
73
|
-
"previousBalance": "10.00",
|
|
74
|
-
"newBalance": "15.00",
|
|
75
|
-
"increase": "5.00",
|
|
76
|
-
"detectedAt": "2025-01-15T12:00:00.000Z"
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Plugin Configuration
|
|
82
|
-
|
|
83
|
-
All config is optional — zero-config if `~/.x402/.env` exists. Config priority:
|
|
84
|
-
|
|
85
|
-
1. Environment variables (highest)
|
|
86
|
-
2. Plugin config (from OpenClaw)
|
|
87
|
-
3. `~/.x402/.env` (dotenv)
|
|
88
|
-
4. Hardcoded defaults
|
|
89
|
-
|
|
90
|
-
Plugin config keys (set in OpenClaw):
|
|
91
|
-
|
|
92
|
-
| Key | Description | Default |
|
|
93
|
-
|-----|-------------|---------|
|
|
94
|
-
| `evmPrivateKey` | EVM private key (0x-prefixed) | from env |
|
|
95
|
-
| `network` | `mainnet` or `testnet` | `mainnet` |
|
|
96
|
-
| `maxPaymentUsd` | Max payment limit in USD | `10` |
|
|
97
|
-
| `x402LinksApiUrl` | 21.cash API URL | `https://21.cash` |
|
|
98
|
-
| `watcher.enabled` | Enable background payment watcher | `true` |
|
|
99
|
-
| `watcher.pollIntervalMs` | Poll interval in ms | `30000` |
|
|
100
|
-
| `watcher.notifyOnPayment` | Send hook on payment detection | `true` |
|
|
101
|
-
|
|
102
|
-
### Plugin CLI Commands
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
openclaw x402 watch # Start watcher in foreground (debugging)
|
|
106
|
-
openclaw x402 watch --interval 10000 # Custom poll interval
|
|
107
|
-
openclaw x402 status # Show watcher state, tracked routers, payment count
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## Installation
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
npm i -g agentic-x402
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
Once installed, the `x402` command is available globally:
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
x402 --help
|
|
120
|
-
x402 --version
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## Setup
|
|
124
|
-
|
|
125
|
-
Run the interactive setup to create a new wallet:
|
|
126
|
-
|
|
127
|
-
```bash
|
|
128
|
-
x402 setup
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
This will:
|
|
132
|
-
1. Generate a new wallet (recommended) or accept an existing key
|
|
133
|
-
2. Save configuration to `~/.x402/.env`
|
|
134
|
-
3. Display your wallet address for funding
|
|
135
|
-
|
|
136
|
-
**Important:** Back up your private key immediately after setup!
|
|
137
|
-
|
|
138
|
-
### Manual Configuration
|
|
139
|
-
|
|
140
|
-
Alternatively, set the environment variable directly:
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
export EVM_PRIVATE_KEY=0x...your_private_key...
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
Or create a config file:
|
|
147
|
-
|
|
148
|
-
```bash
|
|
149
|
-
mkdir -p ~/.x402
|
|
150
|
-
echo "EVM_PRIVATE_KEY=0x..." > ~/.x402/.env
|
|
151
|
-
chmod 600 ~/.x402/.env
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
Verify setup:
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
x402 balance
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
## Paying for Resources
|
|
161
|
-
|
|
162
|
-
### When you encounter HTTP 402 Payment Required
|
|
163
|
-
|
|
164
|
-
Use `x402 pay` to make the payment and access the content:
|
|
165
|
-
|
|
166
|
-
```bash
|
|
167
|
-
x402 pay https://api.example.com/paid-endpoint
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
The command will:
|
|
171
|
-
1. Check payment requirements
|
|
172
|
-
2. Verify amount is within limits
|
|
173
|
-
3. Process the payment
|
|
174
|
-
4. Return the gated content
|
|
175
|
-
|
|
176
|
-
### Automatic payment with fetch
|
|
177
|
-
|
|
178
|
-
Use `x402 fetch` for seamless payment handling:
|
|
179
|
-
|
|
180
|
-
```bash
|
|
181
|
-
x402 fetch https://api.example.com/data --json
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
This wraps fetch with x402 payment handling - if the resource requires payment, it's handled automatically.
|
|
185
|
-
|
|
186
|
-
### Payment limits
|
|
187
|
-
|
|
188
|
-
By default, payments are limited to $10 USD. Override with `--max`:
|
|
189
|
-
|
|
190
|
-
```bash
|
|
191
|
-
x402 pay https://expensive-api.com/data --max 50
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
Or set globally:
|
|
195
|
-
```bash
|
|
196
|
-
export X402_MAX_PAYMENT_USD=25
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### Dry run
|
|
200
|
-
|
|
201
|
-
Preview payment without executing:
|
|
202
|
-
|
|
203
|
-
```bash
|
|
204
|
-
x402 pay https://api.example.com/data --dry-run
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
## Creating Payment Links (Seller)
|
|
208
|
-
|
|
209
|
-
Create payment links to monetize your own content using x402-links-server:
|
|
210
|
-
|
|
211
|
-
### Setup for link creation
|
|
212
|
-
|
|
213
|
-
Add to `.env`:
|
|
214
|
-
```bash
|
|
215
|
-
X402_LINKS_API_URL=https://your-x402-links-server.com
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
### Create a link
|
|
219
|
-
|
|
220
|
-
Gate a URL:
|
|
221
|
-
```bash
|
|
222
|
-
x402 create-link --name "Premium API" --price 1.00 --url https://api.example.com/premium
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
Gate text content:
|
|
226
|
-
```bash
|
|
227
|
-
x402 create-link --name "Secret" --price 0.50 --text "The secret message..."
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
With webhook notification:
|
|
231
|
-
```bash
|
|
232
|
-
x402 create-link --name "Guide" --price 5.00 --url https://mysite.com/guide --webhook https://mysite.com/payment-hook
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
### Get link info
|
|
236
|
-
|
|
237
|
-
```bash
|
|
238
|
-
x402 link-info 0x1234...5678
|
|
239
|
-
x402 link-info https://21.cash/pay/0x1234...5678
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
## Managing Routers
|
|
243
|
-
|
|
244
|
-
### List your routers
|
|
245
|
-
|
|
246
|
-
See all payment routers where your wallet is a beneficiary:
|
|
247
|
-
|
|
248
|
-
```bash
|
|
249
|
-
x402 routers
|
|
250
|
-
x402 routers --with-balance # Include on-chain USDC balances
|
|
251
|
-
x402 routers --json
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
| Flag | Description | Default |
|
|
255
|
-
|------|-------------|---------|
|
|
256
|
-
| `--with-balance` | Fetch on-chain USDC balance for each router | — |
|
|
257
|
-
| `--json` | Output as JSON | — |
|
|
258
|
-
| `-h, --help` | Show help | — |
|
|
259
|
-
|
|
260
|
-
### Distribute funds
|
|
261
|
-
|
|
262
|
-
Withdraw accumulated USDC from a PaymentRouter contract:
|
|
263
|
-
|
|
264
|
-
```bash
|
|
265
|
-
x402 distribute 0x1234...5678
|
|
266
|
-
x402 distribute 0x1234...5678 --amount 5.00
|
|
267
|
-
x402 distribute 0x1234...5678 --force --json
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
| Flag | Description | Default |
|
|
271
|
-
|------|-------------|---------|
|
|
272
|
-
| `<router-address>` | PaymentRouter contract address (positional) | **required** |
|
|
273
|
-
| `--amount` | Specific USDC amount to distribute (defaults to full balance) | full balance |
|
|
274
|
-
| `--force` | Skip gas balance warning | — |
|
|
275
|
-
| `--json` | Output as JSON | — |
|
|
276
|
-
| `-h, --help` | Show help | — |
|
|
277
|
-
|
|
278
|
-
## Command Reference
|
|
279
|
-
|
|
280
|
-
### x402 balance
|
|
281
|
-
|
|
282
|
-
Check wallet balances.
|
|
283
|
-
|
|
284
|
-
```bash
|
|
285
|
-
x402 balance [--json] [--full]
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
| Flag | Description | Default |
|
|
289
|
-
|------|-------------|---------|
|
|
290
|
-
| `--json` | Output as JSON (address, network, chainId, balances) | — |
|
|
291
|
-
| `--full` | Show full wallet address instead of truncated | — |
|
|
292
|
-
| `-h, --help` | Show help | — |
|
|
293
|
-
|
|
294
|
-
### x402 pay
|
|
295
|
-
|
|
296
|
-
Pay for an x402-gated resource.
|
|
297
|
-
|
|
298
|
-
```bash
|
|
299
|
-
x402 pay <url> [options]
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
| Flag | Description | Default |
|
|
303
|
-
|------|-------------|---------|
|
|
304
|
-
| `<url>` | The URL of the x402-gated resource (positional) | **required** |
|
|
305
|
-
| `--method` | HTTP method | `GET` |
|
|
306
|
-
| `--body` | Request body (for POST/PUT requests) | — |
|
|
307
|
-
| `--header` | Add custom header (can be used multiple times) | — |
|
|
308
|
-
| `--max` | Maximum payment in USD (overrides config) | from config |
|
|
309
|
-
| `--dry-run` | Show payment details without paying | — |
|
|
310
|
-
| `-h, --help` | Show help | — |
|
|
311
|
-
|
|
312
|
-
### x402 fetch
|
|
313
|
-
|
|
314
|
-
Fetch with automatic payment.
|
|
315
|
-
|
|
316
|
-
```bash
|
|
317
|
-
x402 fetch <url> [options]
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
| Flag | Description | Default |
|
|
321
|
-
|------|-------------|---------|
|
|
322
|
-
| `<url>` | The URL to fetch (positional) | **required** |
|
|
323
|
-
| `--method` | HTTP method | `GET` |
|
|
324
|
-
| `--body` | Request body (for POST/PUT) | — |
|
|
325
|
-
| `--header` | Add header as `"Key: Value"` | — |
|
|
326
|
-
| `--json` | Output as JSON only (for piping to other tools) | — |
|
|
327
|
-
| `--raw` | Output raw response body only (no headers or status) | — |
|
|
328
|
-
| `-h, --help` | Show help | — |
|
|
329
|
-
|
|
330
|
-
### x402 create-link
|
|
331
|
-
|
|
332
|
-
Create a payment link.
|
|
333
|
-
|
|
334
|
-
```bash
|
|
335
|
-
x402 create-link --name <name> --price <usd> [options]
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
| Flag | Description | Default |
|
|
339
|
-
|------|-------------|---------|
|
|
340
|
-
| `--name` | Name of the payment link | **required** |
|
|
341
|
-
| `--price` | Price in USD (e.g., `"5.00"` or `"0.10"`) | **required** |
|
|
342
|
-
| `--url` | URL to gate behind payment | — |
|
|
343
|
-
| `--text` | Text content to gate behind payment | — |
|
|
344
|
-
| `--desc` | Description of the link | — |
|
|
345
|
-
| `--webhook` | Webhook URL for payment notifications | — |
|
|
346
|
-
| `--json` | Output as JSON | — |
|
|
347
|
-
| `-h, --help` | Show help | — |
|
|
348
|
-
|
|
349
|
-
> **Note:** Either `--url` or `--text` is required. The link is deployed as a smart contract on Base.
|
|
350
|
-
|
|
351
|
-
### x402 link-info
|
|
352
|
-
|
|
353
|
-
Get payment link details.
|
|
354
|
-
|
|
355
|
-
```bash
|
|
356
|
-
x402 link-info <router-address> [--json]
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
| Flag | Description | Default |
|
|
360
|
-
|------|-------------|---------|
|
|
361
|
-
| `<address>` | Router contract address or full payment URL (positional) | **required** |
|
|
362
|
-
| `--json` | Output as JSON | — |
|
|
363
|
-
| `-h, --help` | Show help | — |
|
|
364
|
-
|
|
365
|
-
## Environment Variables
|
|
366
|
-
|
|
367
|
-
| Variable | Description | Default |
|
|
368
|
-
|----------|-------------|---------|
|
|
369
|
-
| `EVM_PRIVATE_KEY` | Wallet private key (0x-prefixed) | **required** |
|
|
370
|
-
| `X402_NETWORK` | `mainnet` (Base, chain 8453) or `testnet` (Base Sepolia, chain 84532) | `mainnet` |
|
|
371
|
-
| `X402_MAX_PAYMENT_USD` | Safety limit — payments exceeding this are rejected unless `--max` is used | `10` |
|
|
372
|
-
| `X402_FACILITATOR_URL` | Custom facilitator URL | Coinbase (mainnet) / x402.org (testnet) |
|
|
373
|
-
| `X402_SLIPPAGE_BPS` | Slippage tolerance in basis points (100 bps = 1%) | `50` |
|
|
374
|
-
| `X402_VERBOSE` | Enable verbose logging (`1` = on, `0` = off) | `0` |
|
|
375
|
-
| `X402_LINKS_API_URL` | Base URL of x402-links-server (e.g., `https://21.cash`) | — |
|
|
376
|
-
|
|
377
|
-
## Supported Networks
|
|
378
|
-
|
|
379
|
-
| Network | Chain ID | CAIP-2 ID |
|
|
380
|
-
|---------|----------|-----------|
|
|
381
|
-
| Base Mainnet | 8453 | eip155:8453 |
|
|
382
|
-
| Base Sepolia | 84532 | eip155:84532 |
|
|
383
|
-
|
|
384
|
-
## Payment Token
|
|
385
|
-
|
|
386
|
-
All payments use **USDC** (USD Coin) on the selected network.
|
|
387
|
-
|
|
388
|
-
- Base Mainnet: `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`
|
|
389
|
-
- Base Sepolia: `0x036CbD53842c5426634e7929541eC2318f3dCF7e`
|
|
390
|
-
|
|
391
|
-
## How x402 Works
|
|
392
|
-
|
|
393
|
-
1. Client requests a resource
|
|
394
|
-
2. Server responds with `402 Payment Required` + payment details
|
|
395
|
-
3. Client signs a payment authorization (USDC transfer)
|
|
396
|
-
4. Client retries request with payment signature
|
|
397
|
-
5. Server verifies payment via facilitator
|
|
398
|
-
6. Server settles payment on-chain
|
|
399
|
-
7. Server returns the gated content
|
|
400
|
-
|
|
401
|
-
The x402 protocol is gasless for buyers - the facilitator sponsors gas fees.
|
|
402
|
-
|
|
403
|
-
## Troubleshooting
|
|
404
|
-
|
|
405
|
-
### "Missing required environment variable: EVM_PRIVATE_KEY"
|
|
406
|
-
|
|
407
|
-
Set your wallet private key:
|
|
408
|
-
```bash
|
|
409
|
-
export EVM_PRIVATE_KEY=0x...
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
Or create a `.env` file in your working directory, or install globally and use `~/.x402/.env`.
|
|
413
|
-
|
|
414
|
-
### "Payment exceeds max limit"
|
|
415
|
-
|
|
416
|
-
Increase the limit:
|
|
417
|
-
```bash
|
|
418
|
-
x402 pay https://... --max 50
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
### Low balance warnings
|
|
422
|
-
|
|
423
|
-
Fund your wallet with:
|
|
424
|
-
- **USDC** for payments
|
|
425
|
-
- **ETH** for gas (small amount, ~0.001 ETH)
|
|
426
|
-
|
|
427
|
-
### Network mismatch
|
|
428
|
-
|
|
429
|
-
Ensure your wallet has funds on the correct network:
|
|
430
|
-
- `X402_NETWORK=mainnet` → Base mainnet
|
|
431
|
-
- `X402_NETWORK=testnet` → Base Sepolia
|
|
432
|
-
|
|
433
|
-
## Backup Your Private Key
|
|
434
|
-
|
|
435
|
-
Your private key is stored in `~/.x402/.env`. If lost, your funds cannot be recovered.
|
|
436
|
-
|
|
437
|
-
### Recommended Backup Methods
|
|
438
|
-
|
|
439
|
-
1. **Password Manager** (Recommended)
|
|
440
|
-
- Store in 1Password, Bitwarden, or similar
|
|
441
|
-
- Create a secure note with your private key
|
|
442
|
-
- Tag it for easy retrieval
|
|
443
|
-
|
|
444
|
-
2. **Encrypted File**
|
|
445
|
-
```bash
|
|
446
|
-
# Encrypt with GPG
|
|
447
|
-
gpg -c ~/.x402/.env
|
|
448
|
-
# Creates ~/.x402/.env.gpg - store this backup securely
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
3. **Paper Backup** (for larger amounts)
|
|
452
|
-
- Write down the private key
|
|
453
|
-
- Store in a safe or safety deposit box
|
|
454
|
-
- Never store digitally unencrypted
|
|
455
|
-
|
|
456
|
-
### View Your Private Key
|
|
457
|
-
|
|
458
|
-
```bash
|
|
459
|
-
cat ~/.x402/.env | grep EVM_PRIVATE_KEY
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
### Recovery
|
|
463
|
-
|
|
464
|
-
To restore from backup:
|
|
465
|
-
```bash
|
|
466
|
-
mkdir -p ~/.x402
|
|
467
|
-
echo "EVM_PRIVATE_KEY=0x...your_backed_up_key..." > ~/.x402/.env
|
|
468
|
-
chmod 600 ~/.x402/.env
|
|
469
|
-
x402 balance # verify
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
## Security Best Practices
|
|
473
|
-
|
|
474
|
-
- **Use a dedicated wallet** — Never use your main wallet with automated agents
|
|
475
|
-
- **Limit funds** — Only transfer what you need for payments
|
|
476
|
-
- **Set payment limits** — Configure `X402_MAX_PAYMENT_USD` to cap exposure
|
|
477
|
-
- **Test first** — Use `X402_NETWORK=testnet` with test tokens before mainnet
|
|
478
|
-
- **Protect the config** — `~/.x402/.env` has 600 permissions; keep it that way
|
|
479
|
-
- **Never share** — Your private key gives full access to your wallet
|
|
480
|
-
|
|
481
|
-
## Links
|
|
482
|
-
|
|
483
|
-
- [x402 Protocol Docs](https://docs.x402.org/)
|
|
484
|
-
- [x402 GitHub](https://github.com/coinbase/x402)
|
|
485
|
-
- [npm: agentic-x402](https://www.npmjs.com/package/agentic-x402)
|
|
486
|
-
- [Base Network](https://base.org/)
|