Points: 200
Labels: frontend, hooks, ux, freighter, session
Background: useWallet.ts stores publicKey in component state — it is lost on every page refresh. Every session requires the user to click "Connect Wallet" again and wait for Freighter to respond. useLocalStorage.ts already exists but is not used by useWallet. The useFreighterAvailable hook confirms Freighter is present, and Freighter's isConnected() can silently verify a persisted session. On reconnect, if the stored public key no longer matches the connected Freighter account (user switched accounts), the stale key must be cleared rather than used silently — this is a security concern since all contract reads and transaction builds use the public key as the sourcePublicKey.
Task: Update useWallet.ts to persist publicKey via useLocalStorage('wallet_public_key', null). On mount, if a stored key exists: call freighterService.isConnected() and freighterService.getPublicKey() silently — if the returned key matches the stored key, auto-restore the session without a user prompt. If the keys differ (account switch), clear storage and set publicKey = null. Expose sessionRestored: boolean in the return value so App.tsx can skip rendering the ConnectWallet screen during the auto-restore check. Add a connecting state that covers both manual connect and auto-restore.
Key files: - frontend/src/hooks/useWallet.ts — integrate useLocalStorage; add auto-reconnect logic; expose sessionRestored
frontend/src/hooks/useLocalStorage.ts — verify it handles null serialization correctly (currently may not — audit)
frontend/src/App.tsx — consume sessionRestored to show a loading state instead of ConnectWallet during restore
frontend/src/__tests__/useFreighterAvailable.test.tsx — add test: stored key matching Freighter key restores session; mismatched key clears storage
Acceptance criteria: - [ ] publicKey persisted to localStorage under key 'wallet_public_key'
Points: 200
Labels: frontend, hooks, ux, freighter, session
Background:
useWallet.tsstorespublicKeyin component state — it is lost on every page refresh. Every session requires the user to click "Connect Wallet" again and wait for Freighter to respond.useLocalStorage.tsalready exists but is not used byuseWallet. TheuseFreighterAvailablehook confirms Freighter is present, and Freighter'sisConnected()can silently verify a persisted session. On reconnect, if the stored public key no longer matches the connected Freighter account (user switched accounts), the stale key must be cleared rather than used silently — this is a security concern since all contract reads and transaction builds use the public key as thesourcePublicKey.Task: Update
useWallet.tsto persistpublicKeyviauseLocalStorage('wallet_public_key', null). On mount, if a stored key exists: callfreighterService.isConnected()andfreighterService.getPublicKey()silently — if the returned key matches the stored key, auto-restore the session without a user prompt. If the keys differ (account switch), clear storage and setpublicKey = null. ExposesessionRestored: booleanin the return value soApp.tsxcan skip rendering the ConnectWallet screen during the auto-restore check. Add aconnectingstate that covers both manual connect and auto-restore.Key files: -
frontend/src/hooks/useWallet.ts— integrate useLocalStorage; add auto-reconnect logic; expose sessionRestoredfrontend/src/hooks/useLocalStorage.ts— verify it handles null serialization correctly (currently may not — audit)frontend/src/App.tsx— consume sessionRestored to show a loading state instead of ConnectWallet during restorefrontend/src/__tests__/useFreighterAvailable.test.tsx— add test: stored key matching Freighter key restores session; mismatched key clears storageAcceptance criteria: - [ ] publicKey persisted to localStorage under key 'wallet_public_key'