diff --git a/src/wallet/injected.ts b/src/wallet/injected.ts index ec67e38..a2c0d4a 100644 --- a/src/wallet/injected.ts +++ b/src/wallet/injected.ts @@ -175,6 +175,28 @@ export function logWalletProviders(): void { }); } +export async function connectInjectedWallet( + kind?: WalletKind, +): Promise { + /* eslint-disable no-console */ + console.info("[wallet-login] start injected connect", { kind }); + logWalletProviders(); + const ethereum = getInjectedWallet(kind); + if (!ethereum) { + console.warn("[wallet-login] no injected provider found"); + throw new Error("No injected wallet found"); + } + + console.info("[wallet-login] requesting BNB wallet account…"); + const address = await requestInjectedAddress(ethereum); + console.info("[wallet-login] injected account", address); + + console.info("[wallet-login] ensuring BNB Chain (0x38)…"); + await ensureBnbChain(ethereum); + return address; + /* eslint-enable no-console */ +} + export async function signInWithInjectedWallet(kind?: WalletKind): Promise<{ token: string; wallet: string; diff --git a/src/wallet/useWalletConnectLogin.ts b/src/wallet/useWalletConnectLogin.ts index 31be95e..dddbc91 100644 --- a/src/wallet/useWalletConnectLogin.ts +++ b/src/wallet/useWalletConnectLogin.ts @@ -2,7 +2,11 @@ import { useCallback, useRef, useState } from "react"; import { useConnect, useDisconnect } from "wagmi"; import { bsc } from "wagmi/chains"; import { hasWalletConnectProjectId } from "./RainbowWalletProvider"; -import type { WalletKind } from "./injected"; +import { + connectInjectedWallet, + getInjectedWallet, + type WalletKind, +} from "./injected"; import { localWalletToken, useWallet } from "./WalletProvider"; export type WalletConnectLoginState = "idle" | "connecting" | "signing"; @@ -15,6 +19,11 @@ function isMobileDevice(): boolean { ); } +function currentUrl(): string { + if (typeof window === "undefined") return "https://ark-library.com"; + return window.location.href; +} + function walletConnectDeeplink( kind: WalletKind | undefined, uri: string, @@ -31,6 +40,27 @@ function walletConnectDeeplink( return null; } +function inAppBrowserFallback(kind: WalletKind | undefined): string | null { + if (kind === "imToken") { + return `imtokenv2://navigate/DappView?url=${encodeURIComponent(currentUrl())}`; + } + return null; +} + +function openWalletDeeplink( + kind: WalletKind | undefined, + deeplink: string, +): void { + window.location.href = deeplink; + const fallback = inAppBrowserFallback(kind); + if (!fallback) return; + window.setTimeout(() => { + if (document.visibilityState === "visible") { + window.location.href = fallback; + } + }, 1500); +} + /** * MetaMask / imToken QR fallback via RainbowKit + WalletConnect. * @@ -76,11 +106,28 @@ export function useWalletConnectLogin() { pendingRef.current = true; setState("connecting"); + if (preferredWallet && getInjectedWallet(preferredWallet)) { + try { + const injectedAddress = await connectInjectedWallet(preferredWallet); + console.info("[wallet-login] injected connected", { + preferredWallet, + address: injectedAddress, + chain: "BNB Chain", + chainId: bsc.id, + }); + completeLogin(localWalletToken(injectedAddress), injectedAddress); + setState("idle"); + return; + } catch (err) { + console.info("[wallet-login] injected connect fallback to wc", { + preferredWallet, + message: err instanceof Error ? err.message : String(err), + }); + } + } + // This modal is QR/WalletConnect-only. RainbowKit also exposes wallet- // specific injected connectors (for example `tokenPocket`) when an - // extension is installed; using those here makes the click try the local - // browser extension and can fail with "wallet must has at least one - // account" before a QR is shown. const connector = connectors.find((item) => item.type === "walletConnect") ?? connectors.find((item) => item.id === "walletConnect"); @@ -114,7 +161,7 @@ export function useWalletConnectLogin() { if (mode === "qr") setQrUri(message.data); const deeplink = walletConnectDeeplink(preferredWallet, message.data); if (mode === "deeplink" && deeplink && isMobileDevice()) { - window.location.href = deeplink; + openWalletDeeplink(preferredWallet, deeplink); } };