Skip to content

fix(wallets): throw a typed FreighterNotInstalledError with the install URL - #834

Open
woahwhattheheck wants to merge 4 commits into
Stellar-split:mainfrom
woahwhattheheck:fix/772-freighter-not-installed-error
Open

fix(wallets): throw a typed FreighterNotInstalledError with the install URL#834
woahwhattheheck wants to merge 4 commits into
Stellar-split:mainfrom
woahwhattheheck:fix/772-freighter-not-installed-error

Conversation

@woahwhattheheck

Copy link
Copy Markdown

Closes #772

FreighterAdapter now fails with a typed, actionable error carrying the install URL instead of a raw crash, and the guard works in non-browser contexts.

What was actually wrong

The adapter already guarded if (!window.freighter) in connect(), sign() and getAddress(), so the plain "extension missing in a browser" case did already throw rather than reach the Freighter API. Two things were still missing against the acceptance criteria:

  1. No typed error and no install URL. All three sites threw a bare Error("Freighter wallet not installed"). Callers had no instanceof to branch on, no error code, and no way to tell the user where to get the extension.

  2. The guard itself crashed off the browser. window.freighter evaluates window first. Where window is undefined — SSR, Node, a worker — that access throws TypeError: Cannot read properties of undefined before the ! check can run. That is the exact error named in the issue, and it came from the guard rather than from an API call.

Change

src/errors.ts — adds FreighterNotInstalledError extends StellarSplitError, code FREIGHTER_NOT_INSTALLED, a readonly installUrl, and the URL in both the message and context. Follows the file's existing subclass convention, with the matching isFreighterNotInstalledError guard and an exported FREIGHTER_INSTALL_URL constant so the URL is not repeated as a literal.

src/wallets/adapters/FreighterAdapter.ts — two module-level helpers replace the three inline guards:

function getFreighter(): FreighterApi | undefined {
  if (typeof window === "undefined") return undefined;
  return window.freighter;
}

typeof window is safe on an undeclared or undefined window, so the non-browser path now reaches the typed error instead of a TypeError. requireFreighter() wraps it and throws. The account-change poller uses the same accessor, so an extension disabled mid-session stops the poll quietly instead of tripping on window.freighter every 2 seconds.

src/index.ts — exports the error, its guard and the constant so consumers can catch it. One appended line.

Behaviour when the extension is present

Unchanged. The adapter reads the API once into a local and calls exactly the same methods with exactly the same arguments; no call order, return value, polling interval or handler semantics moved. The existing FreighterAdapter cases in test/walletSessionManager.test.ts pass unmodified — that file is untouched here, and it asserts on adapter behaviour rather than on the old message string.

WalletNotConnectedError is deliberately left alone: it means something different (present but not connected) and callers may already depend on it.

Tests

New test/freighterAdapter.test.ts, 13 cases: the typed error from all four entry points, the URL/code/context/name payload, instanceof StellarSplitError so existing catch blocks still match, the exported type guard, the window === undefined regression, the unchanged happy path for connect/sign/getAddress, account-change notification, and the poller surviving both an extension that disappears and a window that goes away.

CI

Fork run 34058011952 — every step green.

Step Result
vitest run test/freighterAdapter.test.ts 13 passed (13)
vitest run test/walletSessionManager.test.ts 26 passed (26) — existing suite, file unmodified
tsc --noEmit 210 errors, the same count this repo reports on unmodified main

On the typecheck: the 210 are pre-existing repo-wide diagnostics, and this PR does not move that number. Broken out by touched file:

  • src/errors.ts, src/wallets/adapters/FreighterAdapter.ts, test/freighterAdapter.test.tszero errors.
  • src/index.ts — carries pre-existing TS2305/TS2724 missing-export errors at lines 411, 482–487, 690, 870, 873–874, 877, 1416 and 1417. They are unrelated to this change and are present without it. The line this PR adds is 1430, the last line of the file, and contributes none.

Not merged, not awarded, nothing paid — submitted for review.

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.

Handle Freighter wallet not-installed error with a user-friendly message

1 participant