fix: auto-login imToken in-app browser without query
All checks were successful
Deploy to Frontend Servers / deploy (push) Successful in 1m0s

This commit is contained in:
TerryM
2026-06-06 00:52:19 +08:00
parent 5408a86cc9
commit fe8dcee9a1
2 changed files with 47 additions and 7 deletions

View File

@@ -0,0 +1,34 @@
---
title: "imToken production cannot get wallet address — Quick Fix"
type: quick-fix
date: 2026-06-06
---
# imToken production cannot get wallet address — Quick Fix
## Bug
`main` serves `ark-library.com`, while `terry-wallet-login` serves the staging site. Staging can log in with imToken, but production can open imToken's in-app browser without getting the wallet address or completing login.
## Root Cause
The auto-login effect only ran when the URL contained an explicit `autoLogin` / `autologin` query parameter. imToken's in-app-browser deeplink can open the DApp page without preserving that query string. In that case the production page was inside imToken and could have an injected wallet provider, but `AutoInjectedLogin` returned early and never attempted to read the wallet address.
The parser was also case-sensitive, so a lowercase `autologin=imtoken` test URL would not start the flow.
## Fix
Updated the auto-login entrypoint to treat an imToken in-app-browser user agent as an imToken direct-login session even when the query parameter is missing. Also made the wallet-kind parser case-insensitive.
### Files Modified
- `src/wallet/AutoInjectedLogin.tsx` — imports `isImTokenBrowser()`, falls back to `imToken` when inside imToken without an auto-login query, and accepts lowercase wallet kind values.
## Verification
- `npx prettier --write src/wallet/AutoInjectedLogin.tsx`
- `npx tsc --noEmit`
## Notes
This is scoped to imToken UA fallback. TokenPocket and MetaMask still require an explicit auto-login query parameter.

View File

@@ -2,6 +2,7 @@ import { useEffect } from "react";
import { import {
connectInjectedWallet, connectInjectedWallet,
getInjectedWallet, getInjectedWallet,
isImTokenBrowser,
type WalletKind, type WalletKind,
} from "./injected"; } from "./injected";
import { useWallet } from "./WalletProvider"; import { useWallet } from "./WalletProvider";
@@ -11,18 +12,23 @@ const ETHEREUM_WAIT_MS = 8000;
const ETHEREUM_POLL_MS = 200; const ETHEREUM_POLL_MS = 200;
function parseKind(value: string | null): WalletKind | null { function parseKind(value: string | null): WalletKind | null {
if (value === "tokenPocket" || value === "metaMask" || value === "imToken") { const normalized = value?.toLowerCase();
return value; if (normalized === "tokenpocket") return "tokenPocket";
} if (normalized === "metamask") return "metaMask";
if (normalized === "imtoken") return "imToken";
return null; return null;
} }
function autoLoginKindFromParams(params: URLSearchParams): WalletKind | null { function autoLoginKind(params: URLSearchParams): WalletKind | null {
for (const key of AUTO_LOGIN_PARAMS) { for (const key of AUTO_LOGIN_PARAMS) {
const kind = parseKind(params.get(key)); const kind = parseKind(params.get(key));
if (kind) return kind; if (kind) return kind;
} }
return null; return isImTokenBrowser() ? "imToken" : null;
}
function hasAutoLoginParam(params: URLSearchParams): boolean {
return AUTO_LOGIN_PARAMS.some((key) => params.has(key));
} }
function stripAutoLoginParam(): void { function stripAutoLoginParam(): void {
@@ -57,10 +63,10 @@ export function AutoInjectedLogin() {
useEffect(() => { useEffect(() => {
if (typeof window === "undefined") return; if (typeof window === "undefined") return;
const params = new URLSearchParams(window.location.search); const params = new URLSearchParams(window.location.search);
const kind = autoLoginKindFromParams(params); const kind = autoLoginKind(params);
if (!kind) return; if (!kind) return;
stripAutoLoginParam(); if (hasAutoLoginParam(params)) stripAutoLoginParam();
if (status === "loggedIn") return; if (status === "loggedIn") return;
let cancelled = false; let cancelled = false;