fix(wallet): improve imtoken mobile login fallback
This commit is contained in:
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user