├── smart_contract ├── .example.env ├── .DS_Store ├── .gitignore ├── package.json ├── hardhat.config.js ├── test │ └── sample-test.js ├── contracts │ ├── Transactions.sol │ ├── TokenSale.sol │ ├── LotteryPool.sol │ ├── AceToken.sol │ ├── StakingPool.sol │ └── Lottery.sol └── scripts │ └── deploy.js ├── client ├── assets │ └── images │ │ ├── link.png │ │ ├── wifi.png │ │ ├── secure.png │ │ ├── wallet.png │ │ ├── cryptoace.png │ │ ├── diamond.png │ │ ├── tri.svg │ │ ├── logo.svg │ │ ├── lottery.svg │ │ ├── buytoken.svg │ │ └── sendEther.svg ├── postcss.config.js ├── src │ ├── utils │ │ ├── shortenAddress.js │ │ └── constants.js │ ├── Icons │ │ ├── index.js │ │ ├── ArrowIcon.jsx │ │ ├── EthIcon.jsx │ │ ├── Tri.jsx │ │ ├── LinkedinIcon.jsx │ │ ├── TwitterIcon.jsx │ │ └── GithubIcon.jsx │ ├── pages │ │ ├── Home.jsx │ │ ├── Lottery.jsx │ │ ├── BuyToken.jsx │ │ ├── SendEther.jsx │ │ └── LotteryPool.jsx │ ├── main.jsx │ ├── components │ │ ├── index.js │ │ ├── NotFound.jsx │ │ ├── Loader.jsx │ │ ├── Services.jsx │ │ ├── Welcome.jsx │ │ ├── Navbar │ │ │ ├── MenuItem.jsx │ │ │ └── Navbar.jsx │ │ ├── Footer.jsx │ │ ├── Notification.jsx │ │ ├── GetStarted.jsx │ │ └── Transactions.jsx │ ├── context │ │ ├── enums.js │ │ ├── reducers.js │ │ └── ContractsContext.jsx │ ├── App.jsx │ └── index.css ├── vite.config.js ├── .gitignore ├── .example.env ├── package.json ├── index.html └── tailwind.config.js ├── .gitignore ├── README.md └── LICENSE /smart_contract/.example.env: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY= Private key of your metamask account. -------------------------------------------------------------------------------- /smart_contract/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samrath49/Cryptoace/HEAD/smart_contract/.DS_Store -------------------------------------------------------------------------------- /client/assets/images/link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samrath49/Cryptoace/HEAD/client/assets/images/link.png -------------------------------------------------------------------------------- /client/assets/images/wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samrath49/Cryptoace/HEAD/client/assets/images/wifi.png -------------------------------------------------------------------------------- /client/assets/images/secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samrath49/Cryptoace/HEAD/client/assets/images/secure.png -------------------------------------------------------------------------------- /client/assets/images/wallet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samrath49/Cryptoace/HEAD/client/assets/images/wallet.png -------------------------------------------------------------------------------- /client/assets/images/cryptoace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samrath49/Cryptoace/HEAD/client/assets/images/cryptoace.png -------------------------------------------------------------------------------- /client/assets/images/diamond.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samrath49/Cryptoace/HEAD/client/assets/images/diamond.png -------------------------------------------------------------------------------- /client/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /client/src/utils/shortenAddress.js: -------------------------------------------------------------------------------- 1 | export const shortenAddress = (address) => `${address.slice(0, 5)}...${address.slice(address.length - 4)}`; 2 | -------------------------------------------------------------------------------- /smart_contract/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | 7 | #Hardhat files 8 | cache 9 | artifacts 10 | -------------------------------------------------------------------------------- /client/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import react from "@vitejs/plugin-react"; 3 | 4 | export default defineConfig({ 5 | plugins: [react()], 6 | }); 7 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | node_modules 9 | dist 10 | *.local 11 | .env 12 | 13 | # Editor directories and files 14 | .vscode/* 15 | !.vscode/extensions.json 16 | .idea 17 | .DS_Store 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /client/src/Icons/index.js: -------------------------------------------------------------------------------- 1 | export { default as Eth } from "./EthIcon.jsx"; 2 | export { default as Twitter } from "./TwitterIcon"; 3 | export { default as Github } from "./GithubIcon.jsx"; 4 | export { default as LinkedIn } from "./LinkedinIcon"; 5 | export { default as Arrow } from "./ArrowIcon.jsx"; 6 | export { default as Tri } from "./Tri.jsx"; 7 | -------------------------------------------------------------------------------- /client/src/pages/Home.jsx: -------------------------------------------------------------------------------- 1 | import { Welcome, GetStarted, Services, Transactions } from "../components"; 2 | 3 | const Home = () => { 4 | return ( 5 |
6 | 7 | 8 | 9 | 10 |
11 | ); 12 | }; 13 | 14 | export default Home; 15 | -------------------------------------------------------------------------------- /client/.example.env: -------------------------------------------------------------------------------- 1 | // Run the smart contracts and then paste your contract addresses here 2 | 3 | VITE_TRANSACTION_CONTRACT=0x0000000000000000000000000000000000000000 4 | 5 | VITE_ACE_TOKEN_CONTRACT=0x0000000000000000000000000000000000000000 6 | 7 | VITE_TOKEN_SALE_CONTRACT=0x0000000000000000000000000000000000000000 8 | 9 | VITE_LOTTERY_CONTRACT=0x0000000000000000000000000000000000000000 10 | -------------------------------------------------------------------------------- /client/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | import { BrowserRouter } from "react-router-dom"; 6 | import { ContractsProvider } from "./context/ContractsContext"; 7 | 8 | ReactDOM.render( 9 | 10 | 11 | 12 | 13 | , 14 | document.getElementById("root") 15 | ); 16 | -------------------------------------------------------------------------------- /client/src/components/index.js: -------------------------------------------------------------------------------- 1 | export { default as Loader } from "./Loader"; 2 | export { default as Navbar } from "./Navbar/Navbar"; 3 | export { default as Welcome } from "./Welcome"; 4 | export { default as Footer } from "./Footer"; 5 | export { default as Services } from "./Services"; 6 | export { default as Transactions } from "./Transactions"; 7 | export { default as GetStarted } from "./GetStarted"; 8 | export { default as NotFound } from "./NotFound"; 9 | export { default as Notification } from "./Notification"; -------------------------------------------------------------------------------- /client/assets/images/tri.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /smart_contract/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test3", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@nomiclabs/hardhat-ethers": "^2.0.3", 14 | "@nomiclabs/hardhat-waffle": "^2.0.1", 15 | "chai": "^4.3.4", 16 | "ethereum-waffle": "^3.4.0", 17 | "ethers": "^5.5.2", 18 | "hardhat": "^2.8.0" 19 | }, 20 | "dependencies": { 21 | "dotenv": "^14.2.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /smart_contract/hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("@nomiclabs/hardhat-waffle"); 2 | 3 | require("dotenv").config(); 4 | 5 | module.exports = { 6 | solidity: "0.8.0", 7 | settings: { 8 | optimizer: { 9 | enabled: true, 10 | runs: 1000, 11 | }, 12 | }, 13 | networks: { 14 | ropsten: { 15 | url: "https://eth-ropsten.alchemyapi.io/v2/Jf5-PQUvqzsci3xk-WwXwHPk-z85g2yV", 16 | accounts: [process.env.PRIVATE_KEY], 17 | }, 18 | }, 19 | paths: { 20 | sources: "./contracts", 21 | tests: "./test", 22 | cache: "./cache", 23 | artifacts: "../client/src/artifacts", 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /client/src/Icons/ArrowIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const ArrowIcon = () => { 4 | return ( 5 |
6 | 12 | 17 | 18 |
19 | ); 20 | }; 21 | 22 | export default ArrowIcon; 23 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cryptace", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build && cp .env dist", 8 | "preview": "vite preview" 9 | }, 10 | "dependencies": { 11 | "dotenv": "^16.0.0", 12 | "ethers": "^5.6.2", 13 | "react": "^17.0.2", 14 | "react-dom": "^17.0.2", 15 | "react-router": "^6.2.2", 16 | "react-router-dom": "^6.2.2" 17 | }, 18 | "devDependencies": { 19 | "@vitejs/plugin-react": "^1.0.7", 20 | "autoprefixer": "^10.4.4", 21 | "postcss": "^8.4.12", 22 | "tailwindcss": "^3.0.23", 23 | "vite": "^2.8.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /client/src/Icons/EthIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const EthIcon = () => { 4 | return ( 5 | <> 6 | 7 | 8 | ); 9 | }; 10 | 11 | export default EthIcon; 12 | -------------------------------------------------------------------------------- /client/src/Icons/Tri.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Tri = () => { 4 | return ( 5 | 6 | 11 | 12 | ); 13 | }; 14 | 15 | export default Tri; 16 | -------------------------------------------------------------------------------- /smart_contract/test/sample-test.js: -------------------------------------------------------------------------------- 1 | const { expect } = require("chai"); 2 | const { ethers } = require("hardhat"); 3 | 4 | describe("Greeter", function () { 5 | it("Should return the new greeting once it's changed", async function () { 6 | const Greeter = await ethers.getContractFactory("Greeter"); 7 | const greeter = await Greeter.deploy("Hello, world!"); 8 | await greeter.deployed(); 9 | 10 | expect(await greeter.greet()).to.equal("Hello, world!"); 11 | 12 | const setGreetingTx = await greeter.setGreeting("Hola, mundo!"); 13 | 14 | // wait until the transaction is mined 15 | await setGreetingTx.wait(); 16 | 17 | expect(await greeter.greet()).to.equal("Hola, mundo!"); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /client/src/Icons/LinkedinIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const LinkedinIcon = () => { 4 | return ( 5 |
6 | 13 | 14 | 15 |
16 | ); 17 | }; 18 | 19 | export default LinkedinIcon; 20 | -------------------------------------------------------------------------------- /client/src/Icons/TwitterIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const TwitterIcon = () => { 4 | return ( 5 |
6 | 7 | 8 | 9 |
10 | ); 11 | }; 12 | 13 | export default TwitterIcon; 14 | -------------------------------------------------------------------------------- /client/assets/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Cryptoace 12 | 13 | 14 |
15 |
16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /smart_contract/contracts/Transactions.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GDP-X 2 | pragma solidity ^0.8.0; 3 | 4 | import "hardhat/console.sol"; 5 | 6 | contract Transactions { 7 | uint256 public transactionCount; 8 | event Transfer(address from, address receiver, uint amount, string message, uint256 timestamp); 9 | 10 | struct TransferStruct { 11 | address sender; 12 | address payable receiver; 13 | uint amount; 14 | string message; 15 | uint256 timestamp; 16 | } 17 | 18 | TransferStruct[] public transactions; 19 | 20 | function addTransaction(address payable receiver, uint amount, string memory message) public { 21 | transactionCount += 1; 22 | transactions.push(TransferStruct(msg.sender, receiver, amount, message, block.timestamp)); 23 | 24 | emit Transfer(msg.sender, receiver, amount, message, block.timestamp); 25 | } 26 | 27 | function getTransactions() public view returns(TransferStruct[] memory) { 28 | return transactions; 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /client/src/context/enums.js: -------------------------------------------------------------------------------- 1 | const contractEnum = { 2 | TRANSACTION_CONTRACT_INIT: "TRANSACTION_CONTRACT_INIT", 3 | TRANSACTIONS: "TRANSACTIONS", 4 | TRANSACTION_COUNT: "TRANSACTION_COUNT", 5 | TOKEN_CONTRACT_INIT: "TOKEN_CONTRACT_INIT", 6 | TOKEN_PRICE: "TOKEN_PRICE", 7 | SALE_CONTRACT_INIT: "SALE_CONTRACT_INIT", 8 | LOTTERY_INIT: "LOTTERY_INIT", 9 | LOTTERY_POOL_CONTRACT_INIT: "LOTTERY_POOL_CONTRACT_INIT", 10 | LOTTERY_TIME_REMAINING: "LOTTERY_TIME_REMAINING", 11 | LOTTERY_MANAGER: "LOTTERY_MANAGER", 12 | LOTTERY_ENTRY_FEE: "LOTTERY_ENTRY_FEE", 13 | LOTTERY_PLAYERS: "LOTTERY_PLAYERS", 14 | LOTTERY_WINNER: "LOTTERY_WINNER", 15 | LOTTERY_PRICE: "LOTTERY_PRICE", 16 | LOTTERIES_DETAILS: "LOTTERIES_DETAILS" 17 | }; 18 | 19 | const web3Enum = { 20 | PROVIDER: "PROVIDER", 21 | }; 22 | 23 | const tokenEnum = { 24 | PRICE: "PRICE", 25 | BALANCE: "BALANCE", 26 | SOLD: "SOLD", 27 | }; 28 | 29 | const userEnum = { 30 | BALANCE: "BALANCE", 31 | CURR_ACCOUNT: "CURR_ACCOUNT", 32 | }; 33 | 34 | export { contractEnum, web3Enum, tokenEnum, userEnum }; 35 | -------------------------------------------------------------------------------- /client/src/Icons/GithubIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const GithubIcon = () => { 4 | return ( 5 |
6 | 13 | 14 | 15 |
16 | ); 17 | }; 18 | 19 | export default GithubIcon; 20 | -------------------------------------------------------------------------------- /client/src/utils/constants.js: -------------------------------------------------------------------------------- 1 | import { abi as transactionABI } from "../artifacts/contracts/Transactions.sol/Transactions.json"; 2 | import { abi as tokenSaleABI } from "../artifacts/contracts/TokenSale.sol/TokenSale.json"; 3 | import { abi as aceTokenABI } from "../artifacts/contracts/AceToken.sol/AceToken.json"; 4 | import { abi as lotteryPoolABI } from "../artifacts/contracts/LotteryPool.sol/LotteryPool.json"; 5 | import { abi as lotteryABI } from "../artifacts/contracts/Lottery.sol/Lottery.json"; 6 | 7 | // ADD YOUR OWN CONTRACT ADDRESSES IN ".env" FILE 8 | 9 | export const transactionContractAddress = import.meta.env 10 | .VITE_TRANSACTION_CONTRACT; 11 | export const transactionContractABI = transactionABI; 12 | 13 | export const aceTokenContractAddress = import.meta.env.VITE_ACE_TOKEN_CONTRACT; 14 | export const aceTokenContractABI = aceTokenABI; 15 | 16 | export const tokenSaleContractAddress = import.meta.env 17 | .VITE_TOKEN_SALE_CONTRACT; 18 | export const tokenSaleContractABI = tokenSaleABI; 19 | 20 | export const lotteryPoolContractAddress = import.meta.env.VITE_LOTTERY_CONTRACT; 21 | export const lotteryPoolContractABI = lotteryPoolABI; 22 | 23 | export const lotteryContractABI = lotteryABI; 24 | -------------------------------------------------------------------------------- /client/src/components/NotFound.jsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | 3 | function NotFound() { 4 | return ( 5 |
6 |
7 |
8 |

9 | 404 10 |

11 | 12 |
13 |
14 | Oops! Page not found 15 |
16 | 17 |

18 | The page you’re looking for doesn’t exist. 19 |

20 |
21 | 25 | Go Home 26 | 27 |
28 |
29 |
30 | ); 31 | } 32 | 33 | export default NotFound; 34 | -------------------------------------------------------------------------------- /smart_contract/contracts/TokenSale.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./AceToken.sol"; 6 | 7 | contract TokenSale { 8 | address payable admin; 9 | AceToken public tokenContract; 10 | uint256 public tokenPrice; 11 | uint256 public tokenSold; 12 | 13 | event Sell(address _buyer, uint256 _amount); 14 | 15 | modifier isAdmin() { 16 | require(msg.sender == admin, "You are not the owner"); 17 | _; 18 | } 19 | 20 | constructor(AceToken _contract, uint256 _tokenPrice) { 21 | admin = payable(msg.sender); 22 | tokenContract = _contract; 23 | tokenPrice = _tokenPrice; 24 | } 25 | 26 | function buyTokens(uint256 _numberOfTokens) public payable { 27 | require(msg.value >= _numberOfTokens * tokenPrice, "Price is less"); 28 | require( 29 | tokenContract.balanceOf(address(tokenContract)) >= _numberOfTokens, 30 | "Available tokens are less" 31 | ); 32 | require( 33 | tokenContract.transfer(msg.sender, _numberOfTokens), 34 | "Transfering is failed" 35 | ); 36 | 37 | tokenSold += _numberOfTokens; 38 | 39 | Sell(msg.sender, _numberOfTokens); 40 | } 41 | 42 | function endSale() public isAdmin { 43 | // get balance of this Contract 44 | uint256 balance = tokenContract.balanceOf(address(tokenContract)); 45 | require( 46 | tokenContract.transfer(admin, balance), 47 | "Transfering is failed" 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /smart_contract/scripts/deploy.js: -------------------------------------------------------------------------------- 1 | const main = async () => { 2 | // Transactions 3 | const transactionsFactory = await hre.ethers.getContractFactory( 4 | "Transactions" 5 | ); 6 | const transactionsContract = await transactionsFactory.deploy(); 7 | 8 | await transactionsContract.deployed(); 9 | console.log("Transactions address: ", transactionsContract.address); 10 | 11 | const tokenPrice = 1000000000000; 12 | 13 | const aceTokenFactory = await hre.ethers.getContractFactory("AceToken"); 14 | const aceTokenContract = await aceTokenFactory.deploy(1000000); 15 | const tokenSaleFactory = await hre.ethers.getContractFactory("TokenSale"); 16 | 17 | const tokenSaleContract = await tokenSaleFactory.deploy( 18 | aceTokenContract.address, 19 | tokenPrice 20 | ); 21 | 22 | await aceTokenContract.deployed(); 23 | await tokenSaleContract.deployed(); 24 | console.log("aceTokenContract address: ", aceTokenContract.address); 25 | console.log("tokenSaleContract address: ", tokenSaleContract.address); 26 | 27 | // Lottery 28 | const lotteryPoolFactory = await hre.ethers.getContractFactory("LotteryPool"); 29 | const lotteryPoolContract = await lotteryPoolFactory.deploy(); 30 | 31 | await lotteryPoolContract.deployed(); 32 | 33 | console.log("LotteryPoolContract address: ", lotteryPoolContract.address); 34 | }; 35 | 36 | const runMain = async () => { 37 | try { 38 | await main(); 39 | process.exit(0); 40 | } catch (error) { 41 | console.error(error); 42 | process.exit(1); 43 | } 44 | }; 45 | 46 | runMain(); 47 | 48 | // npx hardhat run scripts/deploy.js --network ropsten 49 | -------------------------------------------------------------------------------- /client/src/components/Loader.jsx: -------------------------------------------------------------------------------- 1 | const Loader = ({ full }) => { 2 | if (full) { 3 | return ( 4 | <> 5 |
6 |
7 |
8 | 9 | ); 10 | } 11 | return ( 12 | <> 13 | 20 | 24 | 28 | 29 | 30 | ); 31 | }; 32 | 33 | export default Loader; 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /client/src/App.jsx: -------------------------------------------------------------------------------- 1 | import React, { Suspense } from "react"; 2 | import { Route, Routes } from "react-router"; 3 | import { Navbar, Footer, NotFound, Loader } from "./components"; 4 | 5 | const Home = React.lazy(() => import("./pages/Home")); 6 | const SendEther = React.lazy(() => import("./pages/SendEther")); 7 | const Lottery = React.lazy(() => import("./pages/Lottery")); 8 | const LotteryPool = React.lazy(() => import("./pages/LotteryPool")); 9 | const BuyToken = React.lazy(() => import("./pages/BuyToken")); 10 | 11 | const App = () => ( 12 |
13 | 14 | 15 | }> 19 | 20 | 21 | } 22 | /> 23 | }> 27 | 28 | 29 | } 30 | /> 31 | }> 35 | 36 | 37 | } 38 | /> 39 | }> 43 | 44 | 45 | } 46 | /> 47 | }> 51 | 52 | 53 | } 54 | /> 55 | }> 59 | 60 | 61 | } 62 | /> 63 | }> 67 | 68 | 69 | } 70 | /> 71 | 72 |
74 | ); 75 | 76 | export default App; 77 | -------------------------------------------------------------------------------- /smart_contract/contracts/LotteryPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./Lottery.sol"; 5 | 6 | contract LotteryPool { 7 | struct lotteryStruct { 8 | Lottery lotteryContract; 9 | address manager; 10 | uint256 endedTimeStamp; 11 | } 12 | 13 | // map lottery address to lottery info 14 | mapping(address => lotteryStruct) public lotteriesMapping; 15 | 16 | uint256 public totalLotteries = 0; 17 | 18 | event LotteryCreated(address lotteryAddress); 19 | 20 | address[] public lotteriesContractsAddresses; 21 | 22 | address public manager; 23 | 24 | constructor() { 25 | manager = msg.sender; 26 | } 27 | 28 | modifier isOwner() { 29 | require(manager == msg.sender, "action requires Owner/manager"); 30 | _; 31 | } 32 | 33 | function createLottery(uint256 _timeInMinutes) public { 34 | // create lottery instance & send the sender's address 35 | Lottery localLottery = new Lottery(msg.sender); 36 | 37 | // start the lottery 38 | localLottery.start(_timeInMinutes); 39 | 40 | // save the lottery in lotteries 41 | lotteriesMapping[address(localLottery)] = lotteryStruct( 42 | localLottery, 43 | msg.sender, 44 | block.timestamp + (_timeInMinutes * 60) 45 | ); 46 | 47 | // increase lottery count. 48 | totalLotteries += 1; 49 | 50 | emit LotteryCreated(address(localLottery)); 51 | 52 | // save lottery address 53 | lotteriesContractsAddresses.push(address(localLottery)); 54 | } 55 | 56 | // will return all lotteries 57 | function getLotteryContractDetails() 58 | public 59 | view 60 | returns (lotteryStruct[] memory) 61 | { 62 | lotteryStruct[] memory ret = new lotteryStruct[](totalLotteries); 63 | 64 | for (uint256 i = 0; i < totalLotteries; i++) { 65 | ret[i] = lotteriesMapping[lotteriesContractsAddresses[i]]; 66 | } 67 | 68 | return ret; 69 | } 70 | 71 | // get lotteries 72 | function getLotteries() public view returns (address[] memory) { 73 | return lotteriesContractsAddresses; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /smart_contract/contracts/AceToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | contract AceToken { 5 | uint256 public totalSupply; 6 | string public name = "AceToken"; 7 | string public symbol = "ACE"; 8 | string public standard = "Ace Token v1.0"; 9 | uint256 public decimals = 18; 10 | 11 | // events 12 | event Transfer(address indexed _from, address indexed _to, uint256 _value); 13 | event Approval( 14 | address indexed _owner, 15 | address indexed _spender, 16 | uint256 _value 17 | ); 18 | 19 | // mappings 20 | mapping(address => uint256) public balanceOf; 21 | mapping(address => mapping(address => uint256)) public allowance; 22 | 23 | constructor(uint256 _initialSupply) { 24 | // set total supply 25 | totalSupply = _initialSupply; 26 | // owner will have all supply at first 27 | balanceOf[address(this)] = _initialSupply; 28 | } 29 | 30 | function transfer(address _to, uint256 _value) 31 | public 32 | returns (bool success) 33 | { 34 | require( 35 | balanceOf[address(this)] >= _value, 36 | "You do not have sufficient funds" 37 | ); 38 | balanceOf[address(this)] -= _value; 39 | balanceOf[_to] += _value; 40 | emit Transfer(address(this), _to, _value); 41 | return true; 42 | } 43 | 44 | function approve(address _spender, uint256 _value) 45 | public 46 | returns (bool success) 47 | { 48 | // allow account to how much value is approved 49 | allowance[msg.sender][_spender] = _value; 50 | emit Approval(msg.sender, _spender, _value); 51 | return true; 52 | } 53 | 54 | function transferFrom( 55 | address _from, 56 | address _to, 57 | uint256 _value 58 | ) public returns (bool success) { 59 | require(_value <= balanceOf[_from], "Value is less in @token"); 60 | require( 61 | _value <= allowance[_from][msg.sender], 62 | "Allowance value is less in @token" 63 | ); 64 | 65 | balanceOf[_from] -= _value; 66 | balanceOf[_to] += _value; 67 | 68 | allowance[_from][msg.sender] -= _value; 69 | 70 | emit Transfer(_from, _to, _value); 71 | return true; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /smart_contract/contracts/StakingPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | interface IDepositContract { 5 | function deposit( 6 | bytes calldata pubkey, 7 | bytes calldata withdrawal_credentials, 8 | bytes calldata signature, 9 | bytes32 deposit_data_root 10 | ) external payable; 11 | } 12 | 13 | contract StakingPool { 14 | mapping(address => uint) public balances; 15 | mapping(bytes => bool) public pubkeysUsed; 16 | IDepositContract public depositContract = IDepositContract(0x00000000219ab540356cBB839Cbe05303d7705Fa); 17 | address public admin; 18 | uint public end; 19 | bool public finalized; 20 | uint public totalInvested; 21 | uint public totalChange; 22 | mapping(address => bool) public changeClaimed; 23 | 24 | event NewInvestor ( 25 | address investor 26 | ); 27 | 28 | constructor() { 29 | admin = msg.sender; 30 | end = block.timestamp + 7 days; 31 | } 32 | 33 | function invest() external payable { 34 | require(block.timestamp < end, 'too late'); 35 | if(balances[msg.sender] == 0) { 36 | emit NewInvestor(msg.sender); 37 | } 38 | balances[msg.sender] += msg.value; 39 | } 40 | 41 | function finalize() external { 42 | require(block.timestamp >= end, 'too early'); 43 | require(finalized == false, 'already finalized'); 44 | finalized = true; 45 | totalInvested = address(this).balance; 46 | totalChange = address(this).balance % 32 ether; 47 | } 48 | 49 | function getChange() external { 50 | require(finalized == true, 'not finalized'); 51 | require(balances[msg.sender] > 0, 'not an investor'); 52 | require(changeClaimed[msg.sender] == false, 'change already claimed'); 53 | changeClaimed[msg.sender] = true; 54 | uint amount = totalChange * balances[msg.sender] / totalInvested; 55 | payable(msg.sender).transfer(amount); 56 | } 57 | 58 | function deposit( 59 | bytes calldata pubkey, 60 | bytes calldata withdrawal_credentials, 61 | bytes calldata signature, 62 | bytes32 deposit_data_root 63 | ) 64 | external 65 | { 66 | require(finalized == true, 'too early'); 67 | require(msg.sender == admin, 'only admin'); 68 | require(address(this).balance >= 32 ether); 69 | require(pubkeysUsed[pubkey] == false, 'this pubkey was already used'); 70 | depositContract.deposit{value: 32 ether}( 71 | pubkey, 72 | withdrawal_credentials, 73 | signature, 74 | deposit_data_root 75 | ); 76 | } 77 | } -------------------------------------------------------------------------------- /client/src/components/Services.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from "react"; 2 | import { Link } from "react-router-dom"; 3 | 4 | function Services() { 5 | const cardData = [ 6 | { 7 | title: "Buy Ace Token", 8 | img: "bg-buytoken", 9 | link: "/buy-token", 10 | description: 11 | "A safe secure crypto token offered from Cryptoace for your own use. Buy a token using ropsten ethereum.", 12 | }, 13 | { 14 | title: "Play Lottery Game", 15 | img: "bg-lottery", 16 | link: "/lottery", 17 | description: 18 | "Play a game of crypto lottery to get a chance of winning ethereum. Create your own lottery and play with friends.", 19 | }, 20 | { 21 | title: "Send Ether", 22 | img: "bg-sendEther", 23 | link: "/send-ether", 24 | description: 25 | "Make ethereum transactions across the world. A safe, secure and easy way to help you send ethereum to anyone.", 26 | }, 27 | ]; 28 | 29 | return ( 30 |
31 |
32 |

33 | Crypto{" "} 34 | Services. 35 |

36 |
37 |
38 | {cardData.map((card, index) => ( 39 | 40 |
43 |

44 | {card.title} 45 |

46 |

{card.description}

47 | 52 | 53 | 54 |
55 |
56 | ))} 57 |
58 |
59 |
60 |
61 |
62 |
63 | ); 64 | } 65 | 66 | export default Services; -------------------------------------------------------------------------------- /client/src/components/Welcome.jsx: -------------------------------------------------------------------------------- 1 | import { Tri } from "../Icons"; 2 | import Diamond from "../../assets/images/diamond.png"; 3 | 4 | const Welcome = () => { 5 | const scrollTo = () => { 6 | const getStarted = document.getElementById("getStarted"); 7 | getStarted.scrollIntoView({ behavior: "smooth", block: "end" }); 8 | }; 9 | 10 | function parallax(event) { 11 | document.querySelectorAll(".plx").forEach((shift) => { 12 | const position = shift.getAttribute("value"); 13 | const x = (window.innerWidth - event.pageX * position) / 90; 14 | const y = (window.innerHeight - event.pageY * position) / 90; 15 | shift.style.transform = `translateX(${x}px) translateY(${y}px)`; 16 | shift.style.transition = `transform 0.25s`; 17 | }); 18 | } 19 | 20 | return ( 21 | <> 22 |
23 |
24 |
25 |

26 | Enter the world of internet economies. 27 |

28 | 29 |

30 | Send cryptos across the world and track your every transaction 31 | with cryptoace. 32 |

33 |
34 | 41 |
42 |
46 | 47 |
48 | 49 |
50 | 51 |
52 | 53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | 61 | ); 62 | }; 63 | 64 | export default Welcome; 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

logoCryptoace

3 |

A web3 etherium based application

4 | 5 | [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)   6 | GitHub stars   7 | 8 | Netlify Build 9 | 10 | View Live 11 |

A simple, convenient & efficient way to send cryptos across the world and track your every transaction on cryptoace


12 |

13 | 14 | ## Features 15 | 16 | - 🔔 **Notifications** : Notifications popup for every event 17 | - 🔥 **Responsive Design** : Design also suited for small and medium devices. 18 | - 🤏 **Optimized Performance** : Performance optimized using [lighthouse](https://developers.google.com/web/tools/lighthouse). 19 | 20 | ## Built With 21 | 22 | `FRONTEND` 23 | - ReactJS 24 | - TailwindCSS 25 | - react-router 26 | - Ethers 27 | 28 | `BACKEND` 29 | - Hardhat 30 | - Ethers 31 | - Chai 32 | 33 | 34 | 35 | ## Getting Started 36 | 37 | Follow these steps to setup this project locally. 38 | 39 | ### Installation 40 | 41 | _Below are the instructions to setup this project and get started with._ 42 | 43 | 1. Clone the repo 44 | ```sh 45 | git clone https://github.com/Samrath49/Cryptoace.git 46 | ``` 47 | 2. Install NPM packages for `client` and `smart_contracts` folder 48 | ```sh 49 | npm install 50 | ``` 51 | 3. Generate an API url for contracts and add your url to `hardhat.config.js` file using [Alchemy.io](https://www.alchemy.com/) 52 | ```js 53 | // hardhat.config.js file in smart_contracts 54 | ropsten: { 55 | url: {/* Your own url of contracts */}, 56 | }, 57 | ``` 58 | 4. Add your metamask account's private key in `.env` file of smart_contract dir 59 | ```sh 60 | PRIVATE_KEY=Metamask account private key 61 | ``` 62 | 5. Compile the smart_contracts using 63 | ```sh 64 | npx hardhat run scripts/deploy.js --network ropsten 65 | ``` 66 | This will compile contracts and provide the addresses of deployed contracts. 67 | 6. Create `.env` file in `client` folder and enter the contract addresses as shown below. 68 | ```sh 69 | // add your addresses to .env 70 | VITE_TRANSACTION_CONTRACT= 71 | VITE_ACE_TOKEN_CONTRACT= 72 | VITE_TOKEN_SALE_CONTRACT= 73 | VITE_LOTTERY_CONTRACT= 74 | ``` 75 | 76 | 7. Run the application by running following command in client folder 77 | ```sh 78 | npm run dev 79 | ``` 80 | 81 | ## Acknowledgments 82 | 83 | A few open-source resources that helped in the development of this project. 84 | 85 | * [Rad Lines](https://msurguy.github.io/rad-lines/) 86 | * [Remix Etherium](https://remix.ethereum.org/) 87 | * [Shapefest](https://www.shapefest.com/) 88 | * [3dIcons](https://3dicons.co/) 89 | 90 | :star: Like the project? Star this repo — It motivates a lot! -------------------------------------------------------------------------------- /client/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"], 3 | mode: "JIT", 4 | darkMode: "class", 5 | content: ["./src/**/*.{js,jsx,ts,tsx}"], 6 | theme: { 7 | extend: { 8 | backgroundImage: { 9 | buytoken: "url('./assets/images/buytoken.svg')", 10 | lottery: "url('./assets/images/lottery.svg')", 11 | sendEther: "url('./assets/images/sendEther.svg')", 12 | eth: "url('./assets/images/eth.svg')", 13 | tri: "url('./assets/images/tri.svg')", 14 | }, 15 | boxShadow: { 16 | "3xl": "0 35px 60px -15px rgba(0, 0, 0, 0.3)", 17 | }, 18 | colors: { 19 | // Theme Colors 20 | mainBg: "#1A1A1A", 21 | btnBorder: "#963DFF", 22 | btnHover: "#712dbe", 23 | btnText: "#bbc4cf", 24 | 25 | // Card specific colors 26 | slateBg: "#202231", 27 | textBg: "#bfbfbf", 28 | borderBg: "#3a4361", 29 | }, 30 | fontFamily: { 31 | raj: ["Rajdhani", "sans-serif"], 32 | rubik: ["Rubik"], 33 | }, 34 | screens: { 35 | mf: "990px", 36 | }, 37 | keyframes: { 38 | "logo-in": { 39 | "0%": { 40 | "-webkit-transform": "translateX(-30%)", 41 | transform: "translateX(-30%)", 42 | }, 43 | "100%": { 44 | "-webkit-transform": "translateX(0%)", 45 | transform: "translateX(0%)", 46 | }, 47 | }, 48 | blob: { 49 | "0%": { 50 | transform: "translate(0px, 0px) scale(1)", 51 | }, 52 | "33%": { 53 | transform: "translate(30px, -50px) scale(1.1)", 54 | }, 55 | "66%": { 56 | transform: "translate(-20px, 20px) scale(0.9)", 57 | }, 58 | "100%": { 59 | transform: "tranlate(0px, 0px) scale(1)", 60 | }, 61 | }, 62 | wiggle: { 63 | "0%, 100%": { 64 | transform: "rotate(-3deg)", 65 | }, 66 | "50%": { 67 | transform: "rotate(3deg)", 68 | }, 69 | }, 70 | "fade-in-down": { 71 | "0%": { 72 | opacity: "0", 73 | transform: "translateY(-10px)", 74 | }, 75 | "100%": { 76 | opacity: "1", 77 | transform: "translateY(0)", 78 | }, 79 | }, 80 | "fade-out-down": { 81 | from: { 82 | opacity: "1", 83 | transform: "translateY(0px)", 84 | }, 85 | to: { 86 | opacity: "0", 87 | transform: "translateY(10px)", 88 | }, 89 | }, 90 | "fade-in-up": { 91 | "0%": { 92 | opacity: "0", 93 | transform: "translateY(10px)", 94 | }, 95 | "100%": { 96 | opacity: "1", 97 | transform: "translateY(0)", 98 | }, 99 | }, 100 | "fade-out-up": { 101 | from: { 102 | opacity: "1", 103 | transform: "translateY(0px)", 104 | }, 105 | to: { 106 | opacity: "0", 107 | transform: "translateY(10px)", 108 | }, 109 | }, 110 | }, 111 | animation: { 112 | "logo-in": "logo-in 0.5s ease-out", 113 | blob: "blob 7s infinite", 114 | wiggle: "wiggle 1s ease-in-out infinite", 115 | "fade-in-down": "fade-in-down 0.5s ease-out", 116 | "fade-out-down": "fade-out-down 0.5s ease-out", 117 | "fade-in-up": "fade-in-up 0.5s ease-out", 118 | "fade-out-up": "fade-out-up 0.5s ease-out", 119 | }, 120 | }, 121 | }, 122 | plugins: [], 123 | }; 124 | -------------------------------------------------------------------------------- /smart_contract/contracts/Lottery.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | contract Lottery { 6 | address public manager; 7 | address[] public players; 8 | uint256 public entryFee = 0.1 ether; 9 | 10 | address winner; 11 | 12 | uint256 public _end; 13 | 14 | uint256 public time = block.timestamp; 15 | 16 | // enums 17 | enum LotteryStatus { 18 | START, 19 | STARTED, 20 | ENDED 21 | } 22 | 23 | // events 24 | event WinnerDeclared(address winner, uint256 winningPrice); 25 | 26 | LotteryStatus public status = LotteryStatus.START; 27 | 28 | constructor(address _manager) { 29 | manager = _manager; 30 | } 31 | 32 | // get all players 33 | function getPlayers() public view returns (address[] memory) { 34 | return players; 35 | } 36 | 37 | // start the lottery 38 | function start(uint256 _timeInMinutes) public { 39 | require( 40 | status == LotteryStatus.START, 41 | "lottery has already been started or ended." 42 | ); 43 | 44 | status = LotteryStatus.STARTED; 45 | 46 | // time for lottery 47 | _end = block.timestamp + (_timeInMinutes * 60); 48 | } 49 | 50 | // enter the lottery 51 | function enter() public payable { 52 | require(_end >= uint256(block.timestamp), "time is up."); 53 | require(!isParticipate(msg.sender), "you are already a participant"); 54 | require(msg.value >= entryFee, "entry fee is less then 0.1 ether"); 55 | require( 56 | status == LotteryStatus.STARTED, 57 | "lottery has not started or its ended." 58 | ); 59 | 60 | players.push(msg.sender); 61 | } 62 | 63 | function isParticipate(address _participant) private view returns (bool) { 64 | for (uint256 i = 0; i < players.length; i++) { 65 | if (players[i] == _participant) { 66 | return true; 67 | } 68 | } 69 | return false; 70 | } 71 | 72 | // get random 73 | function random() private view returns (uint256) { 74 | return 75 | uint256( 76 | keccak256( 77 | abi.encodePacked(block.difficulty, block.timestamp, players) 78 | ) 79 | ); 80 | } 81 | 82 | function end() public { 83 | require( 84 | block.timestamp >= _end, 85 | "you can not end lottery before time." 86 | ); 87 | status = LotteryStatus.ENDED; 88 | 89 | require(players.length > 0, "0 participants"); 90 | uint256 winnerIndex = random() % players.length; 91 | winner = players[winnerIndex]; 92 | uint256 priceMoney = winningPrice(); 93 | 94 | // transfer everything to winner; 95 | payable(winner).transfer(address(this).balance); 96 | 97 | // reset players. 98 | players = new address[](0); 99 | 100 | // winner declared event; 101 | emit WinnerDeclared(winner, priceMoney); 102 | } 103 | 104 | function getRemainingTime() public returns (uint256) { 105 | if (_end <= uint256(block.timestamp)) { 106 | end(); 107 | return 0; 108 | } else { 109 | // require(_end >= block.timestamp, "time is already up"); 110 | require( 111 | !(status == LotteryStatus.ENDED), 112 | "lottery is not started or its ended." 113 | ); 114 | 115 | return _end - block.timestamp; 116 | } 117 | } 118 | 119 | function getWinner() public view returns (address) { 120 | return winner; 121 | } 122 | 123 | // get winning price 124 | function winningPrice() public view returns (uint256) { 125 | return address(this).balance; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /client/src/components/Navbar/MenuItem.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import { shortenAddress } from "../../utils/shortenAddress"; 4 | 5 | const MenuItem = ({ showMenu, active, currentAccount }) => { 6 | return ( 7 | 15 | 32 |
  • 33 | 40 | Buy Token 41 | 42 |
  • 43 |
  • 44 | 51 | Lottery 52 | 53 |
  • 54 |
  • 55 | 62 | Send Ether 63 | 64 |
  • 65 | 66 | 97 |
    98 | ); 99 | }; 100 | 101 | export default MenuItem; 102 | 103 | // background-color: #ffffff; 104 | // background-image: linear-gradient(315deg, #ffffff 0%, #d7e1ec 74%); 105 | -------------------------------------------------------------------------------- /client/assets/images/lottery.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/components/Footer.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import Logo from "../../assets/images/logo.svg"; 4 | import { Twitter, Github, LinkedIn } from "../Icons"; 5 | 6 | const Footer = () => { 7 | const date = new Date() 8 | const year = date.getFullYear() 9 | 10 | return ( 11 |
    12 |
    13 |
    14 | 20 | CryptoAce Logo 21 | 22 | Crypto 23 | ace 24 | 25 | 26 |
    27 | 28 |
    29 |
    30 | 36 | Buy Token 37 | 38 |
    39 | 40 |
    41 | 47 | Lottery 48 | 49 |
    50 | 51 |
    52 | 58 | Send Ether 59 | 60 |
    61 |
    62 |
    63 | 64 |
    65 | 66 |
    67 |
    68 |

    69 | © 2021 - {year}, All rights reserved 70 |

    71 | 72 |
    73 | 79 | 80 | 81 | 82 | 88 | 89 | 90 | 91 | 97 | 98 | 99 |
    100 | 101 |
    102 |

    103 | Made with ❤️ by {""} 104 | 109 | Samrath Chauhan 110 | 111 |

    112 |
    113 |
    114 |
    115 |
    116 | ); 117 | }; 118 | 119 | export default Footer; 120 | -------------------------------------------------------------------------------- /client/assets/images/buytoken.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/context/reducers.js: -------------------------------------------------------------------------------- 1 | import { contractEnum, web3Enum, tokenEnum, userEnum } from "./enums.js"; 2 | 3 | const contractReducer = (state, action) => { 4 | switch (action.type) { 5 | case contractEnum.TRANSACTION_CONTRACT_INIT: 6 | console.log("Transaction contract made"); 7 | return { ...state, transactionContract: action.value }; 8 | 9 | case contractEnum.TRANSACTIONS: 10 | console.log("Transactions updated"); 11 | return { ...state, transactions: action.value }; 12 | 13 | case contractEnum.TRANSACTION_COUNT: 14 | console.log("Transactions count updated"); 15 | return { ...state, transactionCount: action.value }; 16 | 17 | case contractEnum.TOKEN_CONTRACT_INIT: 18 | console.log("Ace token contract made"); 19 | return { ...state, aiboostTokenContract: action.value }; 20 | 21 | case contractEnum.TOKEN_PRICE: 22 | console.log("Ace token price updated"); 23 | return { ...state, tokenPrice: action.value }; 24 | 25 | case contractEnum.SALE_CONTRACT_INIT: 26 | console.log("Sale contract made"); 27 | return { ...state, aiboostTokenSaleContract: action.value }; 28 | 29 | case contractEnum.LOTTERY_POOL_CONTRACT_INIT: 30 | console.log("Lottery pool init"); 31 | return { ...state, lotteryPoolContract: action.value }; 32 | 33 | case contractEnum.LOTTERY_INIT: 34 | console.log("Lottery contract init"); 35 | return { ...state, lotteryContract: action.value }; 36 | 37 | case contractEnum.LOTTERIES_DETAILS: 38 | console.log("Lottery details init"); 39 | return { ...state, lotteriesDetails: action.value }; 40 | 41 | case contractEnum.LOTTERY_MANAGER: 42 | console.log("LOTTERY_MANAGER updated"); 43 | return { ...state, lotteryManager: action.value }; 44 | 45 | case contractEnum.LOTTERY_ENTRY_FEE: 46 | console.log("LOTTERY_ENTRY_FEE updated"); 47 | return { ...state, lotteryEntryFee: action.value }; 48 | 49 | case contractEnum.LOTTERY_PLAYERS: 50 | console.log("LOTTERY_PLAYERS updated"); 51 | return { ...state, lotteryPlayers: action.value }; 52 | 53 | case contractEnum.LOTTERY_WINNER: 54 | console.log("LOTTERY_WINNER updated"); 55 | return { ...state, lotteryWinner: action.value }; 56 | 57 | case contractEnum.LOTTERY_TIME_REMAINING: 58 | console.log("LOTTERY_TIME_REMAINING updated"); 59 | return { ...state, lotteryTimeRemaining: action.value }; 60 | 61 | case contractEnum.LOTTERY_STATUS: 62 | console.log("LOTTERY_STATUS updated"); 63 | return { ...state, lotteryStatus: action.value }; 64 | 65 | case contractEnum.LOTTERY_PRICE: 66 | console.log("LOTTERY_PRICE updated"); 67 | return { ...state, lotteryPrice: action.value }; 68 | 69 | case contractEnum.LOTTERY_START: 70 | console.log("LOTTERY game started"); 71 | return { ...state, lotteryStart: action.value }; 72 | 73 | case contractEnum.LOTTERY_ENTER: 74 | console.log("You have entered the lottery"); 75 | return { ...state, lotteryEnter: action.value }; 76 | 77 | case contractEnum.LOTTERY_END: 78 | console.log("LOTTERY has ended"); 79 | return { ...state, lotteryEnd: action.value }; 80 | 81 | default: 82 | console.log( 83 | "Invalid value at Transaction Provider", 84 | action.type, 85 | action.value 86 | ); 87 | } 88 | }; 89 | 90 | const web3Reducer = (state, action) => { 91 | switch (action.type) { 92 | case web3Enum.PROVIDER: 93 | console.log("Web3 Provider init"); 94 | return { ...state, provider: action.value }; 95 | default: 96 | console.log( 97 | "Invalid value at web3Reducer Provider", 98 | action.type, 99 | action.value 100 | ); 101 | } 102 | }; 103 | 104 | const userReducer = (state, action) => { 105 | switch (action.type) { 106 | case userEnum.BALANCE: 107 | console.log("Balance updated"); 108 | return { ...state, balance: action.value }; 109 | case userEnum.CURR_ACCOUNT: 110 | console.log("Curr account updated"); 111 | return { ...state, currentAccount: action.value }; 112 | default: 113 | console.log( 114 | "Invalid value at web3Reducer Provider", 115 | action.type, 116 | action.value 117 | ); 118 | } 119 | }; 120 | 121 | const tokenReducer = (state, action) => { 122 | switch (action.type) { 123 | case tokenEnum.BALANCE: 124 | console.log("Token balance updated"); 125 | return { ...state, balance: action.value }; 126 | case tokenEnum.PRICE: 127 | console.log("Token price updated"); 128 | return { ...state, price: action.value }; 129 | case tokenEnum.SOLD: 130 | console.log("Token sold updated"); 131 | return { ...state, sold: action.value }; 132 | default: 133 | console.log( 134 | "Invalid value at token reducer Provider", 135 | action.type, 136 | action.value 137 | ); 138 | } 139 | }; 140 | 141 | export { contractReducer, web3Reducer, userReducer, tokenReducer }; 142 | -------------------------------------------------------------------------------- /client/src/components/Notification.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import ReactDOM from "react-dom"; 3 | 4 | const Notification = ({ props }) => { 5 | const [view, setView] = useState(true); 6 | 7 | const close = () => { 8 | setView(false); 9 | }; 10 | 11 | if (props.timerValue) { 12 | useEffect(() => { 13 | const timer = setTimeout(() => { 14 | close(); 15 | }, props.timerValue); 16 | return () => clearTimeout(timer); 17 | }, []); 18 | } 19 | 20 | const notificationToast = (type, message) => { 21 | if (type === 1 && view) { 22 | return ( 23 | <> 24 |
    25 | 31 | 36 | 37 |
    38 | 39 | ); 40 | } 41 | 42 | if (type === 2 && view) { 43 | return ( 44 | <> 45 |
    46 | 52 | 57 | 58 |
    59 | 60 | ); 61 | } 62 | 63 | if (type === 3 && view) { 64 | return ( 65 | <> 66 |
    67 | 73 | 78 | 79 |
    80 | 81 | ); 82 | } 83 | }; 84 | 85 | return ReactDOM.createPortal( 86 | <> 87 | {view && ( 88 |
    91 | 132 |
    133 | )} 134 | , 135 | document.getElementById("notification") 136 | ); 137 | }; 138 | 139 | export default Notification; 140 | -------------------------------------------------------------------------------- /client/src/index.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Rajdhani:wght@400;500;600;700&family=Rubik:wght@600;700;800&display=swap"); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | } 7 | 8 | .secure-shadow{ 9 | filter: drop-shadow(1px 1px 7px #963dff); 10 | } 11 | 12 | .transaction-shadow{ 13 | filter: drop-shadow(1px 1px 2px #491e7e); 14 | } 15 | 16 | .text-logo-gradient { 17 | background-color: #fff; 18 | background-image: radial-gradient( 19 | at 4% 36%, 20 | rgb(87, 44, 206) 0, 21 | transparent 53% 22 | ), 23 | radial-gradient(at 100% 60%, rgb(107, 46, 206) 0, transparent 75%); 24 | -webkit-background-clip: text; 25 | -webkit-text-fill-color: transparent; 26 | } 27 | 28 | .gradient-bg-services { 29 | background-color: #231b41; 30 | background-image: radial-gradient(at 0% 100%, rgb(0, 0, 0) 0, transparent 50%), 31 | radial-gradient(at 50% 0%, hsl(256, 39%, 25%) 0, transparent 50%); 32 | } 33 | 34 | .gradient-bg-ball { 35 | background-color: #a4508b; 36 | background-image: linear-gradient(326deg, #a4508b 0%, #5f0a87 74%); 37 | } 38 | 39 | .gradient-bg-ball1 { 40 | background-color: #1e1d1b; 41 | background-image: linear-gradient(315deg, #1e1d1b 0%, #cc9934 74%); 42 | } 43 | 44 | @tailwind base; 45 | 46 | @layer base { 47 | html { 48 | font-family: Rajdhani; 49 | scroll-behavior: smooth; 50 | } 51 | 52 | input[type="number"]::-webkit-inner-spin-button, 53 | input[type="number"]::-webkit-outer-spin-button { 54 | -webkit-appearance: none; 55 | margin: 0; 56 | } 57 | } 58 | @tailwind components; 59 | @tailwind utilities; 60 | 61 | @layer utilities { 62 | .animation-delay-2000 { 63 | animation-delay: 2s; 64 | } 65 | .animation-delay-4000 { 66 | animation-delay: 4s; 67 | } 68 | /* Menu */ 69 | .menu { 70 | background-color: transparent; 71 | border: none; 72 | cursor: pointer; 73 | display: flex; 74 | padding: 0; 75 | } 76 | .line { 77 | fill: none; 78 | stroke: #b9c3ce; 79 | stroke-width: 6; 80 | transition: stroke-dasharray 700ms cubic-bezier(0.4, 0, 0.2, 1), 81 | stroke-dashoffset 700ms cubic-bezier(0.4, 0, 0.2, 1); 82 | } 83 | .line1 { 84 | stroke-dasharray: 60 207; 85 | stroke-width: 6; 86 | } 87 | .line2 { 88 | stroke-dasharray: 60 60; 89 | stroke-width: 6; 90 | } 91 | .line3 { 92 | stroke-dasharray: 60 207; 93 | stroke-width: 6; 94 | } 95 | .opened .line1 { 96 | stroke-dasharray: 90 207; 97 | stroke-dashoffset: -134; 98 | stroke-width: 6; 99 | } 100 | .opened .line2 { 101 | stroke-dasharray: 1 60; 102 | stroke-dashoffset: -30; 103 | stroke-width: 6; 104 | } 105 | .opened .line3 { 106 | stroke-dasharray: 90 207; 107 | stroke-dashoffset: -134; 108 | stroke-width: 6; 109 | } 110 | 111 | /* Link Hover */ 112 | .hoverEffect { 113 | transition: 0.35s; 114 | } 115 | .hoverEffect:hover { 116 | text-shadow: 0 -1.05px 0 #fff, 0 2px 0 #30132b, 0 4px 0 #2c0d99, 117 | 0 6px 0 #701781, 0 8px 0 #2a105a, 0 10px 0 #2e0a42; 118 | } 119 | 120 | /* Loader */ 121 | .triple-spinner { 122 | display: block; 123 | position: relative; 124 | width: 125px; 125 | height: 125px; 126 | border-radius: 50%; 127 | border: 4px solid transparent; 128 | border-top: 4px solid #a894d0; 129 | -webkit-animation: spin 2s linear infinite; 130 | animation: spin 2s linear infinite; 131 | } 132 | 133 | .triple-spinner::before, 134 | .triple-spinner::after { 135 | content: ""; 136 | position: absolute; 137 | border-radius: 50%; 138 | border: 4px solid transparent; 139 | } 140 | .triple-spinner::before { 141 | top: 5px; 142 | left: 5px; 143 | right: 5px; 144 | bottom: 5px; 145 | border-top-color: #7b3ec8; 146 | -webkit-animation: spin 3s linear infinite; 147 | animation: spin 3.5s linear infinite; 148 | } 149 | .triple-spinner::after { 150 | top: 15px; 151 | left: 15px; 152 | right: 15px; 153 | bottom: 15px; 154 | border-top-color: #7680e3; 155 | -webkit-animation: spin 1.5s linear infinite; 156 | animation: spin 1.75s linear infinite; 157 | } 158 | 159 | @-webkit-keyframes spin { 160 | from { 161 | -webkit-transform: rotate(0deg); 162 | transform: rotate(0deg); 163 | } 164 | to { 165 | -webkit-transform: rotate(360deg); 166 | transform: rotate(360deg); 167 | } 168 | } 169 | 170 | @keyframes spin { 171 | from { 172 | -webkit-transform: rotate(0deg); 173 | transform: rotate(0deg); 174 | } 175 | to { 176 | -webkit-transform: rotate(360deg); 177 | transform: rotate(360deg); 178 | } 179 | } 180 | 181 | /* Moz */ 182 | @-moz-document url-prefix() { 183 | menu { 184 | padding: 5px; 185 | border-radius: 5px; 186 | background-color: #2d3436; 187 | background-image: linear-gradient(315deg, #2d3436 0%, #000000 74%); 188 | } 189 | } 190 | } 191 | 192 | ::-webkit-scrollbar { 193 | width: 14px; 194 | height: 100vh; 195 | background-color: #171717; 196 | margin-block: 0.5em; 197 | } 198 | 199 | ::-webkit-scrollbar-track { 200 | margin-block: 0.5em; 201 | } 202 | 203 | ::-webkit-scrollbar-thumb { 204 | border: 3px solid rgba(255, 255, 255, 0); 205 | border-radius: 99999px; 206 | background-clip: padding-box; 207 | background-color: #963dff; 208 | } 209 | 210 | ::-webkit-scrollbar-thumb:hover { 211 | background-color: #772ace; 212 | } 213 | 214 | @supports (scrollbar-color: #772ace #000000e5) { 215 | * { 216 | scrollbar-color: #772ace #000000e5; 217 | scroll-behavior: smooth; 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /client/src/pages/Lottery.jsx: -------------------------------------------------------------------------------- 1 | import { useContext, useEffect, useState } from "react"; 2 | import { Notification, Loader } from "../components"; 3 | import { ContractsContext } from "../context/ContractsContext"; 4 | import { shortenAddress } from "../utils/shortenAddress"; 5 | import { useParams } from "react-router"; 6 | import { Eth } from "../Icons"; 7 | 8 | function Lottery() { 9 | const { lotteryAddress } = useParams(); 10 | 11 | const { 12 | initLotteryContract, 13 | lotteryManager, 14 | lotteryEntryFee, 15 | lotteryPlayers, 16 | balance, 17 | getBalanceOf, 18 | lotteryPrice, 19 | isLoading, 20 | lotteryStatus, 21 | enterLottery, 22 | lotteryTimeRemaining, 23 | isEther, 24 | currentAccount, 25 | } = useContext(ContractsContext); 26 | 27 | const [state, setState] = useState({ 28 | lotteryManager: null, 29 | lotteryEntryFee: 0, 30 | lotteryPlayers: [], 31 | lotteryWinner: null, 32 | lotteryPrice: 0, 33 | }); 34 | 35 | const [manager, setIsManager] = useState(false); 36 | 37 | useEffect(() => { 38 | if ( 39 | currentAccount === lotteryManager.toLowerCase() && 40 | (currentAccount || lotteryManager.toLowerCase() !== null) 41 | ) { 42 | setIsManager(true); 43 | } 44 | }); 45 | 46 | async function getBalance(address = currentAccount) { 47 | if (!address) { 48 | return; 49 | } 50 | await getBalanceOf(address); 51 | } 52 | 53 | // console.log("Lottery", lottery); 54 | 55 | useEffect(() => { 56 | async function load() { 57 | await initLotteryContract(lotteryAddress); 58 | 59 | setState(() => { 60 | return { 61 | ...state, 62 | lotteryManager, 63 | lotteryEntryFee, 64 | lotteryPlayers, 65 | lotteryPrice, 66 | }; 67 | }); 68 | } 69 | 70 | load(); 71 | getBalance(); 72 | }, []); 73 | 74 | console.log("Lottery Things🔫"); 75 | 76 | return ( 77 |
    78 | {/* first div */} 79 |
    80 |
    81 |

    82 | Lottery Details 83 |

    84 | {currentAccount && ( 85 |
    86 |

    {balance}

    87 | 88 |
    89 | )} 90 |
    91 | 92 |
    93 |

    94 | Lottery Contract :{" "} 95 | 101 | {shortenAddress(lotteryAddress)} 102 | 103 |

    104 |

    105 | Lottery Manager :{" "} 106 | 112 | {" "} 113 | {manager 114 | ? "You are the lottery manager" 115 | : shortenAddress(lotteryManager)} 116 | 117 |

    118 |

    119 | Lottery Status :{" "} 120 | 121 | {" "} 122 | {`Lottery has ended`} 123 | 124 |

    125 |
    126 | 127 | 140 |
    141 | {!isEther ? ( 142 | 149 | ) : !currentAccount ? ( 150 | 153 | ) : ( 154 | false && ( 155 | 162 | ) 163 | )} 164 | {/* TODO: Lottery Message */} 165 |
    166 | ); 167 | } 168 | 169 | export default Lottery; 170 | -------------------------------------------------------------------------------- /client/src/pages/BuyToken.jsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useContext, useRef } from "react"; 2 | import { Notification, Loader } from "../components"; 3 | import { ContractsContext } from "../context/ContractsContext"; 4 | import { Eth } from "../Icons"; 5 | 6 | const BuyToken = () => { 7 | const inputRef = useRef(); 8 | const [cost, setCost] = useState(); 9 | const [inputErr, setInputErr] = useState(false); 10 | 11 | const { 12 | initToken, 13 | token, 14 | buyTokens, 15 | isBuyingToken, 16 | isEther, 17 | isLoading, 18 | balance, 19 | getBalanceOf, 20 | currentAccount, 21 | tokenMessage, 22 | } = useContext(ContractsContext); 23 | 24 | async function getBalance(address = currentAccount) { 25 | if (!address) { 26 | return; 27 | } 28 | await getBalanceOf(address); 29 | } 30 | useEffect(() => { 31 | initToken(); 32 | getBalance(); 33 | }, []); 34 | 35 | const getCost = (e) => { 36 | if ( 37 | (e.target.value > 0 && e.target.value % 1 == 0) || 38 | e.target.value === "" 39 | ) { 40 | setCost(e.target.value * 0.01); 41 | setInputErr(false); 42 | } else { 43 | setInputErr(true); 44 | } 45 | }; 46 | 47 | return ( 48 |
    49 | {/* first div */} 50 |
    51 |
    52 |

    53 | Ace Token 54 |

    55 | {currentAccount && ( 56 |
    57 |

    {balance}

    58 | 59 |
    60 | )} 61 |
    62 | 63 |
    64 |

    65 | Token Price :{" "} 66 | 67 | {token.price} 68 | 69 |

    70 |

    71 | Tokens Owned :{" "} 72 | 73 | {token.balance} 74 | 75 |

    76 |

    77 | Total Tokens Sold :{" "} 78 | 79 | {token.sold} 80 | 81 |

    82 |
    83 | 84 | {!isBuyingToken ? ( 85 |
    92 |
    93 | {cost ? ( 94 |

    95 | ETH: {cost} 96 |

    97 | ) : ( 98 | "" 99 | )} 100 | 111 |
    112 |
    113 | ) : ( 114 | "" 115 | )} 116 | 117 | 139 |
    140 | 141 | {!isEther ? ( 142 | 149 | ) : !currentAccount ? ( 150 | 153 | ) : ( 154 | isBuyingToken && ( 155 | 162 | ) 163 | )} 164 | 165 | {typeof tokenMessage === "string" && ( 166 | 173 | )} 174 |
    175 | ); 176 | }; 177 | 178 | export default BuyToken; 179 | -------------------------------------------------------------------------------- /client/assets/images/sendEther.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/components/Navbar/Navbar.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useContext } from "react"; 2 | import { Link } from "react-router-dom"; 3 | import { shortenAddress } from "../../utils/shortenAddress"; 4 | import { ContractsContext } from "../../context/ContractsContext"; 5 | import Logo from "../../../assets/images/logo.svg"; 6 | import MenuItem from "./MenuItem"; 7 | 8 | const Navbar = () => { 9 | const [isMenuOpen, setIsMenuOpen] = useState(false); 10 | 11 | const { currentAccount, connectWallet } = useContext(ContractsContext); 12 | 13 | const showMenu = () => { 14 | setIsMenuOpen(!isMenuOpen); 15 | }; 16 | 17 | return ( 18 |
    19 |
    20 |
    21 | 27 | CryptoAce 28 | 29 | Crypto 30 | ace 31 | 32 | 33 | 34 | {/* Navigation Buttons */} 35 | 36 |
      37 |
    • 38 | 44 | Buy Token 45 | 46 |
    • 47 |
    • 48 | 54 | Lottery 55 | 56 |
    • 57 |
    • 58 | 64 | Send Ether 65 | 66 |
    • 67 |
    68 | 69 | {/* Button */} 70 | 71 | 111 | 112 | {/* Toggler */} 113 | 114 |
    115 | 132 |
    133 |
    134 |
    135 | 140 |
    141 | ); 142 | }; 143 | 144 | export default Navbar; 145 | -------------------------------------------------------------------------------- /client/src/components/GetStarted.jsx: -------------------------------------------------------------------------------- 1 | import { Fragment } from "react"; 2 | import { Arrow } from "../Icons"; 3 | import Wallet from "../../assets/images/wallet.png"; 4 | import Secure from "../../assets/images/secure.png"; 5 | import Wifi from "../../assets/images/wifi.png"; 6 | import Link from "../../assets/images/link.png"; 7 | 8 | function GetStarted() { 9 | const stepsData = [ 10 | { 11 | title: "Connect your metamask wallet.", 12 | description: "Login to your metamask wallet connect to Cryptoace.", 13 | url: "https://metamask.io/faqs/", 14 | img: Wallet, 15 | }, 16 | { 17 | title: "Switch to ropsten test network.", 18 | description: 19 | "Not a commercial web3 project hence contracts are deployed on ropsten test network.", 20 | url: "http://www.herongyang.com/Ethereum/MetaMask-Extension-Add-Ropsten-Test-Network.html", 21 | img: Wifi, 22 | }, 23 | { 24 | title: "Connect your account.", 25 | description: 26 | "Connect any of your account by clicking on connect button on metamask wallet.", 27 | url: "https://archenetwork.medium.com/how-to-use-ropsten-with-metamask-and-connect-with-arche-v1-1-eros-48be365b4e04/", 28 | img: Link, 29 | }, 30 | ]; 31 | 32 | return ( 33 |
    34 |
    35 |
    36 |
    37 |

    38 | Safe & 39 | Secured 40 |

    41 |

    42 | Every transaction made from Cryptoace is safe and secured. You can 43 | also track any of your transactions on the metamask wallet and 44 | also on ehterscan. 45 | 46 | All the transactions on cryptoace works transparently and hence 47 | follows the web3 rules. 48 | 49 |

    50 |
    51 |
    52 |
    53 | Security 58 |
    59 |
    60 |
    61 |
    62 | 63 | {/*Get Started Section */} 64 |

    65 | Get Started. 66 |

    67 |
    68 | {stepsData.map((data, index) => ( 69 | 70 |
    1 73 | ? "flex items-center lg:w-3/5 mx-auto sm:flex-row flex-col" 74 | : "flex items-center lg:w-3/5 mx-auto border-b pb-5 mb-5 sm:pb-10 sm:mb-10 border-gray-700 sm:flex-row flex-col" 75 | } 76 | > 77 | {" "} 78 | {index != 1 ? ( 79 | <> 80 |
    81 | 82 |
    83 |
    84 |

    85 | {data.title} 86 |

    87 |

    88 | {data.description} 89 |

    90 | 95 | Learn More{" "} 96 |
    97 | 98 |
    99 |
    100 |
    101 | 102 | ) : ( 103 | <> 104 |
    105 |

    106 | {data.title} 107 |

    108 |

    109 | {data.description} 110 |

    111 | 116 | Learn More{" "} 117 |
    118 | 119 |
    120 |
    121 |
    122 |
    123 | 124 |
    125 | 126 | )} 127 |
    128 |
    129 | ))} 130 | 131 | 143 |
    144 |
    145 | ); 146 | } 147 | 148 | export default GetStarted; 149 | -------------------------------------------------------------------------------- /client/src/components/Transactions.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect } from "react"; 2 | import { ContractsContext } from "../context/ContractsContext"; 3 | import { shortenAddress } from "../utils/shortenAddress"; 4 | import { Eth } from "../Icons"; 5 | 6 | const TransactionsCard = ({ 7 | addressTo, 8 | addressFrom, 9 | timestamp, 10 | message, 11 | amount, 12 | }) => { 13 | const dateArr = timestamp.split(" "); 14 | const meridiem = dateArr[2]; 15 | const timeArr = dateArr[1].split(":"); 16 | timeArr.pop(); 17 | const time = timeArr.join(":"); 18 | 19 | const tranDate = new Date(timestamp); 20 | const date = tranDate.getDate(); 21 | const strDate = tranDate.toString(); 22 | const month = strDate.slice(4, 7).toUpperCase(); 23 | 24 | let bigMessage = false; 25 | let smallMessage = ""; 26 | if (message.length > 130) { 27 | bigMessage = true; 28 | smallMessage = message.split(" ").slice(0, 1).join(" "); 29 | } 30 | 31 | return ( 32 | <> 33 | { 34 |
    35 |
    36 |
    37 |
    38 |
    39 |
    40 |
    41 |

    {month}

    42 |
    43 |
    44 |

    45 | {date} 46 |

    47 |
    48 | 49 |
    50 |
    51 |

    52 | {time} 53 |

    54 |
    55 |
    56 |

    {meridiem}

    57 |
    58 |
    59 |
    60 |
    61 |
    62 | 72 | 83 |

    84 | {amount} 85 | 86 |

    87 | {message && ( 88 | <> 89 |

    90 | {bigMessage 91 | ? smallMessage + " ...Read More" 92 | : message} 93 |

    94 | 95 | )} 96 | 124 |
    125 |
    126 |
    127 |
    128 |
    129 |
    130 | } 131 | 132 | ); 133 | }; 134 | 135 | const Transaction = () => { 136 | const { transactions, currentAccount, getAllTransactions } = 137 | useContext(ContractsContext); 138 | 139 | useEffect(() => { 140 | getAllTransactions(); 141 | }, []); 142 | 143 | if (transactions.length > 4) { 144 | for (let i = 0; i < transactions.length - 3; i++) { 145 | transactions.shift(); 146 | } 147 | } 148 | return ( 149 |
    150 | {currentAccount ? ( 151 |
    152 |

    153 | Latest{" "} 154 | 155 | Transactions. 156 | 157 |

    158 | 159 |
    160 | {transactions.map((transaction, i) => ( 161 | 162 | ))} 163 |
    164 |
    165 | ) : ( 166 | "" 167 | )} 168 |
    169 | ); 170 | }; 171 | 172 | export default Transaction; 173 | -------------------------------------------------------------------------------- /client/src/pages/SendEther.jsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useContext } from "react"; 2 | import { Notification, Loader } from "../components"; 3 | import { ContractsContext } from "../context/ContractsContext"; 4 | import { Eth } from "../Icons"; 5 | 6 | const Input = ({ 7 | placeholder, 8 | name, 9 | type, 10 | value, 11 | checkValue, 12 | handleChange, 13 | }) => ( 14 | { 20 | checkValue(e, name); 21 | handleChange(e, name); 22 | }} 23 | className="w-full rounded-xl p-2 mt-2 outline-none bg-transparent text-slate-100 border-none text-lg font-raj font-semibold" 24 | /> 25 | ); 26 | 27 | const SendEther = () => { 28 | const { 29 | isEther, 30 | isLoading, 31 | formData, 32 | sendTransaction, 33 | handleChange, 34 | balance, 35 | getBalanceOf, 36 | currentAccount, 37 | etherMessage, 38 | sendingEther, 39 | } = useContext(ContractsContext); 40 | 41 | const [amountErr, setAmountErr] = useState(false); 42 | const [addressErr, setAddressErr] = useState(false); 43 | const [noInput, setNotInput] = useState(true); 44 | 45 | const checkValue = (e, type) => { 46 | // Amount Validation 47 | if (type === "amount") { 48 | if (e.target.value > 0 || e.target.value === "") { 49 | setAmountErr(false); 50 | } else { 51 | setAmountErr(true); 52 | } 53 | } 54 | 55 | // Address Validation 56 | if (type === "addressTo") { 57 | console.log(typeof e.target.value); 58 | function isHex(num) { 59 | return Boolean(num.match(/^0x[0-9a-f]+$/i)); 60 | } 61 | if (e.target.value.length == 42 || e.target.value === "") { 62 | if (isHex(e.target.value) || e.target.value === "") { 63 | setAddressErr(false); 64 | } 65 | } else { 66 | setAddressErr(true); 67 | } 68 | } 69 | 70 | // No validation needed for message as it is just text 71 | if (e.target.value.length || !e.target.value === "") { 72 | setNotInput(false); 73 | } else { 74 | setNotInput(true); 75 | } 76 | }; 77 | 78 | function handleSubmit(e) { 79 | { 80 | isLoading && ; 81 | } 82 | const { addressTo, amount, message } = formData; 83 | 84 | e.preventDefault(); 85 | 86 | if (!addressTo || !amount || !message) return; 87 | 88 | sendTransaction(); 89 | } 90 | 91 | async function getBalance(address = currentAccount) { 92 | if (!address) { 93 | return; 94 | } 95 | await getBalanceOf(address); 96 | } 97 | useEffect(() => { 98 | getBalance(); 99 | },[]); 100 | 101 | return ( 102 |
    103 |
    104 |
    105 |

    106 | Send Ether 107 |

    108 | {currentAccount && ( 109 |
    110 |

    {balance}

    111 | 112 |
    113 | )} 114 |
    115 | 116 | {/* Enter Ether */} 117 |
    124 |
    125 | 132 |
    133 |
    134 | 135 | {/* Enter Address */} 136 |
    143 |
    144 | 151 |
    152 |
    153 | 154 | {/* Enter Message */} 155 |
    158 |
    159 | 166 |
    167 |
    168 | 169 | 190 |
    191 | 192 | {!isEther ? ( 193 | 200 | ) : !currentAccount ? ( 201 | 204 | ) : ( 205 | sendingEther && ( 206 | 213 | ) 214 | )} 215 | 216 | {typeof etherMessage === "string" && ( 217 | 224 | )} 225 |
    226 | ); 227 | }; 228 | 229 | export default SendEther; 230 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /client/src/pages/LotteryPool.jsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useContext, useRef } from "react"; 2 | import { Notification, Loader } from "../components"; 3 | import { Link } from "react-router-dom"; 4 | import { ContractsContext } from "../context/ContractsContext"; 5 | import { shortenAddress } from "../utils/shortenAddress"; 6 | import { Eth, Arrow } from "../Icons"; 7 | 8 | const LotteryPool = () => { 9 | const inputRef = useRef(); 10 | const [time, setTime] = useState(); 11 | const [showEnded, setShowEnded] = useState(false); 12 | const [inputErr, setInputErr] = useState(false); 13 | const [blockTimeStamp, setBlockTimeStamp] = useState(0); 14 | const [showActiveLottery, setShowActiveLottery] = useState(false); 15 | const [showMoreEndedLottery, setShowMoreEndedLottery] = useState(false); 16 | 17 | const { 18 | isEther, 19 | isLoading, 20 | balance, 21 | getBalanceOf, 22 | currentAccount, 23 | lotteriesDetails, 24 | initLotteryPool, 25 | startLottery, 26 | provider, 27 | isCreatingLottery, 28 | createLotteryMessage, 29 | } = useContext(ContractsContext); 30 | 31 | async function getBalance(address = currentAccount) { 32 | if (!address) { 33 | return; 34 | } 35 | await getBalanceOf(address); 36 | } 37 | 38 | console.log(lotteriesDetails); 39 | 40 | const toggle = (id) => { 41 | if (id == 1) { 42 | setShowActiveLottery(!showActiveLottery); 43 | } 44 | if (id == 2) { 45 | setShowEnded(!showEnded); 46 | } 47 | }; 48 | 49 | const showMore = () => { 50 | setShowMoreEndedLottery(!showMoreEndedLottery); 51 | }; 52 | 53 | const checkTime = (e) => { 54 | if ( 55 | (e.target.value > 0 && e.target.value % 1 == 0) || 56 | e.target.value === "" 57 | ) { 58 | setTime(e.target.value * 60); 59 | setInputErr(false); 60 | } else { 61 | setInputErr(true); 62 | } 63 | }; 64 | 65 | useEffect(() => { 66 | getBalance(); 67 | }, []); 68 | 69 | useEffect(() => { 70 | initLotteryPool(); 71 | if (provider) { 72 | provider.getBlock().then((block) => { 73 | setBlockTimeStamp(() => +block.timestamp); 74 | }); 75 | } 76 | }, [blockTimeStamp]); 77 | 78 | const getRemainingTime = (timestamp) => { 79 | return Math.floor((timestamp - blockTimeStamp) / 60); 80 | }; 81 | 82 | return ( 83 |
    84 | {/* first div */} 85 |
    86 |
    87 |

    88 | Enter Lottery 89 |

    90 | {currentAccount && ( 91 |
    92 |

    {balance}

    93 | 94 |
    95 | )} 96 |
    97 | 98 | {/* For active lotteries */} 99 | {currentAccount ? ( 100 |
    101 |
    toggle(1)}> 102 |

    103 | Ongoing Lotteries{" "} 104 |

    105 |
    112 | 115 |
    116 |
    117 | 118 | {lotteriesDetails.length > 0 && 119 | !isLoading && 120 | lotteriesDetails.map((lottery, index) => { 121 | if (index > 25) { 122 | return; 123 | } 124 | if (+getRemainingTime(lottery.endedTimeStamp) > 0) { 125 | return ( 126 | 130 | {showActiveLottery && ( 131 |
    132 |
    133 |

    134 | Lottery{" "} 135 | 136 | #{index + 1} 137 | 138 |

    139 |
    140 | Ending In:{" "} 141 | 142 | {getRemainingTime(lottery.endedTimeStamp) + 143 | "min"} 144 | 145 |
    146 |
    147 |

    148 | Address :{" "} 149 |

    150 | {shortenAddress(lottery.lotteryContract)} 151 |

    152 |

    153 |
    154 | )} 155 | 156 | ); 157 | } 158 | })} 159 |
    160 | ) : ( 161 |
    162 |

    163 | Connect your wallet to enter 164 |

    165 |
    166 | )} 167 | 168 | {/* For ended Lotteries */} 169 | {currentAccount && ( 170 |
    171 |
    toggle(2)}> 172 |

    173 | Ended Lotteries{" "} 174 |

    175 |
    182 | 185 |
    186 |
    187 | {lotteriesDetails.length > 0 && 188 | !isLoading && 189 | lotteriesDetails.map((lottery, index) => { 190 | if (index > 3 && !showMoreEndedLottery) { 191 | return; 192 | } 193 | if (+getRemainingTime(lottery.endedTimeStamp) < 0) { 194 | return ( 195 | 199 | {showEnded && ( 200 |
    201 |
    202 |

    203 | Lottery{" "} 204 | 205 | #{index + 1} 206 | 207 |

    208 |
    209 | Ended : 210 | 211 | {getRemainingTime(lottery.endedTimeStamp)} 212 | 213 |
    214 |
    215 |

    216 | Address :{" "} 217 |

    218 | {shortenAddress(lottery.lotteryContract)} 219 |

    220 |

    221 |
    222 | )} 223 | 224 | ); 225 | } 226 | })} 227 | {showEnded && ( 228 | 234 | )} 235 |
    236 | )} 237 | 238 | {/* Input Field */} 239 | {!false ? ( 240 |
    247 |
    248 | {time ? ( 249 |

    250 | Ending in: {time + "sec"} 251 |

    252 | ) : ( 253 | "" 254 | )} 255 | 266 |
    267 |
    268 | ) : ( 269 | "" 270 | )} 271 | 272 | 289 |
    290 | 291 | {!isEther ? ( 292 | 299 | ) : !currentAccount ? ( 300 | 303 | ) : ( 304 | isCreatingLottery && ( 305 | 312 | ) 313 | )} 314 | 315 | {typeof createLotteryMessage === "string" && ( 316 | 323 | )} 324 |
    325 | ); 326 | }; 327 | 328 | export default LotteryPool; 329 | -------------------------------------------------------------------------------- /client/src/context/ContractsContext.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useReducer, useState } from "react"; 2 | import { ethers, utils } from "ethers"; 3 | import { shortenAddress } from "../utils/shortenAddress.js"; 4 | 5 | // import enums 6 | import { contractEnum, web3Enum, tokenEnum, userEnum } from "./enums.js"; 7 | 8 | // import reducers 9 | import { 10 | contractReducer, 11 | web3Reducer, 12 | userReducer, 13 | tokenReducer, 14 | } from "./reducers"; 15 | 16 | import { 17 | transactionContractAddress, 18 | transactionContractABI, 19 | tokenSaleContractAddress, 20 | tokenSaleContractABI, 21 | aceTokenContractAddress, 22 | aceTokenContractABI, 23 | lotteryPoolContractABI, 24 | lotteryPoolContractAddress, 25 | lotteryContractABI, 26 | } from "../utils/constants"; 27 | 28 | export const ContractsContext = React.createContext(); 29 | 30 | export const ContractsProvider = ({ children }) => { 31 | const { ethereum } = window; 32 | const [isLoading, setIsLoading] = useState(false); 33 | const [isEther, setIsEther] = useState(false); 34 | const [isBuyingToken, setIsBuyingToken] = useState(false); 35 | const [tokenMessage, setTokenMessage] = useState(null); 36 | const [sendingEther, setSendingEther] = useState(false); 37 | const [etherMessage, setEtherMessage] = useState(null); 38 | const [isCreatingLottery, setIsCreatingLottery] = useState(false); 39 | const [createLotteryMessage, setCreateLotteryMessage] = useState(false); 40 | 41 | const [contracts, dispatchContracts] = useReducer(contractReducer, { 42 | transactionContract: null, 43 | aiboostTokenContract: null, 44 | aiboostTokenSaleContract: null, 45 | transactions: [], 46 | transactionCount: +localStorage.getItem("transactionCount"), 47 | tokenPrice: 0, 48 | lotteryContract: null, 49 | lotteryPoolContract: null, 50 | lotteryManager: "", 51 | lotteryEntryFee: 0, 52 | lotteriesDetails: [], 53 | lotteryTimeRemaining: 0, 54 | lotteryStart: null, 55 | lotteryEnter: null, 56 | lotteryEnd: null, 57 | lotteryPlayers: [], 58 | lotteryWinner: null, 59 | lotteryPrice: 0, 60 | }); 61 | 62 | const [web3, dispatchWeb3] = useReducer(web3Reducer, { 63 | provider: null, 64 | }); 65 | 66 | const [user, dispatchUser] = useReducer(userReducer, { 67 | balance: 0, 68 | currentAccount: null, 69 | }); 70 | 71 | const [token, dispatchToken] = useReducer(tokenReducer, { 72 | balance: 0, 73 | price: 0, 74 | sold: 0, 75 | }); 76 | 77 | const [formData, setformData] = useState({ 78 | addressTo: "", 79 | amount: "", 80 | message: "", 81 | }); 82 | 83 | const handleChange = (e, name) => { 84 | setformData((prevState) => ({ ...prevState, [name]: e.target.value })); 85 | }; 86 | 87 | const createEthereumContract = async () => { 88 | // const url = "http://localhost:7545"; 89 | const provider = new ethers.providers.Web3Provider(ethereum); 90 | 91 | // ganache 92 | // const provider = new ethers.providers.JsonRpcProvider(url); 93 | dispatchWeb3({ type: web3Enum.PROVIDER, value: provider }); 94 | const signer = provider.getSigner(); 95 | 96 | const transactionsContract = new ethers.Contract( 97 | transactionContractAddress, 98 | transactionContractABI, 99 | signer 100 | ); 101 | 102 | const tokenSaleContract = new ethers.Contract( 103 | tokenSaleContractAddress, 104 | tokenSaleContractABI, 105 | signer 106 | ); 107 | 108 | const aiboostTokenContract = new ethers.Contract( 109 | aceTokenContractAddress, 110 | aceTokenContractABI, 111 | signer 112 | ); 113 | 114 | const lotteryPoolContract = new ethers.Contract( 115 | lotteryPoolContractAddress, 116 | lotteryPoolContractABI, 117 | signer 118 | ); 119 | 120 | dispatchContracts({ 121 | type: contractEnum.TRANSACTION_CONTRACT_INIT, 122 | value: transactionsContract, 123 | }); 124 | 125 | dispatchContracts({ 126 | type: contractEnum.TOKEN_CONTRACT_INIT, 127 | value: aiboostTokenContract, 128 | }); 129 | 130 | dispatchContracts({ 131 | type: contractEnum.SALE_CONTRACT_INIT, 132 | value: tokenSaleContract, 133 | }); 134 | 135 | dispatchContracts({ 136 | type: contractEnum.LOTTERY_POOL_CONTRACT_INIT, 137 | value: lotteryPoolContract, 138 | }); 139 | 140 | return { 141 | aiboostTokenContract, 142 | tokenSaleContract, 143 | transactionsContract, 144 | lotteryPoolContract, 145 | }; 146 | }; 147 | 148 | const getBalanceOf = async (address = user.currentAccount) => { 149 | let balance = await web3.provider.getBalance(address); 150 | let formatBalance = ethers.utils.formatEther(balance); 151 | dispatchUser({ 152 | type: userEnum.BALANCE, 153 | value: formatBalance.substring(0, 7), 154 | }); 155 | return formatBalance.substring(0, 7); 156 | }; 157 | 158 | const initToken = async () => { 159 | try { 160 | if ( 161 | ethereum && 162 | contracts.aiboostTokenSaleContract && 163 | contracts.aiboostTokenContract 164 | ) { 165 | setIsLoading(true); 166 | let tokenPrice = await contracts.aiboostTokenSaleContract.tokenPrice(); 167 | let tokenSold = await contracts.aiboostTokenSaleContract.tokenSold(); 168 | let userBalance = await contracts.aiboostTokenContract.balanceOf( 169 | user.currentAccount 170 | ); 171 | 172 | tokenPrice = ethers.utils.formatEther(tokenPrice); 173 | 174 | dispatchToken({ 175 | type: tokenEnum.BALANCE, 176 | value: userBalance.toNumber(), 177 | }); 178 | dispatchToken({ type: tokenEnum.PRICE, value: tokenPrice }); 179 | dispatchToken({ type: tokenEnum.SOLD, value: tokenSold.toNumber() }); 180 | setIsLoading(false); 181 | setTokenMessage(null); 182 | } else { 183 | console.log("contract is not initialized @initToken"); 184 | } 185 | } catch (error) { 186 | console.error(error); 187 | } 188 | }; 189 | 190 | const buyTokens = async (tokens) => { 191 | console.log("buying tokens for", tokens); 192 | if (tokens <= 0) { 193 | console.log("can not buy tokens"); 194 | } else { 195 | const value = ethers.BigNumber.from( 196 | ethers.utils.parseEther(token.price).toString() 197 | ).mul(tokens); 198 | const transactionHash = 199 | await contracts.aiboostTokenSaleContract.buyTokens(tokens, { 200 | from: user.currentAccount, 201 | value: value, 202 | gasLimit: 500000, 203 | }); 204 | setIsBuyingToken(true); 205 | console.log(`Loading - ${transactionHash.hash}`); 206 | await transactionHash.wait(); 207 | console.log(`Success - ${transactionHash.hash}`); 208 | setTokenMessage( 209 | `Token buy was successful from account ${shortenAddress( 210 | user.currentAccount 211 | )}.` 212 | ); 213 | setIsBuyingToken(false); 214 | } 215 | }; 216 | 217 | const getAllTransactions = async () => { 218 | try { 219 | if (ethereum && contracts.transactionContract) { 220 | const availableTransactions = 221 | await contracts.transactionContract.getTransactions(); 222 | 223 | const structuredTransactions = availableTransactions.map( 224 | (transaction) => { 225 | return { 226 | addressTo: transaction.receiver, 227 | addressFrom: transaction.sender, 228 | timestamp: new Date( 229 | +transaction.timestamp * 1000 230 | ).toLocaleString(), 231 | message: transaction.message, 232 | amount: +transaction.amount / 10 ** 18, 233 | }; 234 | } 235 | ); 236 | dispatchContracts({ 237 | type: contractEnum.TRANSACTIONS, 238 | value: structuredTransactions, 239 | }); 240 | } else { 241 | console.log("Ethereum is not present"); 242 | } 243 | } catch (error) { 244 | console.log(error); 245 | } 246 | }; 247 | 248 | const checkIfWalletIsConnect = async () => { 249 | try { 250 | if (!ethereum) { 251 | console.log("No ether found"); 252 | } else { 253 | setIsEther(true); 254 | } 255 | 256 | const accounts = await ethereum.request({ method: "eth_accounts" }); 257 | 258 | if (accounts.length) { 259 | dispatchUser({ type: userEnum.CURR_ACCOUNT, value: accounts[0] }); 260 | getAllTransactions(); 261 | } else { 262 | console.log("No accounts found"); 263 | } 264 | } catch (error) { 265 | console.log(error); 266 | } 267 | }; 268 | 269 | const checkIfTransactionsExists = async () => { 270 | try { 271 | if (ethereum && contracts.transactionContract) { 272 | const currentTransactionCount = 273 | await contracts.transactionContract.transactionCount(); 274 | 275 | window.localStorage.setItem( 276 | "transactionCount", 277 | currentTransactionCount 278 | ); 279 | } 280 | } catch (error) { 281 | console.log(error); 282 | 283 | throw new Error("No ethereum object"); 284 | } 285 | }; 286 | 287 | const connectWallet = async () => { 288 | try { 289 | if (!ethereum) { 290 | return alert( 291 | "Please install MetaMask and then connect to your wallet." 292 | ); 293 | } 294 | 295 | const accounts = await ethereum.request({ 296 | method: "eth_requestAccounts", 297 | }); 298 | 299 | dispatchUser({ type: userEnum.CURR_ACCOUNT, value: accounts[0] }); 300 | } catch (error) { 301 | console.log(error); 302 | 303 | throw new Error("No ethereum object"); 304 | } 305 | }; 306 | 307 | const sendTransaction = async () => { 308 | try { 309 | console.log(contracts); 310 | if (ethereum && contracts.transactionContract) { 311 | const { addressTo, amount, message } = formData; 312 | const parsedAmount = ethers.utils.parseEther(amount); 313 | 314 | await ethereum.request({ 315 | method: "eth_sendTransaction", 316 | params: [ 317 | { 318 | from: user.currentAccount, 319 | to: addressTo, 320 | gas: "0x5208", 321 | value: parsedAmount._hex, 322 | }, 323 | ], 324 | }); 325 | 326 | const transactionHash = 327 | await contracts.transactionContract.addTransaction( 328 | addressTo, 329 | parsedAmount, 330 | message 331 | ); 332 | 333 | setIsLoading(true); 334 | setSendingEther(true); 335 | console.log(`Loading - ${transactionHash.hash}`); 336 | await transactionHash.wait(); 337 | console.log(`Success - ${transactionHash.hash}`); 338 | setEtherMessage( 339 | `Sending ethereum was successful from ${shortenAddress( 340 | user.currentAccount 341 | )} to ${shortenAddress(addressTo)}.` 342 | ); 343 | 344 | setIsLoading(false); 345 | setSendingEther(false); 346 | getBalanceOf(); 347 | 348 | const transactionsCount = 349 | await contracts.transactionContract.transactionCount(); 350 | 351 | console.log(`transaction count => ${transactionsCount}`); 352 | 353 | dispatchContracts({ 354 | type: contractEnum.TRANSACTION_COUNT, 355 | value: +transactionsCount, 356 | }); 357 | } else { 358 | console.log("No ethereum object"); 359 | } 360 | } catch (error) { 361 | console.log(error); 362 | 363 | throw new Error("No ethereum object"); 364 | } 365 | }; 366 | 367 | // lottery pool contract 368 | const initLotteryPool = async () => { 369 | try { 370 | if (ethereum && contracts.lotteryPoolContract) { 371 | setIsLoading(true); 372 | // get all lotteries 373 | const lotteries = 374 | await contracts.lotteryPoolContract.getLotteryContractDetails(); 375 | 376 | // type cast lotteries. 377 | const lotteriesDetails = lotteries.map((lottery) => ({ 378 | endedTimeStamp: +lottery.endedTimeStamp, 379 | lotteryContract: lottery.lotteryContract, 380 | manager: lottery.manager, 381 | })); 382 | 383 | dispatchContracts({ 384 | type: contractEnum.LOTTERIES_DETAILS, 385 | value: lotteriesDetails, 386 | }); 387 | 388 | setIsLoading(false); 389 | } else { 390 | console.log("contract is not initialized @lottery"); 391 | } 392 | } catch (error) { 393 | console.error(error); 394 | } 395 | }; 396 | 397 | const initLotteryContract = async (lotteryAddress) => { 398 | try { 399 | if (ethereum && contracts.lotteryPoolContract) { 400 | setIsLoading(true); 401 | const lotteryContract = new ethers.Contract( 402 | lotteryAddress, 403 | lotteryContractABI, 404 | web3.provider.getSigner() 405 | ); 406 | 407 | const lotteryPrice = await lotteryContract.winningPrice(); 408 | const status = await lotteryContract.status(); 409 | console.log("Lottery Status", status); 410 | const manager = await lotteryContract.manager(); 411 | const winner = await lotteryContract.getWinner(); 412 | const players = await lotteryContract.getPlayers(); 413 | const entryFee = await lotteryContract.entryFee(); 414 | 415 | dispatchContracts({ 416 | type: contractEnum.LOTTERY_INIT, 417 | value: lotteryContract, 418 | }); 419 | 420 | dispatchContracts({ 421 | type: contractEnum.LOTTERY_MANAGER, 422 | value: manager, 423 | }); 424 | 425 | dispatchContracts({ 426 | type: contractEnum.LOTTERY_ENTRY_FEE, 427 | value: +entryFee, 428 | }); 429 | 430 | dispatchContracts({ 431 | type: contractEnum.LOTTERY_PLAYERS, 432 | value: players, 433 | }); 434 | 435 | dispatchContracts({ 436 | type: contractEnum.LOTTERY_WINNER, 437 | value: winner, 438 | }); 439 | 440 | dispatchContracts({ 441 | type: contractEnum.LOTTERY_PRICE, 442 | value: +lotteryPrice, 443 | }); 444 | 445 | setIsLoading(false); 446 | } else { 447 | console.log("ethereum || contracts.lotteryPoolContract not init"); 448 | } 449 | } catch (e) { 450 | console.error(e); 451 | } 452 | }; 453 | 454 | const getLotteryDetails = async (lotteryAddress) => { 455 | try { 456 | if (ethereum && contracts.lotteryPoolContract) { 457 | const lotteryDetail = 458 | await contracts.lotteryPoolContract.getLotteryContract( 459 | lotteryAddress 460 | ); 461 | let local = { 462 | lotteryAddress: lotteryDetail.lotteryContract, 463 | endedTimeStamp: +lotteryDetail.endedTimeStamp, 464 | manager: lotteryDetail.manager, 465 | }; 466 | return local; 467 | } else { 468 | console.log("contract is not initialized @lottery"); 469 | } 470 | } catch (e) { 471 | console.error(error); 472 | } 473 | }; 474 | 475 | const startLottery = async (startTime) => { 476 | try { 477 | if (startTime <= 0) { 478 | console.error(`Cannot Start Lottery with ${startTime} time`); 479 | } else { 480 | if (ethereum && contracts.lotteryPoolContract) { 481 | const start = await contracts.lotteryPoolContract.createLottery( 482 | startTime 483 | ); 484 | setIsLoading(true); 485 | setIsCreatingLottery(true); 486 | console.log(`Loading - ${start.hash}`); 487 | await start.wait(); 488 | console.log(`Success - ${start.hash}`); 489 | setCreateLotteryMessage( 490 | `Lottery Created Successful by ${shortenAddress( 491 | user.currentAccount 492 | )}.` 493 | ); 494 | // dispatchContracts({ type: contractEnum.LOTTERY_START, value: start }); 495 | setIsLoading(false); 496 | setIsCreatingLottery(false); 497 | } else { 498 | console.log("The lottery has not started yet"); 499 | } 500 | } 501 | } catch (error) { 502 | console.error(error); 503 | } 504 | }; 505 | 506 | const enterLottery = async () => { 507 | try { 508 | if (ethereum && contracts.lotteryContract) { 509 | setIsLoading(true); 510 | const enter = await contracts.lotteryContract.enter({ 511 | from: user.currentAccount, 512 | value: contracts.lotteryEntryFee, 513 | gasLimit: 500000, 514 | }); 515 | console.log(`Entering Lottery Plz Wait - ${enter.hash}`); 516 | await enter.wait(); 517 | console.log(`Entered Lottery Successfully - ${enter.hash}`); 518 | if ( 519 | !alert( 520 | `Transaction Confirmed ${enter.hash} \n from: ${user.currentAccount}` 521 | ) 522 | ) { 523 | location.reload(); 524 | } 525 | dispatchContracts({ type: contractEnum.LOTTERY_ENTER, value: enter }); 526 | setIsLoading(false); 527 | } else { 528 | console.log("You have not entered the lottery yet"); 529 | } 530 | } catch (error) { 531 | console.error(error); 532 | } 533 | }; 534 | 535 | const endLottery = async () => { 536 | try { 537 | if (ethereum && contracts.lotteryContract) { 538 | setIsLoading(true); 539 | const end = await contracts.lotteryContract.end(); 540 | console.log(`Ending Lottery Plz Wait - ${end.hash}`); 541 | await end.wait(); 542 | console.log(`Lottery Ended Successfully - ${end.hash}`); 543 | if ( 544 | !alert( 545 | `Transaction Confirmed ${end.hash} \n from: ${user.currentAccount}` 546 | ) 547 | ) { 548 | location.reload(); 549 | } 550 | dispatchContracts({ type: contractEnum.LOTTERY_END, value: end }); 551 | setIsLoading(false); 552 | } else { 553 | console.log("Lottery is not initiated or no ether found"); 554 | } 555 | } catch (error) { 556 | console.error(error); 557 | } 558 | }; 559 | 560 | const lotteryTimeRemaining = async () => { 561 | try { 562 | setIsLoading(true); 563 | if (ethereum && contracts.lotteryPoolContract) { 564 | const timeRemaining = 565 | await contracts.lotteryPoolContract.getRemainingTime(); 566 | console.log("Contract ⌚ Remaining", timeRemaining); 567 | dispatchContracts({ 568 | type: contractEnum.LOTTERY_TIME_REMAINING, 569 | value: timeRemaining, 570 | }); 571 | setIsLoading(false); 572 | } else { 573 | console.log("Lottery is not initiated or no ether will be found"); 574 | } 575 | } catch (error) { 576 | console.error(error); 577 | } 578 | }; 579 | 580 | if (ethereum) { 581 | useEffect(() => { 582 | async function init() { 583 | await checkIfWalletIsConnect(); 584 | await createEthereumContract(); 585 | await checkIfTransactionsExists(); 586 | await initLotteryPool(); 587 | 588 | window.ethereum.on("chainChanged", async () => { 589 | console.log("network changed!!"); 590 | window.location.reload(); 591 | }); 592 | 593 | window.ethereum.on("accountsChanged", async () => { 594 | console.log("accounts changed"); 595 | window.location.reload(); 596 | }); 597 | } 598 | init(); 599 | }, []); 600 | } 601 | 602 | return ( 603 | 650 | {children} 651 | 652 | ); 653 | }; 654 | --------------------------------------------------------------------------------