From 8c52fc72a24cb3b8126f3bdd91473c1ca2633a01 Mon Sep 17 00:00:00 2001 From: nacadmin Date: Sun, 22 Mar 2026 09:07:42 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=9B=B4=E6=96=B0=E5=90=88=E7=BA=A6?= =?UTF-8?q?=E5=9C=B0=E5=9D=80=E4=B8=BA=20XICClaimContract=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20EVM=20=E6=8E=A5=E6=94=B6=E9=92=B1=E5=8C=85?= =?UTF-8?q?=E5=9C=B0=E5=9D=80=20(2026-03-22)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/lib/contracts.ts | 232 ++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 client/src/lib/contracts.ts diff --git a/client/src/lib/contracts.ts b/client/src/lib/contracts.ts new file mode 100644 index 0000000..158e59f --- /dev/null +++ b/client/src/lib/contracts.ts @@ -0,0 +1,232 @@ +// NAC XIC Token Presale — Contract Configuration +// Design: Dark Cyberpunk / Quantum Finance +// Colors: Amber Gold #f0b429, Quantum Blue #00d4ff, Deep Black #0a0a0f + +// ============================================================ +// 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 }, + // XICClaimContract — 预售结束后用于领取 XIC + presale: "0x9d8ea8223c8d7d977744f2f7cfc076341355a419", + token: "0x59FF34dD59680a7125782b1f6df2A86ed46F5A24", + usdt: "0x55d398326f99059fF775485246999027B3197955", + // 接收 USDT 的钱包地址(购买时转账到此地址) + receivingWallet: "0x43DAb577f3279e11D311E7d628C6201d893A9Aa3", + }, + // 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: "0x9d8ea8223c8d7d977744f2f7cfc076341355a419", + token: "", + usdt: "0xdAC17F958D2ee523a2206206994597C13D831ec7", + // 接收 USDT 的钱包地址(购买时转账到此地址) + receivingWallet: "0x43DAb577f3279e11D311E7d628C6201d893A9Aa3", + }, + // TRON (TRC20) — Manual transfer + TRON: { + chainId: 0, // Not EVM + chainName: "TRON", + explorerUrl: "https://tronscan.org", + presale: "", + token: "", + usdt: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", + // 接收 TRC20 USDT 的钱包地址 + receivingWallet: "TWc2ugYBFN5aSoimAh4qGt9oMyket6NYZp", + }, +} 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, // No minimum purchase limit + maxPurchaseUSDT: 50000, // Max $50,000 USDT per purchase + totalSupply: 100_000_000_000, // 100 billion XIC + presaleAllocation: 2_500_000_000, // 2.5 billion for presale (25亿) + // TRC20 memo format + trc20Memo: "XIC_PRESALE", +}; + +// ============================================================ +// XIC CLAIM CONTRACT ABI (BSC — XICClaimContract) +// 用于预售结束后领取 XIC 代币 +// ============================================================ +export const PRESALE_ABI = [ + // Read functions + { + "inputs": [], + "name": "hasPresaleEnded", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "presaleEndTime", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "depositedTokens", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "user", "type": "address" }, + { "internalType": "uint256", "name": "roundId", "type": "uint256" } + ], + "name": "getClaimableTokensForUser", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "user", "type": "address" }], + "name": "getTotalClaimable", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "user", "type": "address" }], + "name": "hasPurchasedTokens", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "usedNonces", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, +] as const; + +// ============================================================ +// ERC20 USDT ABI (minimal — approve + allowance + balanceOf + transfer) +// ============================================================ +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" + }, + { + "inputs": [ + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "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) { + // Chain not added yet — add it + 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 window.ethereum for TypeScript +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; + }; + } +}