Skip to content

fix: honor experimental_preferUniversalLinks on session-request re-opens - #5706

Merged
tomiir merged 4 commits into
mainfrom
fix-boolean-var-naming
Jul 14, 2026
Merged

fix: honor experimental_preferUniversalLinks on session-request re-opens#5706
tomiir merged 4 commits into
mainfrom
fix-boolean-var-naming

Conversation

@ignaciosantise

Copy link
Copy Markdown
Collaborator

Problem

With experimental_preferUniversalLinks: true, AppKit opens a wallet via its universal link on connect (pairing), but every subsequent session request (signing / confirming a tx) re-opens the wallet via its native custom scheme instead, e.g. rn-web3wallet-internal://wc?requestId=...&sessionTopic=....

Root cause: at connect time ConnectionControllerUtil.onConnectMobile opens the universal link but persists the native href (safeAppUrl) as the WalletConnect deeplink choice (WALLETCONNECT_DEEPLINK_CHOICE). @walletconnect/universal-provider replays that stored href on every request() (handleDeeplinkRedirect builds ${href}wc?requestId=...&sessionTopic=...). Since the stored href is the native base, all request re-opens use the native scheme.

This breaks hosts that embed a dapp in an iOS webview and rely on universal links so they don't have to list every wallet's custom scheme in LSApplicationQueriesSchemes. Connect works, but the signing step falls back to a native scheme the host can't open. Reproduced headless (appKit.connectWallet(...)), the path WalletConnect Pay uses.

onConnectMobile is the single unified path — the headful w3m-connecting-wc-mobile partial delegates to it — so one fix covers both headful and headless. No wallet-side or universal-provider change required.

Fix

  • formatNativeUrl now also returns universalHref, the normalized universal-link base (reuses the same safeUniversalLink that already produces redirectUniversalLink).
  • onConnectMobile persists universalHref as the deeplink choice when the flag is on and a universal link exists, so the stored choice matches what we open with.
  • Behavior is unchanged when the flag is off or the wallet has no link_mode (native scheme, no regression).

Tests

  • CoreHelperUtil.test.ts: universalHref equals the normalized universal base, and is undefined when no universal link is passed.
  • w3m-connecting-wc-mobile.test.ts: setWcLinking receives the universal base (flag on + link_mode), the native base (no link_mode), and the native base (flag off).

Manual verification (recommended)

On mobile / iOS webview: connect a wallet advertising both mobile_link and link_mode, confirm localStorage.WALLETCONNECT_DEEPLINK_CHOICE holds the https://…/ universal base, then trigger personal_sign / eth_sendTransaction and confirm the re-open uses the universal link.

🤖 Generated with Claude Code

…requests

AppKit opened a wallet via its universal link on connect when
experimental_preferUniversalLinks was set, but persisted the native
custom-scheme href as the WalletConnect deeplink choice. universal-provider
replays that stored href on every session request, so signing/tx re-opens fell
back to the native scheme.

Persist the universal-link base as the deeplink choice when the flag is on and
a universal link exists, so request re-opens use the same link we connect with.
formatNativeUrl now returns the normalized universal base as universalHref.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ed7b70d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 26 packages
Name Type
@reown/appkit-utils Patch
@reown/appkit Patch
@reown/appkit-cdn Patch
@reown/appkit-cli Patch
@reown/appkit-codemod Patch
@reown/appkit-common Patch
@reown/appkit-core Patch
@reown/appkit-experimental Patch
@reown/appkit-pay Patch
@reown/appkit-polyfills Patch
@reown/appkit-scaffold-ui Patch
@reown/appkit-siwe Patch
@reown/appkit-siwx Patch
@reown/appkit-testing Patch
@reown/appkit-ui Patch
@reown/appkit-universal-connector Patch
@reown/appkit-wallet-button Patch
@reown/appkit-wallet Patch
@reown/appkit-controllers Patch
@reown/appkit-adapter-bitcoin Patch
@reown/appkit-adapter-ethers Patch
@reown/appkit-adapter-ethers5 Patch
@reown/appkit-adapter-solana Patch
@reown/appkit-adapter-ton Patch
@reown/appkit-adapter-tron Patch
@reown/appkit-adapter-wagmi Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
appkit-demo Ready Ready Preview, Comment Jul 13, 2026 4:36pm
appkit-gallery Ready Ready Preview, Comment Jul 13, 2026 4:36pm
appkit-headless-sample-app Ready Ready Preview, Comment Jul 13, 2026 4:36pm
appkit-laboratory Ready Ready Preview, Comment Jul 13, 2026 4:36pm
9 Skipped Deployments
Project Deployment Actions Updated (UTC)
appkit-basic-example Ignored Ignored Jul 13, 2026 4:36pm
appkit-basic-sign-client-example Ignored Ignored Jul 13, 2026 4:36pm
appkit-basic-up-example Ignored Ignored Jul 13, 2026 4:36pm
appkit-ethers5-bera Ignored Ignored Jul 13, 2026 4:36pm
appkit-nansen-demo Ignored Ignored Jul 13, 2026 4:36pm
appkit-wagmi-cdn-example Ignored Ignored Jul 13, 2026 4:36pm
ethereum-provider-wagmi-example Ignored Ignored Jul 13, 2026 4:36pm
next-wagmi-solana-bitcoin-example Ignored Ignored Jul 13, 2026 4:36pm
vue-wagmi-example Ignored Ignored Jul 13, 2026 4:36pm

Request Review

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Visual Regression Test Results ✅ Passed

⚠️ 20 visual change(s) detected

Chromatic Build: https://www.chromatic.com/build?appId=6493191bf4b10fed8ca7353f&number=960
Storybook Preview: https://6493191bf4b10fed8ca7353f-ijvtehlrwq.chromatic.com/

👉 Please review the visual changes in Chromatic and accept or reject them.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor
Warnings
⚠️

🌐 Non-company domain introduced (host: example.com) in packages/controllers/tests/utils/CoreHelperUtil.test.ts (line 147): https://example.com/app

Generated by 🚫 dangerJS against ed7b70d

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle Size Check

All bundles are within size limits

📊 View detailed bundle sizes

> @reown/appkit-monorepo@1.7.1 size /home/runner/work/appkit/appkit


> size-limit

@reown/appkit - Main Entry
Size limit:   80 kB
Size:         75.87 kB with all dependencies, minified and gzipped
Loading time: 1.5 s    on slow 3G
Running time: 3.3 s    on Snapdragon 410
Total time:   4.8 s
@reown/appkit/react
Size limit:   236 kB
Size:         235.11 kB with all dependencies, minified and gzipped
Loading time: 4.6 s     on slow 3G
Running time: 8.4 s     on Snapdragon 410
Total time:   13 s
@reown/appkit/vue
Size limit:   80 kB
Size:         75.87 kB with all dependencies, minified and gzipped
Loading time: 1.5 s    on slow 3G
Running time: 1.9 s    on Snapdragon 410
Total time:   3.4 s
@reown/appkit-scaffold-ui
Size limit:   220 kB
Size:         214.41 kB with all dependencies, minified and gzipped
Loading time: 4.2 s     on slow 3G
Running time: 5.3 s     on Snapdragon 410
Total time:   9.4 s
@reown/appkit-ui
Size limit:   500 kB
Size:         13.16 kB with all dependencies, minified and gzipped
Loading time: 258 ms   on slow 3G
Running time: 779 ms   on Snapdragon 410
Total time:   1.1 s

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 78.55% 40095 / 51038
🔵 Statements 78.55% 40095 / 51038
🔵 Functions 76.06% 4283 / 5631
🔵 Branches 86.67% 9792 / 11297
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/controllers/src/utils/ConnectionControllerUtil.ts 77.98% 81.25% 81.81% 77.98% 28-29, 36-37, 82, 90-96, 133-144, 141
packages/controllers/src/utils/CoreHelperUtil.ts 74.61% 85.96% 66.3% 74.61% 22-23, 42, 67-68, 84, 88, 95-96, 112-113, 124, 147-148, 184, 201-202, 220-226, 256-257, 269-277, 324-329, 337, 353, 361, 363, 365-366, 376-381, 385-388, 398, 403, 408-414, 416, 479, 483-487, 496-499, 502-504, 508-523, 526-550, 553-557, 438
Generated in workflow #17178 for commit ed7b70d by the Vitest Coverage Report Action

Comment thread packages/controllers/src/utils/ConnectionControllerUtil.ts Outdated
Comment thread .changeset/prefer-universal-links-deeplink-choice.md Outdated
Comment thread packages/controllers/src/utils/ConnectionControllerUtil.ts
- changeset: list all publishable @reown/appkit-* packages (repo convention)
- test: use neutral example domain to avoid DangerJS non-company-domain warning

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 8, 2026

Copy link
Copy Markdown

Bugbot is not enabled for this team, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Comment thread packages/controllers/src/utils/CoreHelperUtil.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes a WalletConnect mobile re-open regression when experimental_preferUniversalLinks is enabled by persisting the universal-link base (instead of the native custom-scheme base) as the WalletConnect deeplink choice, so subsequent session requests re-open the wallet via the same universal link.

Changes:

  • Extend CoreHelperUtil.formatNativeUrl() to also return universalHref (normalized universal-link base).
  • Update ConnectionControllerUtil.onConnectMobile() to persist universalHref as the WC deeplink choice when universal links are preferred and available.
  • Add/expand unit tests to cover universal base persistence and fallback behavior; add a changeset for the patch release.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/scaffold-ui/test/partials/w3m-connecting-wc-mobile.test.ts Adds assertions that setWcLinking persists the correct base href across universal/native/flag-off scenarios.
packages/controllers/tests/utils/CoreHelperUtil.test.ts Adds coverage for universalHref normalization and undefined behavior when no universal link is provided.
packages/controllers/src/utils/TypeUtil.ts Extends LinkingRecord with optional universalHref.
packages/controllers/src/utils/CoreHelperUtil.ts Returns universalHref from formatNativeUrl() alongside existing redirect fields.
packages/controllers/src/utils/ConnectionControllerUtil.ts Persists the universal-link base when preferred so WC session-request re-opens match the initial link mode.
.changeset/prefer-universal-links-deeplink-choice.md Patch changeset documenting the behavioral fix across the versioned group.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/controllers/src/utils/ConnectionControllerUtil.ts Outdated
…ting

Address Copilot review: remove the `as string` assertions in onConnectMobile
by narrowing inside the selection ternaries, and collapse the duplicated
openHref call into one. Behavior is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 8, 2026

Copy link
Copy Markdown

Bugbot is not enabled for this team, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants