@@ -47,6 +47,12 @@ const WalletContext = createContext<WalletContextValue | null>(null)
4747
4848const LS_WALLET_KEY = 'niffyinsure:lastWalletId'
4949const LS_NETWORK_KEY = 'niffyinsure:appNetwork'
50+ const LS_WALLET_SESSION = 'niffyinsur-wallet-session-v1'
51+
52+ interface WalletSession {
53+ walletId : WalletId ;
54+ publicKey : string ;
55+ }
5056
5157function kitNetworkFor ( app : AppNetwork ) : Networks {
5258 if ( app === 'mainnet' ) return Networks . PUBLIC
@@ -94,6 +100,7 @@ export function WalletProvider({ children }: { children: React.ReactNode }) {
94100 setActiveWalletId ( null )
95101 setWalletNetwork ( null )
96102 setWalletNetworkResolution ( { status : 'idle' } )
103+ localStorage . removeItem ( LS_WALLET_SESSION )
97104 }
98105 } catch {
99106 setAddress ( null )
@@ -106,28 +113,48 @@ export function WalletProvider({ children }: { children: React.ReactNode }) {
106113 setActiveWalletId ( null )
107114 setWalletNetwork ( null )
108115 setWalletNetworkResolution ( { status : 'idle' } )
116+ localStorage . removeItem ( LS_WALLET_SESSION )
109117 } )
110118
111- // Auto-reconnect last wallet
112- const lastWallet = localStorage . getItem ( LS_WALLET_KEY ) as WalletId | null
113- if ( lastWallet ) {
114- reconnect ( lastWallet )
119+ // Auto-reconnect last wallet (Silent reconnect on app mount)
120+ const sessionRaw = localStorage . getItem ( LS_WALLET_SESSION )
121+ if ( sessionRaw ) {
122+ try {
123+ const session = JSON . parse ( sessionRaw ) as WalletSession
124+ reconnect ( session )
125+ } catch {
126+ localStorage . removeItem ( LS_WALLET_SESSION )
127+ }
115128 }
116129 // eslint-disable-next-line react-hooks/exhaustive-deps
117130 } , [ ] )
118131
119- async function reconnect ( walletId : WalletId ) {
132+ async function reconnect ( session : WalletSession ) {
120133 try {
121- StellarWalletsKit . setWallet ( walletId )
134+ StellarWalletsKit . setWallet ( session . walletId )
122135 const { address : addr } = await StellarWalletsKit . getAddress ( )
136+
123137 if ( addr ) {
138+ // Validate reconnected public key matches stored value (Requirement: clear if mismatched)
139+ if ( addr !== session . publicKey ) {
140+ console . warn ( 'Wallet address mismatch during reconnect. Clearing session.' )
141+ localStorage . removeItem ( LS_WALLET_SESSION )
142+ return
143+ }
144+
124145 setAddress ( addr )
125- setActiveWalletId ( walletId )
146+ setActiveWalletId ( session . walletId )
126147 setConnectionStatus ( 'connected' )
127148 await refreshWalletNetwork ( )
128149 }
129- } catch {
130- // Silent — wallet may not be unlocked yet
150+ } catch ( err ) {
151+ // Failed to reconnect (extension locked or unavailable)
152+ // Requirement: show a non-blocking banner if it fails.
153+ toast ( {
154+ title : 'Reconnect failed' ,
155+ description : 'Unable to auto-reconnect to your wallet. Please unlock your extension or connect manually.' ,
156+ variant : 'default' , // non-blocking (not 'destructive' if we want it subtle)
157+ } )
131158 }
132159 }
133160
@@ -148,11 +175,21 @@ export function WalletProvider({ children }: { children: React.ReactNode }) {
148175 try {
149176 StellarWalletsKit . setWallet ( walletId )
150177 const { address : addr } = await StellarWalletsKit . getAddress ( )
151- setAddress ( addr ?? null )
152- setActiveWalletId ( walletId )
153- setConnectionStatus ( 'connected' )
154- localStorage . setItem ( LS_WALLET_KEY , walletId )
155- await refreshWalletNetwork ( )
178+
179+ if ( addr ) {
180+ setAddress ( addr )
181+ setActiveWalletId ( walletId )
182+ setConnectionStatus ( 'connected' )
183+
184+ // Save session data (Requirement: {walletType, publicKey})
185+ // SECURITY NOTE: We only store the public key. Never store private keys or seed phrases in localStorage.
186+ localStorage . setItem ( LS_WALLET_SESSION , JSON . stringify ( {
187+ walletId,
188+ publicKey : addr
189+ } ) )
190+
191+ await refreshWalletNetwork ( )
192+ }
156193 } catch ( err : unknown ) {
157194 setWalletNetworkResolution ( { status : 'idle' } )
158195 setConnectionStatus ( 'error' )
@@ -173,7 +210,7 @@ export function WalletProvider({ children }: { children: React.ReactNode }) {
173210 setActiveWalletId ( null )
174211 setWalletNetwork ( null )
175212 setWalletNetworkResolution ( { status : 'idle' } )
176- localStorage . removeItem ( LS_WALLET_KEY )
213+ localStorage . removeItem ( LS_WALLET_SESSION )
177214 } , [ ] )
178215
179216 const signTransaction = useCallback ( async ( xdr : string ) : Promise < string > => {
0 commit comments