Skip to content

Handle Freighter network-mismatch and wallet-state edge cases before signing #2

Description

@chonilius

Problem

src/lib/wallet.ts#connectWallet and signTransaction call directly into @stellar/freighter-api with no handling for the extension being absent, locked, on the wrong network, or the user rejecting the permission prompt mid-flow. isFreighterInstalled checks freighterIsConnected(), but nothing in WalletContext.tsx or the /connect flow re-verifies network match before a signing operation is attempted from IssueActions.tsx or MilestoneActions.tsx. Given STELLAR_NETWORK is an env-driven constant (TESTNET default) and Freighter itself has an independently user-selected network, there is a realistic scenario where a contributor has Freighter set to Stellar PUBLIC while the app is configured for TESTNET (or vice versa after an env misconfiguration), and signTransaction will happily sign a transaction with the wrong network passphrase, producing a transaction Soroban will reject — but only after the user has already approved it in the extension, burning their attention and creating a confusing "why did my claim fail" support case.

Why this is hard

  • Freighter's API surface (isConnected, isAllowed, setAllowed, getAddress, signTransaction) doesn't expose "what network is the extension currently on" in a stable way across Freighter versions — you'll need to research the current @stellar/freighter-api version pinned in package.json (^6.0.1) and determine what's actually available (e.g. getNetwork/getNetworkDetails) and handle it being undefined on older installed extension versions.
  • You must design a pre-flight check that runs before every signTransaction call site (currently there's only one wrapper, but callers in IssueActions.tsx/MilestoneActions.tsx need to be identified and each guarded) without introducing a race between the check and the actual sign call (user could switch networks in the extension between the two).
  • Error surfaces must be humane: distinguish "extension not installed," "extension locked," "wrong network," "user rejected," and "unknown error" with different UI treatments — right now connectWallet collapses everything into generic thrown Errors.
  • WalletContext's WALLET_KEY localStorage persistence needs to be reconciled: what happens on next page load if the persisted address no longer matches the currently unlocked Freighter account?

Scope

  • Add a network-mismatch pre-flight check used by every signing call site.
  • Expand WalletConnection/error types to a discriminated union covering the failure modes above.
  • Update WalletContext.tsx to expose a networkMismatch boolean and surface it in the connect UI.
  • Add graceful re-sync when the stored address diverges from the live extension address on mount.

Acceptance criteria

  • Simulate (via mocking @stellar/freighter-api) each failure mode and confirm distinct, correct UI messaging.
  • No transaction signing is attempted when a network mismatch is detected; the user is blocked with an actionable message instead.

Metadata

Metadata

Assignees

No one assigned

    Labels

    GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26bugSomething isn't workingsecuritySecurity-related issuevery hardVery difficult task, expert-level effort required

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions