@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/index.js CHANGED
@@ -1,28 +1,36 @@
1
1
  #!/usr/bin/env node
2
2
  if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
3
+ import {
4
+ createPolicyInteractive,
5
+ errNotLoggedInForPolicyLookup,
6
+ errSponsorshipNeedsPolicy,
7
+ selectOrCreatePolicy
8
+ } from "./chunk-5Y7UQ27V.js";
3
9
  import {
4
10
  registerAuth
5
- } from "./chunk-2OUAYCVA.js";
11
+ } from "./chunk-EKS2THJU.js";
6
12
  import {
7
13
  openBrowser
8
- } from "./chunk-WCZIVY4O.js";
14
+ } from "./chunk-NGF46GZP.js";
9
15
  import {
10
16
  SETUP_CAPABILITY_LABELS,
11
17
  SETUP_CAPABILITY_ORDER,
12
18
  getSetupStatus,
13
19
  isSetupComplete,
14
20
  shouldRunOnboarding
15
- } from "./chunk-UYZH6GSY.js";
21
+ } from "./chunk-GNOTKJF4.js";
16
22
  import {
17
23
  isInteractiveAllowed
18
- } from "./chunk-AUGBYMHT.js";
24
+ } from "./chunk-L7VFXQSF.js";
19
25
  import {
20
26
  adminClientFromFlags,
21
27
  clearSession,
22
28
  clientFromFlags,
23
29
  createPendingSession,
30
+ fromAdminNetworkId,
31
+ gasManagerClientFromFlags,
24
32
  getRPCNetworks,
25
- getWalletSessionByChain,
33
+ hasAuthLoginToken,
26
34
  isSessionValid,
27
35
  isSolanaNetwork,
28
36
  loadSession,
@@ -43,13 +51,14 @@ import {
43
51
  resolveWalletSession,
44
52
  resolveX402Client,
45
53
  saveSession,
54
+ toAdminNetworkId,
46
55
  updateSession
47
- } from "./chunk-5HYOZ773.js";
56
+ } from "./chunk-JWLZAO7S.js";
48
57
  import {
49
58
  getAvailableUpdate,
50
59
  getUpdateStatus,
51
60
  printUpdateNotice
52
- } from "./chunk-6UHKZ5EN.js";
61
+ } from "./chunk-76ZO4UJ4.js";
53
62
  import {
54
63
  bold,
55
64
  brand,
@@ -73,7 +82,7 @@ import {
73
82
  weiToEth,
74
83
  withSpinner,
75
84
  yellow
76
- } from "./chunk-HR2UZ6ZU.js";
85
+ } from "./chunk-DGZYRBXR.js";
77
86
  import {
78
87
  KEY_MAP,
79
88
  configDir,
@@ -84,7 +93,7 @@ import {
84
93
  save,
85
94
  toMap,
86
95
  validKeys
87
- } from "./chunk-PX2YJ7XC.js";
96
+ } from "./chunk-ROBA7SR7.js";
88
97
  import {
89
98
  CLIError,
90
99
  EXIT_CODES,
@@ -120,7 +129,7 @@ import {
120
129
  setFlags,
121
130
  setNoColor,
122
131
  verbose
123
- } from "./chunk-MYHXAACL.js";
132
+ } from "./chunk-46LMXT54.js";
124
133
 
125
134
  // src/index.ts
126
135
  import { Command, Help } from "commander";
@@ -553,12 +562,39 @@ function registerConfig(program2) {
553
562
  exitWithError(err);
554
563
  }
555
564
  });
556
- setCmd.command("evm-gas-policy-id <id>").description("Set the EVM gas policy ID for sponsored transactions").action((id) => {
565
+ setCmd.command("evm-gas-policy-id [id]").description("Set the EVM gas policy ID for sponsored transactions (omit ID for interactive)").action(async (id) => {
557
566
  try {
558
- const cfg = load();
559
- save({ ...cfg, evm_gas_policy_id: id });
560
- printHuman(`${green("\u2713")} Set evm-gas-policy-id
567
+ if (id) {
568
+ const cfg = load();
569
+ save({ ...cfg, evm_gas_policy_id: id });
570
+ printHuman(`${green("\u2713")} Set evm-gas-policy-id
561
571
  `, { key: "evm-gas-policy-id", status: "set" });
572
+ return;
573
+ }
574
+ if (!isInteractiveAllowed(program2)) {
575
+ throw errInvalidArgs(
576
+ "Interactive policy selection requires an interactive terminal. Pass an ID: `alchemy config set evm-gas-policy-id <id>`."
577
+ );
578
+ }
579
+ const { selectOrCreatePolicy: selectOrCreatePolicy2 } = await import("./policy-prompt-7AUZOA7S.js");
580
+ const { resolveNetwork: resolveNetwork2 } = await import("./resolve-N3SX252M.js");
581
+ const network = resolveNetwork2(program2);
582
+ await selectOrCreatePolicy2({
583
+ flavor: "sponsorship",
584
+ network,
585
+ program: program2,
586
+ skipPersistPrompt: true
587
+ }).then((policyId) => {
588
+ if (!policyId) return;
589
+ const cfg = load();
590
+ save({ ...cfg, evm_gas_policy_id: policyId });
591
+ printHuman(`${green("\u2713")} Set evm-gas-policy-id
592
+ `, {
593
+ key: "evm-gas-policy-id",
594
+ value: policyId,
595
+ status: "set"
596
+ });
597
+ });
562
598
  } catch (err) {
563
599
  exitWithError(err);
564
600
  }
@@ -581,12 +617,39 @@ function registerConfig(program2) {
581
617
  exitWithError(err);
582
618
  }
583
619
  });
584
- setCmd.command("solana-fee-policy-id <id>").description("Set the Solana fee policy ID for sponsored transactions").action((id) => {
620
+ setCmd.command("solana-fee-policy-id [id]").description("Set the Solana fee policy ID for sponsored transactions (omit ID for interactive)").action(async (id) => {
585
621
  try {
586
- const cfg = load();
587
- save({ ...cfg, solana_fee_policy_id: id });
588
- printHuman(`${green("\u2713")} Set solana-fee-policy-id
622
+ if (id) {
623
+ const cfg = load();
624
+ save({ ...cfg, solana_fee_policy_id: id });
625
+ printHuman(`${green("\u2713")} Set solana-fee-policy-id
589
626
  `, { key: "solana-fee-policy-id", status: "set" });
627
+ return;
628
+ }
629
+ if (!isInteractiveAllowed(program2)) {
630
+ throw errInvalidArgs(
631
+ "Interactive policy selection requires an interactive terminal. Pass an ID: `alchemy config set solana-fee-policy-id <id>`."
632
+ );
633
+ }
634
+ const { selectOrCreatePolicy: selectOrCreatePolicy2 } = await import("./policy-prompt-7AUZOA7S.js");
635
+ const { resolveSolanaNetwork: resolveSolanaNetwork2 } = await import("./resolve-N3SX252M.js");
636
+ const network = resolveSolanaNetwork2(program2);
637
+ await selectOrCreatePolicy2({
638
+ flavor: "solana",
639
+ network,
640
+ program: program2,
641
+ skipPersistPrompt: true
642
+ }).then((policyId) => {
643
+ if (!policyId) return;
644
+ const cfg = load();
645
+ save({ ...cfg, solana_fee_policy_id: policyId });
646
+ printHuman(`${green("\u2713")} Set solana-fee-policy-id
647
+ `, {
648
+ key: "solana-fee-policy-id",
649
+ value: policyId,
650
+ status: "set"
651
+ });
652
+ });
590
653
  } catch (err) {
591
654
  exitWithError(err);
592
655
  }
@@ -627,7 +690,7 @@ function registerConfig(program2) {
627
690
  printJSON(toMap(cfg));
628
691
  return;
629
692
  }
630
- const { resolveAuthToken: resolveAuthToken2 } = await import("./resolve-PAQKIAX3.js");
693
+ const { resolveAuthToken: resolveAuthToken2 } = await import("./resolve-N3SX252M.js");
631
694
  const validToken = resolveAuthToken2(cfg);
632
695
  const authStatus = cfg.auth_token ? validToken ? `${green("\u2713")} authenticated${cfg.auth_token_expires_at ? ` ${dim(`(expires ${cfg.auth_token_expires_at})`)}` : ""}` : `${yellow("\u25C6")} expired${cfg.auth_token_expires_at ? ` ${dim(`(${cfg.auth_token_expires_at})`)}` : ""}` : dim("(not set) \u2014 run 'alchemy auth' to log in");
633
696
  const pairs = [
@@ -1306,19 +1369,7 @@ var walletSessionCreateResponseSchema = z.object({
1306
1369
  approvalUrl: z.string().url(),
1307
1370
  expiresAt: z.string().datetime().optional()
1308
1371
  }).passthrough();
1309
- var walletSessionRequestSessionCreateResponseSchema = z.object({
1310
- walletSessionId: z.string().min(1),
1311
- chainType: z.string().min(1),
1312
- status: rawWalletSessionStateSchema.transform(normalizeWalletSessionState)
1313
- }).passthrough();
1314
- var walletSessionRequestCreateResponseSchema = z.object({
1315
- sessionId: z.string().min(1),
1316
- approvalUrl: z.string().url(),
1317
- expiresAt: z.string().datetime().optional(),
1318
- sessions: z.array(walletSessionRequestSessionCreateResponseSchema).min(1)
1319
- }).passthrough();
1320
1372
  var rawWalletSessionStatusResponseSchema = z.object({
1321
- type: z.literal("session").optional(),
1322
1373
  sessionId: z.string().min(1).optional(),
1323
1374
  status: rawWalletSessionStateSchema,
1324
1375
  expiresAt: z.string().datetime().optional(),
@@ -1334,15 +1385,6 @@ var rawWalletSessionStatusResponseSchema = z.object({
1334
1385
  chainType: z.string().min(1).optional(),
1335
1386
  capabilities: z.record(z.string(), z.boolean()).optional()
1336
1387
  }).passthrough();
1337
- var walletSessionRequestStatusResponseSchema = z.object({
1338
- type: z.literal("sessionRequest"),
1339
- sessionId: z.string().min(1),
1340
- sessions: z.array(
1341
- rawWalletSessionStatusResponseSchema.extend({
1342
- walletSessionId: z.string().min(1)
1343
- })
1344
- ).min(1)
1345
- }).passthrough();
1346
1388
  var walletSessionDisconnectResponseSchema = z.object({
1347
1389
  sessionId: z.string().min(1).optional(),
1348
1390
  status: rawWalletSessionStateSchema.optional().transform(
@@ -1369,14 +1411,9 @@ var rawEvmSigningChallengeResponseSchema = z.object({
1369
1411
  challenge: z.string().min(1),
1370
1412
  expiresAt: z.string().datetime(),
1371
1413
  requestExpiry: z.string().min(1),
1372
- method: z.enum([
1373
- "personal_sign",
1374
- "eth_signTypedData_v4",
1375
- "eth_sign7702Authorization",
1376
- "signTransaction"
1377
- ]),
1414
+ method: z.enum(["personal_sign", "eth_signTypedData_v4", "eth_sign7702Authorization"]),
1378
1415
  walletId: z.string().min(1),
1379
- walletAddress: z.string().min(1),
1416
+ walletAddress: z.string().regex(/^0x[a-fA-F0-9]{40}$/),
1380
1417
  providerKeyQuorumId: z.string().min(1).optional(),
1381
1418
  providerSignerId: z.string().min(1).optional()
1382
1419
  }).strict();
@@ -1402,10 +1439,6 @@ var signAuthorizationCompleteResponseSchema = z.object({
1402
1439
  y_parity: z.number().int()
1403
1440
  }).strict()
1404
1441
  }).strict();
1405
- var solanaSignTransactionCompleteResponseSchema = z.object({
1406
- signedTransaction: z.string().min(1),
1407
- encoding: z.literal("base64")
1408
- }).strict();
1409
1442
  function baseURLOverride() {
1410
1443
  const options = { allowedHostnames: [STAGING_ADMIN_API_HOST] };
1411
1444
  return parseBaseURLOverride(WALLET_API_BASE_URL_ENV, options) ?? parseBaseURLOverride(ADMIN_API_BASE_URL_ENV, options);
@@ -1499,17 +1532,6 @@ function normalizeWalletSessionStatus(session) {
1499
1532
  privySignerId: session.providerSignerId
1500
1533
  };
1501
1534
  }
1502
- function normalizeWalletSessionRequestStatus(request2) {
1503
- return {
1504
- sessionId: request2.sessionId,
1505
- sessions: request2.sessions.map(({ walletSessionId, ...session }) => {
1506
- return normalizeWalletSessionStatus({
1507
- ...session,
1508
- sessionId: walletSessionId
1509
- });
1510
- })
1511
- };
1512
- }
1513
1535
  function normalizeEvmSigningChallengeResponse(response) {
1514
1536
  return {
1515
1537
  ...response,
@@ -1525,15 +1547,7 @@ function toProviderSigningBindingInput(input) {
1525
1547
  ...privySignerId ? { providerSignerId: privySignerId } : {}
1526
1548
  };
1527
1549
  }
1528
- function toProviderSolanaSigningBindingInput(input) {
1529
- const { privyKeyQuorumId, privySignerId, ...rest } = input;
1530
- return {
1531
- ...rest,
1532
- ...privyKeyQuorumId ? { providerKeyQuorumId: privyKeyQuorumId } : {},
1533
- ...privySignerId ? { providerSignerId: privySignerId } : {}
1534
- };
1535
- }
1536
- async function createRemoteWalletSessionRequest(token, input) {
1550
+ async function createRemoteWalletSession(token, input) {
1537
1551
  let data;
1538
1552
  let requestInput = input;
1539
1553
  for (let attempt = 0; attempt < 3; attempt += 1) {
@@ -1544,19 +1558,16 @@ async function createRemoteWalletSessionRequest(token, input) {
1544
1558
  "/wallet/sessions",
1545
1559
  requestInput
1546
1560
  );
1547
- return unwrapAdminData(walletSessionRequestCreateResponseSchema, data);
1561
+ return unwrapAdminData(walletSessionCreateResponseSchema, data);
1548
1562
  } catch (err) {
1549
- const retryInput = getClientInstanceCompatibilityRetryInput(
1550
- requestInput,
1551
- err
1552
- );
1563
+ const retryInput = getClientInstanceCompatibilityRetryInput(requestInput, err);
1553
1564
  if (retryInput === void 0) {
1554
1565
  throw err;
1555
1566
  }
1556
1567
  requestInput = retryInput;
1557
1568
  }
1558
1569
  }
1559
- throw new CLIError(ErrorCode.NETWORK_ERROR, "Unable to create wallet session request.");
1570
+ throw new CLIError(ErrorCode.NETWORK_ERROR, "Unable to create wallet session.");
1560
1571
  }
1561
1572
  function getClientInstanceCompatibilityRetryInput(input, err) {
1562
1573
  if (input.environment.clientInstanceName !== void 0 && isUnsupportedClientInstanceMetadataError(err, "clientInstanceName")) {
@@ -1591,16 +1602,6 @@ async function getRemoteWalletSession(token, sessionId) {
1591
1602
  unwrapAdminData(rawWalletSessionStatusResponseSchema, data)
1592
1603
  );
1593
1604
  }
1594
- async function getRemoteWalletSessionRequest(token, sessionId) {
1595
- const data = await request(
1596
- token,
1597
- "GET",
1598
- `/wallet/sessions/${encodeURIComponent(sessionId)}`
1599
- );
1600
- return normalizeWalletSessionRequestStatus(
1601
- unwrapAdminData(walletSessionRequestStatusResponseSchema, data)
1602
- );
1603
- }
1604
1605
  async function disconnectRemoteWalletSession(token, sessionId) {
1605
1606
  try {
1606
1607
  const data = await request(
@@ -1679,24 +1680,6 @@ var signAuthorizationChallengeInputSchema = evmSigningSessionBindingBaseSchema.e
1679
1680
  executor: z.literal("self").optional()
1680
1681
  }).strict()
1681
1682
  }).strict().superRefine(ensureSessionSignerBinding);
1682
- var solanaSigningSessionBindingBaseSchema = z.object({
1683
- sessionId: z.string().uuid(),
1684
- walletId: z.string().min(1),
1685
- walletAddress: z.string().min(1),
1686
- privyKeyQuorumId: z.string().min(1).optional(),
1687
- privySignerId: z.string().min(1).optional()
1688
- });
1689
- var solanaSignTransactionChallengeInputSchema = solanaSigningSessionBindingBaseSchema.extend({
1690
- transaction: z.string().min(1),
1691
- encoding: z.literal("base64")
1692
- }).strict().superRefine((input, ctx) => {
1693
- if (!input.privyKeyQuorumId && !input.privySignerId) {
1694
- ctx.addIssue({
1695
- code: z.ZodIssueCode.custom,
1696
- message: "Provide privyKeyQuorumId or privySignerId."
1697
- });
1698
- }
1699
- });
1700
1683
  async function createRemoteSignTypedDataChallenge(token, input) {
1701
1684
  const parsedInput = signTypedDataChallengeInputSchema.parse(input);
1702
1685
  return createEvmSigningChallenge(
@@ -1735,25 +1718,6 @@ async function completeRemoteSignAuthorizationChallenge(token, input) {
1735
1718
  adminApiResponseSchema(signAuthorizationCompleteResponseSchema).transform((resp) => resp.data)
1736
1719
  );
1737
1720
  }
1738
- async function createRemoteSolanaSignTransactionChallenge(token, input) {
1739
- const parsedInput = solanaSignTransactionChallengeInputSchema.parse(input);
1740
- return createEvmSigningChallenge(
1741
- token,
1742
- "/wallet/solana/sign-transaction/challenge",
1743
- toProviderSolanaSigningBindingInput(parsedInput),
1744
- adminApiResponseSchema(rawEvmSigningChallengeResponseSchema).transform(
1745
- (resp) => normalizeEvmSigningChallengeResponse(resp.data)
1746
- )
1747
- );
1748
- }
1749
- async function completeRemoteSolanaSignTransactionChallenge(token, input) {
1750
- return completeEvmSigningChallenge(
1751
- token,
1752
- "/wallet/solana/sign-transaction/complete",
1753
- input,
1754
- adminApiResponseSchema(solanaSignTransactionCompleteResponseSchema).transform((resp) => resp.data)
1755
- );
1756
- }
1757
1721
 
1758
1722
  // src/commands/wallet.ts
1759
1723
  import QRCode from "qrcode";
@@ -1764,9 +1728,6 @@ var DEFAULT_WALLET_CAPABILITIES = {
1764
1728
  "evm.signTypedData": true,
1765
1729
  "evm.signAuthorization": true
1766
1730
  };
1767
- var DEFAULT_SOLANA_SESSION_CAPABILITIES = {
1768
- "solana.signTransaction": true
1769
- };
1770
1731
  function createEvmWallet() {
1771
1732
  const privateKey = generatePrivateKey();
1772
1733
  const account = privateKeyToAccount(privateKey);
@@ -1890,13 +1851,7 @@ async function withApprovalInterruptHandler(args) {
1890
1851
  return await args.run(controller.signal);
1891
1852
  } catch (err) {
1892
1853
  if (isWalletConnectInterruptedError(err)) {
1893
- await Promise.all(
1894
- args.sessionIds.map(
1895
- (sessionId) => disconnectRemoteWalletSession(args.authToken, sessionId).catch(
1896
- () => void 0
1897
- )
1898
- )
1899
- );
1854
+ await disconnectRemoteWalletSession(args.authToken, args.sessionId).catch(() => void 0);
1900
1855
  clearSession();
1901
1856
  }
1902
1857
  throw err;
@@ -1907,9 +1862,23 @@ async function withApprovalInterruptHandler(args) {
1907
1862
  }
1908
1863
  }
1909
1864
  }
1910
- function deriveWalletStatus(session) {
1865
+ function isFutureIsoDate(value) {
1866
+ const date = new Date(value);
1867
+ if (Number.isNaN(date.getTime())) {
1868
+ return false;
1869
+ }
1870
+ return date > /* @__PURE__ */ new Date();
1871
+ }
1872
+ function isActiveWalletSession(session, remoteStatus) {
1873
+ if (!session) return false;
1874
+ if (session.status !== "approved") return false;
1875
+ if (!isFutureIsoDate(session.expiresAt)) return false;
1876
+ if (remoteStatus && remoteStatus !== "approved") return false;
1877
+ return true;
1878
+ }
1879
+ function deriveWalletStatus(session, remoteStatus) {
1911
1880
  if (!session) return "none";
1912
- if (isSessionValid(session)) return "active";
1881
+ if (isActiveWalletSession(session, remoteStatus)) return "active";
1913
1882
  if (session.status === "pending") return "none";
1914
1883
  return "expired";
1915
1884
  }
@@ -2019,7 +1988,7 @@ function resolveQrAddress(args) {
2019
1988
  function missingQrWalletError(type, source) {
2020
1989
  if (source === "session") {
2021
1990
  return type === "solana" ? errInvalidArgs(
2022
- "No Solana session wallet is configured. Run `alchemy wallet connect --mode session --force`."
1991
+ "The session wallet does not yet support Solana QR selection. Use `alchemy wallet use local` or configure a local Solana wallet with `alchemy wallet connect --mode local --chain solana`."
2023
1992
  ) : errNoActiveSession();
2024
1993
  }
2025
1994
  if (source === "local") {
@@ -2030,6 +1999,20 @@ function missingQrWalletError(type, source) {
2030
1999
  function indentBlock(text, prefix = " ") {
2031
2000
  return text.split("\n").map((line) => line ? `${prefix}${line}` : line).join("\n");
2032
2001
  }
2002
+ function generateAndPersistWallet() {
2003
+ const wallet = createEvmWallet();
2004
+ const keyPath = persistWalletKey("wallet-key", wallet.privateKey, wallet.address);
2005
+ const cfg = load();
2006
+ save({ ...cfg, wallet_key_file: keyPath, wallet_address: wallet.address });
2007
+ return { address: wallet.address, keyFile: keyPath };
2008
+ }
2009
+ async function generateAndPersistSolanaWallet() {
2010
+ const wallet = await createSolanaWallet();
2011
+ const keyPath = persistWalletKey("solana-wallet-key", wallet.secretKey, wallet.address);
2012
+ const cfg = load();
2013
+ save({ ...cfg, solana_wallet_key_file: keyPath, solana_wallet_address: wallet.address });
2014
+ return { address: wallet.address, keyFile: keyPath };
2015
+ }
2033
2016
  async function createAndPersistWallets() {
2034
2017
  const evm = createEvmWallet();
2035
2018
  const solana = await createSolanaWallet();
@@ -2094,12 +2077,14 @@ function getEffectiveLocalWalletState(program2, cfg) {
2094
2077
  }
2095
2078
  async function runLocalCreate(opts) {
2096
2079
  const cfg = load();
2097
- const evmConflict = Boolean(cfg.wallet_key_file);
2098
- const solanaConflict = Boolean(cfg.solana_wallet_key_file);
2080
+ const wantsEvm = opts.chain === "evm" || opts.chain === "both";
2081
+ const wantsSolana = opts.chain === "solana" || opts.chain === "both";
2082
+ const evmConflict = wantsEvm && Boolean(cfg.wallet_key_file);
2083
+ const solanaConflict = wantsSolana && Boolean(cfg.solana_wallet_key_file);
2099
2084
  if ((evmConflict || solanaConflict) && !opts.force) {
2100
2085
  if (!isInteractiveAllowed(opts.program)) {
2101
2086
  throw errInvalidArgs(
2102
- "A local key is already configured. Re-run with --force to replace it."
2087
+ "A local key is already configured for the selected chain. Re-run with --force to replace it."
2103
2088
  );
2104
2089
  }
2105
2090
  const kinds = [evmConflict ? "EVM" : null, solanaConflict ? "Solana" : null].filter(Boolean).join(" and ");
@@ -2112,7 +2097,16 @@ async function runLocalCreate(opts) {
2112
2097
  throw errInvalidArgs("Aborted. Existing local key preserved.");
2113
2098
  }
2114
2099
  }
2115
- return await createAndPersistWallets();
2100
+ if (opts.chain === "both") {
2101
+ const { evm, solana: solana2 } = await createAndPersistWallets();
2102
+ return { evm, solana: solana2 };
2103
+ }
2104
+ if (opts.chain === "evm") {
2105
+ const evm = generateAndPersistWallet();
2106
+ return { evm };
2107
+ }
2108
+ const solana = await generateAndPersistSolanaWallet();
2109
+ return { solana };
2116
2110
  }
2117
2111
  function runLocalImport(opts) {
2118
2112
  const cfg = load();
@@ -2145,27 +2139,7 @@ async function runLocalImportInteractive(opts) {
2145
2139
  return runLocalImport({ ...opts, force: true });
2146
2140
  }
2147
2141
  }
2148
- function capabilitiesForChain(chain) {
2149
- return chain === "evm" ? { ...DEFAULT_WALLET_CAPABILITIES } : { ...DEFAULT_SOLANA_SESSION_CAPABILITIES };
2150
- }
2151
- function capabilitiesForChains(chains) {
2152
- return Object.fromEntries(
2153
- chains.map((chain) => [chain, capabilitiesForChain(chain)])
2154
- );
2155
- }
2156
- function getApprovedSessionWalletMetadata(chain, session) {
2157
- const walletId = chain === "evm" ? session.walletId ?? session.evmWalletId : session.solanaWalletId ?? session.walletId;
2158
- const walletAddress = chain === "evm" ? session.evmAddress ?? session.address : session.solanaAddress ?? session.address;
2159
- if (!walletId || !walletAddress) {
2160
- throw new CLIError(
2161
- ErrorCode.INTERNAL_ERROR,
2162
- "Approved wallet session response missing required metadata."
2163
- );
2164
- }
2165
- return { walletId, walletAddress };
2166
- }
2167
2142
  async function runSessionConnect(opts) {
2168
- const requestedChains = ["evm", "solana"];
2169
2143
  const authToken = resolveAuthToken();
2170
2144
  if (!authToken) throw errAuthRequired();
2171
2145
  const existing = loadSession();
@@ -2203,51 +2177,32 @@ async function runSessionConnect(opts) {
2203
2177
  ...clientInstance.name === void 0 ? {} : { clientInstanceName: clientInstance.name }
2204
2178
  };
2205
2179
  updateSession({
2206
- chainType: "both",
2207
- capabilities: Object.assign(
2208
- {},
2209
- ...requestedChains.map((chain) => capabilitiesForChain(chain))
2210
- ),
2180
+ chainType: "evm",
2181
+ capabilities: { ...DEFAULT_WALLET_CAPABILITIES },
2211
2182
  backendBaseUrl: getWalletApiBaseUrl(),
2212
2183
  environment: sessionEnvironment
2213
2184
  });
2214
- const remoteRequest = await createRemoteWalletSessionRequest(authToken, {
2185
+ const remoteSession = await createRemoteWalletSession(authToken, {
2215
2186
  publicKeyJwk: session.publicKeyJwk,
2216
2187
  requestSignerVersion: session.envelopeVersion,
2217
- chains: requestedChains,
2218
- capabilities: capabilitiesForChains(requestedChains),
2188
+ chainType: "evm",
2189
+ capabilities: { ...DEFAULT_WALLET_CAPABILITIES },
2219
2190
  environment: sessionEnvironment
2220
2191
  }).catch((err) => {
2221
2192
  clearSession();
2222
2193
  throw err;
2223
2194
  });
2224
- const pendingSessionsByChain = Object.fromEntries(
2225
- remoteRequest.sessions.map((remoteSession) => [
2226
- remoteSession.chainType,
2227
- {
2228
- sessionId: remoteSession.walletSessionId,
2229
- status: "pending",
2230
- expiresAt: remoteRequest.expiresAt ?? session.expiresAt,
2231
- chainType: remoteSession.chainType,
2232
- capabilities: capabilitiesForChain(
2233
- remoteSession.chainType
2234
- )
2235
- }
2236
- ])
2237
- );
2238
2195
  updateSession({
2239
- connectionRequestId: remoteRequest.sessionId,
2240
- sessionId: remoteRequest.sessions[0].walletSessionId,
2241
- expiresAt: remoteRequest.expiresAt ?? session.expiresAt,
2242
- sessionsByChain: pendingSessionsByChain
2196
+ sessionId: remoteSession.sessionId,
2197
+ expiresAt: remoteSession.expiresAt ?? session.expiresAt
2243
2198
  });
2244
2199
  if (!isJSONMode()) {
2245
2200
  const summaryPairs = [
2246
- ["Connection Request ID", remoteRequest.sessionId],
2201
+ ["Session ID", remoteSession.sessionId],
2247
2202
  ["Status", "pending"],
2248
- ["Approval URL", remoteRequest.approvalUrl],
2203
+ ["Approval URL", remoteSession.approvalUrl],
2249
2204
  ["Created", session.createdAt],
2250
- ["Expires", remoteRequest.expiresAt ?? session.expiresAt]
2205
+ ["Expires", remoteSession.expiresAt ?? session.expiresAt]
2251
2206
  ];
2252
2207
  if (clientInstance.name !== void 0) {
2253
2208
  summaryPairs.splice(1, 0, ["Instance", clientInstance.name]);
@@ -2262,14 +2217,7 @@ async function runSessionConnect(opts) {
2262
2217
  });
2263
2218
  if (answer === null) {
2264
2219
  clearSession();
2265
- await Promise.all(
2266
- remoteRequest.sessions.map(
2267
- (remoteSession) => disconnectRemoteWalletSession(
2268
- authToken,
2269
- remoteSession.walletSessionId
2270
- ).catch(() => void 0)
2271
- )
2272
- );
2220
+ await disconnectRemoteWalletSession(authToken, remoteSession.sessionId).catch(() => void 0);
2273
2221
  throw new WalletConnectInterruptedError();
2274
2222
  }
2275
2223
  }
@@ -2277,41 +2225,25 @@ async function runSessionConnect(opts) {
2277
2225
  console.log(` Opening browser for approval...`);
2278
2226
  console.log(` ${dim("Waiting for dashboard approval to complete connection.")}`);
2279
2227
  }
2280
- openBrowser(remoteRequest.approvalUrl);
2281
- const approvedSessions = await withApprovalInterruptHandler({
2228
+ openBrowser(remoteSession.approvalUrl);
2229
+ const approvedSession = await withApprovalInterruptHandler({
2282
2230
  authToken,
2283
- sessionIds: remoteRequest.sessions.map(
2284
- (remoteSession) => remoteSession.walletSessionId
2285
- ),
2231
+ sessionId: remoteSession.sessionId,
2286
2232
  run: async (signal) => {
2287
2233
  const startedAt = Date.now();
2288
2234
  while (Date.now() - startedAt < CONNECT_TIMEOUT_MS) {
2289
- const currentSessions = await waitForInterruptible(
2290
- remoteRequest.sessionId ? getRemoteWalletSessionRequest(
2291
- authToken,
2292
- remoteRequest.sessionId
2293
- ).then((request2) => request2.sessions) : Promise.all(
2294
- remoteRequest.sessions.map(
2295
- (remoteSession) => getRemoteWalletSession(authToken, remoteSession.walletSessionId)
2296
- )
2297
- ),
2235
+ const current = await waitForInterruptible(
2236
+ getRemoteWalletSession(authToken, remoteSession.sessionId),
2298
2237
  signal
2299
2238
  );
2300
- if (requestedChains.every(
2301
- (chain) => currentSessions.some((current) => {
2302
- return current.chainType === chain && current.status === "approved";
2303
- })
2304
- )) {
2305
- return currentSessions;
2239
+ if (current.status === "approved") {
2240
+ return current;
2306
2241
  }
2307
- const terminalSession = currentSessions.find((current) => {
2308
- return current.status === "denied" || current.status === "revoked" || current.status === "expired";
2309
- });
2310
- if (terminalSession) {
2242
+ if (current.status === "denied" || current.status === "revoked" || current.status === "expired") {
2311
2243
  clearSession();
2312
2244
  throw new CLIError(
2313
2245
  ErrorCode.INTERNAL_ERROR,
2314
- `Wallet session ${terminalSession.status}.`,
2246
+ `Wallet session ${current.status}.`,
2315
2247
  "Run 'alchemy wallet connect' to start a new approval flow."
2316
2248
  );
2317
2249
  }
@@ -2320,123 +2252,58 @@ async function runSessionConnect(opts) {
2320
2252
  return null;
2321
2253
  }
2322
2254
  });
2323
- if (!approvedSessions) {
2255
+ if (!approvedSession) {
2324
2256
  throw new CLIError(
2325
2257
  ErrorCode.NETWORK_ERROR,
2326
2258
  "Timed out waiting for wallet approval.",
2327
2259
  "Finish approval in the dashboard and rerun 'alchemy wallet connect --force' if needed."
2328
2260
  );
2329
2261
  }
2330
- const missingProviderAppId = approvedSessions.find((approvedSession) => {
2331
- return !approvedSession.privyAppId;
2332
- });
2333
- if (missingProviderAppId) {
2262
+ const walletId = approvedSession.walletId ?? approvedSession.evmWalletId;
2263
+ const evmAddress = approvedSession.evmAddress ?? approvedSession.address;
2264
+ if (!approvedSession.privyAppId || !walletId || !evmAddress) {
2334
2265
  throw new CLIError(
2335
2266
  ErrorCode.INTERNAL_ERROR,
2336
2267
  "Approved wallet session response missing required metadata."
2337
2268
  );
2338
2269
  }
2339
- const approvedSessionsByChain = Object.fromEntries(
2340
- requestedChains.map((chain) => {
2341
- const approvedSession = approvedSessions.find((current) => {
2342
- return current.chainType === chain;
2343
- });
2344
- if (!approvedSession) {
2345
- throw new CLIError(
2346
- ErrorCode.INTERNAL_ERROR,
2347
- "Approved wallet session response missing requested chain."
2348
- );
2349
- }
2350
- const { walletId, walletAddress } = getApprovedSessionWalletMetadata(
2351
- chain,
2352
- approvedSession
2353
- );
2354
- return [
2355
- chain,
2356
- {
2357
- sessionId: approvedSession.sessionId ?? remoteRequest.sessions.find((remoteSession) => remoteSession.chainType === chain)?.walletSessionId ?? session.sessionId,
2358
- status: "approved",
2359
- expiresAt: approvedSession.expiresAt ?? remoteRequest.expiresAt ?? session.expiresAt,
2360
- chainType: chain,
2361
- walletId,
2362
- walletAddress,
2363
- providerKeyQuorumId: approvedSession.privyKeyQuorumId,
2364
- providerSignerId: approvedSession.privySignerId,
2365
- capabilities: approvedSession.capabilities ?? capabilitiesForChain(chain)
2366
- }
2367
- ];
2368
- })
2369
- );
2370
- const firstApprovedSession = approvedSessions.find((approvedSession) => {
2371
- return approvedSession.chainType === requestedChains[0];
2372
- }) ?? approvedSessions[0];
2373
- const evmSession = approvedSessionsByChain.evm;
2374
- const solanaSession = approvedSessionsByChain.solana;
2375
2270
  updateSession({
2376
- connectionRequestId: remoteRequest.sessionId,
2377
- sessionId: firstApprovedSession.sessionId ?? remoteRequest.sessions[0].walletSessionId,
2271
+ sessionId: approvedSession.sessionId ?? remoteSession.sessionId,
2378
2272
  status: "approved",
2379
- expiresAt: firstApprovedSession.expiresAt ?? remoteRequest.expiresAt ?? session.expiresAt,
2380
- privyAppId: firstApprovedSession.privyAppId,
2381
- walletId: evmSession?.walletId ?? solanaSession?.walletId,
2382
- evmWalletId: evmSession?.walletId,
2383
- evmAddress: evmSession?.walletAddress,
2384
- solanaWalletId: solanaSession?.walletId,
2385
- solanaAddress: solanaSession?.walletAddress,
2386
- privyKeyQuorumId: evmSession?.providerKeyQuorumId ?? solanaSession?.providerKeyQuorumId,
2387
- privySignerId: evmSession?.providerSignerId ?? solanaSession?.providerSignerId,
2388
- chainType: "both",
2389
- capabilities: Object.assign(
2390
- {},
2391
- ...requestedChains.map((chain) => capabilitiesForChain(chain)),
2392
- ...approvedSessions.map((approvedSession) => approvedSession.capabilities ?? {})
2393
- ),
2394
- sessionsByChain: approvedSessionsByChain,
2273
+ expiresAt: approvedSession.expiresAt ?? remoteSession.expiresAt ?? session.expiresAt,
2274
+ privyAppId: approvedSession.privyAppId,
2275
+ walletId,
2276
+ evmWalletId: approvedSession.evmWalletId ?? walletId,
2277
+ evmAddress,
2278
+ solanaWalletId: approvedSession.solanaWalletId,
2279
+ solanaAddress: approvedSession.solanaAddress,
2280
+ privyKeyQuorumId: approvedSession.privyKeyQuorumId,
2281
+ privySignerId: approvedSession.privySignerId,
2282
+ chainType: approvedSession.chainType ?? "evm",
2283
+ capabilities: approvedSession.capabilities ?? { ...DEFAULT_WALLET_CAPABILITIES },
2395
2284
  backendBaseUrl: getWalletApiBaseUrl(),
2396
2285
  environment: sessionEnvironment
2397
2286
  });
2398
2287
  if (isJSONMode()) {
2399
2288
  printJSON({
2400
- connectionRequestId: remoteRequest.sessionId,
2401
- sessionId: firstApprovedSession.sessionId ?? remoteRequest.sessions[0].walletSessionId,
2402
- walletSessionId: firstApprovedSession.sessionId ?? remoteRequest.sessions[0].walletSessionId,
2289
+ sessionId: approvedSession.sessionId ?? remoteSession.sessionId,
2403
2290
  status: "approved",
2404
- privyAppId: firstApprovedSession.privyAppId,
2405
- walletId: evmSession?.walletId ?? solanaSession?.walletId,
2406
- ...evmSession ? {
2407
- evmAddress: evmSession.walletAddress,
2408
- evmWalletId: evmSession.walletId
2409
- } : {},
2410
- ...solanaSession ? {
2411
- solanaAddress: solanaSession.walletAddress,
2412
- solanaWalletId: solanaSession.walletId
2413
- } : {},
2414
- chainType: "both",
2415
- capabilities: Object.assign(
2416
- {},
2417
- ...requestedChains.map((chain) => capabilitiesForChain(chain))
2418
- ),
2419
- expiresAt: firstApprovedSession.expiresAt ?? remoteRequest.expiresAt ?? session.expiresAt,
2420
- sessionsByChain: approvedSessionsByChain
2291
+ privyAppId: approvedSession.privyAppId,
2292
+ walletId,
2293
+ evmAddress,
2294
+ evmWalletId: approvedSession.evmWalletId ?? walletId,
2295
+ chainType: approvedSession.chainType ?? "evm",
2296
+ capabilities: approvedSession.capabilities ?? { ...DEFAULT_WALLET_CAPABILITIES },
2297
+ expiresAt: approvedSession.expiresAt ?? remoteSession.expiresAt ?? session.expiresAt
2421
2298
  });
2422
2299
  } else {
2423
- const pairs = [
2424
- ["Connection Request ID", remoteRequest.sessionId],
2425
- ["Status", green("approved")]
2426
- ];
2427
- for (const chain of requestedChains) {
2428
- const chainSession = approvedSessionsByChain[chain];
2429
- if (!chainSession) continue;
2430
- pairs.push(
2431
- [`${chain.toUpperCase()} Wallet ID`, chainSession.walletId ?? ""],
2432
- [`${chain.toUpperCase()} Address`, green(chainSession.walletAddress ?? "")]
2433
- );
2434
- }
2435
- pairs.push([
2436
- "Expires",
2437
- firstApprovedSession.expiresAt ?? remoteRequest.expiresAt ?? session.expiresAt
2300
+ printKeyValue([
2301
+ ["Session ID", approvedSession.sessionId ?? remoteSession.sessionId],
2302
+ ["Status", green("approved")],
2303
+ ["Wallet ID", walletId],
2304
+ ["EVM Address", green(evmAddress)],
2305
+ ["Expires", approvedSession.expiresAt ?? remoteSession.expiresAt ?? session.expiresAt]
2438
2306
  ]);
2439
- printKeyValue(pairs);
2440
2307
  console.log(` ${green("\u2713")} Wallet connected`);
2441
2308
  }
2442
2309
  }
@@ -2505,6 +2372,17 @@ async function runConnectFlow(program2, opts) {
2505
2372
  }
2506
2373
  mode2 = "local";
2507
2374
  }
2375
+ let chain = "both";
2376
+ if (opts.chain !== void 0) {
2377
+ if (opts.chain !== "evm" && opts.chain !== "solana" && opts.chain !== "both") {
2378
+ throw errInvalidArgs("`--chain` must be 'evm', 'solana', or 'both'.");
2379
+ }
2380
+ chain = opts.chain;
2381
+ }
2382
+ if (importPath && chain !== "evm" && opts.chain !== void 0) {
2383
+ throw errInvalidArgs("`--import` implies `--chain evm`; omit `--chain` or set it to 'evm'.");
2384
+ }
2385
+ if (importPath) chain = "evm";
2508
2386
  if (!mode2) {
2509
2387
  if (!isInteractiveAllowed(program2)) {
2510
2388
  throw errInvalidArgs(
@@ -2514,7 +2392,7 @@ async function runConnectFlow(program2, opts) {
2514
2392
  const choice = await promptSelect({
2515
2393
  message: "Choose a wallet to connect",
2516
2394
  options: [
2517
- { value: "session", label: "Session wallet", hint: "Recommended \u2014 Alchemy-managed, more secure" },
2395
+ { value: "session", label: "Session wallet", hint: "Recommended \u2014 Alchemy/Privy-managed, more secure" },
2518
2396
  { value: "local", label: "Local wallet", hint: "Private key stored on this machine" }
2519
2397
  ],
2520
2398
  initialValue: "session",
@@ -2524,11 +2402,7 @@ async function runConnectFlow(program2, opts) {
2524
2402
  mode2 = choice;
2525
2403
  }
2526
2404
  if (mode2 === "session") {
2527
- await runSessionConnect({
2528
- program: program2,
2529
- force,
2530
- instanceName: opts.instanceName
2531
- });
2405
+ await runSessionConnect({ program: program2, force, instanceName: opts.instanceName });
2532
2406
  printCrossModeHintAfterSessionConnect();
2533
2407
  return;
2534
2408
  }
@@ -2538,30 +2412,9 @@ async function runConnectFlow(program2, opts) {
2538
2412
  printCrossModeHintAfterLocal("evm");
2539
2413
  return;
2540
2414
  }
2541
- const result = await runLocalCreate({ force, program: program2 });
2415
+ const result = await runLocalCreate({ chain, force, program: program2 });
2542
2416
  printPostLocalCreateSummary(result);
2543
- printCrossModeHintAfterLocal("both");
2544
- }
2545
- function uniqueSessionIds(session) {
2546
- const ids = Object.values(session.sessionsByChain ?? {}).map((chainSession) => chainSession?.sessionId).filter((sessionId) => Boolean(sessionId));
2547
- if (ids.length === 0) {
2548
- ids.push(session.sessionId);
2549
- }
2550
- return Array.from(new Set(ids));
2551
- }
2552
- function selectRemoteSessionForStatus(session, remoteSessions) {
2553
- return remoteSessions.find((remoteSession) => {
2554
- return remoteSession.status !== "approved";
2555
- }) ?? remoteSessions.find((remoteSession) => {
2556
- return remoteSession.sessionId === session.sessionId;
2557
- }) ?? remoteSessions[0];
2558
- }
2559
- function mergeRemoteCapabilities(session, remoteSessions) {
2560
- return Object.assign(
2561
- {},
2562
- session.capabilities ?? {},
2563
- ...remoteSessions.map((remoteSession) => remoteSession.capabilities ?? {})
2564
- );
2417
+ printCrossModeHintAfterLocal(chain);
2565
2418
  }
2566
2419
  async function buildSessionSnapshot(program2, verify) {
2567
2420
  let session = loadStoredSession?.() ?? loadSession();
@@ -2569,55 +2422,25 @@ async function buildSessionSnapshot(program2, verify) {
2569
2422
  if (verify && session) {
2570
2423
  const authToken = resolveAuthToken();
2571
2424
  if (!authToken) throw errAuthRequired();
2572
- const remoteSessions = session.connectionRequestId ? await getRemoteWalletSessionRequest(authToken, session.connectionRequestId).then((request2) => request2.sessions) : await Promise.all(
2573
- uniqueSessionIds(session).map(
2574
- (sessionId) => getRemoteWalletSession(authToken, sessionId)
2575
- )
2576
- );
2577
- const remote = selectRemoteSessionForStatus(session, remoteSessions);
2425
+ const remote = await getRemoteWalletSession(authToken, session.sessionId);
2578
2426
  remoteStatus = remote.status;
2579
- const nextSessionsByChain = { ...session.sessionsByChain ?? {} };
2580
- for (const remoteSession of remoteSessions) {
2581
- const chain = remoteSession.chainType === "solana" ? "solana" : "evm";
2582
- const walletIdForChain = chain === "solana" ? remoteSession.solanaWalletId ?? remoteSession.walletId : remoteSession.evmWalletId ?? remoteSession.walletId;
2583
- const walletAddressForChain = chain === "solana" ? remoteSession.solanaAddress ?? remoteSession.address : remoteSession.evmAddress ?? remoteSession.address;
2584
- nextSessionsByChain[chain] = {
2585
- ...nextSessionsByChain[chain] ?? {},
2586
- sessionId: remoteSession.sessionId ?? nextSessionsByChain[chain]?.sessionId ?? session.sessionId,
2587
- status: normalizeRemoteStatusForStorage(remoteSession.status),
2588
- expiresAt: remoteSession.expiresAt ?? nextSessionsByChain[chain]?.expiresAt ?? session.expiresAt,
2589
- chainType: chain,
2590
- ...walletIdForChain ? { walletId: walletIdForChain } : {},
2591
- ...walletAddressForChain ? { walletAddress: walletAddressForChain } : {},
2592
- ...remoteSession.privyKeyQuorumId ? { providerKeyQuorumId: remoteSession.privyKeyQuorumId } : {},
2593
- ...remoteSession.privySignerId ? { providerSignerId: remoteSession.privySignerId } : {},
2594
- ...remoteSession.capabilities ? { capabilities: remoteSession.capabilities } : {}
2595
- };
2596
- }
2597
- const remoteChain = remote.chainType === "solana" ? "solana" : "evm";
2598
- const remoteWalletId = remoteChain === "solana" ? remote.solanaWalletId ?? remote.walletId : remote.evmWalletId ?? remote.walletId;
2599
- const evmWalletId = remoteChain === "evm" ? remoteWalletId ?? session.evmWalletId : session.evmWalletId;
2600
- const evmAddress = remoteChain === "evm" ? remote.evmAddress ?? remote.address ?? session.evmAddress : session.evmAddress;
2601
- const solanaWalletId = remoteChain === "solana" ? remoteWalletId ?? session.solanaWalletId : session.solanaWalletId;
2602
- const solanaAddress = remoteChain === "solana" ? remote.solanaAddress ?? remote.address ?? session.solanaAddress : session.solanaAddress;
2603
- const chainType = nextSessionsByChain.evm && nextSessionsByChain.solana ? "both" : remote.chainType ?? session.chainType;
2427
+ const walletId2 = remote.walletId ?? remote.evmWalletId;
2604
2428
  session = {
2605
2429
  ...session,
2606
2430
  status: normalizeRemoteStatusForStorage(remote.status),
2607
2431
  expiresAt: remote.expiresAt ?? session.expiresAt,
2608
2432
  privyAppId: remote.privyAppId ?? session.privyAppId,
2609
- walletId: evmWalletId ?? solanaWalletId ?? session.walletId,
2610
- evmWalletId,
2611
- evmAddress,
2612
- solanaWalletId,
2613
- solanaAddress,
2614
- chainType,
2615
- capabilities: mergeRemoteCapabilities(session, remoteSessions),
2616
- sessionsByChain: nextSessionsByChain
2433
+ walletId: walletId2 ?? session.walletId,
2434
+ evmWalletId: remote.evmWalletId ?? walletId2 ?? session.evmWalletId,
2435
+ evmAddress: remote.evmAddress ?? remote.address ?? session.evmAddress,
2436
+ solanaWalletId: remote.solanaWalletId ?? session.solanaWalletId,
2437
+ solanaAddress: remote.solanaAddress ?? session.solanaAddress,
2438
+ chainType: remote.chainType ?? session.chainType,
2439
+ capabilities: remote.capabilities ?? session.capabilities
2617
2440
  };
2618
2441
  saveSession(session);
2619
2442
  }
2620
- const status = deriveWalletStatus(session);
2443
+ const status = deriveWalletStatus(session, remoteStatus ?? void 0);
2621
2444
  const walletAddress = resolveSessionAddress(session);
2622
2445
  const environment = resolveSessionEnvironment(session);
2623
2446
  const signerCapabilities = resolveEnabledCapabilities(session);
@@ -2633,16 +2456,14 @@ async function buildSessionSnapshot(program2, verify) {
2633
2456
  walletId,
2634
2457
  expiresAt,
2635
2458
  sessionId: session?.sessionId ?? null,
2636
- connectionRequestId: session?.connectionRequestId ?? null,
2637
2459
  sessionState: session?.status ?? null,
2638
2460
  chainType: session?.chainType ?? null,
2639
- sessionsByChain: session?.sessionsByChain ?? null,
2640
2461
  valid: session ? isSessionValid(session) : false
2641
2462
  };
2642
2463
  }
2643
2464
  function registerWallets(program2) {
2644
2465
  const cmd = program2.command("wallet").description("Manage wallets");
2645
- cmd.command("connect").description("Connect a wallet for onchain actions (session or local)").option("--mode <mode>", "session | local").option("--import <path>", "For --mode local: import an EVM key from file instead of creating both wallets").option("--instance-name <name>", "For --mode session: name this CLI instance").option("--force", "Replace the existing signer").action(async (opts) => {
2466
+ cmd.command("connect").description("Connect a wallet for onchain actions (session or local)").option("--mode <mode>", "session | local").option("--chain <chain>", "For --mode local: evm | solana | both (default: both)").option("--import <path>", "For --mode local: import EVM key from file (implies --chain evm)").option("--instance-name <name>", "For --mode session: name this CLI instance").option("--force", "Replace the existing signer").action(async (opts) => {
2646
2467
  try {
2647
2468
  await runConnectFlow(program2, opts);
2648
2469
  } catch (err) {
@@ -2672,12 +2493,10 @@ function registerWallets(program2) {
2672
2493
  expiresAt: snap.expiresAt,
2673
2494
  environment: snap.environment,
2674
2495
  signerCapabilities: snap.signerCapabilities,
2675
- connectionRequestId: snap.connectionRequestId,
2676
2496
  sessionId: snap.sessionId,
2677
2497
  sessionState: snap.sessionState,
2678
2498
  walletId: snap.walletId,
2679
2499
  chainType: snap.chainType,
2680
- sessionsByChain: snap.sessionsByChain,
2681
2500
  verified: Boolean(opts.verify),
2682
2501
  remoteStatus: snap.remoteStatus,
2683
2502
  valid: snap.valid,
@@ -2688,12 +2507,10 @@ function registerWallets(program2) {
2688
2507
  expiresAt: snap.expiresAt,
2689
2508
  environment: snap.environment,
2690
2509
  signerCapabilities: snap.signerCapabilities,
2691
- connectionRequestId: snap.connectionRequestId,
2692
2510
  sessionId: snap.sessionId,
2693
2511
  sessionState: snap.sessionState,
2694
2512
  walletId: snap.walletId,
2695
2513
  chainType: snap.chainType,
2696
- sessionsByChain: snap.sessionsByChain,
2697
2514
  valid: snap.valid
2698
2515
  },
2699
2516
  localEvm: localState.evmAddress ? { address: localState.evmAddress, keyFile: localState.evmKeyFile } : null,
@@ -2711,11 +2528,7 @@ function registerWallets(program2) {
2711
2528
  ["Environment", snap.environment ?? dim("none")],
2712
2529
  ["Signer Capabilities", snap.signerCapabilities.length > 0 ? snap.signerCapabilities.join(", ") : dim("none")]
2713
2530
  ];
2714
- if (snap.connectionRequestId) {
2715
- pairs.push(["Connection Request ID", snap.connectionRequestId]);
2716
- } else if (snap.sessionId) {
2717
- pairs.push(["Session ID", snap.sessionId]);
2718
- }
2531
+ if (snap.sessionId) pairs.push(["Session ID", snap.sessionId]);
2719
2532
  if (snap.walletId) pairs.push(["Wallet ID", snap.walletId]);
2720
2533
  if (opts.verify) {
2721
2534
  pairs.push(["Backend Status", snap.remoteStatus ?? dim("not checked")]);
@@ -2870,7 +2683,7 @@ function registerWallets(program2) {
2870
2683
  }
2871
2684
  if (target === "local" && !hasLocalEvmKey()) {
2872
2685
  throw errInvalidArgs(
2873
- "No local EVM key configured. Run `alchemy wallet connect --mode local` first."
2686
+ "No local EVM key configured. Run `alchemy wallet connect --mode local --chain evm` first."
2874
2687
  );
2875
2688
  }
2876
2689
  const cfg = load();
@@ -2885,11 +2698,8 @@ function registerWallets(program2) {
2885
2698
  exitWithError(err);
2886
2699
  }
2887
2700
  });
2888
- cmd.command("disconnect").description("Revoke the current wallet session").option("--chain <chain>", "evm | solana").action(async (opts) => {
2701
+ cmd.command("disconnect").description("Revoke the current wallet session").action(async () => {
2889
2702
  try {
2890
- if (opts.chain !== void 0 && opts.chain !== "evm" && opts.chain !== "solana") {
2891
- throw errInvalidArgs("`--chain` must be 'evm' or 'solana'.");
2892
- }
2893
2703
  const session = loadStoredSession?.() ?? loadSession();
2894
2704
  if (!session) {
2895
2705
  if (isJSONMode()) {
@@ -2907,40 +2717,15 @@ function registerWallets(program2) {
2907
2717
  let revoked = false;
2908
2718
  let alreadyDisconnected = false;
2909
2719
  let remoteStatus = null;
2910
- const sessionsToDisconnect = opts.chain ? [
2911
- getWalletSessionByChain(
2912
- session,
2913
- opts.chain
2914
- )
2915
- ].filter(
2916
- (value) => value !== null
2917
- ) : Object.values(session.sessionsByChain ?? {}).filter(
2918
- (value) => value !== void 0
2919
- ).map(
2920
- (chainSession) => getWalletSessionByChain(session, chainSession.chainType)
2921
- ).filter(
2922
- (value) => value !== null
2923
- );
2924
- const disconnectTargets = sessionsToDisconnect.length > 0 ? sessionsToDisconnect : [session];
2925
2720
  if (authToken) {
2926
- const results = await Promise.all(
2927
- disconnectTargets.map(
2928
- (target) => disconnectRemoteWalletSession(authToken, target.sessionId)
2929
- )
2930
- );
2931
- revoked = results.some((remote) => !remote.alreadyDisconnected);
2932
- alreadyDisconnected = results.every((remote) => remote.alreadyDisconnected);
2933
- remoteStatus = results[0]?.status ?? null;
2934
- }
2935
- const removed = opts.chain === void 0 ? clearSession() : updateSession({
2936
- sessionsByChain: {
2937
- ...session.sessionsByChain ?? {},
2938
- [opts.chain]: void 0
2939
- },
2940
- ...opts.chain === "evm" ? { evmWalletId: void 0, evmAddress: void 0 } : { solanaWalletId: void 0, solanaAddress: void 0 }
2941
- }) != null;
2721
+ const remote = await disconnectRemoteWalletSession(authToken, session.sessionId);
2722
+ revoked = !remote.alreadyDisconnected;
2723
+ alreadyDisconnected = remote.alreadyDisconnected;
2724
+ remoteStatus = remote.status;
2725
+ }
2726
+ const removed = clearSession();
2942
2727
  const cfg = load();
2943
- if (cfg.active_signer === "session" && opts.chain !== "solana") {
2728
+ if (cfg.active_signer === "session") {
2944
2729
  const { active_signer: _omit, ...rest } = cfg;
2945
2730
  save(rest);
2946
2731
  }
@@ -3335,10 +3120,9 @@ import {
3335
3120
  createKeyPairSignerFromBytes as createKeyPairSignerFromBytes2,
3336
3121
  createKeyPairSignerFromPrivateKeyBytes as createKeyPairSignerFromPrivateKeyBytes2
3337
3122
  } from "@solana/kit";
3338
- import { sign as signWithPrivateKey } from "crypto";
3123
+ import { getTransferSolInstruction } from "@solana-program/system";
3339
3124
  var SOL_DECIMALS = 9;
3340
3125
  var SPONSOR_FEE_PAYER_PLACEHOLDER = address("Amh6quo1FcmL16Qmzdugzjq3Lv1zXzTW7ktswyLDzits");
3341
- var SYSTEM_PROGRAM_ADDRESS = address("11111111111111111111111111111111");
3342
3126
  var SPL_TOKEN_PROGRAM_ADDRESS = address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
3343
3127
  function parseSolanaKeyBytes(secret) {
3344
3128
  const trimmed = secret.trim();
@@ -3369,28 +3153,11 @@ async function createSolanaSignerFromKeyBytes(keyBytes) {
3369
3153
  throw errInvalidArgs("Invalid Solana key: expected 64-byte secret key or 32-byte private key.");
3370
3154
  }
3371
3155
  function buildSolTransferInstruction(from, to, lamports) {
3372
- return {
3373
- programAddress: SYSTEM_PROGRAM_ADDRESS,
3374
- accounts: [
3375
- { address: from.address, role: AccountRole.WRITABLE_SIGNER },
3376
- { address: to, role: AccountRole.WRITABLE }
3377
- ],
3378
- data: new Uint8Array([
3379
- ...encodeU32LE(2),
3380
- ...encodeU64LE(lamports)
3381
- ])
3382
- };
3383
- }
3384
- function encodeU32LE(value) {
3385
- if (!Number.isSafeInteger(value) || value < 0 || value > 4294967295) {
3386
- throw errInvalidArgs("Instruction discriminator must fit in an unsigned 32-bit integer.");
3387
- }
3388
- const bytes = new Uint8Array(4);
3389
- bytes[0] = value & 255;
3390
- bytes[1] = value >> 8 & 255;
3391
- bytes[2] = value >> 16 & 255;
3392
- bytes[3] = value >> 24 & 255;
3393
- return bytes;
3156
+ return getTransferSolInstruction({
3157
+ source: from,
3158
+ destination: to,
3159
+ amount: lamports
3160
+ });
3394
3161
  }
3395
3162
  function encodeU64LE(value) {
3396
3163
  if (value < 0n || value > 0xffffffffffffffffn) {
@@ -3471,38 +3238,6 @@ async function buildAndSendSolanaTransaction(opts) {
3471
3238
  const signature = await client.call("sendTransaction", [wireTransaction, { encoding: "base64" }]);
3472
3239
  return { signature, fromAddress: signer.address };
3473
3240
  }
3474
- async function buildAndSendSolanaTransactionWithSession(opts) {
3475
- const { client, instructions, session, authToken, sponsored, gasPolicyId } = opts;
3476
- const fromAddress = getSolanaSessionAddress(session);
3477
- const blockhashResult = await client.call("getLatestBlockhash", [{ commitment: "finalized" }]);
3478
- const { blockhash, lastValidBlockHeight } = blockhashResult.value;
3479
- const feePayer = sponsored ? SPONSOR_FEE_PAYER_PLACEHOLDER : address(fromAddress);
3480
- const txMessage = pipe(
3481
- createTransactionMessage({ version: 0 }),
3482
- (msg) => setTransactionMessageFeePayer(feePayer, msg),
3483
- (msg) => setTransactionMessageLifetimeUsingBlockhash(
3484
- { blockhash, lastValidBlockHeight },
3485
- msg
3486
- ),
3487
- (msg) => appendTransactionMessageInstructions(instructions, msg)
3488
- );
3489
- const compiledTx = compileTransaction(txMessage);
3490
- const transactionToSign = sponsored ? await sponsorSolanaTransaction({
3491
- client,
3492
- compiledTransactionBase64: getBase64EncodedWireTransaction(compiledTx),
3493
- gasPolicyId
3494
- }) : getBase64EncodedWireTransaction(compiledTx);
3495
- const signedTransaction = await signSolanaTransactionWithSession({
3496
- authToken,
3497
- session,
3498
- transactionBase64: transactionToSign
3499
- });
3500
- const signature = await client.call("sendTransaction", [
3501
- signedTransaction,
3502
- { encoding: "base64" }
3503
- ]);
3504
- return { signature, fromAddress };
3505
- }
3506
3241
  async function waitForSolanaConfirmation(client, signature, timeoutMs = 6e4, pollIntervalMs = 2e3) {
3507
3242
  const start = Date.now();
3508
3243
  while (Date.now() - start < timeoutMs) {
@@ -3519,87 +3254,29 @@ async function waitForSolanaConfirmation(client, signature, timeoutMs = 6e4, pol
3519
3254
  }
3520
3255
  return false;
3521
3256
  }
3522
- async function sponsorSolanaTransaction(args) {
3523
- if (!args.gasPolicyId) {
3524
- throw errInvalidArgs("Fee sponsorship requires a fee policy ID.");
3525
- }
3526
- const feePayerResponse = await args.client.call("alchemy_requestFeePayer", [{
3527
- policyId: args.gasPolicyId,
3528
- serializedTransaction: args.compiledTransactionBase64
3529
- }]);
3530
- return feePayerResponse.serializedTransaction;
3531
- }
3532
- async function signSolanaTransactionWithSession(args) {
3533
- const binding = getSolanaSessionBinding(args.session);
3534
- if (args.session.capabilities?.["solana.signTransaction"] === false) {
3535
- throw errInvalidArgs(
3536
- "Delegated wallet session does not allow 'solana.signTransaction'. Reconnect the wallet session to refresh capabilities."
3537
- );
3538
- }
3539
- const challenge = await createRemoteSolanaSignTransactionChallenge(args.authToken, {
3540
- ...binding,
3541
- transaction: args.transactionBase64,
3542
- encoding: "base64"
3543
- });
3544
- const completion = await completeRemoteSolanaSignTransactionChallenge(args.authToken, {
3545
- challengeId: challenge.challengeId,
3546
- signature: signChallengePayload({
3547
- challengePayload: challenge.challenge,
3548
- privateKeyPem: args.session.privateKeyPem
3549
- })
3550
- });
3551
- return completion.signedTransaction;
3552
- }
3553
- function getSolanaSessionBinding(session) {
3554
- const walletId = session.solanaWalletId ?? session.walletId;
3555
- const walletAddress = getSolanaSessionAddress(session);
3556
- if (!walletId) {
3557
- throw errInvalidArgs(
3558
- "Delegated wallet session is missing Solana wallet ID metadata. Run 'alchemy wallet connect --mode session --force'."
3559
- );
3560
- }
3561
- if (!session.privyKeyQuorumId && !session.privySignerId) {
3562
- throw errInvalidArgs(
3563
- "Delegated wallet session is missing signer binding metadata. Run 'alchemy wallet connect --mode session --force'."
3564
- );
3565
- }
3566
- return {
3567
- sessionId: session.sessionId,
3568
- walletId,
3569
- walletAddress,
3570
- privyKeyQuorumId: session.privyKeyQuorumId,
3571
- privySignerId: session.privySignerId
3572
- };
3573
- }
3574
- function getSolanaSessionAddress(session) {
3575
- if (!session.solanaAddress) {
3576
- throw errInvalidArgs(
3577
- "Delegated wallet session is missing Solana address metadata. Run 'alchemy wallet connect --mode session --force'."
3578
- );
3579
- }
3580
- return session.solanaAddress;
3581
- }
3582
- function signChallengePayload(args) {
3583
- return signWithPrivateKey(
3584
- "sha256",
3585
- Buffer.from(args.challengePayload, "utf8"),
3586
- {
3587
- key: args.privateKeyPem,
3588
- dsaEncoding: "der"
3589
- }
3590
- ).toString("base64url");
3591
- }
3592
3257
 
3593
3258
  // src/lib/solana-fees.ts
3594
- function resolveSolanaFeeSponsorship(program2) {
3259
+ async function resolveSolanaFeeSponsorship(program2) {
3595
3260
  const sponsored = resolveSolanaFeeSponsored(program2);
3596
- const feePolicyId = resolveSolanaFeePolicyId(program2);
3597
- if (sponsored && !feePolicyId) {
3598
- throw errInvalidArgs(
3599
- "Fee sponsorship requires a fee policy ID. Set one with --fee-policy-id or configure a Solana fee policy."
3600
- );
3261
+ const existing = resolveSolanaFeePolicyId(program2);
3262
+ if (!sponsored) return { sponsored, feePolicyId: existing };
3263
+ if (existing) return { sponsored, feePolicyId: existing };
3264
+ if (!isInteractiveAllowed(program2)) {
3265
+ throw errSponsorshipNeedsPolicy("solana");
3266
+ }
3267
+ if (!hasAuthLoginToken()) {
3268
+ throw errNotLoggedInForPolicyLookup();
3601
3269
  }
3602
- return { sponsored, feePolicyId };
3270
+ const network = resolveSolanaNetwork(program2);
3271
+ const selected = await selectOrCreatePolicy({
3272
+ flavor: "solana",
3273
+ network,
3274
+ program: program2
3275
+ });
3276
+ if (!selected) {
3277
+ throw errSponsorshipNeedsPolicy("solana");
3278
+ }
3279
+ return { sponsored, feePolicyId: selected };
3603
3280
  }
3604
3281
 
3605
3282
  // src/commands/solana-delegate.ts
@@ -3610,54 +3287,23 @@ function parseDecimals(value) {
3610
3287
  }
3611
3288
  return decimals;
3612
3289
  }
3613
- async function resolveSolanaDelegateSigner(program2, signerOpt) {
3290
+ async function resolveLocalSolanaDelegateSigner(program2, signerOpt) {
3614
3291
  const signer = parseSignerOpt(signerOpt);
3615
3292
  if (signer === "session") {
3616
- return resolveSessionSolanaDelegateSigner();
3617
- }
3618
- if (signer === void 0 && resolveActiveSigner(program2) === "session") {
3619
- return resolveSessionSolanaDelegateSigner();
3293
+ throw errInvalidArgs(
3294
+ "The session wallet does not yet support Solana. Use `--signer local` or configure a local Solana wallet with `alchemy wallet connect --mode local --chain solana`."
3295
+ );
3620
3296
  }
3621
3297
  const solanaKey = resolveSolanaWalletKey(program2);
3622
3298
  if (!solanaKey) {
3623
- if (signer === void 0) {
3624
- const sessionSigner = tryResolveSessionSolanaDelegateSigner();
3625
- if (sessionSigner) {
3626
- return sessionSigner;
3627
- }
3628
- }
3629
3299
  throw errSolanaWalletKeyRequired();
3630
3300
  }
3631
3301
  const keyBytes = parseSolanaKeyBytes(solanaKey);
3632
3302
  return {
3633
- type: "local",
3634
3303
  keyBytes,
3635
3304
  signer: await createSolanaSignerFromKeyBytes(keyBytes)
3636
3305
  };
3637
3306
  }
3638
- function resolveSessionSolanaDelegateSigner() {
3639
- const sessionSigner = tryResolveSessionSolanaDelegateSigner();
3640
- if (!sessionSigner) {
3641
- throw errInvalidArgs(
3642
- "No active Solana wallet session. Run `alchemy wallet connect --mode session` first."
3643
- );
3644
- }
3645
- return sessionSigner;
3646
- }
3647
- function tryResolveSessionSolanaDelegateSigner() {
3648
- const authToken = resolveAuthToken();
3649
- const session = resolveWalletSession();
3650
- const solanaSession = session ? getWalletSessionByChain(session, "solana") : null;
3651
- if (!authToken || !solanaSession?.solanaAddress) {
3652
- return void 0;
3653
- }
3654
- return {
3655
- type: "session",
3656
- address: solanaSession.solanaAddress,
3657
- session: solanaSession,
3658
- authToken
3659
- };
3660
- }
3661
3307
  function registerSolanaDelegate(program2) {
3662
3308
  const cmd = program2.command("delegate").description("Delegate Solana token authority");
3663
3309
  const approveCmd = cmd.command("approve").description("Approve a delegate for an SPL token account").requiredOption("--token-account <address>", "SPL token account to delegate from").requiredOption("--mint <address>", "SPL token mint").requiredOption("--delegate <address>", "Delegate address").requiredOption("--amount <number>", "Amount to delegate in decimal token units").requiredOption("--decimals <n>", "Mint decimals").option("--fee-sponsored", "Enable Solana fee sponsorship").option("--fee-policy-id <id>", "Solana fee policy ID for sponsorship");
@@ -3691,40 +3337,28 @@ async function performSolanaDelegateApprove(program2, opts) {
3691
3337
  validateSolanaAddress(opts.delegate);
3692
3338
  const decimals = parseDecimals(opts.decimals);
3693
3339
  const rawAmount = parseAmount(opts.amount, decimals);
3694
- const signer = await resolveSolanaDelegateSigner(program2, opts.signer);
3340
+ const { keyBytes, signer } = await resolveLocalSolanaDelegateSigner(program2, opts.signer);
3695
3341
  const network = resolveSolanaNetwork(program2);
3696
- const { sponsored, feePolicyId } = resolveSolanaFeeSponsorship(program2);
3342
+ const { sponsored, feePolicyId } = await resolveSolanaFeeSponsorship(program2);
3697
3343
  const client = clientFromFlags(program2, { forceNetwork: network });
3698
3344
  const instruction = buildSplTokenApproveCheckedInstruction({
3699
3345
  tokenAccount: solAddress(opts.tokenAccount),
3700
3346
  mint: solAddress(opts.mint),
3701
3347
  delegate: solAddress(opts.delegate),
3702
- owner: { address: solAddress(signer.type === "session" ? signer.address : signer.signer.address) },
3348
+ owner: signer,
3703
3349
  amount: rawAmount,
3704
3350
  decimals
3705
3351
  });
3706
3352
  const result = await withSpinner(
3707
3353
  "Approving delegate...",
3708
3354
  "Delegate approved",
3709
- async () => {
3710
- if (signer.type === "session") {
3711
- return await buildAndSendSolanaTransactionWithSession({
3712
- client,
3713
- instructions: [instruction],
3714
- session: signer.session,
3715
- authToken: signer.authToken,
3716
- sponsored,
3717
- gasPolicyId: feePolicyId
3718
- });
3719
- }
3720
- return await buildAndSendSolanaTransaction({
3721
- client,
3722
- instructions: [instruction],
3723
- senderKeyBytes: signer.keyBytes,
3724
- sponsored,
3725
- gasPolicyId: feePolicyId
3726
- });
3727
- }
3355
+ () => buildAndSendSolanaTransaction({
3356
+ client,
3357
+ instructions: [instruction],
3358
+ senderKeyBytes: keyBytes,
3359
+ sponsored,
3360
+ gasPolicyId: feePolicyId
3361
+ })
3728
3362
  );
3729
3363
  const confirmed = await withSpinner(
3730
3364
  "Waiting for confirmation...",
@@ -3765,36 +3399,24 @@ async function performSolanaDelegateApprove(program2, opts) {
3765
3399
  }
3766
3400
  async function performSolanaDelegateRevoke(program2, opts) {
3767
3401
  validateSolanaAddress(opts.tokenAccount);
3768
- const signer = await resolveSolanaDelegateSigner(program2, opts.signer);
3402
+ const { keyBytes, signer } = await resolveLocalSolanaDelegateSigner(program2, opts.signer);
3769
3403
  const network = resolveSolanaNetwork(program2);
3770
- const { sponsored, feePolicyId } = resolveSolanaFeeSponsorship(program2);
3404
+ const { sponsored, feePolicyId } = await resolveSolanaFeeSponsorship(program2);
3771
3405
  const client = clientFromFlags(program2, { forceNetwork: network });
3772
3406
  const instruction = buildSplTokenRevokeInstruction({
3773
3407
  tokenAccount: solAddress(opts.tokenAccount),
3774
- owner: { address: solAddress(signer.type === "session" ? signer.address : signer.signer.address) }
3408
+ owner: signer
3775
3409
  });
3776
3410
  const result = await withSpinner(
3777
3411
  "Revoking delegate...",
3778
3412
  "Delegate revoked",
3779
- async () => {
3780
- if (signer.type === "session") {
3781
- return await buildAndSendSolanaTransactionWithSession({
3782
- client,
3783
- instructions: [instruction],
3784
- session: signer.session,
3785
- authToken: signer.authToken,
3786
- sponsored,
3787
- gasPolicyId: feePolicyId
3788
- });
3789
- }
3790
- return await buildAndSendSolanaTransaction({
3791
- client,
3792
- instructions: [instruction],
3793
- senderKeyBytes: signer.keyBytes,
3794
- sponsored,
3795
- gasPolicyId: feePolicyId
3796
- });
3797
- }
3413
+ () => buildAndSendSolanaTransaction({
3414
+ client,
3415
+ instructions: [instruction],
3416
+ senderKeyBytes: keyBytes,
3417
+ sponsored,
3418
+ gasPolicyId: feePolicyId
3419
+ })
3798
3420
  );
3799
3421
  const confirmed = await withSpinner(
3800
3422
  "Waiting for confirmation...",
@@ -4038,41 +3660,35 @@ async function performSolanaSend(program2, toArg, amountArg, tokenAddress, opts
4038
3660
  if (tokenAddress) {
4039
3661
  throw errInvalidArgs("SPL token transfers are not yet supported. Omit --token for native SOL transfers.");
4040
3662
  }
4041
- const signer = await resolveSolanaSigner(program2, opts.signer);
3663
+ if (opts.signer === "session") {
3664
+ throw errInvalidArgs(
3665
+ "The session wallet does not yet support Solana. Use `--signer local` or configure a local Solana wallet with `alchemy wallet connect --mode local --chain solana`."
3666
+ );
3667
+ }
3668
+ const solanaKey = resolveSolanaWalletKey(program2);
3669
+ if (!solanaKey) {
3670
+ throw errSolanaWalletKeyRequired();
3671
+ }
3672
+ const keyBytes = parseSolanaKeyBytes(solanaKey);
4042
3673
  validateSolanaAddress(toArg);
4043
3674
  const to = solAddress2(toArg);
4044
3675
  const network = resolveSolanaNetwork(program2);
4045
3676
  const symbol = nativeTokenSymbol(network);
4046
3677
  const lamports = parseAmount(amountArg, SOL_DECIMALS);
4047
- const instruction = buildSolTransferInstruction(
4048
- { address: solAddress2(signer.address) },
4049
- to,
4050
- lamports
4051
- );
4052
- const { sponsored, feePolicyId } = resolveSolanaFeeSponsorship(program2);
3678
+ const signer = await createSolanaSignerFromKeyBytes(keyBytes);
3679
+ const instruction = buildSolTransferInstruction(signer, to, lamports);
3680
+ const { sponsored, feePolicyId } = await resolveSolanaFeeSponsorship(program2);
4053
3681
  const client = clientFromFlags(program2, { forceNetwork: network });
4054
3682
  const result = await withSpinner(
4055
3683
  "Sending transaction\u2026",
4056
3684
  "Transaction submitted",
4057
- async () => {
4058
- if (signer.type === "session") {
4059
- return await buildAndSendSolanaTransactionWithSession({
4060
- client,
4061
- instructions: [instruction],
4062
- session: signer.session,
4063
- authToken: signer.authToken,
4064
- sponsored,
4065
- gasPolicyId: feePolicyId
4066
- });
4067
- }
4068
- return await buildAndSendSolanaTransaction({
4069
- client,
4070
- instructions: [instruction],
4071
- senderKeyBytes: signer.keyBytes,
4072
- sponsored,
4073
- gasPolicyId: feePolicyId
4074
- });
4075
- }
3685
+ () => buildAndSendSolanaTransaction({
3686
+ client,
3687
+ instructions: [instruction],
3688
+ senderKeyBytes: keyBytes,
3689
+ sponsored,
3690
+ gasPolicyId: feePolicyId
3691
+ })
4076
3692
  );
4077
3693
  const confirmed = await withSpinner(
4078
3694
  "Waiting for confirmation\u2026",
@@ -4105,70 +3721,6 @@ async function performSolanaSend(program2, toArg, amountArg, tokenAddress, opts
4105
3721
  printKeyValue(pairs);
4106
3722
  }
4107
3723
  }
4108
- async function resolveSolanaSigner(program2, signer) {
4109
- if (signer === "session") {
4110
- const authToken = resolveAuthToken();
4111
- const session = resolveWalletSession();
4112
- const solanaSession = session ? getWalletSessionByChain(session, "solana") : null;
4113
- if (!authToken) {
4114
- throw errInvalidArgs("Session Solana signing requires CLI authentication.");
4115
- }
4116
- if (!solanaSession?.solanaAddress) {
4117
- throw errInvalidArgs(
4118
- "No active Solana wallet session. Run `alchemy wallet connect --mode session` first."
4119
- );
4120
- }
4121
- return {
4122
- type: "session",
4123
- address: solanaSession.solanaAddress,
4124
- session: solanaSession,
4125
- authToken
4126
- };
4127
- }
4128
- if (signer === void 0 && resolveActiveSigner(program2) === "session") {
4129
- const authToken = resolveAuthToken();
4130
- const session = resolveWalletSession();
4131
- const solanaSession = session ? getWalletSessionByChain(session, "solana") : null;
4132
- if (!authToken) {
4133
- throw errInvalidArgs("Session Solana signing requires CLI authentication.");
4134
- }
4135
- if (!solanaSession?.solanaAddress) {
4136
- throw errInvalidArgs(
4137
- "No active Solana wallet session. Run `alchemy wallet connect --mode session` first."
4138
- );
4139
- }
4140
- return {
4141
- type: "session",
4142
- address: solanaSession.solanaAddress,
4143
- session: solanaSession,
4144
- authToken
4145
- };
4146
- }
4147
- const solanaKey = resolveSolanaWalletKey(program2);
4148
- if (!solanaKey) {
4149
- if (signer === void 0) {
4150
- const authToken = resolveAuthToken();
4151
- const session = resolveWalletSession();
4152
- const solanaSession = session ? getWalletSessionByChain(session, "solana") : null;
4153
- if (authToken && solanaSession?.solanaAddress) {
4154
- return {
4155
- type: "session",
4156
- address: solanaSession.solanaAddress,
4157
- session: solanaSession,
4158
- authToken
4159
- };
4160
- }
4161
- }
4162
- throw errSolanaWalletKeyRequired();
4163
- }
4164
- const keyBytes = parseSolanaKeyBytes(solanaKey);
4165
- const localSigner = await createSolanaSignerFromKeyBytes(keyBytes);
4166
- return {
4167
- type: "local",
4168
- address: localSigner.address,
4169
- keyBytes
4170
- };
4171
- }
4172
3724
 
4173
3725
  // src/lib/smart-wallet.ts
4174
3726
  import { createSmartWalletClient } from "@alchemy/wallet-apis";
@@ -4228,7 +3780,7 @@ function networkToChain(network) {
4228
3780
  }
4229
3781
 
4230
3782
  // src/lib/delegated-signer.ts
4231
- import { sign as signWithPrivateKey2 } from "crypto";
3783
+ import { sign as signWithPrivateKey } from "crypto";
4232
3784
  import { isAddressEqual, recoverMessageAddress, recoverTypedDataAddress } from "viem";
4233
3785
  import { toAccount } from "viem/accounts";
4234
3786
  var messageCapabilities = {
@@ -4242,8 +3794,8 @@ function toHex(bytes) {
4242
3794
  function normalizeSignedChallengeSignature(signature) {
4243
3795
  return signature.toString("base64url");
4244
3796
  }
4245
- function signChallengePayload2(args) {
4246
- const signature = signWithPrivateKey2(
3797
+ function signChallengePayload(args) {
3798
+ const signature = signWithPrivateKey(
4247
3799
  "sha256",
4248
3800
  Buffer.from(args.challengePayload, "utf8"),
4249
3801
  {
@@ -4426,7 +3978,7 @@ function createDelegatedAccount(args) {
4426
3978
  message: remoteMessage.message,
4427
3979
  encoding: remoteMessage.encoding
4428
3980
  });
4429
- const signature = signChallengePayload2({
3981
+ const signature = signChallengePayload({
4430
3982
  challengePayload: challenge.challenge,
4431
3983
  privateKeyPem: args.session.privateKeyPem
4432
3984
  });
@@ -4461,7 +4013,7 @@ function createDelegatedAccount(args) {
4461
4013
  ...sessionBinding,
4462
4014
  typedData: serializedTypedData
4463
4015
  });
4464
- const signature = signChallengePayload2({
4016
+ const signature = signChallengePayload({
4465
4017
  challengePayload: challenge.challenge,
4466
4018
  privateKeyPem: args.session.privateKeyPem
4467
4019
  });
@@ -4490,7 +4042,7 @@ function createDelegatedAccount(args) {
4490
4042
  ...sessionBinding,
4491
4043
  authorization
4492
4044
  });
4493
- const signature = signChallengePayload2({
4045
+ const signature = signChallengePayload({
4494
4046
  challengePayload: challenge.challenge,
4495
4047
  privateKeyPem: args.session.privateKeyPem
4496
4048
  });
@@ -4522,6 +4074,28 @@ function createAlchemyWalletTransport(apiKey) {
4522
4074
  }
4523
4075
 
4524
4076
  // src/lib/smart-wallet.ts
4077
+ async function ensureGasPolicyResolved(program2) {
4078
+ const cfg = load();
4079
+ if (!resolveGasSponsored(program2, cfg)) return void 0;
4080
+ const existing = resolveGasPolicyId(program2, cfg);
4081
+ if (existing) return existing;
4082
+ if (!isInteractiveAllowed(program2)) {
4083
+ throw errSponsorshipNeedsPolicy("sponsorship");
4084
+ }
4085
+ if (!hasAuthLoginToken(cfg)) {
4086
+ throw errNotLoggedInForPolicyLookup();
4087
+ }
4088
+ const network = resolveNetwork(program2, cfg);
4089
+ const policyId = await selectOrCreatePolicy({
4090
+ flavor: "sponsorship",
4091
+ network,
4092
+ program: program2
4093
+ });
4094
+ if (!policyId) {
4095
+ throw errSponsorshipNeedsPolicy("sponsorship");
4096
+ }
4097
+ return policyId;
4098
+ }
4525
4099
  function normalizeKey(key) {
4526
4100
  const trimmed = key.trim();
4527
4101
  return trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
@@ -4569,7 +4143,7 @@ function buildWalletClient(program2, options = {}) {
4569
4143
  const network = resolveNetwork(program2, cfg);
4570
4144
  const chain = networkToChain(network);
4571
4145
  const gasSponsored = resolveGasSponsored(program2, cfg);
4572
- const gasPolicyId = resolveGasPolicyId(program2, cfg);
4146
+ const gasPolicyId = options.gasPolicyIdOverride ?? resolveGasPolicyId(program2, cfg);
4573
4147
  if (gasSponsored && !gasPolicyId) {
4574
4148
  throw errInvalidArgs(
4575
4149
  "Gas sponsorship requires a gas policy ID. Set one with --gas-policy-id or `alchemy config set evm-gas-policy-id <id>`."
@@ -4589,13 +4163,12 @@ function buildWalletClient(program2, options = {}) {
4589
4163
  }
4590
4164
  throw errNoActiveSession();
4591
4165
  }
4592
- const evmSession = getWalletSessionByChain(validSession, "evm");
4593
- if (!evmSession) {
4166
+ assertSessionMetadata(validSession);
4167
+ if (validSession.chainType && validSession.chainType !== "evm") {
4594
4168
  throw errInvalidArgs(
4595
- "Wallet session is missing EVM metadata. Run 'alchemy wallet connect --mode session --force'."
4169
+ `Wallet session is configured for '${validSession.chainType}', not EVM. Run 'alchemy wallet connect --force'.`
4596
4170
  );
4597
4171
  }
4598
- assertSessionMetadata(evmSession);
4599
4172
  const authToken = resolveAuthToken(cfg);
4600
4173
  if (!authToken) {
4601
4174
  throw errAuthRequired();
@@ -4603,9 +4176,9 @@ function buildWalletClient(program2, options = {}) {
4603
4176
  return {
4604
4177
  signer: createDelegatedAccount({
4605
4178
  authToken,
4606
- session: evmSession
4179
+ session: validSession
4607
4180
  }),
4608
- address: evmSession.evmAddress
4181
+ address: validSession.evmAddress
4609
4182
  };
4610
4183
  }
4611
4184
  if (!localKey) throw errWalletKeyRequired();
@@ -5344,7 +4917,7 @@ function buildAgentPrompt(program2) {
5344
4917
  method: "Local wallet + API key",
5345
4918
  envVar: "ALCHEMY_WALLET_KEY",
5346
4919
  flag: "--wallet-key-file <path> | --signer local",
5347
- setup: "alchemy wallet connect --mode local",
4920
+ setup: "alchemy wallet connect --mode local --chain evm",
5348
4921
  commandFamilies: [
5349
4922
  "evm send",
5350
4923
  "evm contract call",
@@ -5608,7 +5181,11 @@ async function performApprove(program2, spenderArg, opts) {
5608
5181
  }
5609
5182
  validateApprovalMode(opts);
5610
5183
  const signer = parseSignerOpt(opts.signer);
5611
- const { client, network, address: from, paymaster } = buildWalletClient(program2, { signer });
5184
+ const gasPolicyIdOverride = await ensureGasPolicyResolved(program2);
5185
+ const { client, network, address: from, paymaster } = buildWalletClient(program2, {
5186
+ signer,
5187
+ ...gasPolicyIdOverride && { gasPolicyIdOverride }
5188
+ });
5612
5189
  const rpcClient = clientFromFlags(program2);
5613
5190
  const tokenMeta = await fetchTokenDecimals(program2, opts.tokenAddress);
5614
5191
  const approval = buildApprovalRequest(opts, tokenMeta);
@@ -6084,7 +5661,11 @@ async function performContractCall(program2, addressArg, functionArg, opts) {
6084
5661
  const { abi, functionName } = resolveAbi(functionArg, opts);
6085
5662
  const args = parseArgs(opts.args);
6086
5663
  const signer = parseSignerOpt(opts.signer);
6087
- const { client, network, address: from, paymaster } = buildWalletClient(program2, { signer });
5664
+ const gasPolicyIdOverride = await ensureGasPolicyResolved(program2);
5665
+ const { client, network, address: from, paymaster } = buildWalletClient(program2, {
5666
+ signer,
5667
+ ...gasPolicyIdOverride && { gasPolicyIdOverride }
5668
+ });
6088
5669
  const rpcClient = clientFromFlags(program2);
6089
5670
  const contractAddress = await resolveAddress(addressArg, rpcClient);
6090
5671
  const data = encodeFunctionData2({ abi, functionName, args });
@@ -7247,7 +6828,7 @@ Examples:
7247
6828
  dryRun: opts.dryRun
7248
6829
  });
7249
6830
  } catch (err) {
7250
- const { exitWithError: exitWithError2 } = await import("./errors-UL3W4ECQ.js");
6831
+ const { exitWithError: exitWithError2 } = await import("./errors-A53DVJDY.js");
7251
6832
  exitWithError2(err);
7252
6833
  }
7253
6834
  });
@@ -7256,7 +6837,11 @@ async function performEvmSend(program2, toArg, amountArg, tokenAddress, opts = {
7256
6837
  if (tokenAddress) {
7257
6838
  validateAddress(tokenAddress);
7258
6839
  }
7259
- const { client, network, address: from, paymaster } = buildWalletClient(program2, { signer: opts.signer });
6840
+ const gasPolicyIdOverride = await ensureGasPolicyResolved(program2);
6841
+ const { client, network, address: from, paymaster } = buildWalletClient(program2, {
6842
+ signer: opts.signer,
6843
+ ...gasPolicyIdOverride && { gasPolicyIdOverride }
6844
+ });
7260
6845
  const rpcClient = clientFromFlags(program2);
7261
6846
  const to = await resolveAddress(toArg, rpcClient);
7262
6847
  let decimals;
@@ -7680,7 +7265,11 @@ async function performSwapExecute(program2, opts) {
7680
7265
  validateAddress(opts.from);
7681
7266
  validateAddress(opts.to);
7682
7267
  const signer = parseSignerOpt(opts.signer);
7683
- const { client, network, address: from, paymaster } = buildWalletClient(program2, { signer });
7268
+ const gasPolicyIdOverride = await ensureGasPolicyResolved(program2);
7269
+ const { client, network, address: from, paymaster } = buildWalletClient(program2, {
7270
+ signer,
7271
+ ...gasPolicyIdOverride && { gasPolicyIdOverride }
7272
+ });
7684
7273
  const swapClient = client.extend(swapActions);
7685
7274
  const fromInfo = await resolveTokenInfo(network, program2, opts.from);
7686
7275
  const rawAmount = parseAmount(opts.amount, fromInfo.decimals);
@@ -7873,6 +7462,174 @@ function registerEvm(program2) {
7873
7462
  registerSimulate(cmd);
7874
7463
  }
7875
7464
 
7465
+ // src/commands/gas-manager.ts
7466
+ function summariseNetworks(p) {
7467
+ return p.networks.map(fromAdminNetworkId).join(", ");
7468
+ }
7469
+ function policyToRow(p) {
7470
+ return [
7471
+ p.policyId,
7472
+ p.policyName,
7473
+ p.policyType,
7474
+ p.status === "active" ? green(p.status) : dim(p.status),
7475
+ summariseNetworks(p) || dim("(none)")
7476
+ ];
7477
+ }
7478
+ function policyToJSON(p) {
7479
+ return {
7480
+ policyId: p.policyId,
7481
+ policyName: p.policyName,
7482
+ policyType: p.policyType,
7483
+ status: p.status,
7484
+ appId: p.appId,
7485
+ networks: p.networks,
7486
+ networkSlugs: p.networks.map(fromAdminNetworkId),
7487
+ policyState: p.policyState ?? null,
7488
+ lastUpdatedUnix: p.lastUpdatedUnix ?? null,
7489
+ policyVersion: p.policyVersion ?? null
7490
+ };
7491
+ }
7492
+ function requireAppId(program2, opts) {
7493
+ if (opts.appId) return opts.appId;
7494
+ const resolved = resolveAppId(program2);
7495
+ if (!resolved) throw errAppRequired();
7496
+ return resolved;
7497
+ }
7498
+ function parseTypeFilter(value) {
7499
+ if (!value) return null;
7500
+ if (value === "sponsorship" || value === "erc20" || value === "solana") return value;
7501
+ throw errInvalidArgs(`Unknown --type ${value}. Expected one of: sponsorship, erc20, solana.`);
7502
+ }
7503
+ function parseStatusFilter(value) {
7504
+ if (!value) return null;
7505
+ if (value === "active" || value === "inactive") return value;
7506
+ throw errInvalidArgs(`Unknown --status ${value}. Expected one of: active, inactive.`);
7507
+ }
7508
+ function registerGasManager(program2) {
7509
+ const cmd = program2.command("gas-manager").description("Manage Alchemy Gas Manager policies");
7510
+ const policyCmd = cmd.command("policy").description("Manage gas sponsorship policies");
7511
+ policyCmd.command("list").description("List gas policies for the default app").option("--app-id <id>", "Override the default app ID").option("--type <type>", "Filter by policy type (sponsorship | erc20 | solana)").option("--network <slug>", "Filter by network slug (e.g. eth-mainnet)").option("--status <status>", "Filter by status (active | inactive)").action(async (opts) => {
7512
+ try {
7513
+ const client = gasManagerClientFromFlags(program2);
7514
+ const appId = requireAppId(program2, opts);
7515
+ const typeFilter = parseTypeFilter(opts.type);
7516
+ const statusFilter = parseStatusFilter(opts.status);
7517
+ const networkFilter = opts.network ? toAdminNetworkId(opts.network) : null;
7518
+ const policies = await withSpinner(
7519
+ "Fetching policies\u2026",
7520
+ "Policies fetched",
7521
+ () => client.listAllPolicies({ appId })
7522
+ );
7523
+ const filtered = policies.filter((p) => {
7524
+ if (typeFilter && p.policyType !== typeFilter) return false;
7525
+ if (statusFilter && p.status !== statusFilter) return false;
7526
+ if (networkFilter && !p.networks.includes(networkFilter)) return false;
7527
+ return true;
7528
+ });
7529
+ if (isJSONMode()) {
7530
+ printJSON({ appId, policies: filtered.map(policyToJSON) });
7531
+ return;
7532
+ }
7533
+ if (filtered.length === 0) {
7534
+ console.log(
7535
+ `
7536
+ ${dim(`No policies for app ${appId}${networkFilter ? ` on ${opts.network}` : ""}.`)}`
7537
+ );
7538
+ console.log(
7539
+ ` ${dim("Create one with: alchemy gas-manager policy create")}`
7540
+ );
7541
+ return;
7542
+ }
7543
+ printTable(
7544
+ ["Policy ID", "Name", "Type", "Status", "Networks"],
7545
+ filtered.map(policyToRow)
7546
+ );
7547
+ console.log(`
7548
+ ${dim(`${filtered.length} policies (app ${appId}).`)}`);
7549
+ } catch (err) {
7550
+ exitWithError(err);
7551
+ }
7552
+ });
7553
+ policyCmd.command("get <policy-id>").description("Show details for a single policy").action(async (policyId) => {
7554
+ try {
7555
+ const client = gasManagerClientFromFlags(program2);
7556
+ const policy = await withSpinner(
7557
+ "Fetching policy\u2026",
7558
+ "Policy fetched",
7559
+ () => client.getPolicy(policyId)
7560
+ );
7561
+ if (isJSONMode()) {
7562
+ printJSON(policyToJSON(policy));
7563
+ return;
7564
+ }
7565
+ printKeyValue([
7566
+ ["Policy ID", policy.policyId],
7567
+ ["Name", policy.policyName],
7568
+ ["Type", policy.policyType],
7569
+ ["Status", policy.status === "active" ? green("active") : dim(policy.status)],
7570
+ ["App", policy.appId],
7571
+ ["Networks", summariseNetworks(policy) || dim("(none)")],
7572
+ ...policy.lastUpdatedUnix ? [["Updated", policy.lastUpdatedUnix]] : []
7573
+ ]);
7574
+ } catch (err) {
7575
+ exitWithError(err);
7576
+ }
7577
+ });
7578
+ policyCmd.command("create").description("Create a new gas policy interactively").option("--type <type>", "Policy type (sponsorship | solana)", "sponsorship").action(async (opts) => {
7579
+ try {
7580
+ const type = parseTypeFilter(opts.type ?? "sponsorship");
7581
+ if (type === "erc20") {
7582
+ throw errInvalidArgs(
7583
+ "ERC-20 policies are not supported in `gas-manager policy create` yet. Create them in the Alchemy dashboard."
7584
+ );
7585
+ }
7586
+ if (!isInteractiveAllowed(program2)) {
7587
+ throw errInvalidArgs(
7588
+ "Policy creation requires an interactive terminal. Create policies in the Alchemy dashboard for non-interactive environments."
7589
+ );
7590
+ }
7591
+ const flavor = type === "solana" ? "solana" : "sponsorship";
7592
+ const network = flavor === "solana" ? resolveSolanaNetwork(program2) : resolveNetwork(program2);
7593
+ const result = await createPolicyInteractive({
7594
+ flavor,
7595
+ network,
7596
+ program: program2
7597
+ });
7598
+ if (!result) return;
7599
+ if (isJSONMode()) {
7600
+ printJSON({
7601
+ policyId: result.policyId,
7602
+ status: result.status,
7603
+ activated: result.activated
7604
+ });
7605
+ }
7606
+ } catch (err) {
7607
+ exitWithError(err);
7608
+ }
7609
+ });
7610
+ policyCmd.command("activate <policy-id>").description("Activate a policy so it can be used for sponsorship").action(async (policyId) => {
7611
+ try {
7612
+ const client = gasManagerClientFromFlags(program2);
7613
+ const policy = await withSpinner(
7614
+ "Activating policy\u2026",
7615
+ "Policy active",
7616
+ () => client.setPolicyStatus(policyId, "active")
7617
+ );
7618
+ if (isJSONMode()) {
7619
+ printJSON(policyToJSON(policy));
7620
+ return;
7621
+ }
7622
+ printKeyValue([
7623
+ ["Policy ID", policy.policyId],
7624
+ ["Name", policy.policyName],
7625
+ ["Status", green(policy.status)]
7626
+ ]);
7627
+ } catch (err) {
7628
+ exitWithError(err);
7629
+ }
7630
+ });
7631
+ }
7632
+
7876
7633
  // src/commands/bridge.ts
7877
7634
  import {
7878
7635
  swapActions as swapActions2
@@ -8073,7 +7830,11 @@ async function performBridgeExecute(program2, opts) {
8073
7830
  const toChainId = bridgeDestinationChainId(opts.toNetwork);
8074
7831
  validateAddress(opts.to);
8075
7832
  const signer = parseSignerOpt(opts.signer);
8076
- const { client, network, address: from, paymaster } = buildWalletClient(program2, { signer });
7833
+ const gasPolicyIdOverride = await ensureGasPolicyResolved(program2);
7834
+ const { client, network, address: from, paymaster } = buildWalletClient(program2, {
7835
+ signer,
7836
+ ...gasPolicyIdOverride && { gasPolicyIdOverride }
7837
+ });
8077
7838
  validateBridgeNetworks(network, opts.toNetwork);
8078
7839
  const swapClient = client.extend(swapActions2);
8079
7840
  const fromInfo = await resolveTokenInfo2(network, program2, opts.from);
@@ -8823,7 +8584,7 @@ async function flushProcessOutput() {
8823
8584
  }
8824
8585
  program.name("alchemy").description(
8825
8586
  "The Alchemy CLI lets you query blockchain data, call JSON-RPC methods, and manage your Alchemy configuration."
8826
- ).version("0.7.4-alpha.37", "-v, --version", "display CLI version").option("--api-key <key>", "Alchemy API key (env: ALCHEMY_API_KEY)").option(
8587
+ ).version("0.8.0", "-v, --version", "display CLI version").option("--api-key <key>", "Alchemy API key (env: ALCHEMY_API_KEY)").option(
8827
8588
  "-n, --network <network>",
8828
8589
  "Target network (default: eth-mainnet) (env: ALCHEMY_NETWORK)"
8829
8590
  ).option("--x402", "Use x402 wallet-based gateway auth").option(
@@ -9010,11 +8771,11 @@ ${styledLine}`;
9010
8771
  "wallet"
9011
8772
  ];
9012
8773
  if (!skipAppPrompt.includes(cmdName) && isInteractiveAllowed(program) && !opts.apiKey && !process.env.ALCHEMY_API_KEY) {
9013
- const { resolveAuthToken: resolveAuthToken2 } = await import("./resolve-PAQKIAX3.js");
8774
+ const { resolveAuthToken: resolveAuthToken2 } = await import("./resolve-N3SX252M.js");
9014
8775
  const authToken = resolveAuthToken2(cfg);
9015
8776
  const hasApiKey = Boolean(cfg.api_key?.trim() || cfg.app?.apiKey);
9016
8777
  if (authToken && !hasApiKey) {
9017
- const { selectAppAfterAuth } = await import("./auth-R5QHPFMA.js");
8778
+ const { selectAppAfterAuth } = await import("./auth-RINQSQDT.js");
9018
8779
  console.log("");
9019
8780
  console.log(` No app selected. Please select an app to continue.`);
9020
8781
  await selectAppAfterAuth(authToken);
@@ -9049,7 +8810,7 @@ ${styledLine}`;
9049
8810
  if (isInteractiveAllowed(program)) {
9050
8811
  let latestForInteractiveStartup = null;
9051
8812
  if (shouldRunOnboarding(program, cfg)) {
9052
- const { runOnboarding } = await import("./onboarding-Q5PBXH3M.js");
8813
+ const { runOnboarding } = await import("./onboarding-YHYXW4F3.js");
9053
8814
  const latest = getAvailableUpdateOnce();
9054
8815
  const completed = await runOnboarding(program, latest);
9055
8816
  updateShownDuringInteractiveStartup = Boolean(latest);
@@ -9063,7 +8824,7 @@ ${styledLine}`;
9063
8824
  latestForInteractiveStartup
9064
8825
  );
9065
8826
  }
9066
- const { startREPL } = await import("./interactive-Z2YHE6ME.js");
8827
+ const { startREPL } = await import("./interactive-6R3VKAPQ.js");
9067
8828
  program.exitOverride();
9068
8829
  program.configureOutput({
9069
8830
  writeErr: () => {
@@ -9078,6 +8839,7 @@ registerEvm(program);
9078
8839
  registerSolana(program);
9079
8840
  registerXchain(program);
9080
8841
  registerWallets(program);
8842
+ registerGasManager(program);
9081
8843
  registerApps(program);
9082
8844
  registerWebhooks(program);
9083
8845
  registerAuth(program);