From a1b318016f7bdf84dc4e25e90759c3ccf6dd7036 Mon Sep 17 00:00:00 2001 From: TerryM Date: Thu, 4 Jun 2026 09:31:07 +0800 Subject: [PATCH] fix: detect imtoken injected provider by browser --- ...imtoken-injected-provider-detection-fix.md | 33 +++++++++++++++++++ src/wallet/injected.ts | 15 ++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 .unipi/docs/fix/2026-06-04-imtoken-injected-provider-detection-fix.md diff --git a/.unipi/docs/fix/2026-06-04-imtoken-injected-provider-detection-fix.md b/.unipi/docs/fix/2026-06-04-imtoken-injected-provider-detection-fix.md new file mode 100644 index 0000000..5e8b037 --- /dev/null +++ b/.unipi/docs/fix/2026-06-04-imtoken-injected-provider-detection-fix.md @@ -0,0 +1,33 @@ +--- +title: "imToken in-app browser cannot connect after deeplink — Quick Fix" +type: quick-fix +date: 2026-06-04 +--- + +# imToken in-app browser cannot connect after deeplink — Quick Fix + +## Bug + +After Chrome opens imToken's in-app browser, wallet login cannot complete and the wallet debug panel shows `connected: no`. + +## Root Cause + +The frontend looked for an injected wallet provider using the wallet-specific `isImToken` flag. Some imToken mobile versions inject a usable EIP-1193 `window.ethereum` provider but do not expose `isImToken`, so `getInjectedWallet("imToken")` returned `null`. That prevented the imToken direct-login path from using the injected provider and left the flow disconnected. + +## Fix + +Added a narrow imToken in-app-browser fallback: when the requested wallet is `imToken`, no provider has `isImToken`, but the user agent indicates imToken and `window.ethereum` exists, use the injected provider. + +### Files Modified + +- `src/wallet/injected.ts` — adds imToken user-agent fallback for injected provider detection. + +## Verification + +- `npx tsc --noEmit` +- `npm run format:check` +- `npm test` + +## Notes + +This fallback is limited to imToken browser user agents to avoid changing MetaMask or TokenPocket provider selection behavior. diff --git a/src/wallet/injected.ts b/src/wallet/injected.ts index f1ecb57..0d811c6 100644 --- a/src/wallet/injected.ts +++ b/src/wallet/injected.ts @@ -138,6 +138,11 @@ export function getInjectedEthereum(): EthereumProvider | null { return maybeWindow.ethereum ?? null; } +function isImTokenBrowser(): boolean { + if (typeof navigator === "undefined") return false; + return /imtoken/i.test(navigator.userAgent || ""); +} + export function getInjectedWallet(kind?: WalletKind): EthereumProvider | null { const ethereum = getInjectedEthereum(); if (!ethereum || !kind) return ethereum; @@ -150,7 +155,15 @@ export function getInjectedWallet(kind?: WalletKind): EthereumProvider | null { if (kind === "imToken") return provider.isImToken; return false; }); - return match ?? null; + if (match) return match; + + // Some imToken mobile versions inject a usable EIP-1193 provider without + // setting `isImToken`. Inside the imToken in-app browser, prefer the injected + // provider instead of falling back to WalletConnect, which can leave the UI at + // connected:no on China networks. + if (kind === "imToken" && isImTokenBrowser()) return providers[0] ?? ethereum; + + return null; } export async function getConnectedInjectedAddress(