@alchemy/cli 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Alchemy CLI is a command-line tool for querying blockchain data and managing Alchemy apps/configuration.
4
4
  It supports both human-friendly terminal output and JSON output for automation.
5
- You can use browser login, API keys, access keys, or x402 wallet auth depending on the command.
5
+ You can use browser login, API keys, or x402 wallet auth depending on the command.
6
6
 
7
7
  ## Installation
8
8
 
@@ -67,7 +67,7 @@ Quick usage examples:
67
67
  alchemy
68
68
 
69
69
  # Agent/script-friendly command
70
- alchemy evm data balance 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --json --no-interactive
70
+ alchemy evm data balance 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 -n eth-mainnet --json --no-interactive
71
71
 
72
72
  # Agent checks whether a newer CLI version is available
73
73
  alchemy update-check --json --no-interactive
@@ -95,22 +95,22 @@ Use `alchemy help` or `alchemy help <command>` for generated command help.
95
95
 
96
96
  | Command | What it does | Example |
97
97
  |---|---|---|
98
- | `evm rpc <method> [params...]` | Makes raw Ethereum JSON-RPC calls | `alchemy evm rpc eth_blockNumber` |
99
- | `evm data balance [address]` | Gets native token balance for an address | `alchemy evm data balance 0x...` |
100
- | `evm data tokens balances [address]` | Lists ERC-20 balances for an address | `alchemy evm data tokens balances 0x...` |
101
- | `evm data nfts [address]` | Lists NFTs owned by an address | `alchemy evm data nfts 0x...` |
102
- | `evm data history [address]` | Gets transfer history (`alchemy_getAssetTransfers`) | `alchemy evm data history 0x... --category erc20,erc721` |
98
+ | `evm rpc <method> [params...]` | Makes raw Ethereum JSON-RPC calls | `alchemy evm rpc eth_blockNumber -n eth-mainnet` |
99
+ | `evm data balance [address]` | Gets native token balance for an address | `alchemy evm data balance 0x... -n eth-mainnet` |
100
+ | `evm data tokens balances [address]` | Lists ERC-20 balances for an address | `alchemy evm data tokens balances 0x... -n eth-mainnet` |
101
+ | `evm data nfts [address]` | Lists NFTs owned by an address | `alchemy evm data nfts 0x... -n eth-mainnet` |
102
+ | `evm data history [address]` | Gets transfer history (`alchemy_getAssetTransfers`) | `alchemy evm data history 0x... --category erc20,erc721 -n eth-mainnet` |
103
103
  | `evm data price symbol <symbols>` | Gets current token prices by symbol | `alchemy evm data price symbol ETH,USDC` |
104
104
  | `evm data portfolio tokens --body <json>` | Gets token portfolio data | `alchemy evm data portfolio tokens --body '{...}'` |
105
- | `evm send <to> <amount>` | Sends native tokens or ERC-20 tokens | `alchemy evm send vitalik.eth 0.1 -n base-mainnet` |
106
- | `evm contract read/call` | Reads or writes smart contracts | `alchemy evm contract read 0x... "balanceOf(address)(uint256)" --args '["0x..."]'` |
107
- | `evm swap quote/execute` | Swaps tokens on the same chain | `alchemy evm swap quote --from 0xEeee... --to 0xA0b8... --amount 1` |
108
- | `evm approve <spender_address>` | Approves an ERC-20 token allowance | `alchemy evm approve 0x... --token-address 0x... --amount 10` |
109
- | `evm status [id]` | Checks transaction or operation status | `alchemy evm status 0x...` |
105
+ | `evm send <to> <amount>` | Sends native tokens for `--network`, or ERC-20 tokens with `--token` | `alchemy evm send vitalik.eth 0.1 -n base-mainnet` |
106
+ | `evm contract read/call` | Reads or writes smart contracts | `alchemy evm contract read 0x... "balanceOf(address)(uint256)" --args '["0x..."]' -n eth-mainnet` |
107
+ | `evm swap quote/execute` | Swaps tokens on the same chain | `alchemy evm swap quote --from 0xEeee... --to 0xA0b8... --amount 1 -n eth-mainnet` |
108
+ | `evm approve <spender_address>` | Approves an ERC-20 token allowance | `alchemy evm approve 0x... --token-address 0x... --amount 10 -n eth-mainnet` |
109
+ | `evm status [id]` | Checks transaction or operation status | `alchemy evm status 0x... -n eth-mainnet` |
110
110
  | `evm network list` | Lists RPC network IDs for use with `--network` | `alchemy evm network list --search base` |
111
- | `evm tx/receipt/block/gas/logs` | Fetches common node resources | `alchemy evm block latest` |
112
- | `evm trace/debug` | Calls Trace and Debug API methods | `alchemy evm trace call '{"to":"0x..."}' '["trace"]' latest` |
113
- | `evm simulate *` | Calls simulation APIs | `alchemy evm simulate execution --tx '{"to":"0x..."}'` |
111
+ | `evm tx/receipt/block/gas/logs` | Fetches common node resources | `alchemy evm block latest -n eth-mainnet` |
112
+ | `evm trace/debug` | Calls Trace and Debug API methods | `alchemy evm trace call '{"to":"0x..."}' '["trace"]' latest -n eth-mainnet` |
113
+ | `evm simulate *` | Calls simulation APIs | `alchemy evm simulate execution --tx '{"to":"0x..."}' -n eth-mainnet` |
114
114
 
115
115
  ### Wallets
116
116
 
@@ -134,14 +134,14 @@ Per-command override: pass `--signer <session\|local>` to `evm send`, `evm appro
134
134
 
135
135
  | Command | What it does | Example |
136
136
  |---|---|---|
137
- | `solana rpc <method> [params...]` | Calls Solana JSON-RPC methods | `alchemy solana rpc getBalance '"<pubkey>"'` |
138
- | `solana das <method> [params...]` | Calls Solana DAS methods | `alchemy solana das getAssetsByOwner '{"ownerAddress":"<pubkey>"}'` |
137
+ | `solana rpc <method> [params...]` | Calls Solana JSON-RPC methods | `alchemy solana rpc getBalance '"<pubkey>"' -n solana-mainnet` |
138
+ | `solana das <method> [params...]` | Calls Solana DAS methods | `alchemy solana das getAssetsByOwner '{"ownerAddress":"<pubkey>"}' -n solana-mainnet` |
139
139
  | `solana network list` | Lists networks from the Solana namespace | `alchemy solana network list --search solana` |
140
- | `solana send <to> <amount>` | Sends SOL or SPL tokens to an address | `alchemy solana send <pubkey> 0.1` |
141
- | `solana send <to> <amount> --token <mint>` | Sends an SPL token and creates the recipient ATA if needed | `alchemy solana send <pubkey> 10 --token <mint>` |
142
- | `solana program accounts/account/show` | Inspects Solana program accounts and account metadata | `alchemy solana program accounts <program-id>` |
143
- | `solana delegate approve/revoke` | Approves or revokes SPL token delegates | `alchemy solana delegate approve --token-account <addr> --mint <mint> --delegate <addr> --amount 1 --decimals 6` |
144
- | `solana status [id]` | Checks Solana transaction or operation status | `alchemy solana status <signature>` |
140
+ | `solana send <to> <amount>` | Sends SOL or SPL tokens to an address | `alchemy solana send <pubkey> 0.1 -n solana-mainnet` |
141
+ | `solana send <to> <amount> --token <mint>` | Sends an SPL token and creates the recipient ATA if needed | `alchemy solana send <pubkey> 10 --token <mint> -n solana-mainnet` |
142
+ | `solana program accounts/account/show` | Inspects Solana program accounts and account metadata | `alchemy solana program accounts <program-id> -n solana-mainnet` |
143
+ | `solana delegate approve/revoke` | Approves or revokes SPL token delegates | `alchemy solana delegate approve --token-account <addr> --mint <mint> --delegate <addr> --amount 1 --decimals 6 -n solana-mainnet` |
144
+ | `solana status [id]` | Checks Solana transaction or operation status | `alchemy solana status <signature> -n solana-mainnet` |
145
145
  | `xchain bridge quote/execute` | Bridges tokens across chains | `alchemy xchain bridge quote --from 0xEeee... --to 0xEeee... --amount 0.1 --to-network base-mainnet -n eth-mainnet` |
146
146
 
147
147
  ### CLI Admin
@@ -175,7 +175,7 @@ Per-command override: pass `--signer <session\|local>` to `evm send`, `evm appro
175
175
  | `install skills` | Installs bundled Alchemy skills | `alchemy install skills --client cursor --dry-run` |
176
176
  | `update-check` | Checks whether a newer CLI version is available | `alchemy update-check --json --no-interactive` |
177
177
  | `config set ...` | Sets config values | `alchemy config set app <app-id>` |
178
- | `config get <key>` | Gets one config value | `alchemy config get network` |
178
+ | `config get <key>` | Gets one config value | `alchemy config get verbose` |
179
179
  | `config list` | Lists all config values | `alchemy config list` |
180
180
  | `config reset [key]` | Resets one or all config values | `alchemy config reset --yes` |
181
181
  | `completions <shell>` | Generates shell completion scripts (bash/zsh/fish) | `eval "$(alchemy completions zsh)"` |
@@ -193,7 +193,7 @@ These apply to all commands.
193
193
  | Flag | Env var | Description |
194
194
  |---|---|---|
195
195
  | `--api-key <key>` | `ALCHEMY_API_KEY` | API key for blockchain query commands |
196
- | `-n, --network <network>` | `ALCHEMY_NETWORK` | Target network (default: `eth-mainnet`) |
196
+ | `-n, --network <network>` | | Target network for networked commands |
197
197
  | `--x402` | — | Enable x402 wallet-based gateway auth |
198
198
  | `--wallet-key-file <path>` | — | EVM wallet private key file for x402 auth and local signing |
199
199
  | `--solana-wallet-key-file <path>` | — | Solana wallet private key file for local signing |
@@ -221,7 +221,6 @@ Additional env vars:
221
221
  | Env var | Description |
222
222
  |---|---|
223
223
  | `ALCHEMY_CONFIG` | Custom path to config file |
224
- | `ALCHEMY_ACCESS_KEY` | Access key for Admin API operations |
225
224
  | `ALCHEMY_WALLET_KEY` | EVM wallet private key for x402 auth and local signing |
226
225
  | `ALCHEMY_SOLANA_WALLET_KEY` | Solana wallet private key |
227
226
  | `ALCHEMY_ACTIVE_SIGNER` | Active EVM signer override (`session` or `local`) |
@@ -245,7 +244,7 @@ Additional env vars:
245
244
  | `evm data price historical` | `--body <json>` (required) |
246
245
  | `evm data portfolio *` | `--body <json>` (required per subcommand) |
247
246
  | `evm simulate *` | `--tx <json>` or `--txs <json>` (required) |
248
- | `evm send` | `--token <address>`, `--gas-sponsored`, `--gas-policy-id <id>`, `--signer <session\|local>` |
247
+ | `evm send` | `-n, --network <network>` (required), `--token <address>`, `--gas-sponsored`, `--gas-policy-id <id>`, `--signer <session\|local>` |
249
248
  | `evm contract call` | `--args <json>`, `--abi-file <path>`, `--abi <json>`, `--value <ether>`, `--gas-sponsored`, `--gas-policy-id <id>`, `--signer <session\|local>` |
250
249
  | `evm swap quote` | `--from <token_address>`, `--to <token_address>`, `--amount <number>`, `--slippage <percent>`, `--signer <session\|local>` |
251
250
  | `evm swap execute` | `--from <token_address>`, `--to <token_address>`, `--amount <number>`, `--slippage <percent>`, `--gas-sponsored`, `--gas-policy-id <id>`, `--signer <session\|local>` |
@@ -11,8 +11,8 @@ import {
11
11
  prepareLogin,
12
12
  revokeToken,
13
13
  waitForCallback
14
- } from "./chunk-AMGGO36F.js";
15
- import "./chunk-CTTW4PA4.js";
14
+ } from "./chunk-I6YQX7PF.js";
15
+ import "./chunk-5BEJA752.js";
16
16
  export {
17
17
  AUTH_PORT,
18
18
  DEFAULT_EXPIRES_IN_SECONDS,
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
3
+ import {
4
+ registerAuth,
5
+ selectAppAfterAuth
6
+ } from "./chunk-XZS6KZHN.js";
7
+ import "./chunk-I6YQX7PF.js";
8
+ import "./chunk-RPSHRYCZ.js";
9
+ import "./chunk-B5KVL3ZR.js";
10
+ import "./chunk-DXQAGBW6.js";
11
+ import "./chunk-LANOFNO6.js";
12
+ import "./chunk-5BEJA752.js";
13
+ export {
14
+ registerAuth,
15
+ selectAppAfterAuth
16
+ };
@@ -2,10 +2,10 @@
2
2
  if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
3
3
  import {
4
4
  configPath
5
- } from "./chunk-GLKB4JM7.js";
5
+ } from "./chunk-LANOFNO6.js";
6
6
  import {
7
7
  esc
8
- } from "./chunk-CTTW4PA4.js";
8
+ } from "./chunk-5BEJA752.js";
9
9
 
10
10
  // src/lib/update-check.ts
11
11
  import { execFileSync } from "child_process";
@@ -53,7 +53,7 @@ function semverLT(a, b) {
53
53
  return false;
54
54
  }
55
55
  function currentVersion() {
56
- return true ? "0.10.0" : "0.0.0";
56
+ return true ? "0.11.0" : "0.0.0";
57
57
  }
58
58
  function toUpdateStatus(latestVersion, checkedAt) {
59
59
  const current = currentVersion();
@@ -113,9 +113,7 @@ async function fetchWithTimeout(url, init) {
113
113
  // src/lib/redact.ts
114
114
  var SENSITIVE_ERROR_CODES = /* @__PURE__ */ new Set([
115
115
  "AUTH_REQUIRED",
116
- "INVALID_API_KEY",
117
- "INVALID_ACCESS_KEY",
118
- "ACCESS_KEY_REQUIRED"
116
+ "INVALID_API_KEY"
119
117
  ]);
120
118
  function getAlchemyKeyPathMarkers() {
121
119
  const domain = getBaseDomain();
@@ -293,8 +291,6 @@ var ErrorCode = {
293
291
  AUTH_REQUIRED: "AUTH_REQUIRED",
294
292
  INVALID_API_KEY: "INVALID_API_KEY",
295
293
  NETWORK_NOT_ENABLED: "NETWORK_NOT_ENABLED",
296
- INVALID_ACCESS_KEY: "INVALID_ACCESS_KEY",
297
- ACCESS_KEY_REQUIRED: "ACCESS_KEY_REQUIRED",
298
294
  APP_REQUIRED: "APP_REQUIRED",
299
295
  ADMIN_API_ERROR: "ADMIN_API_ERROR",
300
296
  NETWORK_ERROR: "NETWORK_ERROR",
@@ -315,8 +311,6 @@ var EXIT_CODES = {
315
311
  AUTH_REQUIRED: 3,
316
312
  INVALID_API_KEY: 3,
317
313
  NETWORK_NOT_ENABLED: 3,
318
- INVALID_ACCESS_KEY: 3,
319
- ACCESS_KEY_REQUIRED: 3,
320
314
  APP_REQUIRED: 3,
321
315
  INVALID_ARGS: 2,
322
316
  NOT_FOUND: 4,
@@ -368,13 +362,6 @@ function errAuthRequired() {
368
362
  "alchemy auth"
369
363
  );
370
364
  }
371
- function errAccessKeyRequired() {
372
- return new CLIError(
373
- ErrorCode.ACCESS_KEY_REQUIRED,
374
- "Access key required. Set ALCHEMY_ACCESS_KEY or run 'alchemy config set access-key <key>'.",
375
- "Get an access key: https://www.alchemy.com/docs/reference/admin-api/overview"
376
- );
377
- }
378
365
  function errLoginRequired() {
379
366
  return new CLIError(
380
367
  ErrorCode.AUTH_REQUIRED,
@@ -406,6 +393,13 @@ function errNetwork(detail) {
406
393
  "Check your internet connection and try again."
407
394
  );
408
395
  }
396
+ function errNetworkRequired(networkListCommand = "alchemy evm network list") {
397
+ return new CLIError(
398
+ ErrorCode.INVALID_ARGS,
399
+ "Network required. Pass -n/--network <network>.",
400
+ networkListCommand
401
+ );
402
+ }
409
403
  var RPC_ERROR_HINTS = {
410
404
  [-32700]: "Parse error. The request JSON is malformed.",
411
405
  [-32600]: "Invalid request. Check the JSON-RPC request format.",
@@ -430,19 +424,12 @@ function errRateLimited() {
430
424
  "Consider upgrading your Alchemy plan for higher rate limits."
431
425
  );
432
426
  }
433
- function errInvalidAccessKey() {
434
- return new CLIError(
435
- ErrorCode.INVALID_ACCESS_KEY,
436
- "Invalid access key. Check your key and try again.",
437
- "Get an access key: https://www.alchemy.com/docs/reference/admin-api/overview"
438
- );
439
- }
440
427
  function errAccessDenied(detail) {
441
- const message = detail ? `Access denied: ${detail}` : "Access denied. Your access key may not have permission for this operation.";
428
+ const message = detail ? `Access denied: ${detail}` : "Access denied. Check that your Alchemy account has permission for this operation.";
442
429
  return new CLIError(
443
- ErrorCode.INVALID_ACCESS_KEY,
430
+ ErrorCode.AUTH_REQUIRED,
444
431
  message,
445
- "Check your account tier and feature access at https://dashboard.alchemy.com/"
432
+ "Run 'alchemy auth login' or check your account access at https://dashboard.alchemy.com/"
446
433
  );
447
434
  }
448
435
  function errAppRequired() {
@@ -455,10 +442,17 @@ function errAppRequired() {
455
442
  function errWalletKeyRequired() {
456
443
  return new CLIError(
457
444
  ErrorCode.AUTH_REQUIRED,
458
- "Wallet key required for x402. Set ALCHEMY_WALLET_KEY, run 'alchemy wallet connect --mode local', or use --wallet-key-file.",
445
+ "No local wallet configured. Run 'alchemy wallet connect --mode local', set ALCHEMY_WALLET_KEY, or use --wallet-key-file.",
459
446
  "alchemy wallet connect --mode local"
460
447
  );
461
448
  }
449
+ function errWalletRequired() {
450
+ return new CLIError(
451
+ ErrorCode.AUTH_REQUIRED,
452
+ "No wallet connected. Run 'alchemy wallet connect' to connect a session wallet, or run 'alchemy wallet connect --mode local' to use a local wallet.",
453
+ "alchemy wallet connect"
454
+ );
455
+ }
462
456
  function errSessionExpired() {
463
457
  return new CLIError(
464
458
  ErrorCode.AUTH_REQUIRED,
@@ -548,19 +542,19 @@ export {
548
542
  EXIT_CODES,
549
543
  CLIError,
550
544
  errAuthRequired,
551
- errAccessKeyRequired,
552
545
  errLoginRequired,
553
546
  errInvalidAPIKey,
554
547
  errNetworkNotEnabled,
555
548
  errNetwork,
549
+ errNetworkRequired,
556
550
  errRPC,
557
551
  errInvalidArgs,
558
552
  errNotFound,
559
553
  errRateLimited,
560
- errInvalidAccessKey,
561
554
  errAccessDenied,
562
555
  errAppRequired,
563
556
  errWalletKeyRequired,
557
+ errWalletRequired,
564
558
  errSessionExpired,
565
559
  errNoActiveSession,
566
560
  errSolanaWalletKeyRequired,
@@ -4,22 +4,21 @@ import {
4
4
  configDir,
5
5
  load,
6
6
  save
7
- } from "./chunk-GLKB4JM7.js";
7
+ } from "./chunk-LANOFNO6.js";
8
8
  import {
9
9
  CLIError,
10
10
  ErrorCode,
11
11
  debug,
12
12
  errAccessDenied,
13
- errAccessKeyRequired,
14
13
  errAdminAPI,
15
14
  errAppRequired,
16
15
  errAuthRequired,
17
16
  errInvalidAPIKey,
18
- errInvalidAccessKey,
19
17
  errInvalidArgs,
20
18
  errLoginRequired,
21
19
  errNetwork,
22
20
  errNetworkNotEnabled,
21
+ errNetworkRequired,
23
22
  errNotFound,
24
23
  errRPC,
25
24
  errRateLimited,
@@ -31,7 +30,7 @@ import {
31
30
  redactSensitiveText,
32
31
  timeout,
33
32
  verbose
34
- } from "./chunk-CTTW4PA4.js";
33
+ } from "./chunk-5BEJA752.js";
35
34
 
36
35
  // src/lib/resolve.ts
37
36
  import { readFileSync as readFileSync2 } from "fs";
@@ -635,6 +634,9 @@ var Client = class _Client {
635
634
  }
636
635
  return null;
637
636
  }
637
+ isFetchFailureError(err) {
638
+ return err.status === void 0 && err.message.trim().toLowerCase() === "fetch failed";
639
+ }
638
640
  verboseLog(message) {
639
641
  if (verbose) {
640
642
  process.stderr.write(`[verbose] ${message}
@@ -671,6 +673,9 @@ var Client = class _Client {
671
673
  if (err.status !== void 0) {
672
674
  throw errNetwork(`HTTP ${err.status}: ${err.message}`);
673
675
  }
676
+ if (this.isFetchFailureError(err)) {
677
+ throw errNetwork(err.message);
678
+ }
674
679
  throw errRPC(err.code, err.message);
675
680
  }
676
681
  throw err;
@@ -945,17 +950,10 @@ var AdminClient = class _AdminClient {
945
950
  static ADMIN_API_BASE_URL_ENV = "ALCHEMY_ADMIN_API_BASE_URL";
946
951
  credential;
947
952
  constructor(credential) {
948
- if (typeof credential === "string") {
949
- this.validateAccessKey(credential);
950
- this.credential = { type: "access_key", key: credential };
951
- } else {
952
- if (credential.type === "access_key") {
953
- this.validateAccessKey(credential.key);
954
- } else if (!credential.token.trim()) {
955
- throw errAuthRequired();
956
- }
957
- this.credential = credential;
953
+ if (!credential.token.trim()) {
954
+ throw errLoginRequired();
958
955
  }
956
+ this.credential = credential;
959
957
  }
960
958
  baseURL() {
961
959
  const override = this.baseURLOverride();
@@ -976,11 +974,6 @@ var AdminClient = class _AdminClient {
976
974
  allowedHostnames: [STAGING_ADMIN_API_HOST]
977
975
  });
978
976
  }
979
- validateAccessKey(accessKey) {
980
- if (!accessKey.trim() || /\s/.test(accessKey)) {
981
- throw errInvalidAccessKey();
982
- }
983
- }
984
977
  assertSafeRequestTarget(url) {
985
978
  let parsed;
986
979
  try {
@@ -1003,7 +996,7 @@ var AdminClient = class _AdminClient {
1003
996
  method,
1004
997
  redirect: "error",
1005
998
  headers: {
1006
- Authorization: `Bearer ${this.credential.type === "access_key" ? this.credential.key : this.credential.token}`,
999
+ Authorization: `Bearer ${this.credential.token}`,
1007
1000
  "Content-Type": "application/json",
1008
1001
  Accept: "application/json"
1009
1002
  },
@@ -1011,7 +1004,7 @@ var AdminClient = class _AdminClient {
1011
1004
  });
1012
1005
  if (resp.status === 401) {
1013
1006
  debug(`401 Unauthorized from ${url}`);
1014
- throw errInvalidAccessKey();
1007
+ throw errLoginRequired();
1015
1008
  }
1016
1009
  if (resp.status === 403) {
1017
1010
  const detail = await resp.text().catch(() => "");
@@ -1127,17 +1120,10 @@ var GasManagerClient = class _GasManagerClient {
1127
1120
  static BASE_URL_ENV = "ALCHEMY_GAS_MANAGER_BASE_URL";
1128
1121
  credential;
1129
1122
  constructor(credential) {
1130
- if (typeof credential === "string") {
1131
- this.validateAccessKey(credential);
1132
- this.credential = { type: "access_key", key: credential };
1133
- } else {
1134
- if (credential.type === "access_key") {
1135
- this.validateAccessKey(credential.key);
1136
- } else if (!credential.token.trim()) {
1137
- throw errAuthRequired();
1138
- }
1139
- this.credential = credential;
1123
+ if (!credential.token.trim()) {
1124
+ throw errLoginRequired();
1140
1125
  }
1126
+ this.credential = credential;
1141
1127
  }
1142
1128
  baseURL() {
1143
1129
  const override = this.baseURLOverride();
@@ -1156,11 +1142,6 @@ var GasManagerClient = class _GasManagerClient {
1156
1142
  baseURLOverride() {
1157
1143
  return parseBaseURLOverride(_GasManagerClient.BASE_URL_ENV);
1158
1144
  }
1159
- validateAccessKey(accessKey) {
1160
- if (!accessKey.trim() || /\s/.test(accessKey)) {
1161
- throw errInvalidAccessKey();
1162
- }
1163
- }
1164
1145
  assertSafeRequestTarget(url) {
1165
1146
  let parsed;
1166
1147
  try {
@@ -1179,19 +1160,18 @@ var GasManagerClient = class _GasManagerClient {
1179
1160
  const url = `${this.baseURL()}${path}`;
1180
1161
  debug(`${method} ${url}`);
1181
1162
  this.assertSafeRequestTarget(url);
1182
- const token = this.credential.type === "access_key" ? this.credential.key : this.credential.token;
1183
1163
  const resp = await fetchWithTimeout(url, {
1184
1164
  method,
1185
1165
  redirect: "error",
1186
1166
  headers: {
1187
- Authorization: `Bearer ${token}`,
1167
+ Authorization: `Bearer ${this.credential.token}`,
1188
1168
  "Content-Type": "application/json",
1189
1169
  Accept: "application/json"
1190
1170
  },
1191
1171
  ...body !== void 0 && { body: JSON.stringify(body) }
1192
1172
  });
1193
1173
  if (resp.status === 401) {
1194
- throw this.credential.type === "auth_token" ? errLoginRequired() : errInvalidAccessKey();
1174
+ throw errLoginRequired();
1195
1175
  }
1196
1176
  if (resp.status === 403) {
1197
1177
  const detail = await resp.text().catch(() => "");
@@ -1202,15 +1182,12 @@ var GasManagerClient = class _GasManagerClient {
1202
1182
  } catch {
1203
1183
  reason = detail || void 0;
1204
1184
  }
1205
- if (this.credential.type === "auth_token") {
1206
- const tail = reason ? ` (${reason})` : "";
1207
- throw new CLIError(
1208
- ErrorCode.AUTH_REQUIRED,
1209
- `Access denied for this Alchemy account or app${tail}. Re-authenticate with 'alchemy auth login' or check that the default app is one you have permission to manage.`,
1210
- "alchemy auth login"
1211
- );
1212
- }
1213
- throw errAccessDenied(typeof reason === "string" ? reason : void 0);
1185
+ const tail = reason ? ` (${reason})` : "";
1186
+ throw new CLIError(
1187
+ ErrorCode.AUTH_REQUIRED,
1188
+ `Access denied for this Alchemy account or app${tail}. Re-authenticate with 'alchemy auth login' or check that the default app is one you have permission to manage.`,
1189
+ "alchemy auth login"
1190
+ );
1214
1191
  }
1215
1192
  if (resp.status === 404) {
1216
1193
  const text = await resp.text().catch(() => "");
@@ -1569,43 +1546,29 @@ function resolveAPIKey(program, cfg) {
1569
1546
  if (config.app?.apiKey) return config.app.apiKey;
1570
1547
  return void 0;
1571
1548
  }
1572
- function resolveAccessKey(_program, cfg) {
1573
- if (process.env.ALCHEMY_ACCESS_KEY) return process.env.ALCHEMY_ACCESS_KEY;
1574
- const config = cfg ?? load();
1575
- if (config.access_key) return config.access_key;
1576
- return void 0;
1577
- }
1578
- function resolveNetwork(program, cfg, defaultNetwork) {
1549
+ function resolveOptionalNetwork(program) {
1579
1550
  const opts = getCommandOptions(program);
1580
- if (opts.network) return opts.network;
1581
- if (process.env.ALCHEMY_NETWORK) return process.env.ALCHEMY_NETWORK;
1582
- const config = cfg ?? load();
1583
- if (config.network) return config.network;
1584
- return defaultNetwork ?? "eth-mainnet";
1551
+ return opts.network;
1585
1552
  }
1586
- function resolveSolanaNetwork(program, cfg) {
1587
- const opts = getCommandOptions(program);
1588
- if (opts.network) {
1589
- if (!isSolanaNetwork(opts.network)) {
1590
- throw errInvalidArgs(
1591
- `Network '${opts.network}' is not a Solana network. Use a solana-* network with the solana namespace.`
1592
- );
1593
- }
1594
- return opts.network;
1595
- }
1596
- if (process.env.ALCHEMY_NETWORK) {
1597
- if (!isSolanaNetwork(process.env.ALCHEMY_NETWORK)) {
1598
- throw errInvalidArgs(
1599
- `ALCHEMY_NETWORK='${process.env.ALCHEMY_NETWORK}' is not a Solana network. Use a solana-* network with the solana namespace.`
1600
- );
1601
- }
1602
- return process.env.ALCHEMY_NETWORK;
1553
+ function resolveNetwork(program) {
1554
+ const network = resolveOptionalNetwork(program);
1555
+ if (network) return network;
1556
+ throw errNetworkRequired();
1557
+ }
1558
+ function resolveRequiredNetwork(program) {
1559
+ return resolveNetwork(program);
1560
+ }
1561
+ function resolveSolanaNetwork(program) {
1562
+ const network = resolveOptionalNetwork(program);
1563
+ if (!network) {
1564
+ throw errNetworkRequired("alchemy solana network list");
1603
1565
  }
1604
- const config = cfg ?? load();
1605
- if (config.network && isSolanaNetwork(config.network)) {
1606
- return config.network;
1566
+ if (!isSolanaNetwork(network)) {
1567
+ throw errInvalidArgs(
1568
+ `Network '${network}' is not a Solana network. Use a solana-* network with the solana namespace.`
1569
+ );
1607
1570
  }
1608
- return "solana-mainnet";
1571
+ return network;
1609
1572
  }
1610
1573
  function resolveAppId(program, cfg) {
1611
1574
  const opts = getCommandOptions(program);
@@ -1627,11 +1590,9 @@ function resolveAuthToken(cfg) {
1627
1590
  }
1628
1591
  function adminClientFromFlags(program) {
1629
1592
  const cfg = load();
1630
- const accessKey = resolveAccessKey(program, cfg);
1631
- if (accessKey) return new AdminClient(accessKey);
1632
1593
  const authToken = resolveAuthToken(cfg);
1633
1594
  if (authToken) return new AdminClient({ type: "auth_token", token: authToken });
1634
- throw errAccessKeyRequired();
1595
+ throw errLoginRequired();
1635
1596
  }
1636
1597
  function hasAuthLoginToken(cfg) {
1637
1598
  return Boolean(resolveAuthToken(cfg));
@@ -1653,7 +1614,7 @@ function resolveX402Client(program) {
1653
1614
  if (!resolveX402(program, cfg)) return null;
1654
1615
  const walletKey = resolveWalletKey(program, cfg);
1655
1616
  if (!walletKey) return null;
1656
- return new X402Client(walletKey, resolveNetwork(program, cfg));
1617
+ return new X402Client(walletKey, resolveNetwork(program));
1657
1618
  }
1658
1619
  function resolveWalletKey(program, cfg) {
1659
1620
  const opts = getCommandOptions(program);
@@ -1743,9 +1704,20 @@ function resolveActiveSigner(program, cfg) {
1743
1704
  function resolveDelegatedMode(program, cfg) {
1744
1705
  return resolveActiveSigner(program, cfg) === "session";
1745
1706
  }
1707
+ function resolveClientNetwork(program, opts) {
1708
+ return opts?.forceNetwork ?? resolveNetwork(program);
1709
+ }
1710
+ function apiKeyClientFromFlags(program, opts) {
1711
+ const cfg = load();
1712
+ const network = resolveClientNetwork(program, opts);
1713
+ debug(`using network=${network}`);
1714
+ const apiKey = resolveAPIKey(program, cfg);
1715
+ if (!apiKey) throw errAuthRequired();
1716
+ return new Client(apiKey, network);
1717
+ }
1746
1718
  function clientFromFlags(program, opts) {
1747
1719
  const cfg = load();
1748
- const network = opts?.forceNetwork ?? resolveNetwork(program, cfg, opts?.defaultNetwork);
1720
+ const network = resolveClientNetwork(program, opts);
1749
1721
  debug(`using network=${network}`);
1750
1722
  if (resolveX402(program, cfg)) {
1751
1723
  const walletKey = resolveWalletKey(program, cfg);
@@ -1807,8 +1779,9 @@ export {
1807
1779
  isSessionValid,
1808
1780
  getWalletSessionByChain,
1809
1781
  resolveAPIKey,
1810
- resolveAccessKey,
1782
+ resolveOptionalNetwork,
1811
1783
  resolveNetwork,
1784
+ resolveRequiredNetwork,
1812
1785
  resolveSolanaNetwork,
1813
1786
  resolveAppId,
1814
1787
  resolveAuthToken,
@@ -1825,6 +1798,7 @@ export {
1825
1798
  resolveSolanaFeePolicyId,
1826
1799
  resolveActiveSigner,
1827
1800
  resolveDelegatedMode,
1801
+ apiKeyClientFromFlags,
1828
1802
  clientFromFlags,
1829
1803
  resolveConfiguredNetworkSlugs,
1830
1804
  resolveWalletSession,
@@ -2,11 +2,11 @@
2
2
  if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
3
3
  import {
4
4
  isInteractiveAllowed
5
- } from "./chunk-3GBDYROJ.js";
5
+ } from "./chunk-RPSHRYCZ.js";
6
6
  import {
7
7
  resolveAuthToken,
8
8
  resolveWalletSession
9
- } from "./chunk-ANONMDDZ.js";
9
+ } from "./chunk-B5KVL3ZR.js";
10
10
 
11
11
  // src/lib/onboarding.ts
12
12
  var SETUP_CAPABILITY_ORDER = [
@@ -26,9 +26,6 @@ var SETUP_CAPABILITY_LABELS = {
26
26
  function hasAPIKey(cfg) {
27
27
  return Boolean(cfg.api_key?.trim());
28
28
  }
29
- function hasAccessKeyAndApp(cfg) {
30
- return Boolean(cfg.access_key?.trim() && cfg.app?.id && cfg.app.apiKey);
31
- }
32
29
  function hasX402Wallet(cfg) {
33
30
  return cfg.x402 === true && Boolean(cfg.wallet_key_file?.trim());
34
31
  }
@@ -40,7 +37,7 @@ function capabilityStatus(args) {
40
37
  }
41
38
  function getSetupCapabilities(cfg) {
42
39
  const hasConfiguredAPIKey = hasAPIKey(cfg) || Boolean(cfg.app?.apiKey?.trim());
43
- const hasAdminAuth = Boolean(cfg.access_key?.trim()) || hasAuthToken(cfg);
40
+ const hasAdminAuth = hasAuthToken(cfg);
44
41
  const hasNotifyAuth = Boolean(
45
42
  cfg.webhook_api_key?.trim() || cfg.app?.webhookApiKey?.trim()
46
43
  );
@@ -58,9 +55,9 @@ function getSetupCapabilities(cfg) {
58
55
  }),
59
56
  admin_api: capabilityStatus({
60
57
  complete: hasAdminAuth,
61
- satisfiedBy: cfg.access_key?.trim() ? "access_key" : hasAuthToken(cfg) ? "auth_token" : null,
62
- missing: hasAdminAuth ? [] : ["access-key or auth token"],
63
- nextCommands: hasAdminAuth ? [] : ["alchemy auth", "alchemy config set access-key <key>"]
58
+ satisfiedBy: hasAdminAuth ? "auth_token" : null,
59
+ missing: hasAdminAuth ? [] : ["auth token"],
60
+ nextCommands: hasAdminAuth ? [] : ["alchemy auth"]
64
61
  }),
65
62
  notify_webhooks: capabilityStatus({
66
63
  complete: hasNotifyAuth,
@@ -87,7 +84,6 @@ function getSetupCapabilities(cfg) {
87
84
  }
88
85
  function getSetupMethod(cfg) {
89
86
  if (hasAPIKey(cfg)) return "api_key";
90
- if (hasAccessKeyAndApp(cfg)) return "access_key_app";
91
87
  if (hasX402Wallet(cfg)) return "x402_wallet";
92
88
  if (hasAuthToken(cfg)) return "auth_token";
93
89
  return null;
@@ -110,11 +106,10 @@ function getSetupStatus(cfg) {
110
106
  return {
111
107
  complete: false,
112
108
  satisfiedBy: null,
113
- missing: ["Provide one auth path: alchemy auth OR api-key OR ALCHEMY_ACCESS_KEY+app OR SIWx wallet"],
109
+ missing: ["Provide one auth path: alchemy auth OR api-key OR SIWx wallet"],
114
110
  nextCommands: [
115
111
  "alchemy auth",
116
112
  "alchemy config set app",
117
- "alchemy config set access-key <key> && alchemy config set app <app-id>",
118
113
  "alchemy wallet connect --mode local && alchemy config set x402 true"
119
114
  ],
120
115
  capabilities
@@ -5,7 +5,7 @@ import {
5
5
  isJSONMode,
6
6
  quiet,
7
7
  rgb
8
- } from "./chunk-CTTW4PA4.js";
8
+ } from "./chunk-5BEJA752.js";
9
9
 
10
10
  // src/lib/terminal-ui.ts
11
11
  import * as readline from "readline";