({ onRefresh, loading, lastSyncTime, onTrade, onTradePosition }: WalletButtonProps)
| 176 | } |
| 177 | |
| 178 | export default function WalletButton({ onRefresh, loading, lastSyncTime, onTrade, onTradePosition }: WalletButtonProps) { |
| 179 | const { t } = useI18n(); |
| 180 | const { address, isConnected, connector, chainId } = useAccount(); |
| 181 | const { connect, connectors } = useConnect(); |
| 182 | const { disconnect } = useDisconnect(); |
| 183 | const { switchChain } = useSwitchChain(); |
| 184 | const { signTypedDataAsync } = useSignTypedData(); |
| 185 | const { setWallet, clearWallet, tradeSession, setTradeSession, clearTradeSession, proxyAddress, setProxyAddress } = useWalletStore(); |
| 186 | const [authorizing, setAuthorizing] = useState(false); |
| 187 | const [error, setError] = useState<string | null>(null); |
| 188 | const [polyBalance, setPolyBalance] = useState<number | null>(() => { |
| 189 | if (typeof window === "undefined") return null; |
| 190 | const v = sessionStorage.getItem("pw:balance"); |
| 191 | return v !== null ? Number(v) : null; |
| 192 | }); |
| 193 | const [portfolioValue, setPortfolioValue] = useState<number | null>(() => { |
| 194 | if (typeof window === "undefined") return null; |
| 195 | const v = sessionStorage.getItem("pw:portfolio"); |
| 196 | return v !== null ? Number(v) : null; |
| 197 | }); |
| 198 | const { approve, status: approveStatus, error: approveError, markDone } = useApproveProxy(); |
| 199 | const allConnectors = useConnectors(); |
| 200 | const [open, setOpen] = useState(false); |
| 201 | const dropdownRef = useRef<HTMLDivElement>(null); |
| 202 | const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null); |
| 203 | |
| 204 | // Proxy wallet lookup state |
| 205 | const [resolvedProxy, setResolvedProxy] = useState<string | null>(null); |
| 206 | const [proxyNotFound, setProxyNotFound] = useState(false); |
| 207 | const [manualProxyInput, setManualProxyInput] = useState(""); |
| 208 | const lookupDoneRef = useRef<string | null>(null); |
| 209 | |
| 210 | const isPolygon = chainId === polygon.id; |
| 211 | |
| 212 | const handleMouseEnter = () => { |
| 213 | if (closeTimer.current) clearTimeout(closeTimer.current); |
| 214 | setOpen(true); |
| 215 | }; |
| 216 | const handleMouseLeave = () => { |
| 217 | closeTimer.current = setTimeout(() => setOpen(false), 200); |
| 218 | }; |
| 219 | |
| 220 | // Sync wagmi → walletStore; restore persisted session on connect |
| 221 | // Validates the saved session; if server lost it, silently re-authorize |
| 222 | useEffect(() => { |
| 223 | if (isConnected && address && isPolygon && chainId) { |
| 224 | setWallet(address, chainId); |
| 225 | const saved = loadTradeSession(address); |
| 226 | if (saved) { |
| 227 | // Optimistically set session immediately so effectiveProxy is available on first render |
| 228 | setTradeSession(saved); |
| 229 | // Verify session in background; if expired, re-authorize or clear |
| 230 | fetch("/api/trade/balance", { |
| 231 | method: "POST", |
| 232 | headers: { "Content-Type": "application/json" }, |
| 233 | body: JSON.stringify({ sessionToken: saved.sessionToken }), |
| 234 | }).then(async (res) => { |
| 235 | if (!res.ok) { |
nothing calls this directly
no test coverage detected