@alchemy/cli 0.2.1 → 0.2.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.
- package/dist/{chunk-SDUCDSCZ.js → chunk-2WI4JODY.js} +19 -2
- package/dist/{chunk-XP5KF4W2.js → chunk-6KOJKH6N.js} +52 -5
- package/dist/{chunk-HBRTTBCY.js → chunk-NA7MQB7X.js} +1 -1
- package/dist/index.js +19 -8
- package/dist/{interactive-L7N4HI7K.js → interactive-EAUEVR63.js} +2 -2
- package/dist/{onboarding-YA32OJOT.js → onboarding-SJ2BRK5I.js} +2 -2
- package/package.json +1 -1
|
@@ -326,8 +326,16 @@ function errNetwork(detail) {
|
|
|
326
326
|
"Check your internet connection and try again."
|
|
327
327
|
);
|
|
328
328
|
}
|
|
329
|
+
var RPC_ERROR_HINTS = {
|
|
330
|
+
[-32700]: "Parse error. The request JSON is malformed.",
|
|
331
|
+
[-32600]: "Invalid request. Check the JSON-RPC request format.",
|
|
332
|
+
[-32601]: "Method not supported. Check the method name and ensure your plan supports it.",
|
|
333
|
+
[-32602]: "Invalid parameters. Check argument types and format.",
|
|
334
|
+
[-32603]: "Internal JSON-RPC error."
|
|
335
|
+
};
|
|
329
336
|
function errRPC(code, message) {
|
|
330
|
-
|
|
337
|
+
const hint = RPC_ERROR_HINTS[code];
|
|
338
|
+
return new CLIError(ErrorCode.RPC_ERROR, `RPC error ${code}: ${message}`, hint);
|
|
331
339
|
}
|
|
332
340
|
function errInvalidArgs(detail) {
|
|
333
341
|
return new CLIError(ErrorCode.INVALID_ARGS, detail);
|
|
@@ -349,6 +357,14 @@ function errInvalidAccessKey() {
|
|
|
349
357
|
"Get an access key: https://www.alchemy.com/docs/reference/admin-api/overview"
|
|
350
358
|
);
|
|
351
359
|
}
|
|
360
|
+
function errAccessDenied(detail) {
|
|
361
|
+
const message = detail ? `Access denied: ${detail}` : "Access denied. Your access key may not have permission for this operation.";
|
|
362
|
+
return new CLIError(
|
|
363
|
+
ErrorCode.INVALID_ACCESS_KEY,
|
|
364
|
+
message,
|
|
365
|
+
"Check your account tier and feature access at https://dashboard.alchemy.com/"
|
|
366
|
+
);
|
|
367
|
+
}
|
|
352
368
|
function errAppRequired() {
|
|
353
369
|
return new CLIError(
|
|
354
370
|
ErrorCode.APP_REQUIRED,
|
|
@@ -1093,7 +1109,7 @@ function semverLT(a, b) {
|
|
|
1093
1109
|
return false;
|
|
1094
1110
|
}
|
|
1095
1111
|
function currentVersion() {
|
|
1096
|
-
return true ? "0.2.
|
|
1112
|
+
return true ? "0.2.2" : "0.0.0";
|
|
1097
1113
|
}
|
|
1098
1114
|
function toUpdateStatus(latestVersion, checkedAt) {
|
|
1099
1115
|
const current = currentVersion();
|
|
@@ -1178,6 +1194,7 @@ export {
|
|
|
1178
1194
|
errNotFound,
|
|
1179
1195
|
errRateLimited,
|
|
1180
1196
|
errInvalidAccessKey,
|
|
1197
|
+
errAccessDenied,
|
|
1181
1198
|
errAppRequired,
|
|
1182
1199
|
errWalletKeyRequired,
|
|
1183
1200
|
errAdminAPI,
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
configDir,
|
|
8
8
|
debug,
|
|
9
9
|
dim,
|
|
10
|
+
errAccessDenied,
|
|
10
11
|
errAccessKeyRequired,
|
|
11
12
|
errAdminAPI,
|
|
12
13
|
errAppRequired,
|
|
@@ -40,7 +41,7 @@ import {
|
|
|
40
41
|
toMap,
|
|
41
42
|
withSpinner,
|
|
42
43
|
yellow
|
|
43
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-2WI4JODY.js";
|
|
44
45
|
|
|
45
46
|
// src/lib/client-utils.ts
|
|
46
47
|
function isLocalhost(hostname) {
|
|
@@ -82,7 +83,24 @@ async function fetchWithTimeout(url, init) {
|
|
|
82
83
|
if (err instanceof DOMException && err.name === "TimeoutError") {
|
|
83
84
|
throw errNetwork(`Request timed out after ${timeout}ms`);
|
|
84
85
|
}
|
|
85
|
-
|
|
86
|
+
const message = err.message ?? String(err);
|
|
87
|
+
const causeMessage = err.cause?.message ?? "";
|
|
88
|
+
const causeCode = err.cause?.code ?? "";
|
|
89
|
+
const fullErrorText = `${message} ${causeMessage} ${causeCode}`;
|
|
90
|
+
if (/ENOTFOUND|EAI_AGAIN|getaddrinfo/i.test(fullErrorText)) {
|
|
91
|
+
try {
|
|
92
|
+
const hostname = new URL(url).hostname;
|
|
93
|
+
const networkSlug = hostname.replace(/\.g\.alchemy\.com$/, "");
|
|
94
|
+
if (networkSlug !== hostname) {
|
|
95
|
+
throw errInvalidArgs(
|
|
96
|
+
`Unknown network '${networkSlug}'. Run 'alchemy network list' to see available networks.`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
} catch (innerErr) {
|
|
100
|
+
if (innerErr instanceof CLIError) throw innerErr;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
throw errNetwork(message);
|
|
86
104
|
}
|
|
87
105
|
}
|
|
88
106
|
|
|
@@ -145,7 +163,18 @@ var AdminClient = class _AdminClient {
|
|
|
145
163
|
},
|
|
146
164
|
...body !== void 0 && { body: JSON.stringify(body) }
|
|
147
165
|
});
|
|
148
|
-
if (resp.status === 401
|
|
166
|
+
if (resp.status === 401) throw errInvalidAccessKey();
|
|
167
|
+
if (resp.status === 403) {
|
|
168
|
+
const detail = await resp.text().catch(() => "");
|
|
169
|
+
let reason;
|
|
170
|
+
try {
|
|
171
|
+
const parsed = JSON.parse(detail);
|
|
172
|
+
reason = parsed?.message || parsed?.error?.message || parsed?.error || void 0;
|
|
173
|
+
} catch {
|
|
174
|
+
reason = detail || void 0;
|
|
175
|
+
}
|
|
176
|
+
throw errAccessDenied(typeof reason === "string" ? reason : void 0);
|
|
177
|
+
}
|
|
149
178
|
if (resp.status === 404) {
|
|
150
179
|
const text = await resp.text().catch(() => "");
|
|
151
180
|
throw errNotFound(text || path);
|
|
@@ -686,10 +715,14 @@ var Client = class _Client {
|
|
|
686
715
|
try {
|
|
687
716
|
parsed = new URL(`https://${hostname}`);
|
|
688
717
|
} catch {
|
|
689
|
-
throw errInvalidArgs(
|
|
718
|
+
throw errInvalidArgs(
|
|
719
|
+
`Unknown network '${network}'. Run 'alchemy network list' to see available networks.`
|
|
720
|
+
);
|
|
690
721
|
}
|
|
691
722
|
if (!parsed.hostname.endsWith(".g.alchemy.com")) {
|
|
692
|
-
throw errInvalidArgs(
|
|
723
|
+
throw errInvalidArgs(
|
|
724
|
+
`Unknown network '${network}'. Run 'alchemy network list' to see available networks.`
|
|
725
|
+
);
|
|
693
726
|
}
|
|
694
727
|
}
|
|
695
728
|
rpcBaseURLOverride() {
|
|
@@ -718,6 +751,16 @@ var Client = class _Client {
|
|
|
718
751
|
if (networkNotEnabled) return networkNotEnabled;
|
|
719
752
|
return errInvalidAPIKey(detail || void 0);
|
|
720
753
|
}
|
|
754
|
+
tryParseRPCError(text) {
|
|
755
|
+
try {
|
|
756
|
+
const parsed = JSON.parse(text);
|
|
757
|
+
if (parsed?.error?.code !== void 0 && parsed?.error?.message !== void 0) {
|
|
758
|
+
return errRPC(parsed.error.code, parsed.error.message);
|
|
759
|
+
}
|
|
760
|
+
} catch {
|
|
761
|
+
}
|
|
762
|
+
return null;
|
|
763
|
+
}
|
|
721
764
|
async doFetch(url, init) {
|
|
722
765
|
return fetchWithTimeout(url, init);
|
|
723
766
|
}
|
|
@@ -743,6 +786,8 @@ var Client = class _Client {
|
|
|
743
786
|
}
|
|
744
787
|
if (!resp.ok) {
|
|
745
788
|
const text = await resp.text().catch(() => "");
|
|
789
|
+
const rpcError = this.tryParseRPCError(text);
|
|
790
|
+
if (rpcError) throw rpcError;
|
|
746
791
|
throw errNetwork(`HTTP ${resp.status}: ${text}`);
|
|
747
792
|
}
|
|
748
793
|
const rpcResp = await resp.json();
|
|
@@ -766,6 +811,8 @@ var Client = class _Client {
|
|
|
766
811
|
}
|
|
767
812
|
if (!resp.ok) {
|
|
768
813
|
const text = await resp.text().catch(() => "");
|
|
814
|
+
const rpcError = this.tryParseRPCError(text);
|
|
815
|
+
if (rpcError) throw rpcError;
|
|
769
816
|
throw errNetwork(`HTTP ${resp.status}: ${text}`);
|
|
770
817
|
}
|
|
771
818
|
return resp.json();
|
|
@@ -2,7 +2,7 @@
|
|
|
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-2WI4JODY.js";
|
|
6
6
|
|
|
7
7
|
// src/lib/networks.ts
|
|
8
8
|
var TESTNET_TOKEN_RE = /(testnet|sepolia|holesky|hoodi|devnet|minato|amoy|fuji|saigon|cardona|aeneid|curtis|chiado|cassiopeia|blaze|ropsten|signet|mocha|fam|bepolia)$/i;
|
package/dist/index.js
CHANGED
|
@@ -14,13 +14,13 @@ import {
|
|
|
14
14
|
splitCommaList,
|
|
15
15
|
validateAddress,
|
|
16
16
|
validateTxHash
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-6KOJKH6N.js";
|
|
18
18
|
import {
|
|
19
19
|
getRPCNetworks,
|
|
20
20
|
getSetupStatus,
|
|
21
21
|
isSetupComplete,
|
|
22
22
|
shouldRunOnboarding
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-NA7MQB7X.js";
|
|
24
24
|
import {
|
|
25
25
|
EXIT_CODES,
|
|
26
26
|
ErrorCode,
|
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
verbose,
|
|
66
66
|
weiToEth,
|
|
67
67
|
withSpinner
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-2WI4JODY.js";
|
|
69
69
|
|
|
70
70
|
// src/index.ts
|
|
71
71
|
import { Command, Help } from "commander";
|
|
@@ -277,6 +277,9 @@ Examples:
|
|
|
277
277
|
"block must be a number, hex, or 'latest'"
|
|
278
278
|
);
|
|
279
279
|
}
|
|
280
|
+
if (num < 0) {
|
|
281
|
+
throw errInvalidArgs("Block number must be non-negative.");
|
|
282
|
+
}
|
|
280
283
|
blockParam = `0x${num.toString(16)}`;
|
|
281
284
|
}
|
|
282
285
|
const client = clientFromFlags(program2);
|
|
@@ -1912,10 +1915,10 @@ function resetUpdateNoticeState() {
|
|
|
1912
1915
|
}
|
|
1913
1916
|
program.name("alchemy").description(
|
|
1914
1917
|
"The Alchemy CLI lets you query blockchain data, call JSON-RPC methods, and manage your Alchemy configuration."
|
|
1915
|
-
).version("0.2.
|
|
1918
|
+
).version("0.2.2", "-v, --version", "display CLI version").option("--api-key <key>", "Alchemy API key (env: ALCHEMY_API_KEY)").option("--access-key <key>", "Alchemy access key (env: ALCHEMY_ACCESS_KEY)").option(
|
|
1916
1919
|
"-n, --network <network>",
|
|
1917
1920
|
"Target network (default: eth-mainnet) (env: ALCHEMY_NETWORK)"
|
|
1918
|
-
).option("--x402", "Use x402 wallet-based gateway auth").option("--wallet-key-file <path>", "Path to wallet private key file for x402").option("--json", "Force JSON output").option("-q, --quiet", "Suppress non-essential output").option("--verbose", "Enable verbose output").option("--no-color", "Disable color output").option("--reveal", "Show secrets in plain text (TTY only)").option("--timeout <ms>", "Request timeout in milliseconds", parseInt).option("--debug", "Enable debug diagnostics").option("--no-interactive", "Disable REPL and prompt-driven interactions").addHelpCommand(false).exitOverride((err) => {
|
|
1921
|
+
).option("--x402", "Use x402 wallet-based gateway auth").option("--wallet-key-file <path>", "Path to wallet private key file for x402").option("--json", "Force JSON output").option("-q, --quiet", "Suppress non-essential output").option("--verbose", "Enable verbose output").option("--no-color", "Disable color output").option("--reveal", "Show secrets in plain text (TTY only)").option("--timeout <ms>", "Request timeout in milliseconds", parseInt).option("--debug", "Enable debug diagnostics").option("--no-interactive", "Disable REPL and prompt-driven interactions").addHelpCommand(false).allowExcessArguments(true).exitOverride((err) => {
|
|
1919
1922
|
if (err.code === "commander.help" || err.code === "commander.helpDisplayed" || err.code === "commander.version") {
|
|
1920
1923
|
process.exit(0);
|
|
1921
1924
|
}
|
|
@@ -2067,7 +2070,15 @@ ${styledLine}`;
|
|
|
2067
2070
|
}
|
|
2068
2071
|
}
|
|
2069
2072
|
resetUpdateNoticeState();
|
|
2070
|
-
}).action(async () => {
|
|
2073
|
+
}).action(async (_opts, cmd) => {
|
|
2074
|
+
const excessArgs = cmd.args;
|
|
2075
|
+
if (excessArgs.length > 0) {
|
|
2076
|
+
exitWithError(
|
|
2077
|
+
errInvalidArgs(
|
|
2078
|
+
`Unknown command '${excessArgs[0]}'. Run 'alchemy help' for available commands.`
|
|
2079
|
+
)
|
|
2080
|
+
);
|
|
2081
|
+
}
|
|
2071
2082
|
const cfg = load();
|
|
2072
2083
|
if (!isSetupComplete(cfg) && !isInteractiveAllowed(program)) {
|
|
2073
2084
|
throw errSetupRequired(getSetupStatus(cfg));
|
|
@@ -2075,7 +2086,7 @@ ${styledLine}`;
|
|
|
2075
2086
|
if (isInteractiveAllowed(program)) {
|
|
2076
2087
|
let latestForInteractiveStartup = null;
|
|
2077
2088
|
if (shouldRunOnboarding(program, cfg)) {
|
|
2078
|
-
const { runOnboarding } = await import("./onboarding-
|
|
2089
|
+
const { runOnboarding } = await import("./onboarding-SJ2BRK5I.js");
|
|
2079
2090
|
const latest = getAvailableUpdateOnce();
|
|
2080
2091
|
const completed = await runOnboarding(program, latest);
|
|
2081
2092
|
updateShownDuringInteractiveStartup = Boolean(latest);
|
|
@@ -2087,7 +2098,7 @@ ${styledLine}`;
|
|
|
2087
2098
|
latestForInteractiveStartup = getAvailableUpdateOnce();
|
|
2088
2099
|
updateShownDuringInteractiveStartup = Boolean(latestForInteractiveStartup);
|
|
2089
2100
|
}
|
|
2090
|
-
const { startREPL } = await import("./interactive-
|
|
2101
|
+
const { startREPL } = await import("./interactive-EAUEVR63.js");
|
|
2091
2102
|
program.exitOverride();
|
|
2092
2103
|
program.configureOutput({
|
|
2093
2104
|
writeErr: () => {
|
|
@@ -3,7 +3,7 @@ if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
|
|
|
3
3
|
import {
|
|
4
4
|
getRPCNetworkIds,
|
|
5
5
|
getSetupMethod
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-NA7MQB7X.js";
|
|
7
7
|
import {
|
|
8
8
|
bgRgb,
|
|
9
9
|
bold,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
rgb,
|
|
20
20
|
setBrandedHelpSuppressed,
|
|
21
21
|
setReplMode
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-2WI4JODY.js";
|
|
23
23
|
|
|
24
24
|
// src/commands/interactive.ts
|
|
25
25
|
import * as readline from "readline";
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
generateAndPersistWallet,
|
|
6
6
|
importAndPersistWallet,
|
|
7
7
|
selectOrCreateApp
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-6KOJKH6N.js";
|
|
9
9
|
import {
|
|
10
10
|
bold,
|
|
11
11
|
brand,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
promptSelect,
|
|
20
20
|
promptText,
|
|
21
21
|
save
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-2WI4JODY.js";
|
|
23
23
|
|
|
24
24
|
// src/commands/onboarding.ts
|
|
25
25
|
function printNextSteps(method) {
|