233 lines
7.7 KiB
TypeScript
233 lines
7.7 KiB
TypeScript
// 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 },
|
|
presale: "0xc65e7a2738ed884db8d26a6eb2fecf7daca2e90c",
|
|
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: "", // XIC not yet on ETH
|
|
usdt: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
},
|
|
// TRON (TRC20) — Manual transfer
|
|
TRON: {
|
|
chainId: 0, // Not EVM
|
|
chainName: "TRON",
|
|
explorerUrl: "https://tronscan.org",
|
|
presale: "", // TRC20 uses manual transfer
|
|
token: "",
|
|
usdt: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
|
// Receiving wallet for TRC20 USDT
|
|
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, // No minimum purchase limit
|
|
maxPurchaseUSDT: 50000, // Maximum $50,000 USDT
|
|
totalSupply: 100_000_000_000, // 100 billion XIC
|
|
presaleAllocation: 30_000_000_000, // 30 billion for presale
|
|
// TRC20 memo format
|
|
trc20Memo: "XIC_PRESALE",
|
|
};
|
|
|
|
// ============================================================
|
|
// PRESALE CONTRACT ABI (BSC & ETH — same interface)
|
|
// ============================================================
|
|
export const PRESALE_ABI = [
|
|
// Read functions
|
|
{
|
|
"inputs": [],
|
|
"name": "tokenPrice",
|
|
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
|
"stateMutability": "view",
|
|
"type": "function"
|
|
},
|
|
{
|
|
"inputs": [],
|
|
"name": "totalTokensSold",
|
|
"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": "presaleActive",
|
|
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
|
|
"stateMutability": "view",
|
|
"type": "function"
|
|
},
|
|
{
|
|
"inputs": [],
|
|
"name": "hardCap",
|
|
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
|
"stateMutability": "view",
|
|
"type": "function"
|
|
},
|
|
{
|
|
"inputs": [{ "internalType": "address", "name": "user", "type": "address" }],
|
|
"name": "userPurchases",
|
|
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
|
|
"stateMutability": "view",
|
|
"type": "function"
|
|
},
|
|
// Write functions
|
|
{
|
|
"inputs": [{ "internalType": "uint256", "name": "usdtAmount", "type": "uint256" }],
|
|
"name": "buyTokensWithUSDT",
|
|
"outputs": [],
|
|
"stateMutability": "nonpayable",
|
|
"type": "function"
|
|
},
|
|
{
|
|
"inputs": [],
|
|
"name": "buyTokens",
|
|
"outputs": [],
|
|
"stateMutability": "payable",
|
|
"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" }
|
|
],
|
|
"name": "TokensPurchased",
|
|
"type": "event"
|
|
}
|
|
] as const;
|
|
|
|
// ============================================================
|
|
// ERC20 USDT ABI (minimal — approve + allowance + balanceOf)
|
|
// ============================================================
|
|
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) {
|
|
// 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<unknown>;
|
|
on: (event: string, handler: (...args: unknown[]) => void) => void;
|
|
removeListener: (event: string, handler: (...args: unknown[]) => void) => void;
|
|
isMetaMask?: boolean;
|
|
};
|
|
}
|
|
}
|