-

-
-
Please switch to a supported network
-
- Click "Unknown network" above to select a different network.
+ <>
+
+
+

+
+
+ {walletChain ? "Please switch to the correct network" : "Please switch to a supported network"}
+
+
+ Click the network dropdown above to select a different network.
+
-
+
+
+ {walletNetworkStatus !== "present" && (
+
+ )}
+
+ >
)}
diff --git a/src/features/ccip/components/WalletConnection.module.css b/src/features/ccip/components/WalletConnection.module.css
index f6840b08f5e..11b8182ded7 100644
--- a/src/features/ccip/components/WalletConnection.module.css
+++ b/src/features/ccip/components/WalletConnection.module.css
@@ -170,6 +170,73 @@
flex-shrink: 0;
}
+/* Wallet picker (injected wallets) */
+.walletPickerContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: var(--space-2x);
+ padding: var(--space-4x) var(--space-4x) 0;
+}
+
+.walletPickerLabel {
+ margin: 0;
+ font-size: var(--text-sm);
+ color: var(--color-text-secondary);
+ font-weight: 500;
+}
+
+.walletPickerOptions {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: var(--space-2x);
+ width: 100%;
+ max-width: 640px;
+}
+
+.walletOptionButton {
+ display: flex !important;
+ align-items: center;
+ gap: var(--space-2x);
+ min-height: 44px;
+ padding: var(--space-2x) var(--space-3x);
+ white-space: nowrap;
+}
+
+.walletOptionButton:focus {
+ /* Override design-system outer focus ring for wallet picker buttons */
+ box-shadow: none !important;
+}
+
+.walletOptionButton:focus-visible {
+ /* Keep an accessible focus indicator, but avoid an outer boundary */
+ box-shadow: inset 0 0 0 2px var(--color-border-interactive-focus) !important;
+}
+
+.walletOptionButtonSelected {
+ /* Persist the same styling as design-system hover state */
+ border-color: var(--blue-800) !important;
+ background-color: var(--blue-100) !important;
+ color: var(--blue-800) !important;
+ font-weight: 600;
+}
+
+.walletOptionButtonSelected:hover,
+.walletOptionButtonSelected:focus,
+.walletOptionButtonSelected:focus-visible {
+ border-color: var(--blue-800) !important;
+ background-color: var(--blue-100) !important;
+ color: var(--blue-800) !important;
+}
+
+.walletOptionIcon {
+ width: 18px;
+ height: 18px;
+ border-radius: 4px;
+ flex-shrink: 0;
+}
+
/* Wallet selection area */
.walletSelection {
width: 100%;
diff --git a/src/features/ccip/components/networkDropdown.module.css b/src/features/ccip/components/networkDropdown.module.css
index 931be79f3b9..6e58e87e3a2 100644
--- a/src/features/ccip/components/networkDropdown.module.css
+++ b/src/features/ccip/components/networkDropdown.module.css
@@ -159,6 +159,7 @@ details {
padding: var(--space-4x);
border-radius: var(--border-radius-primary);
margin-top: var(--space-3x);
+ margin-bottom: var(--space-3x);
border: var(--border-width-primary) solid var(--red-200);
}
@@ -190,11 +191,20 @@ details {
color: var(--color-text-primary);
}
+.networkCtas {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-2x);
+ align-items: center;
+ padding-bottom: var(--space-4x);
+}
+
/* Responsive adjustments */
@media screen and (max-width: 767px) {
.unknownNetworkWarning {
padding: var(--space-3x);
margin-top: var(--space-2x);
+ margin-bottom: var(--space-2x);
}
.warningContent {
diff --git a/src/features/utils/index.ts b/src/features/utils/index.ts
index a9d35372df4..7b4fe7f1b3f 100644
--- a/src/features/utils/index.ts
+++ b/src/features/utils/index.ts
@@ -33,6 +33,17 @@ export const getEthereumChainParameter = (chainId: string) => {
throw new Error(`Chain with chainId '${chainId}' not found in reference data`)
}
+ const rpcUrls = (Array.isArray(chain.rpc) ? chain.rpc : [])
+ .filter((url: unknown): url is string => typeof url === "string")
+ .filter((url) => url.startsWith("https://"))
+ // Drop placeholder endpoints like https://.../${INFURA_API_KEY}
+ .filter((url) => !url.includes("$"))
+ .slice(0, 3)
+
+ if (rpcUrls.length === 0) {
+ throw new Error(`No valid https rpcUrls found for chainId '${chainId}'`)
+ }
+
const params: AddEthereumChainParameter = {
chainId,
chainName: chain.name,
@@ -42,7 +53,7 @@ export const getEthereumChainParameter = (chainId: string) => {
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
chain.explorers.map((explorer: any) => explorer.url)
: [chain.infoURL],
- rpcUrls: chain.rpc,
+ rpcUrls,
}
return params
}
diff --git a/src/hooks/useEIP6963Providers.tsx b/src/hooks/useEIP6963Providers.tsx
index 44648160685..07903408a15 100644
--- a/src/hooks/useEIP6963Providers.tsx
+++ b/src/hooks/useEIP6963Providers.tsx
@@ -123,7 +123,7 @@ export function useWalletSelector() {
const providers = useInjectedProviders()
const walletOptions = useMemo(() => {
- return providers.map((provider) => ({
+ const eip6963Options = providers.map((provider) => ({
uuid: provider.info.uuid,
name: provider.info.name,
icon: provider.info.icon,
@@ -132,6 +132,24 @@ export function useWalletSelector() {
isMetaMask: provider.info.rdns === "io.metamask",
isPhantom: provider.info.rdns === "app.phantom",
}))
+ if (eip6963Options.length > 0) return eip6963Options
+
+ // Legacy fallback for wallets that haven't implemented EIP-6963 announcements.
+ // This preserves basic injected-wallet support via window.ethereum.
+ if (typeof window === "undefined") return []
+ const ethereum = (window as WindowWithEthereum).ethereum
+ if (!ethereum) return []
+ return [
+ {
+ uuid: "legacy-window-ethereum",
+ name: "Browser wallet",
+ icon: "",
+ rdns: undefined,
+ provider: ethereum,
+ isMetaMask: !!ethereum.isMetaMask,
+ isPhantom: false,
+ },
+ ]
}, [providers])
return {