@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 +25 -26
- package/dist/{auth-KS6VPHHU.js → auth-5XFZB2BU.js} +2 -2
- package/dist/auth-6X2DBBYQ.js +16 -0
- package/dist/{chunk-HRWD4V2P.js → chunk-4QSVWWSK.js} +3 -3
- package/dist/{chunk-CTTW4PA4.js → chunk-5BEJA752.js} +21 -27
- package/dist/{chunk-ANONMDDZ.js → chunk-B5KVL3ZR.js} +61 -87
- package/dist/{chunk-VN5JUWHO.js → chunk-CSBYGYG6.js} +7 -12
- package/dist/{chunk-PMNRIXJI.js → chunk-DXQAGBW6.js} +1 -1
- package/dist/{chunk-AMGGO36F.js → chunk-I6YQX7PF.js} +1 -1
- package/dist/{chunk-D2RUM2DD.js → chunk-KIYIW6SX.js} +4 -4
- package/dist/{chunk-GLKB4JM7.js → chunk-LANOFNO6.js} +1 -11
- package/dist/{chunk-3GBDYROJ.js → chunk-RPSHRYCZ.js} +1 -1
- package/dist/{chunk-L5E7GEUU.js → chunk-XZS6KZHN.js} +6 -6
- package/dist/{errors-YPNK3AVF.js → errors-6BEPCY5N.js} +5 -5
- package/dist/index.js +152 -147
- package/dist/{interactive-D34T7RI6.js → interactive-EXQM6HWQ.js} +7 -9
- package/dist/{onboarding-A7IOH2MX.js → onboarding-2FLKQYLY.js} +6 -6
- package/dist/{policy-prompt-V6W7CPAO.js → policy-prompt-3EVE7DW3.js} +5 -5
- package/dist/{resolve-REZCFZZ7.js → resolve-FRMIY357.js} +9 -5
- package/package.json +1 -1
- package/dist/auth-23OYLRWN.js +0 -16
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,
|
|
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
|
|
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>` |
|
|
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>` |
|
|
@@ -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-
|
|
5
|
+
} from "./chunk-LANOFNO6.js";
|
|
6
6
|
import {
|
|
7
7
|
esc
|
|
8
|
-
} from "./chunk-
|
|
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.
|
|
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.
|
|
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.
|
|
430
|
+
ErrorCode.AUTH_REQUIRED,
|
|
444
431
|
message,
|
|
445
|
-
"
|
|
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
|
-
"
|
|
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-
|
|
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-
|
|
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 (
|
|
949
|
-
|
|
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.
|
|
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
|
|
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 (
|
|
1131
|
-
|
|
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
|
|
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
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
1587
|
-
const
|
|
1588
|
-
if (
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
if (
|
|
1597
|
-
|
|
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
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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-
|
|
5
|
+
} from "./chunk-RPSHRYCZ.js";
|
|
6
6
|
import {
|
|
7
7
|
resolveAuthToken,
|
|
8
8
|
resolveWalletSession
|
|
9
|
-
} from "./chunk-
|
|
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 =
|
|
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:
|
|
62
|
-
missing: hasAdminAuth ? [] : ["
|
|
63
|
-
nextCommands: hasAdminAuth ? [] : ["alchemy auth"
|
|
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
|
|
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
|