Files
Arkie-Library-Frontend/src/wallet/AutoInjectedLogin.tsx

206 lines
6.0 KiB
TypeScript
Raw Normal View History

import { useCallback, useEffect, useState } from "react";
import { useI18n } from "../i18n";
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
import {
getConnectedInjectedAddress,
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
getInjectedWallet,
signInWithInjectedWallet,
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
type WalletKind,
} from "./injected";
import { shortenAddress, useWallet } from "./WalletProvider";
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
const AUTO_LOGIN_PARAM = "autoLogin";
const ETHEREUM_WAIT_MS = 8000;
const ETHEREUM_POLL_MS = 200;
type AutoLoginRequest = {
kind: WalletKind;
ready: boolean;
address: string | null;
signing: boolean;
error: string;
};
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
function parseKind(value: string | null): WalletKind | null {
if (value === "tokenPocket" || value === "metaMask" || value === "imToken") {
return value;
}
return null;
}
function stripAutoLoginParam(): void {
const url = new URL(window.location.href);
url.searchParams.delete(AUTO_LOGIN_PARAM);
const qs = url.searchParams.toString();
const next = url.pathname + (qs ? `?${qs}` : "") + url.hash;
window.history.replaceState({}, "", next);
}
function waitForInjected(kind: WalletKind): Promise<boolean> {
return new Promise((resolve) => {
const start = Date.now();
const tick = () => {
if (getInjectedWallet(kind)) {
resolve(true);
return;
}
if (Date.now() - start >= ETHEREUM_WAIT_MS) {
resolve(false);
return;
}
window.setTimeout(tick, ETHEREUM_POLL_MS);
};
tick();
});
}
/**
* When the page is opened via a `?autoLogin=<wallet>` deeplink (typically from
* inside TokenPocket / imToken in-app browsers), show an explicit verification
* prompt first. The wallet signature and backend verification only start after
* the user taps the verification button, so Chrome -> wallet handoff never logs
* in silently from a cached in-app-browser session.
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
*/
export function AutoInjectedLogin() {
const { t } = useI18n();
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
const { completeLogin, status } = useWallet();
const [request, setRequest] = useState<AutoLoginRequest | null>(null);
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
useEffect(() => {
if (typeof window === "undefined") return;
const params = new URLSearchParams(window.location.search);
const kind = parseKind(params.get(AUTO_LOGIN_PARAM));
if (!kind) return;
if (status === "loading") return;
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
stripAutoLoginParam();
if (status === "loggedIn") {
setRequest(null);
return;
}
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
let cancelled = false;
setRequest({
kind,
ready: false,
address: null,
signing: false,
error: "",
});
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
void waitForInjected(kind).then(async (ready) => {
if (cancelled) return;
if (!ready) {
setRequest((current) =>
current?.kind === kind
? { ...current, ready: false, error: t("walletNoBrowserWallet") }
: current,
);
return;
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
}
const address = await getConnectedInjectedAddress(kind);
if (cancelled) return;
setRequest((current) =>
current?.kind === kind
? { ...current, ready: true, address, error: "" }
: current,
);
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
});
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
return () => {
cancelled = true;
};
}, [status, t]);
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
const verifyAddress = useCallback(async () => {
if (!request || !request.ready || request.signing) return;
setRequest((current) =>
current ? { ...current, signing: true, error: "" } : current,
);
try {
const res = await signInWithInjectedWallet(request.kind);
completeLogin(res.token, res.wallet);
setRequest(null);
} catch (err) {
const message =
err instanceof Error ? err.message : t("walletLoginFailed");
setRequest((current) =>
current
? {
...current,
signing: false,
error: message || t("walletLoginFailed"),
}
: current,
);
// eslint-disable-next-line no-console
console.warn("[wallet-autologin] verification failed", err);
}
}, [completeLogin, request, t]);
if (!request) return null;
const addressLabel = request.address
? shortenAddress(request.address)
: t("walletVerifyAddressUnknown");
return (
<div
className="fixed inset-0 z-[130] flex items-end justify-center bg-black/75 px-3 pb-3 pt-10 backdrop-blur-sm md:items-center md:p-6"
role="dialog"
aria-modal="true"
aria-labelledby="wallet-verify-title"
>
<div className="w-full max-w-[420px] rounded-3xl border border-white/10 bg-[#17171d] p-5 shadow-2xl shadow-black/70 md:p-6">
<p className="text-xs font-semibold uppercase tracking-[0.24em] text-ark-gold">
{t(walletNameKey(request.kind))}
</p>
<h2
id="wallet-verify-title"
className="mt-3 text-xl font-semibold text-white"
>
{t("walletVerifyAddressTitle")}
</h2>
<p className="mt-2 text-sm leading-6 text-neutral-400">
{t("walletVerifyAddressDesc")}
</p>
<div className="mt-5 rounded-2xl border border-white/10 bg-white/[0.03] px-4 py-3">
<p className="text-xs text-neutral-500">
{t("walletDetectedAddress")}
</p>
<p className="mt-1 break-all font-mono text-sm text-neutral-100">
{addressLabel}
</p>
</div>
{request.error ? (
<p className="mt-4 rounded-2xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-200">
{request.error}
</p>
) : null}
<button
type="button"
onClick={verifyAddress}
disabled={!request.ready || request.signing}
className="mt-5 w-full rounded-full bg-ark-gold px-4 py-3 text-sm font-bold text-black transition hover:bg-ark-gold2 disabled:cursor-wait disabled:opacity-70"
>
{request.signing
? t("walletSigning")
: request.ready
? t("walletVerifyAddressButton")
: t("walletConnecting")}
</button>
</div>
</div>
);
}
function walletNameKey(kind: WalletKind): string {
if (kind === "tokenPocket") return "walletTokenPocket";
if (kind === "metaMask") return "walletMetaMask";
return "walletImToken";
feat(wallet): bypass WalletConnect for TP/imToken on mobile to fix China users The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR) depends on it, so Chinese users see the login button hang forever and the QR code never appears. When RainbowKit's render fails, the whole site goes white because nothing catches the error. Changes: - Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so RainbowKit init failures no longer blank the entire app. - Hoist <WalletProvider> above the boundary; it only depends on the injected provider, so useWallet keeps working for header / favorites / etc. even when the WC stack is dead. - On mobile, the TP/imToken 'Open Wallet App' button now navigates directly to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind> query, pulling the site into the wallet's in-app browser without ever touching the WC relay. MetaMask still uses the WC path (no equivalent deeplink). - Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait up to 8s for window.ethereum, then connectInjectedWallet + completeLogin. Strips the param via history.replaceState to avoid re-firing on reload. - Guard against the in-app-browser disconnect/reconnect case: if getInjectedWallet(kind) is already truthy, skip the deeplink and let useWalletConnectLogin's deeplink mode take the injected fast path (avoids TP trying to open TP recursively).
2026-06-03 20:07:23 +08:00
}