fix: remove wallet verification popup
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: "Remove wallet address verification popup — Quick Fix"
|
||||
type: quick-fix
|
||||
date: 2026-06-04
|
||||
---
|
||||
|
||||
# Remove wallet address verification popup — Quick Fix
|
||||
|
||||
## Bug
|
||||
|
||||
The in-app-browser wallet address verification popup added friction and interfered with imToken login. The requested behavior is to remove that popup and keep the deeplink login flow direct.
|
||||
|
||||
## Root Cause
|
||||
|
||||
`AutoInjectedLogin` rendered a blocking confirmation dialog for `?autoLogin=` deeplink sessions before calling the injected wallet signature flow. That UI was unnecessary for the current wallet-login flow and could block or confuse imToken users.
|
||||
|
||||
## Fix
|
||||
|
||||
Removed the verification dialog and restored direct deeplink behavior: after the wallet in-app browser injects `window.ethereum`, the app calls `signInWithInjectedWallet()` and completes backend-verified login. Existing logged-in sessions still skip auto-login after stripping the deeplink parameter.
|
||||
|
||||
### Files Modified
|
||||
|
||||
- `src/wallet/AutoInjectedLogin.tsx` — removes the verification popup UI and auto-runs signature login for logged-out deeplink sessions.
|
||||
- `src/wallet/injected.ts` — removes now-unused connected-address helper.
|
||||
- `src/locales/zh-CN.ts` — removes unused verification popup copy.
|
||||
- `src/locales/en.ts` — removes unused verification popup copy.
|
||||
|
||||
## Verification
|
||||
|
||||
- `rg -n "walletVerifyAddress|walletDetectedAddress|getConnectedInjectedAddress|wallet-verify" src || true`
|
||||
- `npx tsc --noEmit`
|
||||
- `npm run format:check`
|
||||
- `npm test`
|
||||
|
||||
## Notes
|
||||
|
||||
The imToken injected-provider fallback remains in place; only the confirmation popup and its supporting copy/helper were removed.
|
||||
@@ -197,13 +197,6 @@ export const enDict: Dict = {
|
||||
walletTpLoginBtn: "Log in with TokenPocket",
|
||||
walletTpWaiting: "Waiting for your signature in TokenPocket…",
|
||||
walletTpReopen: "Reopen TokenPocket",
|
||||
walletVerifyAddressTitle: "Verify wallet address",
|
||||
walletVerifyAddressDesc:
|
||||
"Confirm the wallet address you want to use. After you tap the button below, your wallet app will ask you to sign and verify the address.",
|
||||
walletDetectedAddress: "Detected wallet address",
|
||||
walletVerifyAddressUnknown:
|
||||
"The wallet address will be requested after verification",
|
||||
walletVerifyAddressButton: "Verify this address",
|
||||
favoritesFilters: "Filters",
|
||||
favoriteSessionExpired: "Your session expired. Please sign in again.",
|
||||
loadFailed: "Could not load your favorites.",
|
||||
|
||||
@@ -186,12 +186,6 @@ export const zhDict: Dict = {
|
||||
walletTpLoginBtn: "使用 TokenPocket 登录",
|
||||
walletTpWaiting: "等待你在 TokenPocket 中完成签名…",
|
||||
walletTpReopen: "重新打开 TokenPocket",
|
||||
walletVerifyAddressTitle: "验证钱包地址",
|
||||
walletVerifyAddressDesc:
|
||||
"请确认将使用当前钱包地址登录。点击下方按钮后,钱包 App 会要求你签名验证地址。",
|
||||
walletDetectedAddress: "检测到的钱包地址",
|
||||
walletVerifyAddressUnknown: "点击验证后将请求钱包地址",
|
||||
walletVerifyAddressButton: "验证此地址",
|
||||
favoritesFilters: "筛选",
|
||||
favoriteSessionExpired: "登录已过期,请重新登录。",
|
||||
loadFailed: "无法加载收藏,请稍后重试。",
|
||||
|
||||
@@ -1,25 +1,15 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useI18n } from "../i18n";
|
||||
import { useEffect } from "react";
|
||||
import {
|
||||
getConnectedInjectedAddress,
|
||||
getInjectedWallet,
|
||||
signInWithInjectedWallet,
|
||||
type WalletKind,
|
||||
} from "./injected";
|
||||
import { shortenAddress, useWallet } from "./WalletProvider";
|
||||
import { useWallet } from "./WalletProvider";
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
function parseKind(value: string | null): WalletKind | null {
|
||||
if (value === "tokenPocket" || value === "metaMask" || value === "imToken") {
|
||||
return value;
|
||||
@@ -55,15 +45,13 @@ function waitForInjected(kind: WalletKind): Promise<boolean> {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* inside TokenPocket / imToken in-app browsers), wait for the wallet to inject
|
||||
* `window.ethereum`, then require a wallet signature and complete a verified
|
||||
* backend wallet session. Bypasses WalletConnect entirely so it works on
|
||||
* networks where the WC relay is blocked.
|
||||
*/
|
||||
export function AutoInjectedLogin() {
|
||||
const { t } = useI18n();
|
||||
const { completeLogin, status } = useWallet();
|
||||
const [request, setRequest] = useState<AutoLoginRequest | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
@@ -73,133 +61,24 @@ export function AutoInjectedLogin() {
|
||||
if (status === "loading") return;
|
||||
|
||||
stripAutoLoginParam();
|
||||
if (status === "loggedIn") {
|
||||
setRequest(null);
|
||||
return;
|
||||
}
|
||||
if (status === "loggedIn") return;
|
||||
|
||||
let cancelled = false;
|
||||
setRequest({
|
||||
kind,
|
||||
ready: false,
|
||||
address: null,
|
||||
signing: false,
|
||||
error: "",
|
||||
});
|
||||
|
||||
void waitForInjected(kind).then(async (ready) => {
|
||||
if (cancelled || !ready) return;
|
||||
try {
|
||||
const res = await signInWithInjectedWallet(kind);
|
||||
if (cancelled) return;
|
||||
if (!ready) {
|
||||
setRequest((current) =>
|
||||
current?.kind === kind
|
||||
? { ...current, ready: false, error: t("walletNoBrowserWallet") }
|
||||
: current,
|
||||
);
|
||||
return;
|
||||
completeLogin(res.token, res.wallet);
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn("[wallet-autologin] failed", err);
|
||||
}
|
||||
|
||||
const address = await getConnectedInjectedAddress(kind);
|
||||
if (cancelled) return;
|
||||
setRequest((current) =>
|
||||
current?.kind === kind
|
||||
? { ...current, ready: true, address, error: "" }
|
||||
: current,
|
||||
);
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [status, t]);
|
||||
}, [completeLogin, status]);
|
||||
|
||||
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";
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -166,17 +166,6 @@ export function getInjectedWallet(kind?: WalletKind): EthereumProvider | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function getConnectedInjectedAddress(
|
||||
kind?: WalletKind,
|
||||
): Promise<string | null> {
|
||||
const ethereum = getInjectedWallet(kind);
|
||||
if (!ethereum) return null;
|
||||
const accounts = await ethereum
|
||||
.request<unknown[]>({ method: "eth_accounts" })
|
||||
.catch((): unknown[] => []);
|
||||
return accounts.find(isAddress) ?? null;
|
||||
}
|
||||
|
||||
/** Diagnostic: log what injected providers the browser exposes. */
|
||||
export function logWalletProviders(): void {
|
||||
const ethereum = getInjectedEthereum();
|
||||
|
||||
Reference in New Issue
Block a user