diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..1f4f560 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +build/* +public/* +src/react-app-env.d.ts +src/serviceWorker.ts \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..7b74b59 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": ["prettier"] +} diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..bc8643e --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "printWidth": 80, + "doubleQuote": true, + "trailingComma": "es5", + "tabWidth": 2 +} diff --git a/example.env b/example.env new file mode 100644 index 0000000..81d5ae3 --- /dev/null +++ b/example.env @@ -0,0 +1,4 @@ +REACT_APP_MORALIS_APP_ID=QT6crraMnABRgb5AqrKcurSLNiNRd2JT3HPLLTTm +REACT_APP_MORALIS_SERVER_URL=https://hjuh3bynravd.usemoralis.com:2053/server +REACT_APP_CHAIN_ID=0x13881 +# REACT_APP_CHAIN_ID=0xfa \ No newline at end of file diff --git a/package.json b/package.json index f760c55..db7909c 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@alpsfinance/core": "^0.0.3", "@emotion/react": "^11.8.1", "@emotion/styled": "^11.8.1", "@mui/icons-material": "^5.4.2", @@ -14,17 +15,23 @@ "@types/node": "^12.0.0", "@types/react": "^16.9.53", "@types/react-dom": "^16.9.8", + "@walletconnect/web3-provider": "^1.7.3", + "@web3auth/web3auth": "^0.3.3", "bignumber.js": "^9.0.2", "lodash": "^4.17.21", + "magic-sdk": "7.0.0", "moralis": "^1.3.2", "react": "^17.0.2", "react-copy-to-clipboard": "^5.0.4", "react-dom": "^17.0.2", "react-icons": "^4.3.1", - "react-moralis": "^1.3.1", - "react-scripts": "5.0.0", + "react-moralis": "^1.3.2", + "react-scripts": "4.0.3", + "react-spinners": "^0.11.0", "typescript": "^4.0.3", + "walletlink": "^2.5.0", "web-vitals": "^0.2.4", + "web3": "^1.7.1", "workbox-background-sync": "^5.1.3", "workbox-broadcast-update": "^5.1.3", "workbox-cacheable-response": "^5.1.3", @@ -42,7 +49,10 @@ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "lint": "eslint --ext .js,.jsx,.ts,.tsx src --color", + "format": "prettier --write 'src/**/*.{ts,tsx,scss,css,json}'", + "isready": "npm run format && npm run lint && npm run build" }, "eslintConfig": { "extends": [ @@ -64,6 +74,12 @@ }, "devDependencies": { "@types/lodash": "^4.14.179", - "@types/react-copy-to-clipboard": "^5.0.2" + "@types/react-copy-to-clipboard": "^5.0.2", + "eslint": "7.32.0", + "eslint-config-prettier": "8.3.0", + "eslint-plugin-prettier": "4.0.0", + "prettier": "2.4.1", + "prettier-eslint": "13.0.0", + "prettier-eslint-cli": "5.0.1" } } diff --git a/src/AlpsTokenPresale.tsx b/src/AlpsTokenPresale.tsx index 089c696..4694c27 100644 --- a/src/AlpsTokenPresale.tsx +++ b/src/AlpsTokenPresale.tsx @@ -3,23 +3,82 @@ import Grid from "@mui/material/Grid"; import Typography from "@mui/material/Typography"; import { Box } from "@mui/material"; import { calculateTimeLeft } from "./utility/helper"; +import { useMoralis } from "react-moralis"; +import preSaleAbi from "@alpsfinance/core/build/contracts/Presale.json"; +import { CHAIN_SYMBOL, PRESALE_CONTRACT_ADDRESS } from "./constant"; +import { useApiContract } from "react-moralis"; interface Props { isLargeScreen: Boolean; } const AlpsTokenPresale: FC = (props) => { - const [timeLeft, setTimeLeft] = useState(calculateTimeLeft()); + const [timeLeft, setTimeLeft] = useState(calculateTimeLeft(Date.now())); + const [currentRound, setCurrentRound] = useState(1); const { isLargeScreen } = props; - useEffect(() => { - const timer = setTimeout(() => { - setTimeLeft(calculateTimeLeft()); - }, 1000); - return () => clearTimeout(timer); + const { isAuthenticated } = useMoralis(); + const getCurrentPresaleRoundFunction = useApiContract({ + address: PRESALE_CONTRACT_ADDRESS, + functionName: "getCurrentPresaleRound", + chain: CHAIN_SYMBOL, + abi: preSaleAbi.abi, + }); + const { data, runContractFunction } = useApiContract({ + address: PRESALE_CONTRACT_ADDRESS, + functionName: "presaleDetailsMapping", + chain: CHAIN_SYMBOL, + abi: preSaleAbi.abi, + params: { "": (currentRound + 1).toString() }, }); + useEffect(() => { + if (isAuthenticated) + if (currentRound < 2) runContractFunction(); + else setTimeLeft(calculateTimeLeft(Date.now())); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [currentRound, isAuthenticated]); + + async function Fetch() { + try { + const res = await getCurrentPresaleRoundFunction.runContractFunction(); + setCurrentRound(Number(res)); + // const nextRound = await getNextRoundFunction.runContractFunction(); + // console.log(res, nextRound) + } catch (err) { + console.log(err); + } + } + + useEffect(() => { + if (isAuthenticated) Fetch(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isAuthenticated]); + + let timer: any; + useEffect(() => { + if (data) { + // eslint-disable-next-line react-hooks/exhaustive-deps + timer = setInterval(() => { + const leftTime = calculateTimeLeft( + 1000 * Number((data as any).startingTime) + ); + if ( + leftTime.days === 0 && + leftTime.hours === 0 && + leftTime.minutes === 0 && + leftTime.seconds === 0 + ) { + Fetch(); + } + setTimeLeft(leftTime); + }, 1000); + } else { + clearTimeout(timer); + } + return () => clearInterval(timer); + }, [data]); return ( - + = (props) => { background: "rgba(0, 36, 0, 0.5)", }} > - - TOKEN PRESALE STARTS IN: + + TOKEN PRESALE ROUND {currentRound + 1} STARTS IN: @@ -51,7 +110,7 @@ const AlpsTokenPresale: FC = (props) => { }} > = (props) => { = (props) => { = (props) => { minutes @@ -63,15 +63,15 @@ export default function App() { container px={3} mt={2} - direction='column' - justifyContent='center' - textAlign='center' + direction="column" + justifyContent="center" + textAlign="center" > Placeholder - - + + Token Info - + Symbol: @@ -100,7 +100,7 @@ export default function App() { - + Contract: @@ -113,10 +113,10 @@ export default function App() { > setTimeout(() => setCopied(false), 200)} > - Copy to Clipboard + Copy to Clipboard diff --git a/src/AppBar.tsx b/src/AppBar.tsx index edaa99b..cf7969c 100644 --- a/src/AppBar.tsx +++ b/src/AppBar.tsx @@ -21,14 +21,24 @@ const CustomAppBar: FC = () => { const ethAddress = user?.get("ethAddress"); setWalletAddress(ethAddress.replace(ethAddress.substring(6, 38), "****")); } - //eslint - disable - next - line; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isAuthenticated]); + const onLoginW = async () => { + const user = await authenticate({ provider: "walletconnect" }); + console.log(user); + }; + + const onLoginM = async () => { + const user = await authenticate(); + console.log(user); + }; + const loginControl = (event: React.MouseEvent) => { event.preventDefault(); event.stopPropagation(); if (!isAuthenticated) { - authenticate(); + onLoginM(); } else { logout(); } @@ -67,7 +77,7 @@ const CustomAppBar: FC = () => { const list = (anchor: String) => ( @@ -87,8 +97,8 @@ const CustomAppBar: FC = () => { = (props: props) => { const { isLargeScreen } = props; - const { isAuthenticated, enableWeb3, isWeb3Enabled, Moralis } = useMoralis(); - const { fetch } = useWeb3ExecuteFunction(); + const { enableWeb3, isWeb3Enabled, Moralis, user } = useMoralis(); + const getPriceFunc = useWeb3ExecuteFunction(); + + const [isProcessing, setIsProcessing] = useState(false); + console.log(process.env.NODE_ENV); + const chain_id = process.env.NODE_ENV === "development" ? "0x13881" : "0xfa"; - const tokens = [ - { - value: "0", - label: "MATIC", - contractAddress: "0x0000000000000000000000000000000000000000", - oracleAddress: "0xd0D5e3DB44DE05E9F294BB0a3bEEaF030DE24Ada", - }, - { - value: "1", - label: "USDT", - contractAddress: "0x72F09c85234C975Da2B6686e472FE40633fA2Cd9", - oracleAddress: "0x92C09849638959196E976289418e5973CC96d645", - }, - { - value: "2", - label: "DAI", - contractAddress: "0x001B3B4d0F3714Ca98ba10F6042DaEbF0B1B7b6F", - oracleAddress: "0x0FCAa9c899EC5A91eBc3D5Dd869De833b06fB046", - }, - ]; - const [selectedToken, setToken] = useState(0); - const changeToken = (event: SelectChangeEvent): void => { - setToken(Number(event.target.value)); + const currencies: { [type: string]: CurrencyData[] } = { + "0xfa": [ + { + value: "FTM", + label: "FTM", + address: "0x0000000000000000000000000000000000000000", + aggregatorAddress: "0xf4766552D15AE4d256Ad41B6cf2933482B0680dc", + }, + { + value: "USDT", + label: "USDT", + address: "0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E", + aggregatorAddress: "0x91d5DEFAFfE2854C7D02F50c80FA1fdc8A721e52", + }, + { + value: "DAI", + label: "DAI", + address: "0x049d68029688eAbF473097a2fC38ef61633A3C7A", + aggregatorAddress: "0xF64b636c5dFe1d3555A847341cDC449f612307d0", + }, + ], + "0x13881": [ + { + value: "MATIC", + label: "MATIC", + address: "0x0000000000000000000000000000000000000000", + aggregatorAddress: "0xd0D5e3DB44DE05E9F294BB0a3bEEaF030DE24Ada", + }, + { + value: "LINK", + label: "LINK", + address: "0x326C977E6efc84E512bB9C30f76E30c160eD06FB", + aggregatorAddress: "0x12162c3E810393dEC01362aBf156D7ecf6159528", + }, + ], + }; + const [token, setToken] = useState(currencies[chain_id][0]); + const changeToken = (event: SelectChangeEvent): void => { + setToken( + currencies[chain_id].filter( + (x: CurrencyData) => x.value === event.target.value + )[0] + ); }; const [amount, setAmount] = useState("0.1"); const changeAmount = ( @@ -55,53 +89,67 @@ const BuyContainer: FC = (props: props) => { ): void => { setAmount(event.target.value); }; - const [isCalculating, setIsCalculating] = useState(false); - const submitHandler = (event: FormEvent): void => { + const [price, setPrice] = useState("1"); + const submitHandler = async (event: FormEvent) => { event.preventDefault(); - fetch({ - params: { - abi: preSaleAbi, - functionName: "presaleTokens", - contractAddress: "0x446D0E6f6d473ef5Ac7DF1bac47a1740c540a1B3", - params: { - _paymentTokenAddress: tokens[selectedToken].contractAddress, - _amount: new BigNumber(amount).multipliedBy("1000000000000000").toString(), - }, - // msgValue: Moralis.Units.ETH(1), - }, - onComplete: () => { - setIsCalculating(false); - }, - onError: (result: any) => { - console.log(result); - }, - onSuccess: (result: any) => { - alert(true); - }, - }); + console.log(price, amount); + if (!isWeb3Enabled) { + await enableWeb3(); + } + setIsProcessing(true); + try { + const ethAddress = user?.get("ethAddress"); + if (token.address === "0x0000000000000000000000000000000000000000") { + const res = await toPresaleContract() + .methods.presaleTokens(token.address, Moralis.Units.ETH(amount)) + .send({ + from: ethAddress, + value: Moralis.Units.ETH(amount), + }); + + console.log(res); + } else { + const tokenContract = toTokenContract(token.address); + const approve = await tokenContract.methods + .allowance(ethAddress, PRESALE_CONTRACT_ADDRESS) + .call(); + console.log(approve < Moralis.Units.ETH(amount)); + if (approve < Moralis.Units.ETH(amount)) { + await tokenContract.methods + .approve(PRESALE_CONTRACT_ADDRESS, Moralis.Units.ETH(amount)) + .send({ from: ethAddress }); + } + const res = await toPresaleContract() + .methods.presaleTokens(token.address, Moralis.Units.ETH(amount)) + .send({ from: ethAddress }); + console.log(res); + } + } catch (err) { + console.log(err); + } finally { + setIsProcessing(false); + } }; + const [isCalculating, setIsCalculating] = useState(false); + useEffect(() => { - if (!isWeb3Enabled) { - enableWeb3(); - } if (isWeb3Enabled) { setIsCalculating(true); - fetch({ + console.log("getting"); + getPriceFunc.fetch({ params: { abi: chainlinkFeedAbi, functionName: "latestRoundData", - contractAddress: tokens[selectedToken].oracleAddress, + contractAddress: token.aggregatorAddress, }, onComplete: () => { setIsCalculating(false); }, - onError: (result: any) => { - console.log(result); - }, onSuccess: (result: any) => { const { answer } = result; + setPrice(answer.toString()); setAmount( String( _.ceil( @@ -115,14 +163,15 @@ const BuyContainer: FC = (props: props) => { ); }, }); - } else if (!isCalculating) { - setIsCalculating(true); + } else { + enableWeb3(); } // eslint-disable-next-line - }, [isAuthenticated, selectedToken]); + }, [isWeb3Enabled, token]); + return ( - + Presale Round 1 = (props: props) => { Price: 1 Alps = $0.000125 - + = (props: props) => { > = (props: props) => { }, }} /> - - + +