@seedhape/local-wallet 0.2.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.
Files changed (47) hide show
  1. package/dist/agent-identity.d.ts +45 -0
  2. package/dist/agent-identity.d.ts.map +1 -0
  3. package/dist/agent-identity.js +300 -0
  4. package/dist/agent-identity.js.map +1 -0
  5. package/dist/hosted.d.ts +82 -0
  6. package/dist/hosted.d.ts.map +1 -0
  7. package/dist/hosted.js +180 -0
  8. package/dist/hosted.js.map +1 -0
  9. package/dist/identity-backup.d.ts +12 -0
  10. package/dist/identity-backup.d.ts.map +1 -0
  11. package/dist/identity-backup.js +130 -0
  12. package/dist/identity-backup.js.map +1 -0
  13. package/dist/index.d.ts +18 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +429 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/keychain.d.ts +30 -0
  18. package/dist/keychain.d.ts.map +1 -0
  19. package/dist/keychain.js +99 -0
  20. package/dist/keychain.js.map +1 -0
  21. package/dist/seedhape-identity.d.ts +87 -0
  22. package/dist/seedhape-identity.d.ts.map +1 -0
  23. package/dist/seedhape-identity.js +110 -0
  24. package/dist/seedhape-identity.js.map +1 -0
  25. package/dist/server.d.ts +43 -0
  26. package/dist/server.d.ts.map +1 -0
  27. package/dist/server.js +160 -0
  28. package/dist/server.js.map +1 -0
  29. package/dist/web-bot-auth.d.ts +37 -0
  30. package/dist/web-bot-auth.d.ts.map +1 -0
  31. package/dist/web-bot-auth.js +87 -0
  32. package/dist/web-bot-auth.js.map +1 -0
  33. package/package.json +20 -0
  34. package/src/agent-identity.ts +293 -0
  35. package/src/hosted.ts +174 -0
  36. package/src/identity-backup.ts +134 -0
  37. package/src/index.ts +374 -0
  38. package/src/keychain.ts +114 -0
  39. package/src/seedhape-identity.ts +113 -0
  40. package/src/server.ts +187 -0
  41. package/src/web-bot-auth.ts +94 -0
  42. package/test/identity-backup.test.mjs +90 -0
  43. package/test/identity-fork.test.mjs +128 -0
  44. package/test/pay-flow.test.mjs +139 -0
  45. package/test/setup-flow.test.mjs +47 -0
  46. package/test/web-bot-auth.test.mjs +134 -0
  47. package/tsconfig.json +15 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hosted.js","sourceRoot":"","sources":["../src/hosted.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { Hex } from "@seedhape/core";
2
+ export interface LocalIdentityBackupPayload {
3
+ version: 1;
4
+ accountId: string;
5
+ controllerPrivateKey: Hex;
6
+ keyStoreMasterKey: string;
7
+ files: Record<string, string>;
8
+ }
9
+ export declare function encryptIdentityBackup(payload: LocalIdentityBackupPayload, passphrase: string): string;
10
+ export declare function decryptIdentityBackup(encoded: string, passphrase: string): LocalIdentityBackupPayload;
11
+ export declare function validatePayload(payload: LocalIdentityBackupPayload): void;
12
+ //# sourceMappingURL=identity-backup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-backup.d.ts","sourceRoot":"","sources":["../src/identity-backup.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAO1C,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,CAAC,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,GAAG,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAaD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,0BAA0B,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAsBrG;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,0BAA0B,CA0BrG;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,0BAA0B,GAAG,IAAI,CAwCzE"}
@@ -0,0 +1,130 @@
1
+ import { createCipheriv, createDecipheriv, createHash, randomBytes, scryptSync } from "node:crypto";
2
+ import { privateKeyToAccount } from "viem/accounts";
3
+ const FORMAT = "seedhape-agent-identity-backup";
4
+ const AAD = Buffer.from(`${FORMAT}:v1`);
5
+ const MAX_BACKUP_BYTES = 10 * 1024 * 1024;
6
+ const FILE_PATH = /^(state\/[a-f0-9]{64}\.state\.json|keys\/[a-f0-9]{64}\.json|metadata\/[a-f0-9]{64}\.(directory|registration)\.json)$/;
7
+ export function encryptIdentityBackup(payload, passphrase) {
8
+ validatePassphrase(passphrase);
9
+ validatePayload(payload);
10
+ const salt = randomBytes(16);
11
+ const iv = randomBytes(12);
12
+ const key = scryptSync(passphrase, salt, 32, { N: 32_768, r: 8, p: 1, maxmem: 64 * 1024 * 1024 });
13
+ const cipher = createCipheriv("aes-256-gcm", key, iv);
14
+ cipher.setAAD(AAD);
15
+ const ciphertext = Buffer.concat([cipher.update(JSON.stringify(payload), "utf8"), cipher.final()]);
16
+ const result = {
17
+ format: FORMAT,
18
+ version: 1,
19
+ kdf: "scrypt-N32768-r8-p1",
20
+ cipher: "aes-256-gcm",
21
+ salt: salt.toString("base64url"),
22
+ iv: iv.toString("base64url"),
23
+ ciphertext: ciphertext.toString("base64url"),
24
+ tag: cipher.getAuthTag().toString("base64url"),
25
+ };
26
+ const encoded = JSON.stringify(result);
27
+ if (Buffer.byteLength(encoded) > MAX_BACKUP_BYTES)
28
+ throw new Error("Identity backup exceeds the 10 MB limit.");
29
+ return encoded;
30
+ }
31
+ export function decryptIdentityBackup(encoded, passphrase) {
32
+ validatePassphrase(passphrase);
33
+ if (Buffer.byteLength(encoded) > MAX_BACKUP_BYTES)
34
+ throw new Error("Identity backup exceeds the 10 MB limit.");
35
+ let backup;
36
+ try {
37
+ backup = JSON.parse(encoded);
38
+ }
39
+ catch {
40
+ throw new Error("Identity backup is not valid JSON.");
41
+ }
42
+ if (backup.format !== FORMAT || backup.version !== 1 || backup.kdf !== "scrypt-N32768-r8-p1" || backup.cipher !== "aes-256-gcm") {
43
+ throw new Error("Unsupported identity backup format.");
44
+ }
45
+ const salt = decodeBase64Url(backup.salt, 16, "salt");
46
+ const iv = decodeBase64Url(backup.iv, 12, "IV");
47
+ const tag = decodeBase64Url(backup.tag, 16, "authentication tag");
48
+ const ciphertext = decodeBase64Url(backup.ciphertext, undefined, "ciphertext");
49
+ const key = scryptSync(passphrase, salt, 32, { N: 32_768, r: 8, p: 1, maxmem: 64 * 1024 * 1024 });
50
+ try {
51
+ const decipher = createDecipheriv("aes-256-gcm", key, iv);
52
+ decipher.setAAD(AAD);
53
+ decipher.setAuthTag(tag);
54
+ const json = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
55
+ const payload = JSON.parse(json);
56
+ validatePayload(payload);
57
+ return payload;
58
+ }
59
+ catch (error) {
60
+ if (error instanceof Error && error.message.startsWith("Invalid identity backup"))
61
+ throw error;
62
+ throw new Error("Could not decrypt identity backup. Check the passphrase and file integrity.");
63
+ }
64
+ }
65
+ export function validatePayload(payload) {
66
+ if (!payload || payload.version !== 1 || typeof payload.accountId !== "string" || payload.accountId.length < 1 || payload.accountId.length > 256) {
67
+ throw new Error("Invalid identity backup: account metadata is missing.");
68
+ }
69
+ if (!/^0x[0-9a-fA-F]{64}$/.test(payload.controllerPrivateKey))
70
+ throw new Error("Invalid identity backup: controller key is malformed.");
71
+ if (privateKeyToAccount(payload.controllerPrivateKey).address === "0x0000000000000000000000000000000000000000")
72
+ throw new Error("Invalid identity backup: controller key is invalid.");
73
+ const masterKey = decodeBase64Url(payload.keyStoreMasterKey, 32, "key-store key");
74
+ if (masterKey.length !== 32)
75
+ throw new Error("Invalid identity backup: key-store key must be 32 bytes.");
76
+ if (!payload.files || typeof payload.files !== "object" || Array.isArray(payload.files))
77
+ throw new Error("Invalid identity backup: file manifest is missing.");
78
+ const names = Object.keys(payload.files);
79
+ if (names.length > 256 || names.some((name) => !FILE_PATH.test(name)))
80
+ throw new Error("Invalid identity backup: file manifest contains an invalid path.");
81
+ if (names.length < 4)
82
+ throw new Error("Invalid identity backup: file manifest is incomplete.");
83
+ let total = 0;
84
+ for (const [name, contents] of Object.entries(payload.files)) {
85
+ if (typeof contents !== "string")
86
+ throw new Error("Invalid identity backup: file contents are malformed.");
87
+ const bytes = decodeBase64Url(contents, undefined, `file ${name}`);
88
+ total += bytes.length;
89
+ if (total > MAX_BACKUP_BYTES)
90
+ throw new Error("Invalid identity backup: files exceed the size limit.");
91
+ }
92
+ const statePaths = names.filter((name) => name.startsWith("state/"));
93
+ const keyPaths = names.filter((name) => name.startsWith("keys/"));
94
+ const metadataPaths = names.filter((name) => name.startsWith("metadata/"));
95
+ if (statePaths.length !== 1 || !keyPaths.length || !metadataPaths.some((path) => path.endsWith(".directory.json")) || !metadataPaths.some((path) => path.endsWith(".registration.json"))) {
96
+ throw new Error("Invalid identity backup: setup state, signing key, and public metadata are all required.");
97
+ }
98
+ try {
99
+ const stateText = Buffer.from(payload.files[statePaths[0]], "base64url").toString("utf8");
100
+ const state = JSON.parse(stateText);
101
+ const controller = privateKeyToAccount(payload.controllerPrivateKey).address;
102
+ if (typeof state.controller !== "string" || state.controller.toLowerCase() !== controller.toLowerCase() || state.stage !== "ready" || typeof state.keyStoreRef !== "string" || !/^[a-f0-9]{64}$/.test(state.keyStoreRef) || typeof state.identityRef !== "string" || typeof state.keyId !== "string") {
103
+ throw new Error();
104
+ }
105
+ if (!payload.files[`keys/${state.keyStoreRef}.json`])
106
+ throw new Error();
107
+ const identityHash = createHash("sha256").update(state.identityRef).digest("hex");
108
+ const directory = JSON.parse(Buffer.from(payload.files[`metadata/${identityHash}.directory.json`] ?? "", "base64url").toString("utf8"));
109
+ const registration = JSON.parse(Buffer.from(payload.files[`metadata/${identityHash}.registration.json`] ?? "", "base64url").toString("utf8"));
110
+ if (directory.identityRef !== state.identityRef || directory.keyId !== state.keyId || !registration.services?.some((service) => service.name === "Web Bot Auth" && service.keyId === state.keyId))
111
+ throw new Error();
112
+ }
113
+ catch {
114
+ throw new Error("Invalid identity backup: controller does not match the saved setup state.");
115
+ }
116
+ }
117
+ function validatePassphrase(passphrase) {
118
+ if (typeof passphrase !== "string" || passphrase.length < 12 || Buffer.byteLength(passphrase) > 1024) {
119
+ throw new Error("Backup passphrase must be at least 12 characters and no more than 1 KB.");
120
+ }
121
+ }
122
+ function decodeBase64Url(value, expectedLength, label) {
123
+ if (typeof value !== "string" || !/^[A-Za-z0-9_-]*$/.test(value))
124
+ throw new Error(`Invalid identity backup: ${label} encoding is malformed.`);
125
+ const decoded = Buffer.from(value, "base64url");
126
+ if (expectedLength !== undefined && decoded.length !== expectedLength)
127
+ throw new Error(`Invalid identity backup: ${label} must be ${expectedLength} bytes.`);
128
+ return decoded;
129
+ }
130
+ //# sourceMappingURL=identity-backup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-backup.js","sourceRoot":"","sources":["../src/identity-backup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Seedhape local wallet (CLI: `seedhape`).
4
+ *
5
+ * Keeps an agent's payment key in the operating system keychain and signs
6
+ * payments on this computer. Spending rules, budget, pause, and history live in
7
+ * the user's Seedhape account; every payment is checked there first.
8
+ *
9
+ * seedhape setup [--client codex|claude] [--agent <id>] one-step setup
10
+ * seedhape login [--token] sign in to Seedhape
11
+ * seedhape logout | seedhape whoami
12
+ * seedhape wallet:init|wallet:address|wallet:delete <agent-id>
13
+ * seedhape webbotauth:init|status|rotate|revoke [--agent <id>] agent identity key
14
+ * seedhape identity:* ERC-8004 identity tools
15
+ * seedhape run the local MCP server (stdio)
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG"}
package/dist/index.js ADDED
@@ -0,0 +1,429 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Seedhape local wallet (CLI: `seedhape`).
4
+ *
5
+ * Keeps an agent's payment key in the operating system keychain and signs
6
+ * payments on this computer. Spending rules, budget, pause, and history live in
7
+ * the user's Seedhape account; every payment is checked there first.
8
+ *
9
+ * seedhape setup [--client codex|claude] [--agent <id>] one-step setup
10
+ * seedhape login [--token] sign in to Seedhape
11
+ * seedhape logout | seedhape whoami
12
+ * seedhape wallet:init|wallet:address|wallet:delete <agent-id>
13
+ * seedhape webbotauth:init|status|rotate|revoke [--agent <id>] agent identity key
14
+ * seedhape identity:* ERC-8004 identity tools
15
+ * seedhape run the local MCP server (stdio)
16
+ */
17
+ import { homedir, hostname } from "node:os";
18
+ import { join, resolve } from "node:path";
19
+ import { readFile, stat, writeFile } from "node:fs/promises";
20
+ import { emitKeypressEvents } from "node:readline";
21
+ import { createServer as createHttpServer } from "node:http";
22
+ import { spawnSync } from "node:child_process";
23
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
24
+ import { LocalSessionKeySigner, USDC } from "@seedhape/core";
25
+ import { privateKeyToAccount } from "viem/accounts";
26
+ import { createServer } from "./server.js";
27
+ import { callHostedTool, deleteToken, loadToken, loginWithBrowser, saveToken, seedhapeUrl, whoAmI } from "./hosted.js";
28
+ import { deleteWebBotAuthKey, loadWebBotAuthKey, saveWebBotAuthKey } from "./keychain.js";
29
+ import { loadSeedhapeHostedAgent, setupSeedhapeHostedAgent } from "./agent-identity.js";
30
+ import { defaultSignatureAgent, generateWebBotAuthKey, registerWebBotAuthKey, revokeWebBotAuthKey } from "./web-bot-auth.js";
31
+ import { createLocalWallet, deleteLocalWallet, exportIdentityControllerPrivateKey, identityControllerPrivateKey, importIdentityController, localWalletAddress, localWalletPrivateKey } from "./keychain.js";
32
+ import { createSelfCustodiedBackupPayload, createSelfCustodiedMetadataHandler, restoreSelfCustodiedBackupPayload, setupSelfCustodiedAgent } from "./agent-identity.js";
33
+ import { decryptIdentityBackup, encryptIdentityBackup } from "./identity-backup.js";
34
+ const AGENT_ID = /^[A-Za-z0-9._-]{1,128}$/;
35
+ const defaultAgentId = () => (hostname().replace(/[^A-Za-z0-9._-]/g, "-").slice(0, 60) || "local") + "-agent";
36
+ const flag = (args, name) => { const index = args.indexOf(name); return index >= 0 ? args[index + 1] : undefined; };
37
+ const say = (line) => console.error(line);
38
+ function promptSecret(label) {
39
+ const input = process.stdin;
40
+ if (!input.isTTY || typeof input.setRawMode !== "function")
41
+ throw new Error("Identity backup/restore requires an interactive terminal so the passphrase is not echoed.");
42
+ return new Promise((resolvePrompt, rejectPrompt) => {
43
+ emitKeypressEvents(input);
44
+ input.setRawMode(true);
45
+ input.resume();
46
+ let value = "";
47
+ process.stderr.write(`${label} (hidden): `);
48
+ const cleanup = () => {
49
+ input.off("keypress", onKeypress);
50
+ input.setRawMode(false);
51
+ process.stderr.write("\n");
52
+ };
53
+ const onKeypress = (character, key) => {
54
+ if (key.ctrl && key.name === "c") {
55
+ cleanup();
56
+ rejectPrompt(new Error("Cancelled."));
57
+ }
58
+ else if (key.name === "return" || key.name === "enter") {
59
+ cleanup();
60
+ resolvePrompt(value);
61
+ }
62
+ else if (key.name === "backspace") {
63
+ if (value.length) {
64
+ value = value.slice(0, -1);
65
+ process.stderr.write("\b \b");
66
+ }
67
+ }
68
+ else if (character && !key.ctrl && !key.meta && character >= " ") {
69
+ value += character;
70
+ process.stderr.write("*");
71
+ }
72
+ };
73
+ input.on("keypress", onKeypress);
74
+ });
75
+ }
76
+ async function login(args) {
77
+ if (args.includes("--token")) {
78
+ const token = (await promptSecret(`Paste a connection token from ${seedhapeUrl()}/connect-mcp`)).trim();
79
+ if (!token)
80
+ throw new Error("No token entered.");
81
+ await saveToken(token);
82
+ }
83
+ else {
84
+ await loginWithBrowser(say);
85
+ }
86
+ const account = await whoAmI();
87
+ if (!account.ok)
88
+ throw new Error(`The saved sign-in did not work: ${account.detail}`);
89
+ say(`✓ Signed in to ${seedhapeUrl()}. Token saved in your keychain.`);
90
+ }
91
+ /** Create (or reuse) the keychain wallet and register its public address with the user's Seedhape account. */
92
+ async function registerWallet(agentId, chain) {
93
+ const address = await createLocalWallet(agentId);
94
+ const key = await localWalletPrivateKey(agentId);
95
+ if (!key)
96
+ throw new Error("The wallet could not be read back from the keychain.");
97
+ const existing = await callHostedTool("external_agent_wallet_status", {});
98
+ if (existing.toLowerCase().includes(address.toLowerCase()))
99
+ return { address, alreadyRegistered: true };
100
+ const challenge = JSON.parse(await callHostedTool("external_agent_wallet_challenge", { agent_id: agentId, address, chain }));
101
+ if (!challenge.message)
102
+ throw new Error(challenge.error ?? "Seedhape did not return a registration challenge.");
103
+ const signature = await privateKeyToAccount(key).signMessage({ message: challenge.message });
104
+ const registered = JSON.parse(await callHostedTool("register_external_agent_wallet", { agent_id: agentId, address, chain, message: challenge.message, signature }));
105
+ if (!registered.registered)
106
+ throw new Error(registered.error ?? "Seedhape did not register the wallet.");
107
+ return { address, alreadyRegistered: false };
108
+ }
109
+ /** Add both the hosted Seedhape MCP and this local wallet to Codex or Claude Code. */
110
+ function addToClient(client, agentId, network) {
111
+ const mcpUrl = `${seedhapeUrl()}/mcp`;
112
+ const env = [`SEEDHAPE_LOCAL_AGENT=${agentId}`, `SEEDHAPE_NETWORK=${network}`, `SEEDHAPE_URL=${seedhapeUrl()}`];
113
+ const commands = client === "codex"
114
+ ? [["codex", "mcp", "add", "Seedhape", "--url", mcpUrl], ["codex", "mcp", "add", "seedhape-wallet", ...env.flatMap((value) => ["--env", value]), "--", "npx", "-y", "@seedhape/local-wallet"]]
115
+ : [["claude", "mcp", "add", "--transport", "http", "seedhape", mcpUrl], ["claude", "mcp", "add", "seedhape-wallet", ...env.flatMap((value) => ["-e", value]), "--", "npx", "-y", "@seedhape/local-wallet"]];
116
+ for (const command of commands) {
117
+ const run = spawnSync(command[0], command.slice(1), { stdio: "inherit" });
118
+ if (run.error || run.status !== 0)
119
+ say(` Could not run it automatically. Run this yourself:\n ${command.join(" ")}`);
120
+ }
121
+ }
122
+ /** Create and register this agent's Web Bot Auth key, reusing an existing one. */
123
+ async function initWebBotAuth(agentId, signatureAgent) {
124
+ const existing = await loadWebBotAuthKey(agentId);
125
+ if (existing && (!signatureAgent || new URL(signatureAgent).toString() === existing.signatureAgent)) {
126
+ // Re-registering a key this account already owns is a no-op on the server.
127
+ await registerWebBotAuthKey(callHostedTool, agentId, existing);
128
+ return { key: existing, created: false };
129
+ }
130
+ const key = generateWebBotAuthKey(signatureAgent ?? defaultSignatureAgent(seedhapeUrl(), agentId));
131
+ await registerWebBotAuthKey(callHostedTool, agentId, key);
132
+ await saveWebBotAuthKey(agentId, key);
133
+ return { key, created: true };
134
+ }
135
+ /** Replace the key: register the new one, switch to it, then revoke the old one. */
136
+ async function rotateWebBotAuth(agentId) {
137
+ const old = await loadWebBotAuthKey(agentId);
138
+ if (!old)
139
+ throw new Error(`No Web Bot Auth key exists for ${agentId}. Run \`seedhape webbotauth:init\` first.`);
140
+ const next = generateWebBotAuthKey(old.signatureAgent);
141
+ await registerWebBotAuthKey(callHostedTool, agentId, next, true);
142
+ await saveWebBotAuthKey(agentId, next);
143
+ await revokeWebBotAuthKey(callHostedTool, old);
144
+ return next;
145
+ }
146
+ async function setup(args) {
147
+ const agentId = flag(args, "--agent") ?? defaultAgentId();
148
+ if (!AGENT_ID.test(agentId))
149
+ throw new Error("Agent ids may use letters, digits, '.', '_' and '-'.");
150
+ const network = process.env.SEEDHAPE_NETWORK ?? "base";
151
+ const asset = USDC[network];
152
+ if (!asset)
153
+ throw new Error(`Unsupported network "${network}". Use one of: ${Object.keys(USDC).join(", ")}`);
154
+ say("1/4 Signing in to Seedhape…");
155
+ if ((await whoAmI()).ok)
156
+ say(" Already signed in.");
157
+ else
158
+ await login([]);
159
+ say(`2/4 Creating the wallet "${agentId}" in your keychain and registering its address…`);
160
+ const wallet = await registerWallet(agentId, asset.network);
161
+ say(` ${wallet.alreadyRegistered ? "Already registered" : "Registered"}: ${wallet.address} (the private key stays on this computer)`);
162
+ say("3/4 Creating this agent's identity so merchants can tell it's you…");
163
+ const dataDir = process.env.SEEDHAPE_DATA_DIR ?? join(homedir(), ".seedhape");
164
+ try {
165
+ // Preferred: an on-chain ERC-8004 identity that any merchant can verify. Seedhape hosts its metadata and covers gas.
166
+ const agent = await setupSeedhapeHostedAgent(dataDir, { name: agentId, description: "A self-custody Seedhape agent. Its keys stay on the owner's computer." }, say);
167
+ say(` On-chain identity ready: ${agent.identityRef}`);
168
+ }
169
+ catch (error) {
170
+ say(` On-chain identity not available (${error instanceof Error ? error.message : String(error)}).`);
171
+ try {
172
+ // Fallback: a Web Bot Auth key registered with Seedhape; works with Seedhape-hosted merchants.
173
+ const identity = await initWebBotAuth(agentId, flag(args, "--signature-agent"));
174
+ say(` Using a Seedhape-registered key instead (${identity.created ? "created" : "already set up"}). Run setup again later to get the on-chain identity.`);
175
+ }
176
+ catch (fallbackError) {
177
+ // Payments don't depend on it, so setup carries on; the user can retry later.
178
+ say(` Skipped: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}\n Payments still work. Run setup again to retry.`);
179
+ }
180
+ }
181
+ const client = flag(args, "--client");
182
+ if (client === "codex" || client === "claude") {
183
+ say(`4/4 Adding Seedhape to ${client === "codex" ? "Codex" : "Claude Code"}…`);
184
+ addToClient(client, agentId, network);
185
+ }
186
+ else {
187
+ say("4/4 Skipped adding to an agent client (use --client codex or --client claude).");
188
+ }
189
+ say(`\nNext:\n • Set its spending limit: ${seedhapeUrl()}/limits/advanced?wallet=${encodeURIComponent(agentId)}\n • Send USDC on ${network} to ${wallet.address}\n • Then ask your agent to buy something.`);
190
+ }
191
+ async function finishFirstUseSetup(agentId, network, dataDir, log) {
192
+ const account = await whoAmI();
193
+ if (!account.ok) {
194
+ log("Opening your browser to connect your Seedhape account…");
195
+ await loginWithBrowser(log);
196
+ const signedIn = await whoAmI();
197
+ if (!signedIn.ok)
198
+ throw new Error(`Sign-in did not finish: ${signedIn.detail}`);
199
+ }
200
+ log("Creating your local wallet and connecting it to Seedhape…");
201
+ const wallet = await registerWallet(agentId, network);
202
+ let identity = await loadSeedhapeHostedAgent(dataDir, (error) => log(`Identity refresh: ${error instanceof Error ? error.message : String(error)}`)).catch(() => undefined);
203
+ let webBotAuth = await loadWebBotAuthKey(agentId).catch(() => null);
204
+ if (!identity && !webBotAuth) {
205
+ log("Setting up your agent identity…");
206
+ try {
207
+ const ready = await setupSeedhapeHostedAgent(dataDir, { name: agentId, description: "A self-custody Seedhape agent. Its keys stay on this computer." }, log);
208
+ identity = await loadSeedhapeHostedAgent(dataDir, (error) => log(`Identity refresh: ${error instanceof Error ? error.message : String(error)}`));
209
+ if (!identity)
210
+ log(`Identity saved (${ready.identityRef}); it will be available after restarting the wallet.`);
211
+ }
212
+ catch (error) {
213
+ log(`On-chain identity is unavailable (${error instanceof Error ? error.message : String(error)}). Setting up a simpler identity instead…`);
214
+ try {
215
+ webBotAuth = (await initWebBotAuth(agentId)).key;
216
+ }
217
+ catch (fallbackError) {
218
+ log(`Identity setup skipped: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}. Payments can still work.`);
219
+ }
220
+ }
221
+ }
222
+ const key = await localWalletPrivateKey(agentId);
223
+ if (!key)
224
+ throw new Error("The local wallet could not be loaded from this computer's keychain.");
225
+ return { address: privateKeyToAccount(key).address, signer: new LocalSessionKeySigner(key), identity: identity ?? null, webBotAuth: webBotAuth ?? null };
226
+ }
227
+ async function main() {
228
+ const args = process.argv.slice(2);
229
+ const [command, commandAgent, commandOption] = args;
230
+ const dataDir = process.env.SEEDHAPE_DATA_DIR ?? join(homedir(), ".seedhape");
231
+ if (command === "login")
232
+ return login(args.slice(1));
233
+ if (command === "logout") {
234
+ say((await deleteToken()) ? "Signed out." : "Not signed in.");
235
+ return;
236
+ }
237
+ if (command === "whoami") {
238
+ const account = await whoAmI();
239
+ say(`${seedhapeUrl()}: ${account.detail}`);
240
+ return;
241
+ }
242
+ if (command === "setup")
243
+ return setup(args.slice(1));
244
+ if (command?.startsWith("webbotauth:")) {
245
+ const agentId = flag(args, "--agent") ?? process.env.SEEDHAPE_LOCAL_AGENT ?? defaultAgentId();
246
+ if (command === "webbotauth:init") {
247
+ const { key, created } = await initWebBotAuth(agentId, flag(args, "--signature-agent"));
248
+ say(`${created ? "Created and registered" : "Already set up"}: ${key.signatureAgent} (key ${key.keyId})`);
249
+ return;
250
+ }
251
+ if (command === "webbotauth:rotate") {
252
+ const key = await rotateWebBotAuth(agentId);
253
+ say(`Rotated. New key ${key.keyId}; the old key is revoked.`);
254
+ return;
255
+ }
256
+ if (command === "webbotauth:revoke") {
257
+ const key = await loadWebBotAuthKey(agentId);
258
+ if (!key) {
259
+ say("No Web Bot Auth key to revoke.");
260
+ return;
261
+ }
262
+ await revokeWebBotAuthKey(callHostedTool, key);
263
+ await deleteWebBotAuthKey(agentId);
264
+ say("Revoked and removed from your keychain.");
265
+ return;
266
+ }
267
+ if (command === "webbotauth:status") {
268
+ const key = await loadWebBotAuthKey(agentId);
269
+ say(key ? `Signing as ${key.signatureAgent}\nKey id: ${key.keyId}\nCreated: ${new Date(key.createdAt * 1000).toISOString()}` : "Not set up. Run `seedhape webbotauth:init`.");
270
+ return;
271
+ }
272
+ throw new Error(`Unknown command "${command}". Use webbotauth:init, webbotauth:status, webbotauth:rotate, or webbotauth:revoke.`);
273
+ }
274
+ if (command === "identity:setup") {
275
+ const agent = await setupSelfCustodiedAgent(dataDir);
276
+ console.log(`Self-custodied ERC-8004 identity ready: ${agent.identityRef}`);
277
+ console.log(`Controller: ${agent.controller}`);
278
+ console.log(`Web Bot Auth directory: ${agent.directoryUri}`);
279
+ console.log(`Network: ${agent.chainId === 8453 ? "Base" : "Base Sepolia"}`);
280
+ console.log("Create a complete encrypted backup with `seedhape identity:backup <file>` and keep its passphrase separate.");
281
+ return;
282
+ }
283
+ if (command === "identity:controller-import") {
284
+ const privateKey = await promptSecret("Existing ERC-8004 controller private key (0x-prefixed)");
285
+ const address = await importIdentityController(process.env.SEEDHAPE_AGENT_IDENTITY_CONTROLLER_ID ?? "local-primary", privateKey);
286
+ console.log(`Imported controller ${address} into the local OS keychain.`);
287
+ console.log("Next run `seedhape identity:import <identity-reference>` to verify ownership and finish local setup.");
288
+ return;
289
+ }
290
+ if (command === "identity:import") {
291
+ if (!commandAgent || commandOption !== "--replace-registration")
292
+ throw new Error("Import replaces the existing onchain metadata URI. Save the existing metadata, then run: seedhape identity:import eip155:<8453|84532>:<registry-address>:<agent-id> --replace-registration");
293
+ const controller = await identityControllerPrivateKey(process.env.SEEDHAPE_AGENT_IDENTITY_CONTROLLER_ID ?? "local-primary");
294
+ if (!controller)
295
+ throw new Error("Import the current ERC-8004 controller first with `seedhape identity:controller-import`.");
296
+ const agent = await setupSelfCustodiedAgent(dataDir, commandAgent, true);
297
+ console.log(`Existing self-custodied ERC-8004 identity ready: ${agent.identityRef}`);
298
+ console.log(`Controller: ${agent.controller}`);
299
+ console.log(`Web Bot Auth directory: ${agent.directoryUri}`);
300
+ console.log(`Network: ${agent.chainId === 8453 ? "Base" : "Base Sepolia"}`);
301
+ return;
302
+ }
303
+ if (command === "identity:export") {
304
+ if (commandAgent !== "--confirm")
305
+ throw new Error("This prints your identity controller private key. Re-run as `seedhape identity:export --confirm` only in a trusted local terminal.");
306
+ const key = await exportIdentityControllerPrivateKey(process.env.SEEDHAPE_AGENT_IDENTITY_CONTROLLER_ID ?? "local-primary");
307
+ if (!key)
308
+ throw new Error("No local identity controller exists. Run `seedhape identity:setup` first.");
309
+ console.error("WARNING: anyone with this key controls the onchain agent identity. Store the next line offline; never paste it into chat or commit it.");
310
+ console.log(key);
311
+ return;
312
+ }
313
+ if (command === "identity:backup") {
314
+ if (!commandAgent)
315
+ throw new Error("Usage: seedhape identity:backup <encrypted-backup-file>");
316
+ const first = await promptSecret("Choose a backup passphrase (12+ characters)");
317
+ const second = await promptSecret("Repeat backup passphrase");
318
+ if (first !== second)
319
+ throw new Error("Passphrases do not match.");
320
+ const payload = await createSelfCustodiedBackupPayload(dataDir);
321
+ const encrypted = encryptIdentityBackup(payload, first);
322
+ const destination = resolve(commandAgent);
323
+ await writeFile(destination, `${encrypted}\n`, { flag: "wx", mode: 0o600 });
324
+ console.log(`Encrypted identity backup created at ${destination}. Keep the passphrase separate from the file.`);
325
+ return;
326
+ }
327
+ if (command === "identity:restore") {
328
+ if (!commandAgent)
329
+ throw new Error("Usage: seedhape identity:restore <encrypted-backup-file>");
330
+ const source = resolve(commandAgent);
331
+ const info = await stat(source);
332
+ if (!info.isFile() || info.size > 10 * 1024 * 1024)
333
+ throw new Error("Identity backup must be a regular file no larger than 10 MB.");
334
+ const passphrase = await promptSecret("Backup passphrase");
335
+ const payload = decryptIdentityBackup(await readFile(source, "utf8"), passphrase);
336
+ const restored = await restoreSelfCustodiedBackupPayload(dataDir, payload);
337
+ console.log(`Restored identity ${restored.identityRef} controlled by ${restored.controller}.`);
338
+ console.log(`Identity keychain slot: ${payload.accountId}. Restore with this SEEDHAPE_AGENT_IDENTITY_CONTROLLER_ID value or leave it unset.`);
339
+ console.log("Verify SEEDHAPE_AGENT_TRUST_* and SEEDHAPE_AGENT_METADATA_ORIGIN match this identity before starting the MCP server.");
340
+ return;
341
+ }
342
+ if (command === "identity:metadata-server") {
343
+ const origin = process.env.SEEDHAPE_AGENT_METADATA_ORIGIN;
344
+ if (!origin)
345
+ throw new Error("Set SEEDHAPE_AGENT_METADATA_ORIGIN to the public HTTPS origin routed to this metadata server.");
346
+ const publicOrigin = new URL(origin);
347
+ if (publicOrigin.protocol !== "https:" || publicOrigin.pathname !== "/" || publicOrigin.search || publicOrigin.hash)
348
+ throw new Error("SEEDHAPE_AGENT_METADATA_ORIGIN must be an HTTPS origin without a path.");
349
+ const handler = await createSelfCustodiedMetadataHandler(dataDir);
350
+ const host = process.env.SEEDHAPE_AGENT_METADATA_BIND ?? "127.0.0.1";
351
+ const port = Number(process.env.SEEDHAPE_AGENT_METADATA_PORT ?? "8787");
352
+ if (!Number.isInteger(port) || port < 1 || port > 65535)
353
+ throw new Error("SEEDHAPE_AGENT_METADATA_PORT must be a valid TCP port.");
354
+ const server = createHttpServer(async (incoming, outgoing) => {
355
+ try {
356
+ const url = new URL(incoming.url ?? "/", origin);
357
+ if (url.origin !== publicOrigin.origin) {
358
+ outgoing.statusCode = 400;
359
+ outgoing.end("Invalid metadata origin.");
360
+ return;
361
+ }
362
+ const response = await handler(new Request(url, { method: incoming.method ?? "GET" }));
363
+ outgoing.statusCode = response.status;
364
+ response.headers.forEach((value, name) => outgoing.setHeader(name, value));
365
+ outgoing.end(incoming.method === "HEAD" ? undefined : Buffer.from(await response.arrayBuffer()));
366
+ }
367
+ catch (error) {
368
+ outgoing.statusCode = 500;
369
+ outgoing.end(error instanceof Error ? error.message : "Metadata request failed.");
370
+ }
371
+ });
372
+ server.listen(port, host, () => console.error(`Self-custodied agent metadata handler listening on ${host}:${port}; proxy ${origin}/.well-known/seedhape-agents/* here.`));
373
+ return;
374
+ }
375
+ if (command === "wallet:init") {
376
+ if (!commandAgent)
377
+ throw new Error("Usage: seedhape wallet:init <agent-id>");
378
+ console.log(await createLocalWallet(commandAgent));
379
+ return;
380
+ }
381
+ if (command === "wallet:address") {
382
+ if (!commandAgent)
383
+ throw new Error("Usage: seedhape wallet:address <agent-id>");
384
+ const address = await localWalletAddress(commandAgent);
385
+ if (!address)
386
+ throw new Error(`No local wallet exists for ${commandAgent}.`);
387
+ console.log(address);
388
+ return;
389
+ }
390
+ if (command === "wallet:delete") {
391
+ if (!commandAgent)
392
+ throw new Error("Usage: seedhape wallet:delete <agent-id>");
393
+ console.log((await deleteLocalWallet(commandAgent)) ? "Deleted." : "No wallet found.");
394
+ return;
395
+ }
396
+ if (command && command !== "serve")
397
+ throw new Error(`Unknown command "${command}". Run \`seedhape setup\` to get started.`);
398
+ // Default: run the local MCP server over stdio for Codex, Claude Code, or another MCP client.
399
+ const network = process.env.SEEDHAPE_NETWORK ?? "base";
400
+ const asset = USDC[network];
401
+ if (!asset)
402
+ throw new Error(`Unsupported network "${network}". Use one of: ${Object.keys(USDC).join(", ")}`);
403
+ const agentId = process.env.SEEDHAPE_LOCAL_AGENT ?? process.env.SEEDHAPE_LOCAL_KEYTAR_AGENT ?? defaultAgentId();
404
+ const key = await localWalletPrivateKey(agentId);
405
+ const hasSavedAccount = Boolean(await loadToken());
406
+ const identity = await loadSeedhapeHostedAgent(process.env.SEEDHAPE_DATA_DIR ?? join(homedir(), ".seedhape"), (error) => say(`seedhape: could not refresh the agent's key directory: ${error instanceof Error ? error.message : String(error)}`)).catch((error) => { say(`seedhape: on-chain identity unavailable (${error instanceof Error ? error.message : String(error)}); continuing without it.`); return undefined; });
407
+ const webBotAuth = await loadWebBotAuthKey(agentId).catch(() => null);
408
+ const server = createServer({
409
+ agentId,
410
+ address: key ? privateKeyToAccount(key).address : null,
411
+ signer: key ? new LocalSessionKeySigner(key) : null,
412
+ webBotAuth,
413
+ identity: identity ?? null,
414
+ asset,
415
+ absoluteMaxPerPayment: BigInt(process.env.SEEDHAPE_ABSOLUTE_MAX ?? "1000000"),
416
+ setupNeeded: !hasSavedAccount || !key || (!identity && !webBotAuth),
417
+ finishSetup: () => finishFirstUseSetup(agentId, asset.network, dataDir, say),
418
+ onSetupError: (error) => say(`seedhape: browser setup did not finish (${error instanceof Error ? error.message : String(error)}). Try any wallet tool again to retry.`),
419
+ });
420
+ await server.connect(new StdioServerTransport());
421
+ const shutdown = () => process.exit(0);
422
+ process.on("SIGINT", shutdown);
423
+ process.on("SIGTERM", shutdown);
424
+ }
425
+ main().catch((error) => {
426
+ console.error(`seedhape: ${error instanceof Error ? error.message : String(error)}`);
427
+ process.exit(1);
428
+ });
429
+ //# sourceMappingURL=index.js.map