diff --git a/packages/keychain/src/components/purchase/checkout/onchain/wallet-drawer.tsx b/packages/keychain/src/components/purchase/checkout/onchain/wallet-drawer.tsx index 57b2cfe31..996def69b 100644 --- a/packages/keychain/src/components/purchase/checkout/onchain/wallet-drawer.tsx +++ b/packages/keychain/src/components/purchase/checkout/onchain/wallet-drawer.tsx @@ -131,6 +131,13 @@ export function WalletSelectionDrawer({ (chain) => chain.isMainnet === isMainnet, )?.chainId; + console.log("[chain-debug] wallet-drawer resolve chainId", { + isMainnet, + platform: selectedNetwork.platform, + chains: selectedNetwork.chains, + resolvedChainId: chainId, + }); + if (chainId) { newChainIds.set(selectedNetwork.platform, chainId); } diff --git a/packages/keychain/src/components/purchase/wallet/wallet.tsx b/packages/keychain/src/components/purchase/wallet/wallet.tsx index a61ab8c17..18b7dee18 100644 --- a/packages/keychain/src/components/purchase/wallet/wallet.tsx +++ b/packages/keychain/src/components/purchase/wallet/wallet.tsx @@ -89,6 +89,13 @@ export function SelectWallet() { (chain) => chain.isMainnet === isMainnet, )?.chainId; + console.log("[chain-debug] wallet.tsx resolve chainId", { + isMainnet, + platform: network.platform, + chains: network.chains, + resolvedChainId: chainId, + }); + if (chainId) { newChainIds.set(network.platform, chainId); } diff --git a/packages/keychain/src/hooks/connection.ts b/packages/keychain/src/hooks/connection.ts index d6ae7f5cb..96b0fa88e 100644 --- a/packages/keychain/src/hooks/connection.ts +++ b/packages/keychain/src/hooks/connection.ts @@ -659,8 +659,20 @@ export function useConnectionValue() { }, [controller?.username, chainId, controller]); useEffect(() => { - setIsMainnet(controller?.chainId() === constants.StarknetChainId.SN_MAIN); - }, [controller]); + // Prefer the RPC-derived chainId state since it tracks network switches; + // controller.chainId() is only re-read when the controller object identity + // changes, so it can go stale (e.g. after an in-place network switch), + // leaving isMainnet wrong regardless of the actual connected network. + const currentChainId = chainId ?? controller?.chainId(); + console.log("[chain-debug] isMainnet effect", { + chainIdState: chainId, + controllerChainId: controller?.chainId(), + currentChainId, + SN_MAIN: constants.StarknetChainId.SN_MAIN, + isMainnet: currentChainId === constants.StarknetChainId.SN_MAIN, + }); + setIsMainnet(currentChainId === constants.StarknetChainId.SN_MAIN); + }, [chainId, controller]); // Load config when preset is provided useEffect(() => { diff --git a/packages/keychain/src/hooks/starterpack/external-wallet.ts b/packages/keychain/src/hooks/starterpack/external-wallet.ts index 6a0817d1f..2bf76b3eb 100644 --- a/packages/keychain/src/hooks/starterpack/external-wallet.ts +++ b/packages/keychain/src/hooks/starterpack/external-wallet.ts @@ -1,8 +1,18 @@ import { useState, useCallback } from "react"; import { ExternalPlatform, ExternalWallet } from "@cartridge/controller"; +import { shortString } from "starknet"; import { useWallets } from "@/hooks/wallets"; import { useConnection } from "../connection"; +function normalizeChainId(chainId: string | number): string { + if (typeof chainId === "number") { + return `0x${chainId.toString(16)}`.toLowerCase(); + } + return ( + chainId.startsWith("0x") ? chainId : shortString.encodeShortString(chainId) + ).toLowerCase(); +} + export interface UseExternalWalletOptions { onError?: (error: Error) => void; } @@ -77,12 +87,32 @@ export function useExternalWallet({ "Braavos does not support `wallet_switchStarknetChain`", ); } else { - const res = await switchChain(wallet.type, chainId.toString()); - if (!res) { - const error = new Error( - `${wallet.name} failed to switch chain (${chainId})`, - ); - throw error; + // Only request a chain switch when the wallet isn't already on the + // target chain. Switching unconditionally makes wallets (e.g. Ready) + // prompt every time, even when no change is needed. + const target = normalizeChainId(chainId); + const current = wallet.chainId + ? normalizeChainId(wallet.chainId) + : undefined; + + console.log("[chain-debug] onExternalConnect switch decision", { + walletType: wallet.type, + walletChainIdRaw: wallet.chainId, + targetChainIdRaw: chainId, + normalizedCurrent: current, + normalizedTarget: target, + controllerChainId: controller?.chainId(), + willSwitch: current !== target, + }); + + if (current !== target) { + const res = await switchChain(wallet.type, chainId.toString()); + if (!res) { + const error = new Error( + `${wallet.name} failed to switch chain (${chainId})`, + ); + throw error; + } } } }