378 lines
12 KiB
TypeScript
378 lines
12 KiB
TypeScript
// 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: "PENDING_DEPLOYMENT",
|
||
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<void> {
|
||
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<unknown>;
|
||
on: (event: string, handler: (...args: unknown[]) => void) => void;
|
||
removeListener: (event: string, handler: (...args: unknown[]) => void) => void;
|
||
isMetaMask?: boolean;
|
||
};
|
||
}
|
||
}
|