"use client"; import { useState, useEffect, useMemo } from 'react'; import { useAccount, useReadContract } from 'wagmi'; import { bscTestnet } from 'wagmi/chains'; import { useQuery } from '@tanstack/react-query'; import { useTokenBalance } from '@/hooks/useBalance'; import { useTokenBySymbol } from '@/hooks/useTokenBySymbol'; import { useApp } from '@/contexts/AppContext'; import { fetchContracts } from '@/lib/api/contracts'; import { abis } from '@/lib/contracts'; import ProductHeader from "./ProductHeader"; import StatsCards from "@/components/fundmarket/StatsCards"; import AssetOverviewCard from "./AssetOverviewCard"; import APYHistoryCard from "./APYHistoryCard"; import AssetDescriptionCard from "./AssetDescriptionCard"; import MintSwapPanel from "./MintSwapPanel"; import ProtocolInformation from "./ProtocolInformation"; import PerformanceAnalysis from "./PerformanceAnalysis"; import Season1Rewards from "./Season1Rewards"; import AssetCustodyVerification from "./AssetCustodyVerification"; import { ProductDetail } from "@/lib/api/fundmarket"; interface OverviewTabProps { product: ProductDetail; } const formatUSD = (v: number) => "$" + v.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 }); export default function OverviewTab({ product }: OverviewTabProps) { const { t } = useApp(); const { isConnected, chainId } = useAccount(); const ytToken = useTokenBySymbol(product.tokenSymbol); const { formattedBalance: ytBalance } = useTokenBalance(ytToken?.contractAddress, ytToken?.decimals ?? 18); // Shared getVaultInfo read — single source of truth for all children const { data: contractConfigs = [] } = useQuery({ queryKey: ['contract-registry'], queryFn: fetchContracts, staleTime: 5 * 60 * 1000, }); const factoryAddress = useMemo(() => { const c = contractConfigs.find(c => c.name === 'YTAssetFactory' && c.chain_id === product.chainId); return c?.address as `0x${string}` | undefined; }, [contractConfigs, product.chainId]); const hasContract = !!factoryAddress && !!product.contractAddress; const { data: vaultInfo, isLoading: isVaultLoading, refetch: refetchVault } = useReadContract({ address: factoryAddress, abi: abis.YTAssetFactory as any, functionName: 'getVaultInfo', args: product.contractAddress ? [product.contractAddress as `0x${string}`] : undefined, chainId: product.chainId, query: { enabled: hasContract }, }); // 3s timeout — after this, fall back to DB snapshot values const [vaultTimedOut, setVaultTimedOut] = useState(false); useEffect(() => { if (!hasContract) return; setVaultTimedOut(false); const t = setTimeout(() => setVaultTimedOut(true), 3000); return () => clearTimeout(t); // eslint-disable-next-line react-hooks/exhaustive-deps }, [hasContract]); const vaultReady = !hasContract || vaultInfo !== undefined || vaultTimedOut; // Real-time TVL: getVaultInfo[1] = totalAssets (USDC) const usdcDecimals = product.chainId === 421614 ? 6 : 18; const totalAssetsRaw: bigint = vaultInfo ? ((vaultInfo as any[])[1] as bigint) ?? 0n : 0n; const liveTVL = totalAssetsRaw > 0n ? Number(totalAssetsRaw) / Math.pow(10, usdcDecimals) : null; const tvlDisplay = !vaultReady ? "..." : liveTVL !== null ? formatUSD(liveTVL) : formatUSD(product.tvlUsd); const balanceUSD = parseFloat(ytBalance) * (product.currentPrice || 1); const balanceDisplay = !isConnected ? "--" : chainId !== bscTestnet.id ? "-- (Switch to BSC)" : formatUSD(balanceUSD); const volume24hDisplay = product.volume24hUsd > 0 ? formatUSD(product.volume24hUsd) : "--"; const volChange = product.volumeChangeVsAvg ?? 0; const volChangeStr = volChange !== 0 ? `${volChange > 0 ? "↑" : "↓"} ${Math.abs(volChange).toFixed(0)}% vs Avg` : ""; const stats = [ { label: t("productPage.totalValueLocked"), value: tvlDisplay, change: "", isPositive: true }, { label: t("productPage.volume24h"), value: volume24hDisplay, change: volChangeStr, isPositive: volChange >= 0 }, { label: t("productPage.cumulativeYield"), value: formatUSD(0), change: "", isPositive: true }, { label: t("productPage.yourTotalBalance"), value: balanceDisplay, change: "", isPositive: true }, { label: t("productPage.yourTotalEarning"), value: "--", change: "", isPositive: true }, ]; return (