Skip to content

[CRITICAL] Fix Wallet Keypair Loss on Page Refresh β€” Wallet Non-Functional After ReloadΒ #172

Description

@devJaja

🎯 Objective

CRITICAL / URGENT β€” Fix the wallet connection architecture so that the Keypair persists across page refreshes. Currently, the wallet appears connected after refresh (pubkey shown) but is completely non-functional (keypair is null), breaking all transaction signing.


πŸ“ Files to Modify

Action File Path Description
Modify frontend/src/context/WalletContext.tsx Fix keypair persistence, implement Freighter support
Modify frontend/src/hooks/useWallet.ts Support Freighter-based signing
Modify frontend/src/hooks/useWalletBalance.ts Adapt to new connection model
Modify frontend/src/pages/WalletPage.tsx Add Freighter connect option
Modify frontend/src/components/wallet/SendXLMForm.tsx Update signing to support Freighter
Modify frontend/src/components/landing/Navbar.tsx Add onClick to Connect button
Modify frontend/src/components/layout/TopNav.tsx Show connection method

πŸ“ Files to Create

Action File Path Description
Create frontend/src/services/freighter.ts Freighter API wrapper

πŸ“ Files to Install

Action Package
Install @stellar/freighter-api

πŸ” Root Cause Analysis

// frontend/src/context/WalletContext.tsx β€” lines 22-26
const [publicKey, setPublicKey] = useState<string | null>(() => {
  return localStorage.getItem('wallet_pubkey') || localStorage.getItem('walletAddress');
});
const [keypair, setKeypair] = useState<Keypair | null>(null); // ← ALWAYS null after refresh

The Stellar SDK Keypair object is not JSON-serializable and cannot be stored in localStorage. After page refresh:

  1. publicKey is restored from localStorage β†’ connected = true
  2. keypair is always null β†’ signing fails
  3. SendXLMForm.handleConfirm() calls transaction.sign(keypair) with null β†’ crash

πŸ’₯ Impact (Severity: CRITICAL)

  • Wallet is non-functional after any page refresh β€” users must disconnect and reconnect every time
  • Send XLM fails silently β€” crashes with unhelpful error
  • Task submission may fail if signing is required
  • Complete block for production deployment β€” no user will tolerate reconnecting on every refresh

βœ… Expected Solution

Strategy 1: Freighter Browser Extension (Preferred)

// frontend/src/services/freighter.ts
import * as Freighter from '@stellar/freighter-api';

export async function isFreighterAvailable(): Promise<boolean> {
  try { return await Freighter.isConnected(); }
  catch { return false; }
}

export async function connectFreighter(): Promise<string> {
  const { address } = await Freighter.getAddress();
  return address;
}

export async function signWithFreighter(xdr: string, network: string): Promise<string> {
  const result = await Freighter.signTransaction(xdr, { networkPassphrase: network });
  return result.signedTxXDR;
}

Strategy 2: Secret Key Fallback (with security warning)

// Store connection METHOD, not the secret key
localStorage.setItem('wallet_method', 'freighter' | 'secret-key');
localStorage.setItem('wallet_pubkey', publicKey);
// Secret key stays in memory only β€” user must re-enter after refresh

Fix the Landing Page Connect Button

// frontend/src/components/landing/Navbar.tsx β€” line 177
// CURRENT: No onClick handler
// FIX: Add onClick={() => navigate('/wallet')} or open connect modal

πŸ“ Reference Files

File Path Lines Issue
frontend/src/context/WalletContext.tsx 22-26 Keypair always null after refresh
frontend/src/components/wallet/SendXLMForm.tsx ~80 Crashes signing with null keypair
frontend/src/components/landing/Navbar.tsx 177-186 Connect button has no onClick
frontend/src/services/api.ts 76-87 Auth header depends on pubkey
frontend/package.json β€” Need to add @stellar/freighter-api

βœ… Acceptance Criteria

  • Install @stellar/freighter-api
  • Create frontend/src/services/freighter.ts
  • Detect Freighter availability on page load
  • Show "Connect with Freighter" as primary option on WalletPage
  • Show "Connect with Secret Key" as fallback with security warning
  • Freighter signing works for SendXLMForm
  • After page refresh, wallet remains functional via Freighter
  • Secret key flow shows reconnect prompt after refresh (not false "connected")
  • Fix landing page Connect button onClick handler
  • Test on Chrome and Firefox with Freighter installed
  • Test without Freighter (graceful fallback to secret key)
  • No more false "connected" state after page refresh

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions