/** * Local mavi activity log (this browser only). * Not a full chain indexer — just what this wallet did here. */ export type MaviActivityKind = "send" | "fund" | "receive_note"; export type MaviActivityItem = { id: string; kind: MaviActivityKind; /** Wallet address that owns this history row */ wallet: string; hash?: string; to?: string; from?: string; amountEth?: string; at: string; note?: string; }; const KEY = "mavi_activity_v1"; const MAX = 40; function loadAll(): MaviActivityItem[] { if (typeof window === "undefined") return []; try { const raw = window.localStorage.getItem(KEY); if (!raw) return []; const parsed: unknown = JSON.parse(raw); if (!Array.isArray(parsed)) return []; return parsed.filter(isItem); } catch { return []; } } function isItem(v: unknown): v is MaviActivityItem { if (!v || typeof v !== "object") return false; const o = v as Record; return ( typeof o.id === "string" && (o.kind === "send" || o.kind === "fund" || o.kind === "receive_note") && typeof o.wallet === "string" && typeof o.at === "string" ); } function saveAll(items: MaviActivityItem[]) { try { window.localStorage.setItem(KEY, JSON.stringify(items.slice(0, MAX))); } catch { /* quota */ } } export function readActivityForWallet( walletAddress: string, limit = 20, ): MaviActivityItem[] { const w = walletAddress.toLowerCase(); return loadAll() .filter((i) => i.wallet.toLowerCase() === w) .slice(0, limit); } export function addActivity( item: Omit & { at?: string }, ): MaviActivityItem { const full: MaviActivityItem = { ...item, id: `act_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`, at: item.at ?? new Date().toISOString(), wallet: item.wallet.toLowerCase(), }; const next = [full, ...loadAll()]; saveAll(next); return full; } export function clearActivityForWallet(walletAddress: string): void { const w = walletAddress.toLowerCase(); saveAll(loadAll().filter((i) => i.wallet.toLowerCase() !== w)); } export function formatActivityTime(iso: string): string { try { const d = new Date(iso); if (Number.isNaN(d.getTime())) return iso; return d.toLocaleString(undefined, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", }); } catch { return iso; } } export function shortHash(hash: string): string { if (hash.length < 14) return hash; return `${hash.slice(0, 8)}…${hash.slice(-6)}`; } /** Call after writing activity so open tabs / home refresh. */ export function notifyActivityChanged() { if (typeof window === "undefined") return; window.dispatchEvent(new Event("mavi-activity")); }