diff --git a/client/src/pages/Home.tsx b/client/src/pages/Home.tsx new file mode 100644 index 0000000..8ade345 --- /dev/null +++ b/client/src/pages/Home.tsx @@ -0,0 +1,1409 @@ +// NAC XIC Token Presale — Main Page v3.0 +// Features: Real on-chain data | Bilingual (EN/ZH) | TRC20 Live Feed | Wallet Connect +// Design: Dark Cyberpunk / Quantum Finance +// Colors: Amber Gold #f0b429 | Quantum Blue #00d4ff | Deep Black #0a0a0f + +import { useState, useEffect, useCallback, useRef, useMemo } from "react"; +import { toast } from "sonner"; +import { Link } from "wouter"; +import { useWallet } from "@/hooks/useWallet"; +import { usePresale } from "@/hooks/usePresale"; +import { CONTRACTS, PRESALE_CONFIG, formatNumber, shortenAddress } from "@/lib/contracts"; +import { trpc } from "@/lib/trpc"; +import { type Lang, useTranslation } from "@/lib/i18n"; +import { WalletSelector } from "@/components/WalletSelector"; + +// ─── Network Tab Types ──────────────────────────────────────────────────────── +type NetworkTab = "BSC" | "ETH" | "TRON"; + +// ─── Assets ─────────────────────────────────────────────────────────────────── +const HERO_BG = "https://d2xsxph8kpxj0f.cloudfront.net/310519663287655625/Ngki3MumDNGduV3xJt3mga/nac-hero-bg_7c6c173e.jpg"; +const TOKEN_ICON = "https://d2xsxph8kpxj0f.cloudfront.net/310519663287655625/Ngki3MumDNGduV3xJt3mga/nac-token-icon_382e5c30.png"; + +// ─── Fallback stats while loading ───────────────────────────────────────────── +const FALLBACK_STATS = { + totalUsdtRaised: 0, + totalTokensSold: 0, + hardCap: 5_000_000, + progressPct: 0, +}; + +// ─── Countdown Timer ────────────────────────────────────────────────────────── +function useCountdown(targetDate: Date) { + const [timeLeft, setTimeLeft] = useState({ days: 0, hours: 0, minutes: 0, seconds: 0 }); + useEffect(() => { + const tick = () => { + const diff = targetDate.getTime() - Date.now(); + if (diff <= 0) { setTimeLeft({ days: 0, hours: 0, minutes: 0, seconds: 0 }); return; } + setTimeLeft({ + days: Math.floor(diff / 86400000), + hours: Math.floor((diff % 86400000) / 3600000), + minutes: Math.floor((diff % 3600000) / 60000), + seconds: Math.floor((diff % 60000) / 1000), + }); + }; + tick(); + const id = setInterval(tick, 1000); + return () => clearInterval(id); + }, [targetDate]); + return timeLeft; +} + +// ─── Animated Counter ───────────────────────────────────────────────────────── +function AnimatedCounter({ value, prefix = "", suffix = "" }: { value: number; prefix?: string; suffix?: string }) { + const [display, setDisplay] = useState(0); + useEffect(() => { + if (value === 0) return; + let start = 0; + const step = value / 60; + const id = setInterval(() => { + start += step; + if (start >= value) { setDisplay(value); clearInterval(id); } + else setDisplay(Math.floor(start)); + }, 16); + return () => clearInterval(id); + }, [value]); + return {prefix}{display.toLocaleString()}{suffix}; +} + +// ─── Network Icon ───────────────────────────────────────────────────────────── +function NetworkIcon({ network }: { network: NetworkTab }) { + if (network === "BSC") return ( + + ); + if (network === "ETH") return ( + + ); + return ( + + ); +} + +// ─── Step Badge ─────────────────────────────────────────────────────────────── +function StepBadge({ num, text }: { num: number; text: string }) { + return ( +
+ {lang === "zh" ? "必填:您的XIC接收地址(BSC/ETH钉包地址)" : "Required: Your XIC Receiving Address (BSC/ETH wallet address)"} +
++ {lang === "zh" + ? "XIC代币将发放到您的BSC/ETH钉包地址(0x开头)。请确保填写正确的地址,否则无法收到代币。" + : "XIC tokens will be sent to your BSC/ETH wallet address (starts with 0x). Please make sure to enter the correct address."} +
+{evmAddrError}
} + {submitted &&✓ {lang === "zh" ? "XIC接收地址已保存" : "XIC receiving address saved"}
} + ++ {lang === "zh" ? "连接 TronLink 钱包(可选)" : "Connect TronLink Wallet (Optional)"} +
++ {lang === "zh" ? "已连接 TronLink 地址:" : "Connected TronLink address:"} +
++ {lang === "zh" + ? "您的 TronLink 已连接。请在上方填写 XIC 接收地址,然后向下方地址发送 USDT。" + : "TronLink connected. Please fill your XIC receiving address above, then send USDT to the address below."} +
++ {lang === "zh" + ? "连接 TronLink 可自动验证您的 TRON 地址。手机用户可通过 TronLink App 内置浏览器打开本页面。" + : "Connect TronLink to auto-verify your TRON address. Mobile users can open this page in TronLink App's built-in browser."} +
+{t("trc20_send_to")}
++ {t("buy_success_msg")} {formatNumber(purchaseState.tokenAmount)} {t("buy_success_tokens")} +
+ {purchaseState.txHash && ( + + {t("buy_view_explorer")} + + )} + +{t("buy_wrong_network")}
+{t("buy_wrong_msg")} {CONTRACTS[network].chainName}
+ +{t("buy_connect_msg")}
++ {lang === "zh" ? "⚠️ 手动地址模式:需连接钱包才能完成链上购买" : "⚠️ Manual mode: Connect wallet to complete on-chain purchase"} +
++ {lang === "zh" ? "请点击右上角连接您的钱包" : "Please connect your wallet via the top-right button"} +
++ {PRESALE_CONFIG.maxPurchaseUSDT > 0 + ? `${t("buy_no_min_max")} $${PRESALE_CONFIG.maxPurchaseUSDT.toLocaleString()} USDT` + : (lang === "zh" ? "无最低/最高购买限制" : "No minimum or maximum purchase limit")} +
+ + {/* Add XIC to Wallet button — only show on BSC where token address is known */} + {network === "BSC" && CONTRACTS.BSC.token && ( + + )} +{a}
+{t("support_msg")}
+{t("support_response")}
++ {lang === "zh" + ? "选择您的钱包进行连接,或手动输入地址" + : "Select your wallet to connect, or enter address manually"} +
+ + {/* MetaMask initialization guide */} ++ {lang === "zh" + ? "💡 首次使用 MetaMask?请先打开 MetaMask 扩展完成初始化(创建或导入钱包),完成后点击下方「刷新」按钮重新检测。" + : "💡 First time using MetaMask? Open the MetaMask extension and complete setup (create or import a wallet), then click Refresh below to re-detect."} +
+{t("nav_connected")}
+{wallet.shortAddress}
+{t("hero_subtitle")}
+{t("buy_subtitle")} $0.02 USDT · {t("buy_no_min")}
+{t("buy_select_network")}
++ {lang === "zh" ? "预售已暂停" : "Presale Paused"} +
++ {lang === "zh" ? "请关注官方 Telegram / Twitter 获取最新公告" : "Follow our official Telegram / Twitter for updates"} +
+{t("buy_contracts")}
+ +{desc}
+{t("faq_subtitle")}
+{t("faq_still")}
+ + + {t("faq_ask")} + +