Files
Arkie-Library-Frontend/.unipi/docs/debug/2026-06-04-imtoken-no-address-debug.md
TerryM fb904d3a55
Some checks failed
Deploy Staging (terry-wallet-login) / deploy (push) Failing after 37s
fix: restore staging imtoken login behavior
2026-06-04 10:27:31 +08:00

7.6 KiB

title, type, date, severity, status
title type date severity status
imToken opens in-app browser but cannot get wallet address — Debug Report debug 2026-06-04 high needs-investigation

imToken opens in-app browser but cannot get wallet address — Debug Report

Summary

imToken can open the site in its in-app browser, but the frontend does not obtain a wallet address and the login flow stays at connected: no.

Expected Behavior

  1. User taps imToken from Chrome or from imToken's in-app browser.
  2. The site detects the imToken injected wallet provider.
  3. The frontend requests accounts via the injected provider.
  4. The frontend receives a wallet address and completes login.

Actual Behavior

The page opens inside imToken, but the wallet modal remains stuck with:

  • state: connecting
  • connected: no
  • address: -
  • qr: -

The supplied screenshot shows the page loaded at 192.168.1.187 and the imToken card selected.

Reproduction Steps

  1. Open the site in Chrome on mobile.
  2. Tap wallet login.
  3. Select imToken.
  4. The app opens imToken's in-app browser.
  5. Login does not complete and no wallet address appears.
  6. Open the same page inside imToken's in-app browser and tap login again.
  7. The wallet debug panel still shows connected: no and address: -.

Environment

  • Branch: terry-wallet-login
  • Frontend URL shown in screenshot: 192.168.1.187
  • Wallet: imToken mobile in-app browser
  • Network path: local LAN IP, likely non-HTTPS

Root Cause Analysis

Failure Chain

  1. WalletLoginModal selects imToken and exposes the mobile actions.
  2. openWalletAppDirect(kind) first checks getInjectedWallet(kind).
  3. If no injected provider is detected, the flow deep-links to imToken or falls through to useWalletConnectLogin.start() depending on which action is tapped.
  4. useWalletConnectLogin.start() sets state to connecting before trying direct injected login.
  5. The direct injected branch only runs when getInjectedWallet(preferredWallet) returns a provider.
  6. The screenshot shows state: connecting, connected: no, address: -, and qr: -, which means no address was completed through either direct injected login or WalletConnect.
  7. AutoInjectedLogin can auto-start imToken login without ?autoLogin=imToken only if isImTokenBrowser() detects the imToken user agent; it still depends on waitForInjected("imToken"), which depends on getInjectedWallet("imToken").
  8. Therefore the app is not obtaining a usable imToken injected provider, or the provider is present but eth_accounts / eth_requestAccounts returns no valid address.

Root Cause

The immediate root cause is failure to obtain a usable injected imToken provider/account. The most likely reason from the screenshot is that the page is running on raw LAN IP 192.168.1.187, likely over HTTP. imToken may not inject its EIP-1193 provider into non-HTTPS/raw-IP pages, or its iOS in-app browser may not expose a user agent/provider shape that matches the current checks.

The code currently assumes at least one of these is true:

  • URL contains ?autoLogin=imToken, or
  • navigator.userAgent matches /imtoken/i, and
  • window.ethereum is present and accepted by getInjectedWallet("imToken"), and
  • eth_accounts or eth_requestAccounts returns a valid 0x... address.

The observed behavior shows that this assumption chain is breaking before a valid address is produced.

Evidence

  • File: src/wallet/WalletLoginModal.tsxopenWalletAppDirect() uses getInjectedWallet(kind) as the gate for direct injected login; if it is false, the flow navigates/deep-links instead of reading an address.
  • File: src/wallet/useWalletConnectLogin.tsstart() sets state to connecting; the imToken direct local-session path only executes inside if (mode === "deeplink" && preferredWallet && getInjectedWallet(preferredWallet)).
  • File: src/wallet/AutoInjectedLogin.tsx — auto-login picks imToken from the query parameter or isImTokenBrowser(), then waits for getInjectedWallet("imToken") before calling connectInjectedWallet("imToken").
  • File: src/wallet/injected.tsgetInjectedWallet("imToken") falls back to generic window.ethereum only when isImTokenBrowser() is true.
  • Screenshot evidence: modal shows state: connecting, connected: no, address: -, qr: -, and URL 192.168.1.187.

Affected Files

  • src/wallet/WalletLoginModal.tsx — user entry point for mobile imToken login.
  • src/wallet/AutoInjectedLogin.tsx — auto-login effect for wallet in-app browsers.
  • src/wallet/useWalletConnectLogin.ts — direct injected login vs WalletConnect fallback selection.
  • src/wallet/injected.ts — provider/account detection and account request logic.
  • src/wallet/deepLinks.ts — imToken in-app browser deeplink target.

Suggested Fix

Do not guess blindly from connected: no; first make the runtime state visible. Add a temporary imToken diagnostic surface or alert that reports:

  • navigator.userAgent
  • location.href
  • whether window.ethereum exists
  • whether window.ethereum.providers exists and its length
  • provider flags: isImToken, isMetaMask, isTokenPocket
  • result/error of eth_accounts
  • result/error of eth_requestAccounts
  • current isSecureContext

Then apply one of these fixes based on the diagnostic result:

Fix Strategy

  1. If window.ethereum is missing on 192.168.1.187, test and deploy through an HTTPS domain/tunnel because imToken is likely not injecting on the LAN IP origin.
  2. If window.ethereum exists but isImTokenBrowser() is false, broaden imToken detection or allow a user-selected imToken flow to try generic window.ethereum before WalletConnect.
  3. If eth_accounts is empty and eth_requestAccounts errors, surface that wallet error in the modal instead of leaving state: connecting.
  4. If a valid address is returned, complete imToken login with the local-session path already used by connectInjectedWallet() + localWalletToken().
  5. Ensure the imToken mobile button never silently falls into WalletConnect when the user is already inside imToken and selected imToken; it should either get an address or show a clear injected-provider/account error.

Risk Assessment

  • Broadly accepting generic window.ethereum could pick the wrong provider in multi-wallet browsers. Mitigation: only do this for explicit user selection of imToken or when already inside imToken.
  • Testing on LAN IP can produce false negatives. Mitigation: verify on the actual HTTPS domain or an HTTPS tunnel before judging imToken support.
  • More diagnostics can expose wallet details on screen. Mitigation: keep diagnostics temporary or behind a debug flag.

Verification Plan

  1. Test in imToken in-app browser on the production HTTPS domain.
  2. Test in imToken in-app browser on the current LAN IP to confirm whether window.ethereum is missing there.
  3. Record diagnostic output for userAgent, hasEthereum, provider flags, eth_accounts, and eth_requestAccounts.
  4. From Chrome, tap imToken and confirm the in-app browser receives either ?autoLogin=imToken or the imToken browser fallback runs.
  5. Inside imToken, tap wallet login and confirm it does not remain at state: connecting without an address.
  • .unipi/docs/fix/2026-06-04-imtoken-injected-provider-detection-fix.md
  • .unipi/docs/fix/2026-06-04-imtoken-restore-local-session-login-fix.md
  • .unipi/docs/fix/2026-06-04-imtoken-auto-login-without-query-fix.md

Notes

The current screenshot strongly suggests that the problem is not backend verification or local token writing. The flow never reaches an address. The next useful step is to confirm whether imToken is injecting window.ethereum on the tested origin.