diff --git a/src/components/providers/WalletProvider.tsx b/src/components/providers/WalletProvider.tsx index 31844b6..89517f3 100644 --- a/src/components/providers/WalletProvider.tsx +++ b/src/components/providers/WalletProvider.tsx @@ -9,6 +9,8 @@ import { useRef, } from "react"; import { Keypair } from "@stellar/stellar-sdk"; +import { abortAllRequests } from "@/services/api"; +import { cacheClearByPrefix } from "@/services/cache"; export interface WalletAccount { address: string; @@ -21,10 +23,11 @@ interface WalletContextValue { isConnected: boolean; isConnecting: boolean; accounts: WalletAccount[]; + cacheVersion: number; connect: () => Promise; disconnect: () => Promise; switchAccount: (address: string) => Promise; - purgeCache: () => void; + purgeCache: (oldAddress?: string) => Promise; } const WalletContext = createContext({ @@ -32,10 +35,11 @@ const WalletContext = createContext({ isConnected: false, isConnecting: false, accounts: [], + cacheVersion: 0, connect: async () => {}, disconnect: async () => {}, switchAccount: async () => {}, - purgeCache: () => {}, + purgeCache: async () => {}, }); let switchGuard = Promise.resolve(); @@ -46,10 +50,21 @@ export function WalletProvider({ children }: { children: React.ReactNode }) { const [isConnecting, setIsConnecting] = useState(false); const cacheVersion = useRef(0); - const purgeCache = useCallback(() => { + const purgeCache = useCallback(async (oldAddress?: string) => { cacheVersion.current += 1; + + setAccount(null); + setAccounts([]); + localStorage.removeItem("utility-wallet-session"); localStorage.removeItem("utility-wallet-accounts"); + localStorage.removeItem("utility-auth-session"); + + abortAllRequests(); + + if (oldAddress) { + await cacheClearByPrefix(`utility:${oldAddress}`); + } }, []); const connect = useCallback(async () => { @@ -76,18 +91,18 @@ export function WalletProvider({ children }: { children: React.ReactNode }) { }, [isConnecting]); const disconnect = useCallback(async () => { - purgeCache(); - setAccount(null); - setAccounts([]); - }, [purgeCache]); + await purgeCache(account?.address); + }, [purgeCache, account]); const switchAccount = useCallback( async (address: string) => { switchGuard = switchGuard.then(async () => { const target = accounts.find((a) => a.address === address); if (!target) return; - setAccount(null); - await new Promise((r) => setTimeout(r, 0)); + + const oldAddress = account?.address; + await purgeCache(oldAddress); + setAccount(target); localStorage.setItem( "utility-wallet-session", @@ -96,7 +111,7 @@ export function WalletProvider({ children }: { children: React.ReactNode }) { }); await switchGuard; }, - [accounts] + [accounts, account, purgeCache] ); useEffect(() => { @@ -123,6 +138,7 @@ export function WalletProvider({ children }: { children: React.ReactNode }) { isConnected: !!account, isConnecting, accounts, + cacheVersion: cacheVersion.current, connect, disconnect, switchAccount, diff --git a/src/services/api.ts b/src/services/api.ts index a9ec969..957e743 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -23,6 +23,7 @@ const defaultConfig: ApiConfig = { }; let sessionToken: string | null = null; +const activeControllers = new Set(); export function setSessionToken(token: string | null) { sessionToken = token; @@ -32,6 +33,13 @@ export function getSessionToken(): string | null { return sessionToken; } +export function abortAllRequests(): void { + for (const ctrl of activeControllers) { + ctrl.abort(); + } + activeControllers.clear(); +} + async function request( method: HttpMethod, path: string, @@ -41,6 +49,7 @@ async function request( const cfg = { ...defaultConfig, ...config }; const url = `${cfg.baseUrl}${path}`; const controller = new AbortController(); + activeControllers.add(controller); const timeoutId = setTimeout(() => controller.abort(), cfg.timeout); try { @@ -83,6 +92,8 @@ async function request( error: (err as Error).message || "Network error", status: 0, }; + } finally { + activeControllers.delete(controller); } } diff --git a/src/services/cache.ts b/src/services/cache.ts index 5ce11ad..a17da64 100644 --- a/src/services/cache.ts +++ b/src/services/cache.ts @@ -103,6 +103,22 @@ export async function cacheClear(): Promise { } } +export async function cacheClearByPrefix(prefix: string): Promise { + try { + const db = await getDb(); + const keys = await db.getAllKeys("kv"); + const tx = db.transaction("kv", "readwrite"); + for (const key of keys) { + if (String(key).startsWith(prefix)) { + tx.store.delete(key); + } + } + await tx.done; + } catch { + // silently fail + } +} + export async function cacheKeys(prefix?: string): Promise { try { const db = await getDb();