@alchemy/cli 0.5.1 → 0.5.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.
@@ -1,227 +0,0 @@
1
- #!/usr/bin/env node
2
- if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
3
- import {
4
- generateAndPersistWallet,
5
- importAndPersistWallet,
6
- selectOrCreateApp
7
- } from "./chunk-44OGGLN4.js";
8
- import {
9
- getUpdateNoticeLines
10
- } from "./chunk-Z7J64GJJ.js";
11
- import {
12
- AdminClient,
13
- bold,
14
- brand,
15
- brandedHelp,
16
- dim,
17
- green,
18
- load,
19
- maskIf,
20
- printKeyValueBox,
21
- promptSelect,
22
- promptText,
23
- save
24
- } from "./chunk-T2XSNZE3.js";
25
- import "./chunk-56ZVYB4G.js";
26
-
27
- // src/commands/onboarding.ts
28
- function printNextSteps(method) {
29
- const commandsByMethod = {
30
- "browser-login": ["alchemy auth"],
31
- "api-key": ["alchemy config set api-key <key>"],
32
- "access-key": [
33
- "alchemy config set access-key <key>",
34
- "alchemy config set app <app-id>"
35
- ],
36
- siwx: [
37
- "alchemy wallet generate",
38
- "alchemy config set wallet-key-file <path>",
39
- "alchemy config set x402 true"
40
- ]
41
- };
42
- console.log("");
43
- console.log(` ${dim("Next steps:")}`);
44
- for (const command of commandsByMethod[method]) {
45
- console.log(` ${dim(`- ${command}`)}`);
46
- }
47
- }
48
- function printAPIKeyPostSetupGuidance() {
49
- const cfg = load() ?? {};
50
- const network = cfg.network ?? "eth-mainnet";
51
- console.log("");
52
- console.log(` ${brand("\u25C6")} ${bold("Your configuration")}`);
53
- printKeyValueBox([
54
- ["api-key", cfg.api_key ? maskIf(cfg.api_key) : dim("(not set)")],
55
- ["network", cfg.network ? network : `${network} ${dim("(default)")}`]
56
- ]);
57
- console.log("");
58
- console.log(` ${brand("\u25C6")} ${bold("Next steps")}`);
59
- printKeyValueBox([
60
- ["Verify setup", "rpc eth_chainId"],
61
- ["Need a different chain?", "config set network <network>"],
62
- ["List available chains", "network list"],
63
- ["View set API key", "config get api-key"],
64
- ["Need help?", "help"]
65
- ]);
66
- }
67
- async function runAPIKeyOnboarding() {
68
- const key = await promptText({
69
- message: "Enter API Key",
70
- cancelMessage: "Skipped API key setup.",
71
- clearAfterSubmit: true
72
- });
73
- if (!key || !key.trim()) return;
74
- const cfg = load();
75
- save({ ...cfg, api_key: key.trim() });
76
- console.log(` ${green("\u2713")} Saved API key`);
77
- }
78
- async function runAccessKeyOnboarding() {
79
- const key = await promptText({
80
- message: "Alchemy access key",
81
- placeholder: "Used for Admin API operations",
82
- cancelMessage: "Skipped access key setup."
83
- });
84
- if (!key || !key.trim()) return;
85
- const cfg = load();
86
- save({ ...cfg, access_key: key.trim() });
87
- console.log(` ${green("\u2713")} Saved access key`);
88
- await selectOrCreateApp(new AdminClient(key.trim()));
89
- }
90
- async function runSiwxOnboarding() {
91
- const action = await promptSelect({
92
- message: "SIWx wallet setup",
93
- options: [
94
- { label: "Generate a new wallet", value: "generate" },
95
- { label: "Import wallet from key file", value: "import" }
96
- ],
97
- initialValue: "generate",
98
- cancelMessage: "Skipped SIWx setup."
99
- });
100
- if (!action) return;
101
- const wallet = action === "generate" ? generateAndPersistWallet() : await (async () => {
102
- const path = await promptText({
103
- message: "Wallet private key file path",
104
- cancelMessage: "Skipped wallet import."
105
- });
106
- if (!path || !path.trim()) return null;
107
- return importAndPersistWallet(path.trim());
108
- })();
109
- if (!wallet) return;
110
- const cfg = load();
111
- save({ ...cfg, x402: true });
112
- console.log(` ${green("\u2713")} SIWx enabled with wallet ${wallet.address}`);
113
- try {
114
- const { signSiwe } = await import("@alchemy/x402");
115
- const { readFileSync } = await import("fs");
116
- const keyPath = wallet.keyFile;
117
- const privateKey = readFileSync(keyPath, "utf-8").trim();
118
- const siweToken = await signSiwe({ privateKey, expiresAfter: "1h" });
119
- const expiresAt = new Date(Date.now() + 60 * 60 * 1e3).toISOString();
120
- save({ ...load(), siwe_token: siweToken, siwe_token_expires_at: expiresAt });
121
- console.log(` ${green("\u2713")} Signed SIWE token (cached for 1h)`);
122
- } catch {
123
- }
124
- }
125
- async function runOnboarding(_program, latestUpdate = null) {
126
- process.stdout.write(brandedHelp({ force: true }));
127
- console.log("");
128
- console.log(` ${brand("\u25C6")} ${bold("Welcome to Alchemy CLI")}`);
129
- console.log(` ${dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}`);
130
- console.log(` ${dim(" Let's get you set up with authentication.")}`);
131
- console.log(` ${dim(" Choose one auth path to continue.")}`);
132
- console.log(` ${dim(" Tip: select 'exit' to skip setup for now.")}`);
133
- console.log("");
134
- if (latestUpdate) {
135
- for (const line of getUpdateNoticeLines(latestUpdate)) {
136
- console.log(line);
137
- }
138
- console.log("");
139
- }
140
- const method = await promptSelect({
141
- message: "Choose an auth setup path",
142
- options: [
143
- {
144
- label: "Browser login",
145
- hint: "Log in via browser (recommended)",
146
- value: "browser-login"
147
- },
148
- {
149
- label: "API key",
150
- hint: "Query Alchemy RPC nodes",
151
- value: "api-key"
152
- },
153
- {
154
- label: "Access Key",
155
- hint: "Admin API plus RPC nodes",
156
- value: "access-key"
157
- },
158
- {
159
- label: "SIWx",
160
- hint: "Sign-In with Ethereum/Solana wallet",
161
- value: "siwx"
162
- },
163
- {
164
- label: "exit",
165
- value: "exit"
166
- }
167
- ],
168
- initialValue: "browser-login",
169
- cancelMessage: "Skipped onboarding."
170
- });
171
- if (!method) return false;
172
- if (method === "exit") {
173
- console.log(` ${dim("Exited onboarding.")}`);
174
- return false;
175
- }
176
- if (method === "browser-login") {
177
- const { performBrowserLogin, AUTH_PORT, getLoginUrl } = await import("./auth-E26YCAJV.js");
178
- console.log(` Opening browser to log in...`);
179
- console.log(` ${dim(getLoginUrl(AUTH_PORT))}`);
180
- console.log(` ${dim("Waiting for authentication...")}`);
181
- try {
182
- const result = await performBrowserLogin();
183
- const cfg2 = load();
184
- save({
185
- ...cfg2,
186
- auth_token: result.token,
187
- auth_token_expires_at: result.expiresAt
188
- });
189
- console.log(` ${green("\u2713")} Logged in successfully`);
190
- const { selectAppAfterAuth } = await import("./auth-7E33EMAI.js");
191
- await selectAppAfterAuth(result.token);
192
- return true;
193
- } catch (err) {
194
- console.log(` ${dim(`Login failed: ${err instanceof Error ? err.message : String(err)}`)}`);
195
- return false;
196
- }
197
- }
198
- if (method === "api-key") {
199
- await runAPIKeyOnboarding();
200
- const complete2 = Boolean(load().api_key?.trim());
201
- if (!complete2) {
202
- printNextSteps("api-key");
203
- } else {
204
- printAPIKeyPostSetupGuidance();
205
- }
206
- return complete2;
207
- }
208
- if (method === "access-key") {
209
- await runAccessKeyOnboarding();
210
- const cfg2 = load();
211
- const complete2 = Boolean(cfg2.access_key?.trim() && cfg2.app?.id && cfg2.app.apiKey);
212
- if (!complete2) {
213
- printNextSteps("access-key");
214
- }
215
- return complete2;
216
- }
217
- await runSiwxOnboarding();
218
- const cfg = load();
219
- const complete = cfg.x402 === true && Boolean(cfg.wallet_key_file?.trim());
220
- if (!complete) {
221
- printNextSteps("siwx");
222
- }
223
- return complete;
224
- }
225
- export {
226
- runOnboarding
227
- };