@aqb-foundation/aqb-agent 1.0.0 → 1.0.2
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 +4 -16
- package/README.md +68 -20
- package/WHITEPAPER.md +2 -1
- package/client/aqb.mjs +232 -148
- package/compile.mjs +44 -0
- package/contracts/AgentQuantumCredit.sol +234 -0
- package/contracts/AgentRegistry.sol +85 -0
- package/contracts/GenesisSale.sol +89 -0
- package/contracts/MLDSAVerifier.sol +65 -0
- package/contracts/PQSmartAccount.sol +105 -0
- package/contracts/interfaces/IPQVerifier.sol +19 -0
- package/contracts/mocks/MockUSDC.sol +30 -0
- package/contracts/mocks/MockVerifier.sol +13 -0
- package/docs/CARD.md +1 -1
- package/docs/SPEC.md +5 -4
- package/docs/articles/01-payment-rail-agents.md +55 -0
- package/docs/articles/01.body +56 -0
- package/docs/articles/02-gated-transfers.md +36 -0
- package/docs/articles/03-peg-without-oracle.md +33 -0
- package/docs/articles/04-discovery-over-landing.md +42 -0
- package/docs/articles/04-discovery-over-landing.md.body +40 -0
- package/docs/articles/04-discovery-over-landing.md.title +1 -0
- package/docs/articles/05-identity-survives-key.md +27 -0
- package/docs/articles/05-identity-survives-key.md.body +25 -0
- package/docs/articles/05-identity-survives-key.md.title +1 -0
- package/docs/articles/06-what-an-agent-needs.md +30 -0
- package/docs/articles/06-what-an-agent-needs.md.body +28 -0
- package/docs/articles/06-what-an-agent-needs.md.title +1 -0
- package/docs/articles/body.json +1 -0
- package/docs/articles/body.txt +50 -0
- package/docs/articles/title.txt +1 -0
- package/docs/marketing-plan.md +55 -0
- package/docs/pq-note.md +1 -0
- package/index.js +241 -0
- package/mcp/server.mjs +118 -25
- package/package.json +40 -10
- package/registry/agent-coin.json +20 -15
- package/registry/banner.png +0 -0
- package/registry/logo.png +0 -0
- package/test/e2e.mjs +100 -0
- package/test/evm.mjs +69 -0
- package/test/local.mjs +86 -0
- package/test/pq.mjs +37 -0
- package/test/smoke.mjs +27 -0
package/index.js
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// AQB CLI. One binary for humans wiring agents and for MCP clients.
|
|
3
|
+
// Usage: aqb-agent <command> [flags]
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import { ContractFactory, parseUnits, formatUnits, formatEther } from "ethers";
|
|
6
|
+
import { AqbAgent, discover, wellKnown, cardHash, newIdentity, USDC } from "./client/aqb.mjs";
|
|
7
|
+
|
|
8
|
+
const pkg = JSON.parse(fs.readFileSync(new URL("./package.json", import.meta.url), "utf8"));
|
|
9
|
+
const regFile = JSON.parse(fs.readFileSync(new URL("./registry/agent-coin.json", import.meta.url), "utf8"));
|
|
10
|
+
|
|
11
|
+
const DEFAULTS = {
|
|
12
|
+
token: process.env.AQB_TOKEN || regFile.contracts.token,
|
|
13
|
+
registry: process.env.AQB_REGISTRY || regFile.contracts.registry,
|
|
14
|
+
verifier: process.env.AQB_VERIFIER || regFile.contracts.verifier,
|
|
15
|
+
pair: process.env.AQB_PAIR || regFile.markets?.[0]?.pair,
|
|
16
|
+
sale: process.env.AQB_SALE || regFile.sale,
|
|
17
|
+
chain: process.env.AQB_CHAIN || "base",
|
|
18
|
+
rpc: process.env.AQB_RPC || process.env.BASE_RPC,
|
|
19
|
+
key: process.env.AQB_KEY || process.env.PRIVATE_KEY,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function parse(argv) {
|
|
23
|
+
const out = { _: [] };
|
|
24
|
+
for (let i = 0; i < argv.length; i++) {
|
|
25
|
+
const a = argv[i];
|
|
26
|
+
if (!a.startsWith("--")) { out._.push(a); continue; }
|
|
27
|
+
const body = a.slice(2);
|
|
28
|
+
if (body.includes("=")) {
|
|
29
|
+
const [k, ...rest] = body.split("=");
|
|
30
|
+
out[k] = rest.join("=");
|
|
31
|
+
} else if (i + 1 < argv.length && !argv[i + 1].startsWith("--")) {
|
|
32
|
+
out[body] = argv[++i];
|
|
33
|
+
} else {
|
|
34
|
+
out[body] = true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function client(args, extra = {}) {
|
|
41
|
+
return new AqbAgent({
|
|
42
|
+
rpc: args.rpc || DEFAULTS.rpc,
|
|
43
|
+
chain: args.chain || DEFAULTS.chain,
|
|
44
|
+
privateKey: args.key || DEFAULTS.key,
|
|
45
|
+
token: args.token || DEFAULTS.token,
|
|
46
|
+
registry: args.registry || DEFAULTS.registry,
|
|
47
|
+
...extra,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function need(v, name) {
|
|
52
|
+
if (!v) throw new Error(`missing --${name}`);
|
|
53
|
+
return v;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const addr = (x) => (typeof x === "string" ? x.toLowerCase() : x);
|
|
57
|
+
|
|
58
|
+
function buildCard(args, account) {
|
|
59
|
+
return {
|
|
60
|
+
aqb: 1,
|
|
61
|
+
name: args.name || "aqb-agent",
|
|
62
|
+
skill: args.skill || "agent service",
|
|
63
|
+
endpoint: args.endpoint || "https://agent.example/a2a",
|
|
64
|
+
pq: "ML-DSA-65",
|
|
65
|
+
kem: "ML-KEM-768",
|
|
66
|
+
pay: `aqb:${account || args.account || "0x0000000000000000000000000000000000000000"}`,
|
|
67
|
+
price: { unit: "AQB", amount: args.price || "0", per: args.per || "call" },
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function readCard(args, account) {
|
|
72
|
+
if (args.card) return JSON.parse(fs.readFileSync(args.card, "utf8"));
|
|
73
|
+
return buildCard(args, account);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const HELP = `aqb-agent ${pkg.version}
|
|
77
|
+
|
|
78
|
+
aqb-agent mcp start the MCP stdio server
|
|
79
|
+
aqb-agent discover <host> read /.well-known/agent-coin.json
|
|
80
|
+
aqb-agent wellknown print this deployment's discovery JSON
|
|
81
|
+
aqb-agent balance [address] AQB + USDC balances
|
|
82
|
+
aqb-agent is-agent <address> registry membership
|
|
83
|
+
aqb-agent quote [--amount 1] vault + Uniswap V2 quote
|
|
84
|
+
aqb-agent pay --to 0x.. --amount 1.5 [--account 0x..]
|
|
85
|
+
aqb-agent fund --amount 10 [--account 0x..] (USDC -> AQB)
|
|
86
|
+
aqb-agent redeem --amount 10 [--account 0x..] (AQB -> USDC)
|
|
87
|
+
aqb-agent register --account 0x.. [--name .. --skill .. --endpoint .. --price ..]
|
|
88
|
+
aqb-agent update-card --account 0x.. [--card file.json | --name .. --skill ..]
|
|
89
|
+
aqb-agent card [--card file.json | --name .. --skill .. --endpoint ..]
|
|
90
|
+
aqb-agent deploy-account deploy a PQSmartAccount (prints its PQ keys)
|
|
91
|
+
aqb-agent announce --account 0x.. --eph-pubkey 0x.. --shared-secret 0x..
|
|
92
|
+
aqb-agent version
|
|
93
|
+
|
|
94
|
+
Env: AQB_KEY/PRIVATE_KEY, AQB_RPC/BASE_RPC, AQB_CHAIN, AQB_TOKEN, AQB_REGISTRY, AQB_VERIFIER, AQB_PAIR, AQB_SALE
|
|
95
|
+
The on-chain account path currently signs with the ECDSA fallback (scheme 0x01); the PQ
|
|
96
|
+
key remains the account identity and is used for off-chain signatures.
|
|
97
|
+
`;
|
|
98
|
+
|
|
99
|
+
async function main() {
|
|
100
|
+
const args = parse(process.argv.slice(2));
|
|
101
|
+
const cmd = args._[0] || "help";
|
|
102
|
+
|
|
103
|
+
if (cmd === "help" || args.help) { process.stdout.write(HELP); return; }
|
|
104
|
+
if (cmd === "version") { console.log(pkg.version); return; }
|
|
105
|
+
|
|
106
|
+
if (cmd === "mcp") {
|
|
107
|
+
await import("./mcp/server.mjs");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (cmd === "discover") {
|
|
112
|
+
const host = need(args._[1] || args.host, "host");
|
|
113
|
+
console.log(JSON.stringify(await discover(host), null, 2));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (cmd === "wellknown") {
|
|
118
|
+
console.log(JSON.stringify(wellKnown({
|
|
119
|
+
token: DEFAULTS.token, registry: DEFAULTS.registry, verifier: DEFAULTS.verifier,
|
|
120
|
+
chainId: Number(DEFAULTS.chain === "base" ? 8453 : 84532),
|
|
121
|
+
pool: DEFAULTS.pair, sale: DEFAULTS.sale,
|
|
122
|
+
}), null, 2));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const c = client(args);
|
|
127
|
+
|
|
128
|
+
if (cmd === "balance") {
|
|
129
|
+
const address = addr(args._[1] || args.address || c.signer?.address);
|
|
130
|
+
if (!address) throw new Error("missing address");
|
|
131
|
+
console.log(JSON.stringify({
|
|
132
|
+
address,
|
|
133
|
+
aqb: formatEther(await c.balance(address)),
|
|
134
|
+
usdc: formatUnits(await c.usdBalance(address), 6),
|
|
135
|
+
}, null, 2));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (cmd === "is-agent") {
|
|
140
|
+
const address = addr(need(args._[1] || args.address, "address"));
|
|
141
|
+
console.log(JSON.stringify({ address, isAgent: await c.isAgent(address) }, null, 2));
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (cmd === "quote") {
|
|
146
|
+
const pair = addr(args.pair || DEFAULTS.pair);
|
|
147
|
+
const amount = parseUnits(args.amount || "1", 18);
|
|
148
|
+
const q = await c.poolQuote(pair, amount);
|
|
149
|
+
console.log(JSON.stringify({
|
|
150
|
+
pool: pair,
|
|
151
|
+
aqb: formatEther(amount),
|
|
152
|
+
vaultUSDC: formatUnits(amount / 10n ** 12n, 6),
|
|
153
|
+
poolUSDC: formatUnits(q.usdc, 6),
|
|
154
|
+
reserves: { aqb: formatEther(q.reserves.aqb), usdc: formatUnits(q.reserves.usdc, 6) },
|
|
155
|
+
}, null, 2));
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (cmd === "pay") {
|
|
160
|
+
const to = addr(need(args.to, "to"));
|
|
161
|
+
const amount = parseUnits(need(args.amount, "amount"), 18);
|
|
162
|
+
const tx = args.account ? await c.payFromAccount(c.account(addr(args.account)), to, amount) : await c.pay(to, amount);
|
|
163
|
+
console.log(JSON.stringify({ tx, to, aqb: formatEther(amount) }, null, 2));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (cmd === "fund") {
|
|
168
|
+
const amount = parseUnits(need(args.amount, "amount"), 6);
|
|
169
|
+
const tx = args.account ? await c.fundFromAccount(c.account(addr(args.account)), amount) : await c.fund(amount);
|
|
170
|
+
console.log(JSON.stringify({ tx, usdc: formatUnits(amount, 6) }, null, 2));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (cmd === "redeem" || cmd === "cash-out") {
|
|
175
|
+
const amount = parseUnits(need(args.amount, "amount"), 18);
|
|
176
|
+
const tx = args.account ? await c.redeemFromAccount(c.account(addr(args.account)), amount) : await c.cashOut(amount);
|
|
177
|
+
console.log(JSON.stringify({ tx, aqb: formatEther(amount), usdc: formatUnits(amount / 10n ** 12n, 6) }, null, 2));
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (cmd === "register") {
|
|
182
|
+
const account = addr(need(args.account, "account"));
|
|
183
|
+
const card = readCard(args, account);
|
|
184
|
+
const tx = await c.registerViaAccount(account, card);
|
|
185
|
+
console.log(JSON.stringify({ tx, account, cardHash: cardHash(card), card }, null, 2));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (cmd === "update-card") {
|
|
190
|
+
const account = addr(need(args.account, "account"));
|
|
191
|
+
const card = readCard(args, account);
|
|
192
|
+
const tx = await c.updateCardFromAccount(account, card);
|
|
193
|
+
console.log(JSON.stringify({ tx, account, cardHash: cardHash(card) }, null, 2));
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (cmd === "card") {
|
|
198
|
+
const card = readCard(args, args.account);
|
|
199
|
+
console.log(JSON.stringify({ card, cardHash: cardHash(card) }, null, 2));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (cmd === "deploy-account") {
|
|
204
|
+
const art = JSON.parse(fs.readFileSync(new URL("./artifacts/PQSmartAccount.json", import.meta.url), "utf8"));
|
|
205
|
+
const id = newIdentity();
|
|
206
|
+
const factory = new ContractFactory(art.abi, art.bytecode, c.requireSigner());
|
|
207
|
+
const acc = await factory.deploy(DEFAULTS.verifier, c.signer.address, id.publicKey);
|
|
208
|
+
await acc.waitForDeployment();
|
|
209
|
+
const address = await acc.getAddress();
|
|
210
|
+
console.log(JSON.stringify({
|
|
211
|
+
account: address,
|
|
212
|
+
ecdsaFallback: c.signer.address,
|
|
213
|
+
verifier: DEFAULTS.verifier,
|
|
214
|
+
pqPublicKey: "0x" + Buffer.from(id.publicKey).toString("hex"),
|
|
215
|
+
pqSecretKey: "0x" + Buffer.from(id.secretKey).toString("hex"),
|
|
216
|
+
pqKeyHash: id.keyHash,
|
|
217
|
+
next: `aqb-agent register --account ${address} --name <name> --skill <skill> --endpoint <url>`,
|
|
218
|
+
}, null, 2));
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (cmd === "announce") {
|
|
223
|
+
const account = addr(need(args.account, "account"));
|
|
224
|
+
const tx = await c.announceFromAccount(
|
|
225
|
+
c.account(account),
|
|
226
|
+
need(args["eph-pubkey"], "eph-pubkey"),
|
|
227
|
+
need(args["shared-secret"], "shared-secret"),
|
|
228
|
+
args["meta-hash"] || "0x" + "00".repeat(32)
|
|
229
|
+
);
|
|
230
|
+
console.log(JSON.stringify({ tx, account }, null, 2));
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
process.stderr.write(HELP);
|
|
235
|
+
process.exitCode = 1;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
main().catch((e) => {
|
|
239
|
+
console.error(e.shortMessage || e.message || String(e));
|
|
240
|
+
process.exit(1);
|
|
241
|
+
});
|
package/mcp/server.mjs
CHANGED
|
@@ -1,37 +1,123 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// AQB MCP server (stdio JSON-RPC 2.0, no deps). Tools every agent can call.
|
|
3
|
-
import
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { parseUnits, formatUnits, formatEther } from "ethers";
|
|
5
|
+
import { AqbAgent, discover, wellKnown, cardHash } from "../client/aqb.mjs";
|
|
6
|
+
|
|
7
|
+
const regFile = JSON.parse(fs.readFileSync(new URL("../registry/agent-coin.json", import.meta.url), "utf8"));
|
|
8
|
+
const TOKEN = process.env.AQB_TOKEN || regFile.contracts.token;
|
|
9
|
+
const REGISTRY = process.env.AQB_REGISTRY || regFile.contracts.registry;
|
|
10
|
+
const VERIFIER = process.env.AQB_VERIFIER || regFile.contracts.verifier;
|
|
11
|
+
const PAIR = process.env.AQB_PAIR || regFile.markets?.[0]?.pair;
|
|
12
|
+
const SALE = process.env.AQB_SALE || regFile.sale;
|
|
4
13
|
|
|
5
14
|
const cfg = () => new AqbAgent({
|
|
6
|
-
rpc: process.env.AQB_RPC
|
|
7
|
-
|
|
15
|
+
rpc: process.env.AQB_RPC || process.env.BASE_RPC,
|
|
16
|
+
chain: process.env.AQB_CHAIN || "base",
|
|
17
|
+
privateKey: process.env.AQB_KEY || process.env.PRIVATE_KEY,
|
|
18
|
+
token: TOKEN,
|
|
19
|
+
registry: REGISTRY,
|
|
8
20
|
});
|
|
9
21
|
|
|
10
22
|
const TOOLS = [
|
|
11
23
|
{ name: "aqb_discover", description: "Fetch AQB discovery doc from an agent host", inputSchema: { type: "object", properties: { host: { type: "string" } }, required: ["host"] } },
|
|
12
|
-
{ name: "aqb_balance", description: "Get AQB and USDC balances (read-only)", inputSchema: { type: "object", properties: { address: { type: "string" } } } },
|
|
24
|
+
{ name: "aqb_balance", description: "Get AQB and USDC balances for an address (read-only)", inputSchema: { type: "object", properties: { address: { type: "string" } } } },
|
|
13
25
|
{ name: "aqb_is_agent", description: "Check whether an address is a registered agent", inputSchema: { type: "object", properties: { address: { type: "string" } }, required: ["address"] } },
|
|
14
|
-
{ name: "
|
|
15
|
-
{ name: "
|
|
16
|
-
{ name: "
|
|
17
|
-
{ name: "
|
|
18
|
-
{ name: "
|
|
19
|
-
{ name: "
|
|
26
|
+
{ name: "aqb_quote", description: "Quote 1 AQB in USDC from the vault (1.0) and the Uniswap V2 pool", inputSchema: { type: "object", properties: { amount: { type: "string" }, pair: { type: "string" } } } },
|
|
27
|
+
{ name: "aqb_register", description: "Register a PQSmartAccount as an agent (caller must be the account)", inputSchema: { type: "object", properties: { account: { type: "string" }, card: { type: "object" }, scheme: { type: "string", enum: ["ecdsa", "pq"] } }, required: ["account", "card"] } },
|
|
28
|
+
{ name: "aqb_update_card", description: "Publish a new agent card hash from a PQSmartAccount", inputSchema: { type: "object", properties: { account: { type: "string" }, card: { type: "object" }, scheme: { type: "string", enum: ["ecdsa", "pq"] } }, required: ["account", "card"] } },
|
|
29
|
+
{ name: "aqb_fund", description: "Mint AQB against USDC, 1:1 (usd in human units, e.g. 10.5)", inputSchema: { type: "object", properties: { usd: { type: "string" }, account: { type: "string" } }, required: ["usd"] } },
|
|
30
|
+
{ name: "aqb_pay", description: "Pay AQB to another agent (amount in human units, e.g. 1.5)", inputSchema: { type: "object", properties: { to: { type: "string" }, aqb: { type: "string" }, account: { type: "string" } }, required: ["to", "aqb"] } },
|
|
31
|
+
{ name: "aqb_redeem", description: "Redeem AQB for USDC, 1:1 (amount in human units)", inputSchema: { type: "object", properties: { aqb: { type: "string" }, account: { type: "string" } }, required: ["aqb"] } },
|
|
32
|
+
{ name: "aqb_cash_out", description: "Alias for aqb_redeem", inputSchema: { type: "object", properties: { aqb: { type: "string" }, account: { type: "string" } }, required: ["aqb"] } },
|
|
33
|
+
{ name: "aqb_announce_stealth", description: "Publish a stealth address for a payer from a PQSmartAccount", inputSchema: { type: "object", properties: { account: { type: "string" }, ephPubKey: { type: "string" }, sharedSecret: { type: "string" }, metaHash: { type: "string" } }, required: ["account", "ephPubKey", "sharedSecret"] } },
|
|
34
|
+
{ name: "aqb_wellknown", description: "Generate your own /.well-known/agent-coin.json", inputSchema: { type: "object", properties: { token: { type: "string" }, registry: { type: "string" }, verifier: { type: "string" }, pool: { type: "string" } } } },
|
|
20
35
|
];
|
|
21
36
|
|
|
37
|
+
function requireArg(a, name) {
|
|
38
|
+
if (!a[name]) throw new Error(`missing argument: ${name}`);
|
|
39
|
+
return a[name];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const addr = (x) => (typeof x === "string" ? x.toLowerCase() : x);
|
|
43
|
+
|
|
44
|
+
function accountOf(c, a) {
|
|
45
|
+
return a.account ? c.account(addr(a.account)) : null;
|
|
46
|
+
}
|
|
47
|
+
|
|
22
48
|
async function run(name, a) {
|
|
23
49
|
const c = cfg();
|
|
24
50
|
switch (name) {
|
|
25
|
-
case "aqb_discover":
|
|
26
|
-
|
|
27
|
-
case "
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
51
|
+
case "aqb_discover":
|
|
52
|
+
return await discover(requireArg(a, "host"));
|
|
53
|
+
case "aqb_balance": {
|
|
54
|
+
const address = addr(a.address || c.signer?.address);
|
|
55
|
+
if (!address) throw new Error("address required");
|
|
56
|
+
return {
|
|
57
|
+
address,
|
|
58
|
+
aqb: formatEther(await c.balance(address)),
|
|
59
|
+
usdc: formatUnits(await c.usdBalance(address), 6),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
case "aqb_is_agent":
|
|
63
|
+
return { isAgent: await c.isAgent(addr(requireArg(a, "address"))) };
|
|
64
|
+
case "aqb_quote": {
|
|
65
|
+
const amount = parseUnits(a.amount || "1", 18);
|
|
66
|
+
const q = await c.poolQuote(addr(a.pair || PAIR), amount);
|
|
67
|
+
return {
|
|
68
|
+
pool: addr(a.pair || PAIR),
|
|
69
|
+
aqb: formatEther(amount),
|
|
70
|
+
vaultUSDC: formatUnits(amount / 10n ** 12n, 6),
|
|
71
|
+
poolUSDC: formatUnits(q.usdc, 6),
|
|
72
|
+
reserves: { aqb: formatEther(q.reserves.aqb), usdc: formatUnits(q.reserves.usdc, 6) },
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
case "aqb_register": {
|
|
76
|
+
const account = addr(requireArg(a, "account"));
|
|
77
|
+
const tx = await c.registerViaAccount(account, requireArg(a, "card"), a.scheme || "ecdsa");
|
|
78
|
+
return { tx, account, cardHash: cardHash(a.card) };
|
|
79
|
+
}
|
|
80
|
+
case "aqb_update_card": {
|
|
81
|
+
const account = addr(requireArg(a, "account"));
|
|
82
|
+
const tx = await c.updateCardFromAccount(account, requireArg(a, "card"), a.scheme || "ecdsa");
|
|
83
|
+
return { tx, account, cardHash: cardHash(a.card) };
|
|
84
|
+
}
|
|
85
|
+
case "aqb_fund": {
|
|
86
|
+
const usd = parseUnits(requireArg(a, "usd"), 6);
|
|
87
|
+
const acc = accountOf(c, a);
|
|
88
|
+
return { tx: acc ? await c.fundFromAccount(acc, usd) : await c.fund(usd), usdc: formatUnits(usd, 6) };
|
|
89
|
+
}
|
|
90
|
+
case "aqb_pay": {
|
|
91
|
+
const aqb = parseUnits(requireArg(a, "aqb"), 18);
|
|
92
|
+
const acc = accountOf(c, a);
|
|
93
|
+
const to = addr(requireArg(a, "to")); return { tx: acc ? await c.payFromAccount(acc, to, aqb) : await c.pay(to, aqb), aqb: formatEther(aqb) };
|
|
94
|
+
}
|
|
95
|
+
case "aqb_redeem":
|
|
96
|
+
case "aqb_cash_out": {
|
|
97
|
+
const aqb = parseUnits(requireArg(a, "aqb"), 18);
|
|
98
|
+
const acc = accountOf(c, a);
|
|
99
|
+
return { tx: acc ? await c.redeemFromAccount(acc, aqb) : await c.cashOut(aqb), aqb: formatEther(aqb) };
|
|
100
|
+
}
|
|
101
|
+
case "aqb_announce_stealth": {
|
|
102
|
+
const tx = await c.announceFromAccount(
|
|
103
|
+
c.account(addr(requireArg(a, "account"))),
|
|
104
|
+
requireArg(a, "ephPubKey"),
|
|
105
|
+
requireArg(a, "sharedSecret"),
|
|
106
|
+
a.metaHash || "0x" + "00".repeat(32)
|
|
107
|
+
);
|
|
108
|
+
return { tx };
|
|
109
|
+
}
|
|
110
|
+
case "aqb_wellknown":
|
|
111
|
+
return wellKnown({
|
|
112
|
+
token: a.token || TOKEN,
|
|
113
|
+
registry: a.registry || REGISTRY,
|
|
114
|
+
verifier: a.verifier || VERIFIER,
|
|
115
|
+
chainId: Number(process.env.AQB_CHAIN_ID || 8453),
|
|
116
|
+
pool: a.pool || PAIR,
|
|
117
|
+
sale: SALE,
|
|
118
|
+
});
|
|
119
|
+
default:
|
|
120
|
+
throw new Error(`unknown tool ${name}`);
|
|
35
121
|
}
|
|
36
122
|
}
|
|
37
123
|
|
|
@@ -47,14 +133,21 @@ process.stdin.on("data", async (chunk) => {
|
|
|
47
133
|
let m;
|
|
48
134
|
try { m = JSON.parse(line); } catch { continue; }
|
|
49
135
|
try {
|
|
50
|
-
if (m.method === "initialize")
|
|
51
|
-
|
|
52
|
-
else if (m.method === "tools/
|
|
136
|
+
if (m.method === "initialize") {
|
|
137
|
+
send({ jsonrpc: "2.0", id: m.id, result: { protocolVersion: "2024-11-05", capabilities: { tools: {} }, serverInfo: { name: "aqb", version: "1.0.2" } } });
|
|
138
|
+
} else if (m.method === "tools/list") {
|
|
139
|
+
send({ jsonrpc: "2.0", id: m.id, result: { tools: TOOLS } });
|
|
140
|
+
} else if (m.method === "tools/call") {
|
|
53
141
|
const out = await run(m.params.name, m.params.arguments || {});
|
|
54
142
|
send({ jsonrpc: "2.0", id: m.id, result: { content: [{ type: "text", text: JSON.stringify(out) }] } });
|
|
55
|
-
} else if (m.id !== undefined)
|
|
143
|
+
} else if (m.id !== undefined) {
|
|
144
|
+
send({ jsonrpc: "2.0", id: m.id, result: {} });
|
|
145
|
+
}
|
|
56
146
|
} catch (e) {
|
|
57
|
-
|
|
147
|
+
const msg = String(e.shortMessage || e.message || e);
|
|
148
|
+
if (m.id !== undefined) {
|
|
149
|
+
send({ jsonrpc: "2.0", id: m.id, result: { content: [{ type: "text", text: msg }], isError: true } });
|
|
150
|
+
}
|
|
58
151
|
}
|
|
59
152
|
}
|
|
60
153
|
});
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aqb-foundation/aqb-agent",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "AQB — agent-only, USD-pegged, post-quantum credit token on Base",
|
|
5
|
-
"main": "
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "AQB — agent-only, USD-pegged, post-quantum credit token on Base. SDK, CLI and MCP server.",
|
|
5
|
+
"main": "client/aqb.mjs",
|
|
6
6
|
"directories": {
|
|
7
7
|
"doc": "docs",
|
|
8
8
|
"test": "test"
|
|
@@ -10,41 +10,71 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"compile": "node compile.mjs",
|
|
12
12
|
"test": "node compile.mjs && node test/pq.mjs && node test/e2e.mjs",
|
|
13
|
-
"
|
|
13
|
+
"mcp": "node mcp/server.mjs"
|
|
14
14
|
},
|
|
15
15
|
"keywords": [
|
|
16
16
|
"ai-agents",
|
|
17
|
+
"agent-payments",
|
|
17
18
|
"x402",
|
|
18
19
|
"post-quantum",
|
|
19
20
|
"ml-dsa",
|
|
20
21
|
"base",
|
|
21
|
-
"stablecoin"
|
|
22
|
+
"stablecoin",
|
|
23
|
+
"mcp",
|
|
24
|
+
"mcp-server"
|
|
22
25
|
],
|
|
23
|
-
"author": "",
|
|
24
|
-
"license": "
|
|
26
|
+
"author": "AgentQubit",
|
|
27
|
+
"license": "MIT",
|
|
25
28
|
"type": "module",
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=20"
|
|
31
|
+
},
|
|
26
32
|
"dependencies": {
|
|
27
33
|
"@noble/post-quantum": "^0.6.0",
|
|
28
34
|
"ethers": "^6.17.0"
|
|
29
35
|
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@ethereumjs/common": "^10.1.3",
|
|
38
|
+
"@ethereumjs/statemanager": "^10.1.3",
|
|
39
|
+
"@ethereumjs/util": "^10.1.3",
|
|
40
|
+
"@ethereumjs/vm": "^10.1.3",
|
|
41
|
+
"solc": "0.8.24"
|
|
42
|
+
},
|
|
30
43
|
"bin": {
|
|
44
|
+
"aqb-agent": "index.js",
|
|
31
45
|
"aqb-mcp": "mcp/server.mjs"
|
|
32
46
|
},
|
|
33
47
|
"exports": {
|
|
34
|
-
"
|
|
48
|
+
".": "./client/aqb.mjs",
|
|
49
|
+
"./client": "./client/aqb.mjs",
|
|
50
|
+
"./pq": "./pq/pq.mjs",
|
|
51
|
+
"./mcp": "./mcp/server.mjs"
|
|
35
52
|
},
|
|
36
53
|
"files": [
|
|
54
|
+
"index.js",
|
|
37
55
|
"client",
|
|
38
56
|
"pq",
|
|
39
57
|
"mcp",
|
|
40
58
|
"registry",
|
|
41
59
|
"docs",
|
|
42
60
|
"artifacts",
|
|
61
|
+
"contracts",
|
|
62
|
+
"test",
|
|
63
|
+
"compile.mjs",
|
|
43
64
|
"WHITEPAPER.md",
|
|
44
|
-
"README.md"
|
|
65
|
+
"README.md",
|
|
66
|
+
"LICENSE"
|
|
45
67
|
],
|
|
46
68
|
"repository": {
|
|
47
69
|
"type": "git",
|
|
48
70
|
"url": "git+https://github.com/yss787976-ai/agent-coin.git"
|
|
71
|
+
},
|
|
72
|
+
"homepage": "https://agentqubit.pages.dev",
|
|
73
|
+
"bugs": {
|
|
74
|
+
"url": "https://github.com/yss787976-ai/agent-coin/issues"
|
|
75
|
+
},
|
|
76
|
+
"mcpName": "io.github.yss787976-ai/aqb-agent",
|
|
77
|
+
"publishConfig": {
|
|
78
|
+
"access": "public"
|
|
49
79
|
}
|
|
50
|
-
}
|
|
80
|
+
}
|
package/registry/agent-coin.json
CHANGED
|
@@ -26,21 +26,23 @@
|
|
|
26
26
|
},
|
|
27
27
|
"contracts": {
|
|
28
28
|
"token": "0x2C54F202B565086B6d8D2226Edb67AC3E14C39d1",
|
|
29
|
+
"vault": "0x2C54F202B565086B6d8D2226Edb67AC3E14C39d1",
|
|
29
30
|
"registry": "0xAa964f6ea767f0D709b268abBFdd8B6C2Beef3eB",
|
|
30
|
-
"verifier": "0x53d34e4Ffd0bd984f8b92561f9e2B7D3EDdbE60d"
|
|
31
|
+
"verifier": "0x53d34e4Ffd0bd984f8b92561f9e2B7D3EDdbE60d",
|
|
32
|
+
"pool": "0xF61Cb078f87425933741Dd7d02F5779c030dB1A6",
|
|
33
|
+
"sale": "0xeDBD6B860c37C411aeeA513cbc0656e3135f59c1"
|
|
31
34
|
},
|
|
32
35
|
"discovery": {
|
|
33
|
-
"wellKnown": "/.well-known/agent-coin.json",
|
|
34
|
-
"llms": "/llms.txt",
|
|
36
|
+
"wellKnown": "https://agentqubit.pages.dev/.well-known/agent-coin.json",
|
|
37
|
+
"llms": "https://agentqubit.pages.dev/llms.txt",
|
|
35
38
|
"dns": "_aqb.<host> TXT v=aqb1",
|
|
36
|
-
"npm": "aqb-agent",
|
|
39
|
+
"npm": "@aqb-foundation/aqb-agent",
|
|
37
40
|
"hosted": {
|
|
38
|
-
"agentCoin": "https://
|
|
39
|
-
"agentCard": "https://
|
|
40
|
-
"llms": "https://
|
|
41
|
-
"cardHash": "
|
|
42
|
-
"
|
|
43
|
-
"note": "jsDelivr CDN over the public GitHub repo"
|
|
41
|
+
"agentCoin": "https://agentqubit.pages.dev/.well-known/agent-coin.json",
|
|
42
|
+
"agentCard": "https://agentqubit.pages.dev/.well-known/agent-card.json",
|
|
43
|
+
"llms": "https://agentqubit.pages.dev/llms.txt",
|
|
44
|
+
"cardHash": "0x3294204f00383bc8f28a0bc52142ceb0bfe7197dd46f68998403fe9d234c1097",
|
|
45
|
+
"mirror": "https://cdn.jsdelivr.net/gh/yss787976-ai/agent-coin@main/.well-known/agent-coin.json"
|
|
44
46
|
}
|
|
45
47
|
},
|
|
46
48
|
"actions": {
|
|
@@ -63,8 +65,10 @@
|
|
|
63
65
|
"token0": "0x2C54F202B565086B6d8D2226Edb67AC3E14C39d1",
|
|
64
66
|
"token1": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
65
67
|
"liquidity": {
|
|
66
|
-
"aqb": "
|
|
67
|
-
"usdc": "
|
|
68
|
+
"aqb": "279337988620041039026",
|
|
69
|
+
"usdc": "241059777",
|
|
70
|
+
"priceUSDC": "0.8629",
|
|
71
|
+
"asOf": "2026-11-13"
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
],
|
|
@@ -79,8 +83,9 @@
|
|
|
79
83
|
}
|
|
80
84
|
},
|
|
81
85
|
"packages": {
|
|
82
|
-
"npm": "@
|
|
83
|
-
"
|
|
84
|
-
"
|
|
86
|
+
"npm": "@aqb-foundation/aqb-agent",
|
|
87
|
+
"install": "npm i @aqb-foundation/aqb-agent",
|
|
88
|
+
"ghPackages": "@yss787976-ai/aqb-agent",
|
|
89
|
+
"cdn": "https://cdn.jsdelivr.net/gh/yss787976-ai/agent-coin@main"
|
|
85
90
|
}
|
|
86
91
|
}
|
|
Binary file
|
|
Binary file
|