Summary
apps/web/src/hooks/useWalletConnect.ts and apps/web/src/lib/wallet.ts are hardcoded to Freighter (connectFreighter/isFreighterInstalled/signTransaction from @stellar/freighter-api), despite the hook's generic name suggesting a wallet-agnostic abstraction. Extract a common wallet interface so additional wallets (xBull, LOBSTR) can be added as separate implementations without touching the connect/sign call sites.
Motivation
Freighter is a desktop-only browser extension. The README targets "users in West Africa and other emerging markets" and the roadmap names low-end Android devices as the target device class, but a user on mobile cannot install Freighter at all. This is the first of several issues to add real multi-wallet support; this one is the foundation the wallet-specific issues depend on.
Proposed Solution
Define a common interface (e.g. connect/sign/isInstalled, matching the shape useWalletConnect.ts and wallet.ts already use for Freighter) and reimplement the existing Freighter calls as the first implementation against it. Freighter's behavior should not change from a user's perspective; this issue is a pure structural extraction, not a UI change.
Optimize for the cleanest interface design. Don't design around preserving the exact current shape of the persisted wallet state in apps/web/src/store/wallet.ts (zustand persist middleware) — if the cleanest design changes that shape, existing connected users seeing a one-time reconnect prompt is an acceptable, trivial cost. Do not add migration logic to avoid it.
Scope
| Field |
Value |
| Area |
Frontend |
| Protocol affected |
None |
| Network |
Both |
| Breaking change? |
No (Freighter-facing behavior unchanged; internal structure only) |
Alternatives Considered
Adding each new wallet directly into the existing Freighter-specific hook with conditional branching: rejected, since it would make useWalletConnect.ts and wallet.ts grow a branch per wallet indefinitely rather than each wallet being an independent, addable implementation.
Acceptance Criteria
Additional Context
First of a small batch of multi-wallet issues: this abstraction layer, then one issue per additional wallet (xBull, LOBSTR), then a wallet-picker UI issue, then a docs update to docs/signing-flow.md/apps/docs/architecture/signing-flow.md, both of which currently say "the user's wallet (Freighter)" specifically.
Summary
apps/web/src/hooks/useWalletConnect.tsandapps/web/src/lib/wallet.tsare hardcoded to Freighter (connectFreighter/isFreighterInstalled/signTransactionfrom@stellar/freighter-api), despite the hook's generic name suggesting a wallet-agnostic abstraction. Extract a common wallet interface so additional wallets (xBull, LOBSTR) can be added as separate implementations without touching the connect/sign call sites.Motivation
Freighter is a desktop-only browser extension. The README targets "users in West Africa and other emerging markets" and the roadmap names low-end Android devices as the target device class, but a user on mobile cannot install Freighter at all. This is the first of several issues to add real multi-wallet support; this one is the foundation the wallet-specific issues depend on.
Proposed Solution
Define a common interface (e.g.
connect/sign/isInstalled, matching the shapeuseWalletConnect.tsandwallet.tsalready use for Freighter) and reimplement the existing Freighter calls as the first implementation against it. Freighter's behavior should not change from a user's perspective; this issue is a pure structural extraction, not a UI change.Optimize for the cleanest interface design. Don't design around preserving the exact current shape of the persisted wallet state in
apps/web/src/store/wallet.ts(zustandpersistmiddleware) — if the cleanest design changes that shape, existing connected users seeing a one-time reconnect prompt is an acceptable, trivial cost. Do not add migration logic to avoid it.Scope
Alternatives Considered
Adding each new wallet directly into the existing Freighter-specific hook with conditional branching: rejected, since it would make
useWalletConnect.tsandwallet.tsgrow a branch per wallet indefinitely rather than each wallet being an independent, addable implementation.Acceptance Criteria
useWalletConnect.ts/wallet.tscall sites go through the interface, not Freighter-specific functions directlyuseWalletConnect.test.ts,wallet.test.ts,store/wallet.test.ts) updated to match the new structure and passpnpm --filter @meridian/web lint && pnpm --filter @meridian/web typecheck && pnpm --filter @meridian/web testpassAdditional Context
First of a small batch of multi-wallet issues: this abstraction layer, then one issue per additional wallet (xBull, LOBSTR), then a wallet-picker UI issue, then a docs update to
docs/signing-flow.md/apps/docs/architecture/signing-flow.md, both of which currently say "the user's wallet (Freighter)" specifically.