feat(controllers): expose WalletConnect URI on public state for headless QR#5697
Merged
Conversation
…ess QR `getState()` / `subscribeState()` now include `wcUri`, `wcError`, and `wcFetchingUri` — the symmetric *read* for the existing `getWalletConnectUri()` trigger. They're mirrored one-way from `ConnectionController` onto `PublicStateController` via a single subscription, so a headless host can render a QR through the AppKit instance without the `useAppKitWallets` React hook. The connection-level `subscribeConnections` is gated behind the `multiWallet` remote feature and so can't serve the URI for a single-wallet QR; the public state is ungated. This completes the headless read surface started in #5695. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 633c3ab The changes in this PR will be included in the next version bump. This PR includes changesets to release 26 packages
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 |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
9 Skipped Deployments
|
Contributor
Visual Regression Test Results ✅ PassedChromatic Build: https://www.chromatic.com/build?appId=6493191bf4b10fed8ca7353f&number=945 👉 Please review the visual changes in Chromatic and accept or reject them. |
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 |
Contributor
enesozturk
commented
Jun 30, 2026
…ot public state
Replace the PublicStateController mirror with a direct read/subscribe pair on
HeadlessWalletUtil, mirroring the existing getWalletList/subscribeWalletList
pattern. A headless host reads the URI ungated through the AppKit instance with
a single source of truth and no controllers import.
- Add HeadlessWalletUtil.getWalletConnectUri() (returns { wcUri, wcError,
wcFetchingUri }) and subscribeWalletConnectUri(), both reading
ConnectionController directly; export WalletConnectUriSnapshot.
- Rename the pre-fetch trigger getWalletConnectUri() -> prefetchWalletConnectUri()
(breaking) to free the natural name for the read.
- Revert the wcUri/wcError/wcFetchingUri fields on PublicStateController and the
module-scope mirror subscription on ConnectionController.
- Update tests + changeset accordingly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0xmkh
approved these changes
Jul 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Exposes the WalletConnect URI on the public AppKit state so a headless host can render a QR without the
useAppKitWalletsReact hook.getState()/subscribeState()now include:wcUri: string | undefinedwcError: booleanwcFetchingUri: booleanThese are the symmetric read for the existing
getWalletConnectUri()trigger added in #5695 — that PR exposed the imperative wallet-list + URI trigger on the client, but the only way to read the generated URI back wassubscribeConnections, which is gated behind themultiWalletremote feature (no-ops when off) and so can't serve the URI for a single-wallet QR.How
A single one-way valtio subscription in
ConnectionControllermirrorswcUri/wcError/wcFetchingUriontoPublicStateControllerwhenever any of them changes — so the mirror stays correct regardless of which setter (setUri,setWcError,resetUri,resetWcConnection,connectWalletConnect, …) mutated it. PublicState never writes back, so there's no feedback loop. This matches the existing precedent whereConnectionControlleralready writesconnectingWalletonto the public state.Why
A framework-neutral host (e.g. a plain-JS integration, or
@walletconnect/pay-appkit) drives everything else through the AppKit instance (getWalletList,getAccount,getState,subscribeState, …). The WC URI was the one piece with no ungated instance read — forcing consumers to import@reown/appkit-controllersdirectly, which breaks when the package resolves to a different physical instance than the host's@reown/appkit(duplicate valtio singleton → the QR reads a copy that's never written). ReadingwcUrioff the public state removes that footgun entirely.Tests
ConnectionController.test.ts: asserts the mirror reflectssetUri/setWcError/resetUrionto the public state.PublicStateController.test.ts: updated default/set()shape assertions for the new fields.pnpm --filter @reown/appkit-controllers typecheckclean; controllers tests green; prettier + eslint clean on changed files.Follow-up
Once this lands in a canary,
@walletconnect/pay-appkitwill readappKit.getState().wcUri/subscribeState()instead of the directConnectionControllerimport.