Skip to content

feat(web): prioritize walletconnect on mobile - #20

Merged
Bekirerdem merged 1 commit into
Bekirerdem:mainfrom
NeduTheDev1:feat/web-mobile-wallet-modal
Jul 29, 2026
Merged

feat(web): prioritize walletconnect on mobile#20
Bekirerdem merged 1 commit into
Bekirerdem:mainfrom
NeduTheDev1:feat/web-mobile-wallet-modal

Conversation

@NeduTheDev1

Copy link
Copy Markdown

Closes #9

@drips-wave

drips-wave Bot commented Jul 25, 2026

Copy link
Copy Markdown

@NeduTheDev1 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Bekirerdem

Copy link
Copy Markdown
Owner

Thanks — this is close, and the shape is right: a pure helper with its own tests, currentDevice() reused from funnel.ts rather than a second detector, and the funnel events left alone. I checked the branch out and ran the full pipeline:

Gate Result
npx tsc -b ✅ pass
npm test ✅ 158/158 (21 files, +4 from your suite)
npm run lint ✅ exit 0 (7 warnings, all pre-existing debt tracked in #5)

So the gates are green. What blocks the merge is that the tested helper isn't the thing that decides behaviour in production.

Blocking

1. sortWalletsForDevice is dead code

It's exported and covered by two tests, but walletKit.ts only imports classifyWalletForDevice — nothing calls the sort. On mobile the module list never gets sorted because the mobile branch returns a hand-built single-element array instead:

if (device === "mobile") {
  if (!WC_PROJECT_ID) return visibleModules;
  return [ new WalletConnectModule({ ... }) ];   // visibleModules discarded
}

classifyWalletForDevice is therefore also inert on mobile — its filtered result is thrown away on the path that actually runs. Either drive the mobile list through sortWalletsForDevice (which is what the issue's "pure, testable helper" criterion is asking for), or drop the unused export.

2. The tests assert the opposite of the production config

walletDevice.test.ts treats Albedo as available on mobile:

const wallets = [{ id: "wallet_connect" }, { id: "freighter", desktopOnly: true }, ..., { id: "albedo" }];
expect(sortWalletsForDevice("mobile", wallets).map(w => w.id)).toEqual(["wallet_connect", "albedo"]);

but walletKit.ts puts Albedo in the desktop-only set:

const desktopOnlyWalletIds = new Set([FREIGHTER_ID, "xbull", "albedo", "lobstr", "rabet", "hana"]);

Because the tests build their own literals instead of importing that set, they pass while describing behaviour the app doesn't have. Please import desktopOnlyWalletIds (export it) and assert against the real thing — otherwise a wrong id in that set is invisible to CI, which matters because those are hand-written strings that must match module.productId exactly.

3. Albedo is not an extension-only wallet

The issue lists the extension-only wallets as Freighter, xBull, Rabet, Hana and the LOBSTR extension. Albedo is web-based (albedo.link) and works in a mobile browser, so hiding it removes a working option from phone users rather than removing a dead end. Unless you've tested it failing on a phone — in which case say so and I'll take your word for it.

4. Empty wallet list when WC_PROJECT_ID is missing

On mobile, visibleModules is empty by construction (every extension is desktop-only). So with no project id the kit initialises with modules: [] and a phone visitor gets a modal with nothing in it — worse than today's "options that don't work". Please keep a fallback, even if it's the current list plus a note.

Non-blocking

  • showMobileWalletConnectHint() builds a DOM node by hand (document.createElement, inline styles, setTimeout removal) inside a React app that already has a toast system in web/src/state/toast.tsx. Please route the hint through that instead — it also makes the copy testable and keeps styling in one place.
  • initKitForDevice() now runs on every connect() call, not once at module load. The comment right below it warns that init resets the selected module and that reload persistence has to restore it — re-initialising per connect fights that mechanism. Since the device can't change mid-session, calling it once at load (as before) plus a re-init only when the device class actually changes would be safer.
  • The two blank lines left at the end of the hint function.

Re-run npm test after wiring the helper into the real path — that's the change that would move this to a merge for me.

Bekirerdem added a commit that referenced this pull request Jul 29, 2026
…against real config

Review follow-ups on #20 (issue #9):

- walletDevice.ts owns a desktopOnlyWalletIds set built from the kit's own ID
  constants; classifyWalletForDevice/sortWalletsForDevice consume it, and
  walletKit.ts now builds its module list THROUGH sortWalletsForDevice - the
  tested helper is the code path production runs, not a parallel one.
- walletDevice.test.ts asserts against the real set and the kit's real IDs;
  no hand-built literals that can drift from walletKit.
- Albedo stays available on mobile (web-based, not an extension).
- With no WalletConnect project id the mobile list still offers Albedo -
  never an empty modal.
- The mobile pairing hint goes through the app's toast system from WalletChip
  (skipped on the landing nav, which renders outside ToastProvider), replacing
  the hand-built DOM banner.
- showsExtensionWallets moved out of funnel.ts - walletDevice's classification
  replaces it on the only path that used it.
- vitest: the kit resolves through vite's pipeline (deps.inline) with a stub
  for CJS @stellar/freighter-api, whose named exports break node-ESM interop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bekirerdem added a commit that referenced this pull request Jul 29, 2026
@Bekirerdem
Bekirerdem merged commit e48179e into Bekirerdem:main Jul 29, 2026
@Bekirerdem

Copy link
Copy Markdown
Owner

Merged to main — with the Wave closing tomorrow and no reply since the review, I took the branch the last mile myself rather than let the work expire. Thanks @NeduTheDev1: the shape you set up (a pure walletDevice.ts helper with its own vitest suite) is exactly what shipped; the follow-up commit (4e0588c) resolves the review blockers on top of it:

  1. Helper wired into the real pathwalletKit.ts now builds its module list through sortWalletsForDevice; the classification set (desktopOnlyWalletIds) lives in walletDevice.ts and is built from the kit's own ID constants, so a renamed productId breaks the build instead of silently missing at runtime.
  2. Tests assert the production configwalletDevice.test.ts imports the real set and the kit's real IDs; no hand-built literals that can drift.
  3. Albedo stays on mobile — it's web-based (albedo.link), not an extension, so hiding it would have removed the one non-WalletConnect option a phone can use.
  4. No empty modal without a WalletConnect project id — the mobile list always keeps Albedo.
  5. The pairing hint goes through the app's toast system from WalletChip (skipped on the landing nav, which renders outside ToastProvider), replacing the hand-built DOM banner, and the kit re-init moved out of the per-connect path.

Gates on the merged result: tsc -b ✅ · vitest 183/183 ✅ · eslint ✅ · Playwright smoke vs testnet ✅. Points should follow once the issue is marked completed on the Wave side.

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.

feat(web): mobile-aware wallet connect modal - WalletConnect first, extension wallets marked

2 participants