UNPKG

leumas-private-shared

Version:

Private React JSX Package For Leumas Shared Components, Headers, Footers, Asides, Login Pages, API Key Manager and much more. Styles and everything reusable to avoid DRY code across all of our subdomains

203 lines (159 loc) 6.94 kB
import { useState, useEffect } from 'react'; import Web3 from 'web3'; import LeumasTokenABI from "../../../assets/LeumasToken.json"; import Manual from './Manual'; import MessageResponse from './MessageResponse'; import Spinner2 from '../../Loaders/Spinner2'; import React from 'react'; const TOKEN_ADDRESS = `${import.meta.env.VITE_REACT_APP_LEUMAS_TOKEN_ADDRESS}`; const PurchaseToken = () => { const [web3, setWeb3] = useState(null); const [tokenContract, setTokenContract] = useState(null); const [ethAmount, setEthAmount] = useState(0); const [leumasTokens, setLeumasTokens] = useState(0); const [userAddress, setUserAddress] = useState(null); const [userBalance, setUserBalance] = useState(0); const [exchangeRate, setExchangeRate] = useState(0); const [message, setMessage] = useState(null); const [loading, setLoading] = useState(false); const [messageType, setMessageType] = useState(null); const [mode, setMode] = useState("dex"); const updateBalance = async (address, contract) => { try { const balance = await contract.methods.balanceOf(address).call(); const balanceNumber = Number(balance.toString()) / 1e18; // Convert to a regular number and divide by 10^18 const roundedBalance = balanceNumber.toFixed(2); // Round to 2 decimal places setUserBalance(roundedBalance); console.log("balance: ", roundedBalance); } catch (err) { console.error("Error fetching balance", err); } }; useEffect(() => { const initialize = async () => { if (window.ethereum) { const web3Instance = new Web3(window.ethereum); setWeb3(web3Instance); const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); setUserAddress(accounts[0]); const checksumAddress = web3Instance.utils.toChecksumAddress(TOKEN_ADDRESS); const contractInstance = new web3Instance.eth.Contract(LeumasTokenABI, checksumAddress); setTokenContract(contractInstance); // Event listeners window.ethereum.on('accountsChanged', async (accounts) => { setUserAddress(accounts[0]); const balance = await contractInstance.methods.balanceOf(accounts[0]).call(); setUserBalance(balance); }); // Initial fetch const rate = await contractInstance.methods.unitsOneEthCanBuy().call(); setExchangeRate(rate); // Get and set the initial balance const initialBalance = await contractInstance.methods.balanceOf(accounts[0]).call(); setUserBalance(initialBalance.toNumber()); // Convert to a number updateBalance(accounts[0], contractInstance); } else { console.error("Please install MetaMask"); } }; initialize(); }, []); useEffect(() => { if (userAddress && tokenContract) { updateBalance(userAddress, tokenContract); } }, [userAddress, tokenContract]); const handleTokenAmountChange = (e) => { const tokens = parseFloat(e.target.value || '0'); setLeumasTokens(tokens); const eth = tokens / parseFloat(exchangeRate.toString()); // Calculate ETH based on token amount and rate setEthAmount(eth); }; const purchaseTokens = async () => { setLoading(true); setMessage(null); if (!userAddress || !tokenContract) { setMessage('Please connect your MetaMask account and ensure the contract is loaded.'); setMessageType('error'); setLoading(false); return; } try { const weiValue = web3.utils.toWei(ethAmount.toString(), 'ether'); const transactionReceipt = await tokenContract.methods.transfer( tokenContract.options.address, web3.utils.toWei(leumasTokens.toString(), 'ether') ).send({ from: userAddress, value: weiValue }); const txHash = transactionReceipt.transactionHash; // Construct the Etherscan URL for Goerli testnet const etherscanURL = `https://goerli.etherscan.io/tx/${txHash}`; setMessage( <span> Tokens purchased successfully! Transaction Hash:{' '} <a href={etherscanURL} target="_blank" rel="noopener noreferrer"> {txHash} </a> </span> ); setMessageType('success'); // Update the user's LeumasTokens balance updateBalance(userAddress, tokenContract); setTimeout(() => { setLoading(false); }, 3000); } catch (error) { setMessage(`Failed to purchase tokens: ${error.message}`); setMessageType('error'); setLoading(false); } }; return ( <div className="min-w-[400px] bg-gray-900 text-gray-100 flex flex-col justify-center items-center p-4 w-full overflow-x-none"> <div className='flex gap-4 p-4 hover:text-blue-400'> <button className='text-white z-50' onClick={()=>setMode("manual")}>Manual</button> <button className='text-white z-50' onClick={()=>setMode("dex")}>Trade</button> </div> <div className="w-full max-w-xl border-2 rounded-lg shadow-xl p-4"> <h2 className="text-3xl font-extrabold mb-4"> {mode === "dex" ? "Purchase Leumas Token" : "Get Started with Leumas Token"} </h2> {mode === "dex" ? ( <> <div className="mb-4 grid grid-cols-1 gap-4 items-center"> <div className="relative"> <input type="number" placeholder="Enter amount in LeumasTokens" onChange={handleTokenAmountChange} value={leumasTokens} className="p-2 pr-12 border-2 border-gray-600 rounded focus:border-blue-500 focus:outline-none text-black w-full" /> <button onClick={purchaseTokens} className="absolute top-0 right-0 h-full px-6 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-r font-bold focus:outline-none focus:ring-2 focus:ring-blue-400" > Buy </button> </div> </div> <div className="flex items-center justify-between text-lg mb-4"> <p>{leumasTokens} Leumas Token = {ethAmount.toFixed(4)} ETH.</p> <p>Your Tokens: {userBalance || 0} LDT</p> </div> <p>1 ETH = 5000 LMS Tokens </p> </> ) : ( <Manual /> )} <Spinner2 loading={loading} /> {message && ( <MessageResponse message={message} messageType={messageType} /> )} </div> </div> ); } export default PurchaseToken;