Skip to content

feat: EIP-6963 wallet discovery, per-connector errors, humanized connect failures - #151

Merged
Adedamola18 merged 7 commits into
mainfrom
feat/eip6963-discovery
Aug 18, 2026
Merged

feat: EIP-6963 wallet discovery, per-connector errors, humanized connect failures#151
Adedamola18 merged 7 commits into
mainfrom
feat/eip6963-discovery

Conversation

@Adedamola18

@Adedamola18 Adedamola18 commented Aug 17, 2026

Copy link
Copy Markdown
Member

Closes https://github.com/IQIndustries/issues/issues/5205 when this PR merged

Description

Fixes multi-wallet connect conflicts and misleading error display in the login UI.

1. EIP-6963 wallet discovery

createIqLoginConfig now enables multiInjectedProviderDiscovery. Every installed wallet extension (MetaMask, Phantom, OKX, Rabby…) announces itself and gets its own connector row with its own name and brand icon, instead of one generic "Browser Wallet" row talking to whichever extension last hijacked window.ethereum. That hijack conflict is the usual cause of the "wallet must has at least one account" (4001) failures where no popup ever appears. The generic injected row still renders when no wallet announces itself.

2. Per-connector error scoping

Previously the one shared useConnect error rendered under every row, so a single failed attempt looked like all connectors failed. ConnectorRow.error (in both Login and useLoginFlow) now carries the error only on the row that attempted the connection. Row building is centralized in buildConnectorRows().

3. humanizeConnectError(error)

New /client export mapping known wallet failures to actionable copy: locked-wallet 4001, pending -32002, missing provider, unreachable WalletConnect relay. The built-in Login uses it for its error line.

Every installed wallet extension now announces itself and gets its own
connector row with its own name and brand icon, instead of one generic
"Browser Wallet" row talking to whichever extension last hijacked
window.ethereum — the usual cause of "wallet must has at least one
account" (4001) failures where no popup ever appears.

- createIqLoginConfig sets multiInjectedProviderDiscovery: true
- new buildConnectorRows() centralizes row building for Login and
  useLoginFlow, and hides the generic injected() row whenever announced
  wallets exist
- ConnectorRow.error is scoped to the connector that attempted the
  connection (previously the one shared useConnect error rendered under
  every row)
- resolveConnectorMeta can now use the wallet's announced EIP-6963 icon
Raw provider failures ("wallet must has at least one account",
"User rejected the request.", -32002 already-pending, unreachable
WalletConnect relay) read as noise or blame the user for wallet-side
bugs. Map the known ones to a sentence that says what happened and what
to do about it, falling back to viem's shortMessage. Exported from
/client for consumers building custom UIs on useLoginFlow.
The built-in Login now renders rows from buildConnectorRows — so
discovered wallets appear with their own name/icon, the generic row
hides when wallets announce, and an error shows only under the row
that attempted, formatted by humanizeConnectError. ConnectorRow moves
to connector-rows.ts (re-exported, no API change). Docs + changeset
for the 8.2.0 minor.
@Adedamola18
Adedamola18 requested a review from Yomzy2223 August 17, 2026 11:45
…tError fallback

- match any message pairing "request" with "pending"/"processing" (word-
  bounded, either order), not just the literal "already pending" phrasing
- treat blank shortMessage/message values as absent: trim candidates, skip
  whitespace-only lines, and reliably fall through to the generic copy
  (previously the fallback was unreachable and empty messages rendered an
  empty error line)
- settle changeset wording on message-pattern phrasing for the humanizer

@Yomzy2223 Yomzy2223 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at e51e3cd. Verified locally in a worktree: tsc --noEmit clean, biome check src clean.

I also read wagmi 2.16.7's createConfig.js / hydrate.js to check the discovery assumptions, and they hold up: providerDetailToConnector does injected({ target: { ...info, id: info.rdns, provider } }), so type === "injected" && id !== "injected" is a valid discriminator, connector.icon really is the announced icon, and wagmi's own dedupe is by rdns only — the generic injected() connector has no rdns, so the manual filter here genuinely is needed rather than duplicating something wagmi already does.

The diagnosis is right and the core mechanism is correct. Centralizing into buildConnectorRows is a good call, and dropping the isPending gate from attempted while keeping it on isConnecting is exactly the right split for error scoping.

Inline comments below, roughly in order of significance. The two I'd want resolved before merge are the all-or-nothing generic-row filter and the first-paint window where the generic row is the only injected option on screen.

One thing not attachable to a line: there are no tests. buildConnectorRows and humanizeConnectError are both pure functions, and they're the two pieces whose correctness can't be confirmed by reading the diff — row filtering, error scoping, and each message branch. vitest is already a dependency (though it's in dependencies rather than devDependencies, and there's no test script), so the suite would need standing up first. Given the whole PR's user-facing value rests on string matching, this feels worth the setup cost.

Comment thread src/components/connector-rows.ts Outdated
Comment thread src/config/iq-login.config.ts
Comment thread .changeset/eip6963-discovery.md Outdated
Comment thread README.md Outdated
Comment thread src/lib/humanize-connect-error.ts Outdated
Comment thread src/lib/humanize-connect-error.ts
Comment thread src/components/connector-meta.ts
Comment thread src/hooks/use-login-flow.ts Outdated
@Adedamola18
Adedamola18 merged commit 67c1fe0 into main Aug 18, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants