fix(wallet): improve imtoken mobile login fallback

This commit is contained in:
TerryM
2026-06-02 23:32:39 +08:00
parent a8863c5478
commit cd85a4bcfa
2 changed files with 74 additions and 5 deletions

View File

@@ -175,6 +175,28 @@ export function logWalletProviders(): void {
});
}
export async function connectInjectedWallet(
kind?: WalletKind,
): Promise<string> {
/* 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;

View File

@@ -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);
}
};