import { create } from 'zustand' // Wallet-specific fields that must be reset whenever the connected address // changes. Extracted so setWallet can wipe them atomically (B34/B42). const WALLET_RESET = { isSubscribed: false, botReadiness: 'unknown' as const, hlApiKeySet: false, hlApiKeyMasked: null as string | null, paperMode: false, } interface DashboardState { selectedPostId: number | null asset: string timeframe: '5m' | '15m' | '1H' | '4H' | '1D' | '1W' walletAddress: string | null isSubscribed: boolean botReadiness: 'unknown' | 'saved' | 'verified' | 'ready' hlApiKeySet: boolean // true if user already has a key saved in backend hlApiKeyMasked: string | null // e.g. "...a1b2c3" shown after successful save paperMode: boolean // true = paper trade mode (no HL key needed) // BUG-08 fix: backend now streams SOL/TRUMP/BNB/etc. — use an open Record // so any asset tick can be stored, not just BTC/ETH. livePrices: Record setSelectedPost: (id: number | null) => void setAsset: (asset: string) => void setTimeframe: (tf: '5m' | '15m' | '1H' | '4H' | '1D' | '1W') => void // B34/B42: setWallet resets ALL wallet-specific fields atomically so // switching wallets never leaks the previous wallet's private state. setWallet: (address: string | null) => void setSubscribed: (subscribed: boolean) => void setBotReadiness: (state: DashboardState['botReadiness']) => void setHlApiKeySet: (set: boolean, masked?: string) => void setPaperMode: (paper: boolean) => void setLivePrice: (asset: string, price: number) => void } export const useDashboardStore = create((set) => ({ selectedPostId: null, asset: 'BTC', timeframe: '4H', walletAddress: null, ...WALLET_RESET, livePrices: { BTC: null, ETH: null, SOL: null, TRUMP: null }, setSelectedPost: (id) => set({ selectedPostId: id }), setAsset: (asset) => set({ asset }), setTimeframe: (timeframe) => set({ timeframe }), // Reset all wallet-specific fields on every address change (including null). setWallet: (walletAddress) => set({ walletAddress, ...WALLET_RESET }), setSubscribed: (isSubscribed) => set({ isSubscribed }), setBotReadiness: (botReadiness) => set({ botReadiness }), setHlApiKeySet: (keySet, masked) => set(() => ({ hlApiKeySet: keySet, // Never preserve the old mask — if the caller doesn't supply one we // don't know the new wallet's mask and must show nothing until the full // /user fetch (BotConfigPanel.applyUserPayload) provides it explicitly. // Old behaviour of "preserve when masked=undefined" was the root cause // of cross-wallet HL key mask leakage (B34 follow-up). hlApiKeyMasked: (keySet && masked !== undefined) ? masked : null, })), setPaperMode: (paperMode) => set({ paperMode }), setLivePrice: (asset, price) => set((s) => ({ livePrices: { ...s.livePrices, [asset]: price } })), }))