@chest-gate/cli 0.2.0 → 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.
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const loginCommand: Command;
3
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2BpC,eAAO,MAAM,YAAY,SAwGrB,CAAC"}
@@ -0,0 +1,228 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import { createServer } from "node:http";
4
+ import { createHash, randomBytes } from "node:crypto";
5
+ import { hostname } from "node:os";
6
+ import { createInterface } from "node:readline/promises";
7
+ import { stdin, stdout } from "node:process";
8
+ import open from "open";
9
+ import { loadCredentials, saveCredentials, getDefaultGateUrl, getDefaultWebUrl, } from "../credentials.js";
10
+ const LOGIN_TIMEOUT_MS = 5 * 60 * 1000;
11
+ export const loginCommand = new Command("login")
12
+ .description("Sign in to Chest. Opens a browser, returns a CLI token to this device.")
13
+ .option("--web-url <url>", "Override chest.sh URL", getDefaultWebUrl())
14
+ .option("--gate-url <url>", "Override gate.chest.sh URL", getDefaultGateUrl())
15
+ .option("--port <port>", "Loopback port (default: random)")
16
+ .option("-f, --force", "Skip the 'already logged in' prompt")
17
+ .option("--no-browser", "Print the URL instead of opening a browser")
18
+ .action(async (opts) => {
19
+ console.log(chalk.bold("\n ⚡ Chest Login\n"));
20
+ const existing = await loadCredentials();
21
+ if (existing && existing.source === "file" && !opts.force) {
22
+ if (!stdin.isTTY) {
23
+ console.error(chalk.red(" Already logged in. Pass --force to mint a new token, or set CHEST_TOKEN env var.\n"));
24
+ process.exit(1);
25
+ }
26
+ console.log(chalk.gray(` Already logged in as `) +
27
+ chalk.cyan(existing.ownerWallet || existing.label) +
28
+ chalk.gray(`.`));
29
+ console.log(chalk.gray(" Re-running mints a new token; the old one stays valid until revoked."));
30
+ const rl = createInterface({ input: stdin, output: stdout });
31
+ const answer = await rl.question(chalk.gray(" Continue? (y/N) "));
32
+ rl.close();
33
+ if (answer.trim().toLowerCase() !== "y") {
34
+ console.log(chalk.gray("\n Cancelled.\n"));
35
+ return;
36
+ }
37
+ console.log();
38
+ }
39
+ if (!stdin.isTTY && !process.env.CI_ALLOW_NON_TTY_LOGIN) {
40
+ console.error(chalk.red(" Non-interactive shell detected. Set CHEST_TOKEN instead of running `login`.\n"));
41
+ process.exit(1);
42
+ }
43
+ const webUrl = (opts.webUrl || getDefaultWebUrl()).replace(/\/$/, "");
44
+ const gateUrl = (opts.gateUrl || getDefaultGateUrl()).replace(/\/$/, "");
45
+ const verifier = base64url(randomBytes(32));
46
+ const challenge = base64url(createHash("sha256").update(verifier).digest());
47
+ const state = base64url(randomBytes(24));
48
+ const host = hostname() || "unknown";
49
+ const portArg = opts.port ? parseInt(opts.port, 10) : 0;
50
+ if (opts.port && (!Number.isFinite(portArg) || portArg < 0 || portArg > 65535)) {
51
+ console.error(chalk.red(` Invalid --port: ${opts.port}`));
52
+ process.exit(1);
53
+ }
54
+ const result = await runLoopbackFlow({
55
+ webUrl,
56
+ state,
57
+ challenge,
58
+ hostname: host,
59
+ desiredPort: portArg,
60
+ openBrowser: opts.noBrowser !== true,
61
+ });
62
+ if (result.kind === "error") {
63
+ console.error(chalk.red(` ✗ ${result.message}\n`));
64
+ process.exit(1);
65
+ }
66
+ process.stdout.write(chalk.gray(" Exchanging code… "));
67
+ const exchanged = await exchangeCode({
68
+ gateUrl,
69
+ code: result.code,
70
+ verifier,
71
+ });
72
+ if (!exchanged.ok) {
73
+ console.log(chalk.red("failed"));
74
+ console.error(chalk.red(`\n ✗ ${exchanged.error}\n`));
75
+ process.exit(1);
76
+ }
77
+ console.log(chalk.green("done"));
78
+ const creds = {
79
+ version: 1,
80
+ token: exchanged.token,
81
+ ownerWallet: exchanged.ownerWallet,
82
+ tokenId: exchanged.tokenId,
83
+ label: exchanged.label,
84
+ gateUrl,
85
+ createdAt: new Date().toISOString(),
86
+ };
87
+ const path = await saveCredentials(creds);
88
+ console.log();
89
+ console.log(chalk.green(" ✓ Logged in as ") + chalk.cyan(exchanged.ownerWallet));
90
+ console.log(chalk.gray(` Token label: `) + chalk.white(exchanged.label));
91
+ console.log(chalk.gray(` Saved to: `) + chalk.white(path));
92
+ console.log();
93
+ console.log(chalk.gray(" Manage tokens at ") + chalk.cyan(`${webUrl}/dashboard/agent-wallet`));
94
+ console.log();
95
+ });
96
+ function runLoopbackFlow(args) {
97
+ return new Promise((resolve) => {
98
+ let settled = false;
99
+ const finish = (r) => {
100
+ if (settled)
101
+ return;
102
+ settled = true;
103
+ try {
104
+ server.close();
105
+ }
106
+ catch { }
107
+ clearTimeout(timer);
108
+ resolve(r);
109
+ };
110
+ const server = createServer((req, res) => {
111
+ const url = new URL(req.url || "/", `http://127.0.0.1`);
112
+ if (url.pathname !== "/callback") {
113
+ res.writeHead(404, { "content-type": "text/plain" });
114
+ res.end("not found");
115
+ return;
116
+ }
117
+ const recvState = url.searchParams.get("state");
118
+ const code = url.searchParams.get("code");
119
+ const error = url.searchParams.get("error");
120
+ if (error) {
121
+ res.writeHead(400, { "content-type": "text/html; charset=utf-8" });
122
+ res.end(htmlPage("Login failed", error, false));
123
+ finish({ kind: "error", message: `Browser returned error: ${error}` });
124
+ return;
125
+ }
126
+ if (!recvState || recvState !== args.state) {
127
+ res.writeHead(400, { "content-type": "text/html; charset=utf-8" });
128
+ res.end(htmlPage("Invalid state", "State mismatch. Try again.", false));
129
+ finish({ kind: "error", message: "State mismatch on callback (possible CSRF)." });
130
+ return;
131
+ }
132
+ if (!code) {
133
+ res.writeHead(400, { "content-type": "text/html; charset=utf-8" });
134
+ res.end(htmlPage("Missing code", "No authorization code on the callback.", false));
135
+ finish({ kind: "error", message: "Callback missing code parameter." });
136
+ return;
137
+ }
138
+ res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
139
+ res.end(htmlPage("You're signed in", "You can close this tab and return to the terminal.", true));
140
+ finish({ kind: "ok", code });
141
+ });
142
+ server.on("error", (err) => {
143
+ finish({ kind: "error", message: `Loopback server failed: ${err.message}` });
144
+ });
145
+ server.listen(args.desiredPort, "127.0.0.1", () => {
146
+ const addr = server.address();
147
+ if (!addr || typeof addr === "string") {
148
+ finish({ kind: "error", message: "Could not bind loopback server." });
149
+ return;
150
+ }
151
+ const port = addr.port;
152
+ const params = new URLSearchParams({
153
+ state: args.state,
154
+ challenge: args.challenge,
155
+ port: String(port),
156
+ hostname: args.hostname,
157
+ });
158
+ const loginUrl = `${args.webUrl}/cli/login?${params.toString()}`;
159
+ console.log(chalk.gray(" Opening browser to authorize this device…"));
160
+ console.log(chalk.gray(" If it doesn't open, visit:"));
161
+ console.log(chalk.cyan(` ${loginUrl}`));
162
+ console.log();
163
+ console.log(chalk.gray(` Listening on http://127.0.0.1:${port}/callback`));
164
+ console.log();
165
+ if (args.openBrowser) {
166
+ open(loginUrl).catch(() => {
167
+ // Non-fatal; the user can still copy the URL.
168
+ });
169
+ }
170
+ });
171
+ const timer = setTimeout(() => {
172
+ finish({ kind: "error", message: "Timed out waiting for browser sign-in (5 min)." });
173
+ }, LOGIN_TIMEOUT_MS);
174
+ });
175
+ }
176
+ async function exchangeCode(args) {
177
+ let res;
178
+ try {
179
+ res = await fetch(`${args.gateUrl}/v1/cli/exchange`, {
180
+ method: "POST",
181
+ headers: { "content-type": "application/json" },
182
+ body: JSON.stringify({ code: args.code, verifier: args.verifier }),
183
+ });
184
+ }
185
+ catch (err) {
186
+ return { ok: false, error: `Network error: ${err.message}` };
187
+ }
188
+ if (!res.ok) {
189
+ let msg = `${res.status} ${res.statusText}`;
190
+ try {
191
+ const body = (await res.json());
192
+ msg = body.error || body.message || msg;
193
+ }
194
+ catch { }
195
+ return { ok: false, error: msg };
196
+ }
197
+ const body = (await res.json());
198
+ if (!body.token || !body.ownerWallet || !body.tokenId) {
199
+ return { ok: false, error: "Malformed response from gate." };
200
+ }
201
+ return {
202
+ ok: true,
203
+ token: body.token,
204
+ ownerWallet: body.ownerWallet,
205
+ tokenId: body.tokenId,
206
+ label: body.label || "CLI",
207
+ };
208
+ }
209
+ function base64url(buf) {
210
+ return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
211
+ }
212
+ function htmlPage(title, body, ok) {
213
+ const accent = ok ? "#10b981" : "#ef4444";
214
+ return `<!doctype html>
215
+ <html><head><meta charset="utf-8"><title>${title}</title>
216
+ <style>
217
+ body { margin:0; min-height:100vh; display:grid; place-items:center;
218
+ font:15px/1.5 -apple-system,BlinkMacSystemFont,sans-serif; background:#0b0b0d; color:#e5e5e5; }
219
+ .card { background:#141418; border:1px solid #26262c; border-radius:12px;
220
+ padding:32px 36px; max-width:420px; }
221
+ .dot { display:inline-block; width:10px; height:10px; border-radius:50%;
222
+ background:${accent}; margin-right:10px; vertical-align:middle; }
223
+ h1 { margin:0 0 8px; font-size:18px; font-weight:600; }
224
+ p { margin:0; color:#a3a3aa; }
225
+ </style></head>
226
+ <body><div class="card"><h1><span class="dot"></span>${title}</h1><p>${body}</p></div></body></html>`;
227
+ }
228
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const logoutCommand: Command;
3
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,aAAa,SA+CtB,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import { loadCredentials, deleteCredentials, getCredentialsPath } from "../credentials.js";
4
+ export const logoutCommand = new Command("logout")
5
+ .description("Sign out: revoke the CLI token and remove local credentials.")
6
+ .option("--keep-remote", "Delete local credentials but don't revoke the token on the server")
7
+ .action(async (opts) => {
8
+ console.log(chalk.bold("\n ⚡ Chest Logout\n"));
9
+ const creds = await loadCredentials();
10
+ if (!creds) {
11
+ console.log(chalk.gray(" Not logged in.\n"));
12
+ return;
13
+ }
14
+ if (creds.source === "env") {
15
+ console.log(chalk.yellow(" CHEST_TOKEN env var is set; logout doesn't unset env vars.\n"));
16
+ return;
17
+ }
18
+ if (!opts.keepRemote && creds.tokenId && creds.gateUrl) {
19
+ process.stdout.write(chalk.gray(" Revoking token on server… "));
20
+ try {
21
+ const res = await fetch(`${creds.gateUrl}/v1/cli/revoke`, {
22
+ method: "POST",
23
+ headers: {
24
+ "content-type": "application/json",
25
+ authorization: `Bearer ${creds.token}`,
26
+ },
27
+ body: JSON.stringify({ tokenId: creds.tokenId }),
28
+ });
29
+ if (res.ok) {
30
+ console.log(chalk.green("done"));
31
+ }
32
+ else {
33
+ console.log(chalk.yellow(`skipped (${res.status})`));
34
+ }
35
+ }
36
+ catch (err) {
37
+ console.log(chalk.yellow(`skipped (${err.message})`));
38
+ }
39
+ }
40
+ const removed = await deleteCredentials();
41
+ if (removed) {
42
+ console.log(chalk.green(` ✓ Removed ${getCredentialsPath()}`));
43
+ }
44
+ else {
45
+ console.log(chalk.gray(` No credentials file at ${getCredentialsPath()}`));
46
+ }
47
+ console.log();
48
+ });
49
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE3F,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,eAAe,EAAE,mEAAmE,CAAC;KAC5F,MAAM,CAAC,KAAK,EAAE,IAA8B,EAAE,EAAE;IAC/C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAEhD,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IACtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CAAC,gEAAgE,CAAC,CAC/E,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,gBAAgB,EAAE;gBACxD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE;iBACvC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;aACjD,CAAC,CAAC;YACH,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,YAAa,GAAa,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,iBAAiB,EAAE,CAAC;IAC1C,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,kBAAkB,EAAE,EAAE,CAAC,CAAC,CAAC;IAClE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,kBAAkB,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const whoamiCommand: Command;
3
+ //# sourceMappingURL=whoami.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,aAAa,SAyCtB,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import { loadCredentials } from "../credentials.js";
4
+ export const whoamiCommand = new Command("whoami")
5
+ .description("Show the wallet and CLI token currently signed in on this device.")
6
+ .action(async () => {
7
+ const creds = await loadCredentials();
8
+ if (!creds) {
9
+ console.log(chalk.gray("\n Not logged in. Run ") + chalk.white("chest-gate login") + chalk.gray(".\n"));
10
+ process.exit(1);
11
+ }
12
+ if (creds.source === "env") {
13
+ console.log();
14
+ console.log(chalk.gray(" Source: ") + chalk.white("CHEST_TOKEN env var"));
15
+ console.log(chalk.gray(" Gate: ") + chalk.white(creds.gateUrl));
16
+ console.log();
17
+ // Best-effort resolve via /v1/cli/session.
18
+ const session = await fetchSession(creds.gateUrl, creds.token);
19
+ if (session) {
20
+ console.log(chalk.green(" ✓ ") + chalk.cyan(session.ownerWallet));
21
+ console.log(chalk.gray(" Token label: ") + chalk.white(session.label));
22
+ if (session.lastUsedAt) {
23
+ console.log(chalk.gray(" Last used: ") + chalk.white(session.lastUsedAt));
24
+ }
25
+ }
26
+ else {
27
+ console.log(chalk.yellow(" Could not verify token with the gate."));
28
+ }
29
+ console.log();
30
+ return;
31
+ }
32
+ console.log();
33
+ console.log(chalk.green(" ✓ ") + chalk.cyan(creds.ownerWallet));
34
+ console.log(chalk.gray(" Token label: ") + chalk.white(creds.label));
35
+ console.log(chalk.gray(" Token id: ") + chalk.white(creds.tokenId));
36
+ console.log(chalk.gray(" Gate: ") + chalk.white(creds.gateUrl));
37
+ console.log(chalk.gray(" Logged in: ") + chalk.white(creds.createdAt));
38
+ const session = await fetchSession(creds.gateUrl, creds.token);
39
+ if (session?.lastUsedAt) {
40
+ console.log(chalk.gray(" Last used: ") + chalk.white(session.lastUsedAt));
41
+ }
42
+ console.log();
43
+ });
44
+ async function fetchSession(gateUrl, token) {
45
+ try {
46
+ const res = await fetch(`${gateUrl}/v1/cli/session`, {
47
+ headers: { authorization: `Bearer ${token}` },
48
+ });
49
+ if (!res.ok)
50
+ return null;
51
+ return (await res.json());
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ //# sourceMappingURL=whoami.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface Credentials {
2
+ version: 1;
3
+ token: string;
4
+ ownerWallet: string;
5
+ tokenId: string;
6
+ label: string;
7
+ gateUrl: string;
8
+ createdAt: string;
9
+ }
10
+ export interface ResolvedCredentials extends Credentials {
11
+ source: "env" | "file";
12
+ }
13
+ /**
14
+ * Load credentials, preferring CHEST_TOKEN env over the on-disk file.
15
+ * Returns null if neither is present.
16
+ */
17
+ export declare function loadCredentials(): Promise<ResolvedCredentials | null>;
18
+ export declare function requireCredentials(): Promise<ResolvedCredentials>;
19
+ export declare function saveCredentials(creds: Credentials): Promise<string>;
20
+ export declare function deleteCredentials(): Promise<boolean>;
21
+ export declare function getCredentialsPath(): string;
22
+ export declare function getDefaultGateUrl(): string;
23
+ export declare function getDefaultWebUrl(): string;
24
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAoB,SAAQ,WAAW;IACtD,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAoB3E;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAMvE;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAMzE;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAI1D;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC"}
@@ -0,0 +1,61 @@
1
+ import { readFile, writeFile, mkdir, chmod, unlink } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ const CHEST_DIR = join(homedir(), ".chest");
6
+ const CREDENTIALS_PATH = join(CHEST_DIR, "credentials.json");
7
+ const DEFAULT_GATE_URL = "https://gate.chest.sh";
8
+ /**
9
+ * Load credentials, preferring CHEST_TOKEN env over the on-disk file.
10
+ * Returns null if neither is present.
11
+ */
12
+ export async function loadCredentials() {
13
+ const envToken = process.env.CHEST_TOKEN?.trim();
14
+ if (envToken) {
15
+ return {
16
+ version: 1,
17
+ token: envToken,
18
+ ownerWallet: "",
19
+ tokenId: "",
20
+ label: "CHEST_TOKEN env",
21
+ gateUrl: process.env.CHEST_GATE_URL?.trim() || DEFAULT_GATE_URL,
22
+ createdAt: "",
23
+ source: "env",
24
+ };
25
+ }
26
+ if (!existsSync(CREDENTIALS_PATH))
27
+ return null;
28
+ const raw = await readFile(CREDENTIALS_PATH, "utf-8");
29
+ const parsed = JSON.parse(raw);
30
+ return { ...parsed, source: "file" };
31
+ }
32
+ export async function requireCredentials() {
33
+ const creds = await loadCredentials();
34
+ if (!creds) {
35
+ throw new Error("Not logged in. Run `chest-gate login` first.");
36
+ }
37
+ return creds;
38
+ }
39
+ export async function saveCredentials(creds) {
40
+ await mkdir(CHEST_DIR, { recursive: true, mode: 0o700 });
41
+ await chmod(CHEST_DIR, 0o700).catch(() => { });
42
+ await writeFile(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), { mode: 0o600 });
43
+ await chmod(CREDENTIALS_PATH, 0o600).catch(() => { });
44
+ return CREDENTIALS_PATH;
45
+ }
46
+ export async function deleteCredentials() {
47
+ if (!existsSync(CREDENTIALS_PATH))
48
+ return false;
49
+ await unlink(CREDENTIALS_PATH);
50
+ return true;
51
+ }
52
+ export function getCredentialsPath() {
53
+ return CREDENTIALS_PATH;
54
+ }
55
+ export function getDefaultGateUrl() {
56
+ return process.env.CHEST_GATE_URL?.trim() || DEFAULT_GATE_URL;
57
+ }
58
+ export function getDefaultWebUrl() {
59
+ return process.env.CHEST_WEB_URL?.trim() || "https://chest.sh";
60
+ }
61
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Sign dashboard-bound API actions (archive, unlist, etc.) with the local
3
+ * deployer / author keypair. Mirrors `signDashboardMessage` in
4
+ * server-auth/dashboard-auth.ts byte-for-byte so the server's
5
+ * `verifyDashboardSignature` accepts the result.
6
+ *
7
+ * Canonical message (utf-8):
8
+ * "chest-dashboard:{wallet}:{action}:{resourceId}:{windowTs}"
9
+ *
10
+ * wallet = base58 Solana pubkey of the signer
11
+ * action = e.g. "deployment:archive", "app:unlist"
12
+ * resourceId = the slug (or "-" when unused)
13
+ * windowTs = Math.floor(Date.now() / 300_000), 5-minute window
14
+ *
15
+ * Output: ed25519 signature, base64-encoded, sent in the X-Dashboard-Sig
16
+ * header.
17
+ */
18
+ export type DashboardAction = "deployment:archive" | "deployment:unlist" | "app:archive" | "app:unlist";
19
+ export interface DashboardSignatureInput {
20
+ wallet: string;
21
+ action: DashboardAction;
22
+ resourceId: string;
23
+ }
24
+ export declare function signDashboardMessage(input: DashboardSignatureInput, secretKey: Uint8Array): string;
25
+ //# sourceMappingURL=dashboard-sig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-sig.d.ts","sourceRoot":"","sources":["../src/dashboard-sig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,MAAM,MAAM,eAAe,GACvB,oBAAoB,GACpB,mBAAmB,GACnB,aAAa,GACb,YAAY,CAAC;AAEjB,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,uBAAuB,EAC9B,SAAS,EAAE,UAAU,GACpB,MAAM,CAOR"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Sign dashboard-bound API actions (archive, unlist, etc.) with the local
3
+ * deployer / author keypair. Mirrors `signDashboardMessage` in
4
+ * server-auth/dashboard-auth.ts byte-for-byte so the server's
5
+ * `verifyDashboardSignature` accepts the result.
6
+ *
7
+ * Canonical message (utf-8):
8
+ * "chest-dashboard:{wallet}:{action}:{resourceId}:{windowTs}"
9
+ *
10
+ * wallet = base58 Solana pubkey of the signer
11
+ * action = e.g. "deployment:archive", "app:unlist"
12
+ * resourceId = the slug (or "-" when unused)
13
+ * windowTs = Math.floor(Date.now() / 300_000), 5-minute window
14
+ *
15
+ * Output: ed25519 signature, base64-encoded, sent in the X-Dashboard-Sig
16
+ * header.
17
+ */
18
+ import { ed25519 } from "@noble/curves/ed25519";
19
+ const WINDOW_MS = 300_000;
20
+ export function signDashboardMessage(input, secretKey) {
21
+ const seed = secretKey.length === 64 ? secretKey.slice(0, 32) : secretKey;
22
+ const windowTs = Math.floor(Date.now() / WINDOW_MS);
23
+ const msg = new TextEncoder().encode(`chest-dashboard:${input.wallet}:${input.action}:${input.resourceId}:${windowTs}`);
24
+ return Buffer.from(ed25519.sign(msg, seed)).toString("base64");
25
+ }
26
+ //# sourceMappingURL=dashboard-sig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-sig.js","sourceRoot":"","sources":["../src/dashboard-sig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAchD,MAAM,SAAS,GAAG,OAAO,CAAC;AAE1B,MAAM,UAAU,oBAAoB,CAClC,KAA8B,EAC9B,SAAqB;IAErB,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAClC,mBAAmB,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,QAAQ,EAAE,CAClF,CAAC;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACjE,CAAC"}
package/dist/index.js CHANGED
@@ -7,6 +7,9 @@ import { statusCommand } from "./commands/status.js";
7
7
  import { keypairCommand } from "./commands/keypair.js";
8
8
  import { splitCommand } from "./commands/split.js";
9
9
  import { appCommand } from "./commands/app.js";
10
+ import { loginCommand } from "./commands/login.js";
11
+ import { logoutCommand } from "./commands/logout.js";
12
+ import { whoamiCommand } from "./commands/whoami.js";
10
13
  const program = new Command();
11
14
  program
12
15
  .name("chest-gate")
@@ -19,5 +22,8 @@ program.addCommand(statusCommand);
19
22
  program.addCommand(keypairCommand);
20
23
  program.addCommand(splitCommand);
21
24
  program.addCommand(appCommand);
25
+ program.addCommand(loginCommand);
26
+ program.addCommand(logoutCommand);
27
+ program.addCommand(whoamiCommand);
22
28
  program.parse();
23
29
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,qDAAqD,CAAC;KAClE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAE/B,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,qDAAqD,CAAC;KAClE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chest-gate/cli",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Chest Gate CLI. One command to monetise any API with x402 on Solana.",
5
5
  "keywords": [
6
6
  "x402",
@@ -37,6 +37,7 @@
37
37
  "dependencies": {
38
38
  "@chest-gate/proxy": "^0.1.0",
39
39
  "@coral-xyz/anchor": "^0.32.1",
40
+ "@noble/curves": "^1.0.0",
40
41
  "@solana/kit": "^5.5.0",
41
42
  "@solana/spl-token": "^0.4.14",
42
43
  "@solana/web3.js": "^1.98.4",
@@ -46,6 +47,7 @@
46
47
  "ed25519-hd-key": "^1.3.0",
47
48
  "gray-matter": "^4.0.3",
48
49
  "inquirer": "^12.0.0",
50
+ "open": "^11.0.0",
49
51
  "yaml": "^2.7.0"
50
52
  },
51
53
  "devDependencies": {