agent402-client 0.2.1 → 0.4.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/README.md +39 -0
- package/index.js +94 -0
- package/package.json +40 -11
package/README.md
CHANGED
|
@@ -63,6 +63,21 @@ const { messages } = await a.getWorkflowPrompt("security-audit", { domain: "stri
|
|
|
63
63
|
// → feed messages straight to any LLM
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
## Discover the live x402 economy
|
|
67
|
+
|
|
68
|
+
Want to see who's actually getting paid on x402 right now — not just what tools
|
|
69
|
+
this service exposes? `topSellers()` returns the live leaderboard of sellers
|
|
70
|
+
settling USDC (primarily on Base) in the last ~24h, derived from on-chain transfers. Free
|
|
71
|
+
to call (no payment, no proof-of-work):
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
const { window, asOf, results, totalSellers } = await a.topSellers({ limit: 10 });
|
|
75
|
+
// → { window: "24h", asOf, totalSellers, results: [{ rank, name, wallet, totalUsd, callsSettled, uniqueBuyers, ... }] }
|
|
76
|
+
|
|
77
|
+
// Rank by call volume instead of USDC, and include the host's own wallet:
|
|
78
|
+
await a.topSellers({ sort: "calls", include: "all" });
|
|
79
|
+
```
|
|
80
|
+
|
|
66
81
|
## API
|
|
67
82
|
|
|
68
83
|
| Method | What |
|
|
@@ -71,6 +86,7 @@ const { messages } = await a.getWorkflowPrompt("security-audit", { domain: "stri
|
|
|
71
86
|
| `await a.find(task, { k = 5 })` | Resolve a plain-language task to the best-matching tools (route, price, schema, example) |
|
|
72
87
|
| `await a.findWorkflows(task, { k = 2 })` | Resolve a task to matching multi-tool workflow templates (skill packs) |
|
|
73
88
|
| `await a.getWorkflowPrompt(slug, args)` | Fetch the rendered prompt messages for a skill pack with arguments substituted in |
|
|
89
|
+
| `await a.topSellers({ limit?, sort?, include? })` | Live x402 leaderboard: which sellers are settling the most USDC (primarily on Base) in the last ~24h (free, no payment) |
|
|
74
90
|
| `await a.call(slug, params, { idempotencyKey?, cache? })` | Call a tool; auto-pays (PoW for free tools, x402 for wallet-only); returns the JSON result |
|
|
75
91
|
| `Agent402.solvePow(pow)` | Solve a proof-of-work challenge object → an `X-Pow-Solution` value |
|
|
76
92
|
| `a.clearCache()` | Drop the in-memory result cache |
|
|
@@ -78,3 +94,26 @@ const { messages } = await a.getWorkflowPrompt("security-audit", { domain: "stri
|
|
|
78
94
|
- **Zero dependencies** for the free/proof-of-work path (uses `node:crypto`).
|
|
79
95
|
- **Non-custodial:** paid settlement is your `@x402/fetch` + wallet; this client never sees your key.
|
|
80
96
|
- MIT licensed. Part of [Agent402](https://github.com/MikeyPetrillo/Agent402).
|
|
97
|
+
|
|
98
|
+
## Pick the settlement chain (`withNetworkPreference`)
|
|
99
|
+
|
|
100
|
+
Multi-chain sellers list Base first, so an unmodified x402 client effectively
|
|
101
|
+
always settles there. To pin a chain — e.g. **USDG on Robinhood Chain** —
|
|
102
|
+
wrap your client before building the fetch:
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
import { withNetworkPreference } from "agent402-client";
|
|
106
|
+
import { x402Client } from "@x402/core/client";
|
|
107
|
+
import { registerExactEvmScheme } from "@x402/evm/exact/client";
|
|
108
|
+
import { wrapFetchWithPayment } from "@x402/fetch";
|
|
109
|
+
|
|
110
|
+
const client = new x402Client();
|
|
111
|
+
registerExactEvmScheme(client, { signer });
|
|
112
|
+
withNetworkPreference(client, ["robinhood"]); // or ["base","solana"], or ["eip155:4663"]
|
|
113
|
+
const payFetch = wrapFetchWithPayment(fetch, client);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Short names map to CAIP-2 (`base`, `solana`, `polygon`, `arbitrum`,
|
|
117
|
+
`robinhood`); unknown entries pass through verbatim so future chains work
|
|
118
|
+
without a package update. If the preference matches none of a seller's
|
|
119
|
+
payment options it throws **before** any payment is signed.
|
package/index.js
CHANGED
|
@@ -77,6 +77,59 @@ export class Agent402 {
|
|
|
77
77
|
return r.json();
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Live x402 leaderboard — the sellers earning the most USDC (or serving the
|
|
82
|
+
* most calls) on Base in the last ~24h, derived from on-chain USDC
|
|
83
|
+
* transfers. Free; no payment, no wallet, no proof-of-work. Useful when
|
|
84
|
+
* building agents that want to discover the live x402 economy beyond a
|
|
85
|
+
* single service's catalog. Hourly snapshot — safe to call freely.
|
|
86
|
+
*
|
|
87
|
+
* @param {object} [opts]
|
|
88
|
+
* @param {number} [opts.limit=10] max rows (1-50)
|
|
89
|
+
* @param {"usd"|"calls"} [opts.sort="usd"] rank by USDC settled or call count
|
|
90
|
+
* @param {"external"|"all"} [opts.include="external"] hide this service's own wallet (default) or include it
|
|
91
|
+
* @returns {Promise<{window:string, asOf:string, sort:string, include:string, totalSellers:number, results:Array<object>, source:string}>}
|
|
92
|
+
*/
|
|
93
|
+
async topSellers({ limit = 10, sort = "usd", include = "external" } = {}) {
|
|
94
|
+
const top = Math.min(Math.max(parseInt(limit, 10) || 10, 1), 50);
|
|
95
|
+
const sortParam = sort === "calls" ? "calls" : "usd";
|
|
96
|
+
const includeParam = include === "all" ? "all" : "external";
|
|
97
|
+
const url = `${this.baseUrl}/api/leaderboard?top=${top}&sort=${sortParam}&include=${includeParam}`;
|
|
98
|
+
const r = await this.f(url);
|
|
99
|
+
if (!r.ok) throw new Error(`topSellers failed: HTTP ${r.status}`);
|
|
100
|
+
const snap = await r.json();
|
|
101
|
+
return {
|
|
102
|
+
window: snap.windowLabel || snap.windowServed || "24h",
|
|
103
|
+
asOf: snap.asOf,
|
|
104
|
+
sort: snap.sortServed || sortParam,
|
|
105
|
+
include: snap.include || includeParam,
|
|
106
|
+
totalSellers: snap.totalSellers ?? (snap.leaderboard || []).length,
|
|
107
|
+
results: snap.leaderboard || [],
|
|
108
|
+
...(snap.warming || snap.scanSkipped ? { warming: true } : {}),
|
|
109
|
+
source: `${this.baseUrl}/api/leaderboard`,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Register a wallet address for Base builder code attribution. Idempotent:
|
|
115
|
+
* the same wallet always returns the same code. No authentication required.
|
|
116
|
+
*
|
|
117
|
+
* @param {string} walletAddress the caller's wallet address (e.g. "0x…")
|
|
118
|
+
* @param {object} [opts]
|
|
119
|
+
* @param {typeof fetch} [opts.fetchImpl] plain fetch (defaults to global fetch)
|
|
120
|
+
* @returns {Promise<{builderCode:string, walletAddress:string}>}
|
|
121
|
+
*/
|
|
122
|
+
static async registerBuilderCode(walletAddress, { fetchImpl = globalThis.fetch } = {}) {
|
|
123
|
+
if (!walletAddress || typeof walletAddress !== "string") throw new Error("walletAddress is required");
|
|
124
|
+
const r = await fetchImpl("https://api.base.dev/v1/agents/builder-codes", {
|
|
125
|
+
method: "POST",
|
|
126
|
+
headers: { "Content-Type": "application/json" },
|
|
127
|
+
body: JSON.stringify({ walletAddress }),
|
|
128
|
+
});
|
|
129
|
+
if (!r.ok) throw new Error(`builder code registration failed: HTTP ${r.status}`);
|
|
130
|
+
return r.json();
|
|
131
|
+
}
|
|
132
|
+
|
|
80
133
|
/** Solve a proof-of-work challenge object (from a 402 body) into an X-Pow-Solution value. */
|
|
81
134
|
static solvePow(pow) {
|
|
82
135
|
let n = 0;
|
|
@@ -145,4 +198,45 @@ export class Agent402 {
|
|
|
145
198
|
clearCache() { this._cache?.clear(); }
|
|
146
199
|
}
|
|
147
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Restrict + order which chains an @x402 client will pay on (duck-typed — any
|
|
203
|
+
* client version with createPaymentPayload works, zero new dependencies).
|
|
204
|
+
* Multi-chain sellers list Base first, so an unmodified client effectively
|
|
205
|
+
* always settles there; this makes rails like USDG on Robinhood Chain
|
|
206
|
+
* (eip155:4663) reachable:
|
|
207
|
+
*
|
|
208
|
+
* import { withNetworkPreference } from "agent402-client";
|
|
209
|
+
* withNetworkPreference(x402client, ["robinhood"]); // or ["eip155:4663"]
|
|
210
|
+
* const payFetch = wrapFetchWithPayment(fetch, x402client);
|
|
211
|
+
*
|
|
212
|
+
* Short names map to CAIP-2; unknown entries pass through verbatim so future
|
|
213
|
+
* chains work without a package update. Throws (before paying) when the
|
|
214
|
+
* preference matches none of a seller's payment options.
|
|
215
|
+
*/
|
|
216
|
+
export const NETWORK_CAIP2 = {
|
|
217
|
+
base: "eip155:8453",
|
|
218
|
+
polygon: "eip155:137",
|
|
219
|
+
arbitrum: "eip155:42161",
|
|
220
|
+
"base-sepolia": "eip155:84532",
|
|
221
|
+
robinhood: "eip155:4663",
|
|
222
|
+
solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
223
|
+
"solana-devnet": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
export function withNetworkPreference(client, networks) {
|
|
227
|
+
const prefs = (networks || []).map((n) => NETWORK_CAIP2[String(n).trim().toLowerCase()] || String(n).trim());
|
|
228
|
+
if (!prefs.length) return client;
|
|
229
|
+
const orig = client.createPaymentPayload.bind(client);
|
|
230
|
+
client.createPaymentPayload = (paymentRequired) => {
|
|
231
|
+
const list = Array.isArray(paymentRequired?.accepts) ? paymentRequired.accepts : [];
|
|
232
|
+
const picked = prefs.flatMap((caip2) => list.filter((a) => String(a?.network || "").toLowerCase() === caip2.toLowerCase()));
|
|
233
|
+
if (!picked.length) {
|
|
234
|
+
const offered = [...new Set(list.map((a) => a?.network).filter(Boolean))];
|
|
235
|
+
throw new Error(`network preference [${prefs.join(", ")}] matched none of the seller's payment options [${offered.join(", ")}]`);
|
|
236
|
+
}
|
|
237
|
+
return orig({ ...paymentRequired, accepts: picked });
|
|
238
|
+
};
|
|
239
|
+
return client;
|
|
240
|
+
}
|
|
241
|
+
|
|
148
242
|
export default Agent402;
|
package/package.json
CHANGED
|
@@ -1,19 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent402-client",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Buyer-side SDK for Agent402.Tools (x402): resolve a task to a tool across 1,338 pay-per-call endpoints and call it with payment handled for you — free tools settle via built-in proof-of-work (no wallet), wallet-only tools via your x402 fetch — with a withNetworkPreference helper to pick the settlement chain (USDC on Base/Solana/Polygon/Arbitrum or USDG on Robinhood Chain). Caching, idempotent retries, cross-seller Smart Order Router.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
|
-
"exports": {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"index.js",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"test": "node test.js"
|
|
19
|
+
},
|
|
11
20
|
"keywords": [
|
|
12
|
-
"x402",
|
|
13
|
-
"
|
|
21
|
+
"x402",
|
|
22
|
+
"ai-agents",
|
|
23
|
+
"agent-tools",
|
|
24
|
+
"llm-tools",
|
|
25
|
+
"usdc",
|
|
26
|
+
"base",
|
|
27
|
+
"proof-of-work",
|
|
28
|
+
"http-402",
|
|
29
|
+
"micropayments",
|
|
30
|
+
"mcp",
|
|
31
|
+
"client",
|
|
32
|
+
"sdk",
|
|
33
|
+
"agent402",
|
|
34
|
+
"tool-discovery",
|
|
35
|
+
"smart-order-router",
|
|
36
|
+
"robinhood-chain",
|
|
37
|
+
"usdg",
|
|
38
|
+
"multi-chain"
|
|
14
39
|
],
|
|
15
|
-
"author": "
|
|
40
|
+
"author": "Mike Petrillo <mike@agent402.tools> (https://github.com/MikeyPetrillo)",
|
|
16
41
|
"license": "MIT",
|
|
17
|
-
"repository": {
|
|
18
|
-
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/MikeyPetrillo/Agent402.git",
|
|
45
|
+
"directory": "client"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://agent402.tools"
|
|
19
48
|
}
|