π― 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:
publicKey is restored from localStorage β connected = true
keypair is always null β signing fails
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
π― 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
frontend/src/context/WalletContext.tsxfrontend/src/hooks/useWallet.tsfrontend/src/hooks/useWalletBalance.tsfrontend/src/pages/WalletPage.tsxfrontend/src/components/wallet/SendXLMForm.tsxfrontend/src/components/landing/Navbar.tsxfrontend/src/components/layout/TopNav.tsxπ Files to Create
frontend/src/services/freighter.tsπ Files to Install
@stellar/freighter-apiπ Root Cause Analysis
The Stellar SDK
Keypairobject is not JSON-serializable and cannot be stored in localStorage. After page refresh:publicKeyis restored from localStorage βconnected = truekeypairis alwaysnullβ signing failsSendXLMForm.handleConfirm()callstransaction.sign(keypair)withnullβ crashπ₯ Impact (Severity: CRITICAL)
β Expected Solution
Strategy 1: Freighter Browser Extension (Preferred)
Strategy 2: Secret Key Fallback (with security warning)
Fix the Landing Page Connect Button
π Reference Files
frontend/src/context/WalletContext.tsxfrontend/src/components/wallet/SendXLMForm.tsxfrontend/src/components/landing/Navbar.tsxfrontend/src/services/api.tsfrontend/package.jsonβ Acceptance Criteria
@stellar/freighter-apifrontend/src/services/freighter.ts