// NAC XIC Token Presale — Contract Configuration v2 // New Contract: XICPresale (购买即时发放版本) // 预售总量: 25亿 XIC | 价格: $0.02/XIC | 时长: 180天 | 无购买上下限 // ============================================================ // CONTRACT ADDRESSES // ============================================================ export const CONTRACTS = { // BSC Mainnet (Chain ID: 56) BSC: { chainId: 56, chainName: "BNB Smart Chain", rpcUrl: "https://bsc-dataseed1.binance.org/", explorerUrl: "https://bscscan.com", nativeCurrency: { name: "BNB", symbol: "BNB", decimals: 18 }, presale: "0x59ff34dd59680a7125782b1f6df2a86ed46f5a24", token: "0x59ff34dd59680a7125782b1f6df2a86ed46f5a24", usdt: "0x55d398326f99059fF775485246999027B3197955", }, // Ethereum Mainnet (Chain ID: 1) ETH: { chainId: 1, chainName: "Ethereum", rpcUrl: "https://eth.llamarpc.com", explorerUrl: "https://etherscan.io", nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, presale: "0x85AB2F2d9f7ca7ecB272b5E8726c70f3fd45D1E3", token: "", usdt: "0xdAC17F958D2ee523a2206206994597C13D831ec7", }, // TRON (TRC20) — Manual transfer TRON: { chainId: 0, chainName: "TRON", explorerUrl: "https://tronscan.org", presale: "", token: "", usdt: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", receivingWallet: "TYASr5UV6HEcXatwdFyffSGZszd6Gkjkvb", }, } as const; // ============================================================ // PRESALE PARAMETERS // ============================================================ export const PRESALE_CONFIG = { tokenPrice: 0.02, // $0.02 per XIC tokenSymbol: "XIC", tokenName: "New AssetChain Token", tokenDecimals: 18, minPurchaseUSDT: 0, // 无最小购买限制 maxPurchaseUSDT: 0, // 无最大购买限制(0 = 无限制) totalSupply: 100_000_000_000, // 1000亿 XIC 总量 presaleAllocation: 2_500_000_000, // 25亿 XIC 预售总量 presaleDurationDays: 180, // 预售时长 180天 trc20Memo: "XIC_PRESALE", }; // ============================================================ // NEW PRESALE CONTRACT ABI (XICPresale v2 — 购买即时发放) // ============================================================ export const PRESALE_ABI = [ // ── Read Functions ────────────────────────────────────── { "inputs": [], "name": "PRESALE_DURATION", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "availableXIC", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "usdtAmount", "type": "uint256" }], "name": "calculateTokenAmount", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "bnbAmount", "type": "uint256" }], "name": "calculateTokenAmountForBNB", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getBNBPrice", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "hardCap", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "isPresaleActive", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "presaleEndTime", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "presalePaused", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "presaleProgress", "outputs": [ { "internalType": "uint256", "name": "sold", "type": "uint256" }, { "internalType": "uint256", "name": "cap", "type": "uint256" }, { "internalType": "uint256", "name": "progressBps", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "presaleStartTime", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "presaleStarted", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "timeRemaining", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "tokenPrice", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "totalRaised", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "totalTokensSold", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "", "type": "address" }], "name": "userPurchases", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "", "type": "address" }], "name": "userSpent", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "wallet", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "xicToken", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, // ── Write Functions ───────────────────────────────────── { "inputs": [], "name": "buyWithBNB", "outputs": [], "stateMutability": "payable", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "usdtAmount", "type": "uint256" }], "name": "buyWithUSDT", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "startPresale", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "bool", "name": "_paused", "type": "bool" }], "name": "setPaused", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "recoverUnsoldTokens", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "token", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" }], "name": "emergencyWithdraw", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, // ── Events ────────────────────────────────────────────── { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "buyer", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "usdtAmount", "type": "uint256" }, { "indexed": false, "internalType": "uint256", "name": "tokenAmount", "type": "uint256" }, { "indexed": false, "internalType": "string", "name": "paymentMethod", "type": "string" } ], "name": "TokensPurchased", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "uint256", "name": "startTime", "type": "uint256" }, { "indexed": false, "internalType": "uint256", "name": "endTime", "type": "uint256" } ], "name": "PresaleStarted", "type": "event" } ] as const; // ============================================================ // ERC20 USDT ABI (minimal) // ============================================================ export const ERC20_ABI = [ { "inputs": [ { "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "approve", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "owner", "type": "address" }, { "internalType": "address", "name": "spender", "type": "address" } ], "name": "allowance", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], "name": "balanceOf", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "decimals", "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], "stateMutability": "view", "type": "function" } ] as const; // ============================================================ // NETWORK SWITCH HELPER // ============================================================ export async function switchToNetwork(chainId: number): Promise { if (!window.ethereum) throw new Error("No wallet detected"); const hexChainId = "0x" + chainId.toString(16); try { await window.ethereum.request({ method: "wallet_switchEthereumChain", params: [{ chainId: hexChainId }], }); } catch (err: unknown) { if ((err as { code?: number }).code === 4902) { const network = Object.values(CONTRACTS).find(n => n.chainId === chainId); if (!network || !("rpcUrl" in network)) throw new Error("Unknown network"); await window.ethereum.request({ method: "wallet_addEthereumChain", params: [{ chainId: hexChainId, chainName: network.chainName, rpcUrls: [(network as { rpcUrl: string }).rpcUrl], nativeCurrency: (network as { nativeCurrency: { name: string; symbol: string; decimals: number } }).nativeCurrency, blockExplorerUrls: [network.explorerUrl], }], }); } else { throw err; } } } // ============================================================ // FORMAT HELPERS // ============================================================ export function formatNumber(n: number, decimals = 2): string { if (n >= 1_000_000_000) return (n / 1_000_000_000).toFixed(decimals) + "B"; if (n >= 1_000_000) return (n / 1_000_000).toFixed(decimals) + "M"; if (n >= 1_000) return (n / 1_000).toFixed(decimals) + "K"; return n.toFixed(decimals); } export function shortenAddress(addr: string): string { if (!addr) return ""; return addr.slice(0, 6) + "..." + addr.slice(-4); } declare global { interface Window { ethereum?: { request: (args: { method: string; params?: unknown[] }) => Promise; on: (event: string, handler: (...args: unknown[]) => void) => void; removeListener: (event: string, handler: (...args: unknown[]) => void) => void; isMetaMask?: boolean; }; } }