@alchemy/cli 0.7.4-alpha.37 → 0.8.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/dist/{auth-D6CT363I.js → auth-JPRZE2MA.js} +2 -2
- package/dist/auth-RINQSQDT.js +16 -0
- package/dist/{chunk-MYHXAACL.js → chunk-46LMXT54.js} +12 -4
- package/dist/chunk-5Y7UQ27V.js +186 -0
- package/dist/{chunk-6UHKZ5EN.js → chunk-76ZO4UJ4.js} +3 -3
- package/dist/{chunk-HR2UZ6ZU.js → chunk-DGZYRBXR.js} +1 -1
- package/dist/{chunk-2OUAYCVA.js → chunk-EKS2THJU.js} +6 -6
- package/dist/{chunk-UYZH6GSY.js → chunk-GNOTKJF4.js} +5 -5
- package/dist/{chunk-5HYOZ773.js → chunk-JWLZAO7S.js} +188 -130
- package/dist/{chunk-AUGBYMHT.js → chunk-L7VFXQSF.js} +1 -1
- package/dist/{chunk-WCZIVY4O.js → chunk-NGF46GZP.js} +1 -1
- package/dist/{chunk-PX2YJ7XC.js → chunk-ROBA7SR7.js} +1 -1
- package/dist/{errors-UL3W4ECQ.js → errors-A53DVJDY.js} +3 -1
- package/dist/index.js +525 -763
- package/dist/{interactive-Z2YHE6ME.js → interactive-6R3VKAPQ.js} +7 -7
- package/dist/{onboarding-Q5PBXH3M.js → onboarding-YHYXW4F3.js} +6 -6
- package/dist/policy-prompt-7AUZOA7S.js +18 -0
- package/dist/{resolve-PAQKIAX3.js → resolve-N3SX252M.js} +7 -3
- package/package.json +1 -1
- package/dist/auth-R5QHPFMA.js +0 -16
|
@@ -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-EKS2THJU.js";
|
|
7
|
+
import "./chunk-NGF46GZP.js";
|
|
8
|
+
import "./chunk-L7VFXQSF.js";
|
|
9
|
+
import "./chunk-JWLZAO7S.js";
|
|
10
|
+
import "./chunk-DGZYRBXR.js";
|
|
11
|
+
import "./chunk-ROBA7SR7.js";
|
|
12
|
+
import "./chunk-46LMXT54.js";
|
|
13
|
+
export {
|
|
14
|
+
registerAuth,
|
|
15
|
+
selectAppAfterAuth
|
|
16
|
+
};
|
|
@@ -375,6 +375,13 @@ function errAccessKeyRequired() {
|
|
|
375
375
|
"Get an access key: https://www.alchemy.com/docs/reference/admin-api/overview"
|
|
376
376
|
);
|
|
377
377
|
}
|
|
378
|
+
function errLoginRequired() {
|
|
379
|
+
return new CLIError(
|
|
380
|
+
ErrorCode.AUTH_REQUIRED,
|
|
381
|
+
"Sign in to Alchemy to continue. Run 'alchemy auth login', then retry.",
|
|
382
|
+
"alchemy auth login"
|
|
383
|
+
);
|
|
384
|
+
}
|
|
378
385
|
function errInvalidAPIKey(details) {
|
|
379
386
|
return new CLIError(
|
|
380
387
|
ErrorCode.INVALID_API_KEY,
|
|
@@ -448,8 +455,8 @@ function errAppRequired() {
|
|
|
448
455
|
function errWalletKeyRequired() {
|
|
449
456
|
return new CLIError(
|
|
450
457
|
ErrorCode.AUTH_REQUIRED,
|
|
451
|
-
"Wallet key required for x402. Set ALCHEMY_WALLET_KEY, run 'alchemy wallet connect --mode local', or use --wallet-key-file.",
|
|
452
|
-
"alchemy wallet connect --mode local"
|
|
458
|
+
"Wallet key required for x402. Set ALCHEMY_WALLET_KEY, run 'alchemy wallet connect --mode local --chain evm', or use --wallet-key-file.",
|
|
459
|
+
"alchemy wallet connect --mode local --chain evm"
|
|
453
460
|
);
|
|
454
461
|
}
|
|
455
462
|
function errSessionExpired() {
|
|
@@ -469,8 +476,8 @@ function errNoActiveSession() {
|
|
|
469
476
|
function errSolanaWalletKeyRequired() {
|
|
470
477
|
return new CLIError(
|
|
471
478
|
ErrorCode.AUTH_REQUIRED,
|
|
472
|
-
"Solana wallet key required. Set ALCHEMY_SOLANA_WALLET_KEY, run 'alchemy wallet connect --mode local', or use --solana-wallet-key-file.",
|
|
473
|
-
"alchemy wallet connect --mode local"
|
|
479
|
+
"Solana wallet key required. Set ALCHEMY_SOLANA_WALLET_KEY, run 'alchemy wallet connect --mode local --chain solana', or use --solana-wallet-key-file.",
|
|
480
|
+
"alchemy wallet connect --mode local --chain solana"
|
|
474
481
|
);
|
|
475
482
|
}
|
|
476
483
|
function errSolanaTransactionFailed(details) {
|
|
@@ -541,6 +548,7 @@ export {
|
|
|
541
548
|
CLIError,
|
|
542
549
|
errAuthRequired,
|
|
543
550
|
errAccessKeyRequired,
|
|
551
|
+
errLoginRequired,
|
|
544
552
|
errInvalidAPIKey,
|
|
545
553
|
errNetworkNotEnabled,
|
|
546
554
|
errNetwork,
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
|
|
3
|
+
import {
|
|
4
|
+
gasManagerClientFromFlags,
|
|
5
|
+
toAdminNetworkId
|
|
6
|
+
} from "./chunk-JWLZAO7S.js";
|
|
7
|
+
import {
|
|
8
|
+
dim,
|
|
9
|
+
green,
|
|
10
|
+
promptAutocomplete,
|
|
11
|
+
promptConfirm,
|
|
12
|
+
promptText,
|
|
13
|
+
withSpinner
|
|
14
|
+
} from "./chunk-DGZYRBXR.js";
|
|
15
|
+
import {
|
|
16
|
+
load,
|
|
17
|
+
save
|
|
18
|
+
} from "./chunk-ROBA7SR7.js";
|
|
19
|
+
import {
|
|
20
|
+
errAppRequired,
|
|
21
|
+
errInvalidArgs,
|
|
22
|
+
errLoginRequired
|
|
23
|
+
} from "./chunk-46LMXT54.js";
|
|
24
|
+
|
|
25
|
+
// src/lib/policy-prompt.ts
|
|
26
|
+
var CREATE_NEW_SENTINEL = "__create_new__";
|
|
27
|
+
var DEFAULT_SPONSORSHIP_EXPIRY_MS = "600000";
|
|
28
|
+
var DEFAULT_SOLANA_MAX_COUNT = "1000";
|
|
29
|
+
function flavorNoun(flavor) {
|
|
30
|
+
return flavor === "solana" ? "fee sponsorship" : "gas sponsorship";
|
|
31
|
+
}
|
|
32
|
+
async function selectOrCreatePolicy(opts) {
|
|
33
|
+
const cfg = load();
|
|
34
|
+
const appId = cfg.app?.id;
|
|
35
|
+
if (!appId) throw errAppRequired();
|
|
36
|
+
const client = opts.client ?? gasManagerClientFromFlags(opts.program);
|
|
37
|
+
const flavorLabel = flavorNoun(opts.flavor);
|
|
38
|
+
const policies = await withSpinner(
|
|
39
|
+
"Fetching gas policies\u2026",
|
|
40
|
+
"Policies fetched",
|
|
41
|
+
() => client.listAllPolicies({ appId })
|
|
42
|
+
);
|
|
43
|
+
const matching = filterPolicies(policies, opts.flavor, opts.network);
|
|
44
|
+
let selectedId = null;
|
|
45
|
+
if (matching.length === 0) {
|
|
46
|
+
console.log(
|
|
47
|
+
` ${dim(`No ${flavorLabel} policies found for ${opts.network} on app ${appId}. Let's create one.`)}`
|
|
48
|
+
);
|
|
49
|
+
const created = await runCreate(opts, client, appId);
|
|
50
|
+
if (!created) return null;
|
|
51
|
+
selectedId = created.policyId;
|
|
52
|
+
} else {
|
|
53
|
+
const selected = await promptAutocomplete({
|
|
54
|
+
message: `Select a ${flavorLabel} policy for ${opts.network}`,
|
|
55
|
+
placeholder: "Policy name or ID",
|
|
56
|
+
options: [
|
|
57
|
+
...matching.map((p) => ({
|
|
58
|
+
label: formatPolicyOption(p),
|
|
59
|
+
value: p.policyId
|
|
60
|
+
})),
|
|
61
|
+
{ label: "Create a new policy", value: CREATE_NEW_SENTINEL }
|
|
62
|
+
],
|
|
63
|
+
cancelMessage: "Cancelled policy selection.",
|
|
64
|
+
commitLabel: null
|
|
65
|
+
});
|
|
66
|
+
if (selected === null) return null;
|
|
67
|
+
if (selected === CREATE_NEW_SENTINEL) {
|
|
68
|
+
const created = await runCreate(opts, client, appId);
|
|
69
|
+
if (!created) return null;
|
|
70
|
+
selectedId = created.policyId;
|
|
71
|
+
} else {
|
|
72
|
+
selectedId = selected;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (!opts.skipPersistPrompt && selectedId) {
|
|
76
|
+
await maybePersist(opts.flavor, selectedId);
|
|
77
|
+
}
|
|
78
|
+
return selectedId;
|
|
79
|
+
}
|
|
80
|
+
async function createPolicyInteractive(opts) {
|
|
81
|
+
const cfg = load();
|
|
82
|
+
const appId = cfg.app?.id;
|
|
83
|
+
if (!appId) throw errAppRequired();
|
|
84
|
+
const client = opts.client ?? gasManagerClientFromFlags(opts.program);
|
|
85
|
+
const result = await runCreate(opts, client, appId);
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
function filterPolicies(policies, flavor, network) {
|
|
89
|
+
const adminId = toAdminNetworkId(network);
|
|
90
|
+
return policies.filter((p) => {
|
|
91
|
+
if (p.policyType !== flavor) return false;
|
|
92
|
+
if (!Array.isArray(p.networks)) return false;
|
|
93
|
+
return p.networks.includes(adminId);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function formatPolicyOption(p) {
|
|
97
|
+
const status = p.status === "active" ? green("active") : dim(p.status);
|
|
98
|
+
return `${p.policyName} (${p.policyId.slice(0, 10)}\u2026) \u2014 ${status}`;
|
|
99
|
+
}
|
|
100
|
+
async function runCreate(opts, client, appId) {
|
|
101
|
+
const name = await promptText({
|
|
102
|
+
message: "Policy name",
|
|
103
|
+
cancelMessage: "Cancelled policy creation."
|
|
104
|
+
});
|
|
105
|
+
if (name === null) return null;
|
|
106
|
+
if (!name.trim()) {
|
|
107
|
+
console.log(` ${dim("Skipped policy creation (no name).")}`);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const adminNetworkId = toAdminNetworkId(opts.network);
|
|
111
|
+
const nowUnix = String(Math.floor(Date.now() / 1e3));
|
|
112
|
+
const payload = opts.flavor === "sponsorship" ? {
|
|
113
|
+
policyName: name.trim(),
|
|
114
|
+
policyType: "sponsorship",
|
|
115
|
+
appId,
|
|
116
|
+
networks: [adminNetworkId],
|
|
117
|
+
rules: {
|
|
118
|
+
startTimeUnix: nowUnix,
|
|
119
|
+
sponsorshipExpiryMs: DEFAULT_SPONSORSHIP_EXPIRY_MS
|
|
120
|
+
}
|
|
121
|
+
} : {
|
|
122
|
+
policyName: name.trim(),
|
|
123
|
+
policyType: "solana",
|
|
124
|
+
appId,
|
|
125
|
+
networks: [adminNetworkId],
|
|
126
|
+
solanaRules: {
|
|
127
|
+
startTimeUnix: nowUnix,
|
|
128
|
+
maxCount: DEFAULT_SOLANA_MAX_COUNT
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const created = await withSpinner(
|
|
132
|
+
"Creating policy\u2026",
|
|
133
|
+
"Policy created",
|
|
134
|
+
() => client.createPolicy(payload)
|
|
135
|
+
);
|
|
136
|
+
console.log(` ${green("\u2713")} Created ${created.policyName} (${created.policyId})`);
|
|
137
|
+
const activate = await promptConfirm({
|
|
138
|
+
message: "Activate this policy now? (required before use)",
|
|
139
|
+
initialValue: true,
|
|
140
|
+
cancelMessage: "Skipped activation."
|
|
141
|
+
});
|
|
142
|
+
let activated = false;
|
|
143
|
+
if (activate === true) {
|
|
144
|
+
await withSpinner(
|
|
145
|
+
"Activating policy\u2026",
|
|
146
|
+
"Policy active",
|
|
147
|
+
() => client.setPolicyStatus(created.policyId, "active")
|
|
148
|
+
);
|
|
149
|
+
activated = true;
|
|
150
|
+
} else {
|
|
151
|
+
console.log(
|
|
152
|
+
` ${dim("Policy left inactive. Activate later with `alchemy gas-manager policy activate " + created.policyId + "`.")}`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
return { policyId: created.policyId, status: "created", activated };
|
|
156
|
+
}
|
|
157
|
+
async function maybePersist(flavor, policyId) {
|
|
158
|
+
const confirmed = await promptConfirm({
|
|
159
|
+
message: "Save as default policy for this CLI?",
|
|
160
|
+
initialValue: true,
|
|
161
|
+
cancelMessage: "Skipped saving default."
|
|
162
|
+
});
|
|
163
|
+
if (confirmed !== true) return;
|
|
164
|
+
const cfg = load();
|
|
165
|
+
const updated = flavor === "sponsorship" ? { ...cfg, evm_gas_policy_id: policyId } : { ...cfg, solana_fee_policy_id: policyId };
|
|
166
|
+
save(updated);
|
|
167
|
+
const key = flavor === "sponsorship" ? "evm-gas-policy-id" : "solana-fee-policy-id";
|
|
168
|
+
console.log(` ${green("\u2713")} Saved ${key} = ${policyId}`);
|
|
169
|
+
}
|
|
170
|
+
function errSponsorshipNeedsPolicy(flavor) {
|
|
171
|
+
const flag = flavor === "sponsorship" ? "--gas-policy-id" : "--fee-policy-id";
|
|
172
|
+
const label = flavor === "sponsorship" ? "Gas sponsorship" : "Fee sponsorship";
|
|
173
|
+
return errInvalidArgs(
|
|
174
|
+
`${label} requires a policy ID. Run 'alchemy gas-manager policy list' to pick one, pass ${flag} <id>, or run interactively to be prompted.`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
function errNotLoggedInForPolicyLookup() {
|
|
178
|
+
return errLoginRequired();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export {
|
|
182
|
+
selectOrCreatePolicy,
|
|
183
|
+
createPolicyInteractive,
|
|
184
|
+
errSponsorshipNeedsPolicy,
|
|
185
|
+
errNotLoggedInForPolicyLookup
|
|
186
|
+
};
|
|
@@ -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-ROBA7SR7.js";
|
|
6
6
|
import {
|
|
7
7
|
esc
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-46LMXT54.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.8.0" : "0.0.0";
|
|
57
57
|
}
|
|
58
58
|
function toUpdateStatus(latestVersion, checkedAt) {
|
|
59
59
|
const current = currentVersion();
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
completeLogin,
|
|
5
5
|
prepareLogin,
|
|
6
6
|
revokeToken
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NGF46GZP.js";
|
|
8
8
|
import {
|
|
9
9
|
isInteractiveAllowed
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-L7VFXQSF.js";
|
|
11
11
|
import {
|
|
12
12
|
AdminClient,
|
|
13
13
|
resolveAuthToken
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-JWLZAO7S.js";
|
|
15
15
|
import {
|
|
16
16
|
bold,
|
|
17
17
|
brand,
|
|
@@ -20,13 +20,13 @@ import {
|
|
|
20
20
|
promptAutocomplete,
|
|
21
21
|
promptText,
|
|
22
22
|
withSpinner
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-DGZYRBXR.js";
|
|
24
24
|
import {
|
|
25
25
|
configPath,
|
|
26
26
|
load,
|
|
27
27
|
maskIf,
|
|
28
28
|
save
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-ROBA7SR7.js";
|
|
30
30
|
import {
|
|
31
31
|
CLIError,
|
|
32
32
|
ErrorCode,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
exitWithError,
|
|
35
35
|
isJSONMode,
|
|
36
36
|
printHuman
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-46LMXT54.js";
|
|
38
38
|
|
|
39
39
|
// src/commands/auth.ts
|
|
40
40
|
function registerAuth(program) {
|
|
@@ -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-L7VFXQSF.js";
|
|
6
6
|
import {
|
|
7
7
|
resolveAuthToken,
|
|
8
8
|
resolveWalletSession
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-JWLZAO7S.js";
|
|
10
10
|
|
|
11
11
|
// src/lib/onboarding.ts
|
|
12
12
|
var SETUP_CAPABILITY_ORDER = [
|
|
@@ -74,14 +74,14 @@ function getSetupCapabilities(cfg) {
|
|
|
74
74
|
missing: hasLocalWallet || hasSessionWallet ? [] : ["wallet signer"],
|
|
75
75
|
nextCommands: hasLocalWallet || hasSessionWallet ? [] : [
|
|
76
76
|
"alchemy wallet connect",
|
|
77
|
-
"alchemy wallet connect --mode local"
|
|
77
|
+
"alchemy wallet connect --mode local --chain evm"
|
|
78
78
|
]
|
|
79
79
|
}),
|
|
80
80
|
x402: capabilityStatus({
|
|
81
81
|
complete: x402Ready,
|
|
82
82
|
satisfiedBy: x402Ready ? "x402_wallet" : null,
|
|
83
83
|
missing: x402Ready ? [] : ["x402 enabled with wallet key file"],
|
|
84
|
-
nextCommands: x402Ready ? [] : ["alchemy wallet connect --mode local && alchemy config set x402 true"]
|
|
84
|
+
nextCommands: x402Ready ? [] : ["alchemy wallet connect --mode local --chain evm && alchemy config set x402 true"]
|
|
85
85
|
})
|
|
86
86
|
};
|
|
87
87
|
}
|
|
@@ -115,7 +115,7 @@ function getSetupStatus(cfg) {
|
|
|
115
115
|
"alchemy auth",
|
|
116
116
|
"alchemy config set app",
|
|
117
117
|
"alchemy config set access-key <key> && alchemy config set app <app-id>",
|
|
118
|
-
"alchemy wallet connect --mode local && alchemy config set x402 true"
|
|
118
|
+
"alchemy wallet connect --mode local --chain evm && alchemy config set x402 true"
|
|
119
119
|
],
|
|
120
120
|
capabilities
|
|
121
121
|
};
|