├── docs ├── HomePage.png ├── CampaignCreation │ ├── 1_CampaignCreation.png │ ├── 3_NewCampaignCreated.png │ ├── 5_CampaignPageToPublic.png │ ├── 2_ApproveWalletForCreation.png │ └── 4_CampaignPageToFundRaiser.png ├── Contributing │ ├── 2_ContributionSuccess.png │ ├── 1_ContributingMinimumAmount.png │ └── 3_ContributionUpdatedStatus.png ├── ViewingTransactionHistoryInEtherScan.png ├── WalletConnection │ ├── 1_WalletConnection.png │ ├── 3_WalletConnected.png │ └── 2_WalletConnection_1.png ├── AbortingCampaign │ ├── 1_Aborting_fundraiser.png │ ├── 2_Aborting_clickAfterReason.png │ ├── 4_Aborting_Backer'sWallet_After.png │ ├── 3_Aborting_acceptingConfirmation.png │ └── 0_Aborting_Backer'sWalletAfterContribution.png ├── ViewingTransactionHistoryInEtherScan_0.png └── EndingCampaign │ ├── 1_BeforeEndCampaignWalletBalance.png │ ├── 3_WalletBalanceAfterSuccessfulEnd.png │ └── 2_ApproveEndCampaignWalletConfirmation.png ├── artifacts ├── hardhat │ └── console.sol │ │ ├── console.dbg.json │ │ └── console.json └── contracts │ ├── Campaign.sol │ ├── Campaign.dbg.json │ └── Campaign.json │ └── CrowdHelp.sol │ └── CrowdHelp.dbg.json ├── vite.config.js ├── utils ├── contract │ ├── campaign.js │ └── crowdHelp.js ├── web3.js └── getCampaigns.js ├── src ├── pages │ ├── campaigns │ │ ├── SetMileStones.jsx │ │ ├── ReviewCampaignDetails.jsx │ │ ├── ActiveCampaigns.jsx │ │ ├── CreateCampaignWrapper.jsx │ │ ├── FillCampaignDetails.jsx │ │ └── ViewCampaign.jsx │ ├── HomePage.jsx │ ├── ForgotPassword.jsx │ ├── Profile.jsx │ ├── SignIn.jsx │ └── SignUp.jsx ├── main.jsx ├── components │ ├── Copyright.jsx │ ├── AuthProtectedRoute.jsx │ ├── Footer.jsx │ ├── CampaignCard.jsx │ └── NavBar.jsx ├── config │ └── firebase-config.js ├── App.css ├── index.css ├── App.jsx ├── contexts │ └── AuthContext.jsx └── assets │ └── react.svg ├── .gitignore ├── index.html ├── LICENSE ├── contracts ├── CampaignSchemeEnums.sol ├── CrowdHelp.sol └── Campaign.sol ├── public └── vite.svg ├── package.json ├── hardhat.config.js ├── scripts └── deploy.js ├── test └── CrowdHelp.test.js └── README.md /docs/HomePage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/HomePage.png -------------------------------------------------------------------------------- /artifacts/hardhat/console.sol/console.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../build-info/c8c1647ad1cca5e3b94146397d3b4f58.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/contracts/Campaign.sol/Campaign.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../build-info/fef89d36fbf081e93b07e94bbd0b0c02.json" 4 | } 5 | -------------------------------------------------------------------------------- /artifacts/contracts/CrowdHelp.sol/CrowdHelp.dbg.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-dbg-1", 3 | "buildInfo": "../../build-info/fef89d36fbf081e93b07e94bbd0b0c02.json" 4 | } 5 | -------------------------------------------------------------------------------- /docs/CampaignCreation/1_CampaignCreation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/CampaignCreation/1_CampaignCreation.png -------------------------------------------------------------------------------- /docs/Contributing/2_ContributionSuccess.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/Contributing/2_ContributionSuccess.png -------------------------------------------------------------------------------- /docs/ViewingTransactionHistoryInEtherScan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/ViewingTransactionHistoryInEtherScan.png -------------------------------------------------------------------------------- /docs/WalletConnection/1_WalletConnection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/WalletConnection/1_WalletConnection.png -------------------------------------------------------------------------------- /docs/WalletConnection/3_WalletConnected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/WalletConnection/3_WalletConnected.png -------------------------------------------------------------------------------- /docs/AbortingCampaign/1_Aborting_fundraiser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/AbortingCampaign/1_Aborting_fundraiser.png -------------------------------------------------------------------------------- /docs/CampaignCreation/3_NewCampaignCreated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/CampaignCreation/3_NewCampaignCreated.png -------------------------------------------------------------------------------- /docs/ViewingTransactionHistoryInEtherScan_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/ViewingTransactionHistoryInEtherScan_0.png -------------------------------------------------------------------------------- /docs/WalletConnection/2_WalletConnection_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/WalletConnection/2_WalletConnection_1.png -------------------------------------------------------------------------------- /docs/CampaignCreation/5_CampaignPageToPublic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/CampaignCreation/5_CampaignPageToPublic.png -------------------------------------------------------------------------------- /docs/Contributing/1_ContributingMinimumAmount.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/Contributing/1_ContributingMinimumAmount.png -------------------------------------------------------------------------------- /docs/Contributing/3_ContributionUpdatedStatus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/Contributing/3_ContributionUpdatedStatus.png -------------------------------------------------------------------------------- /docs/CampaignCreation/2_ApproveWalletForCreation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/CampaignCreation/2_ApproveWalletForCreation.png -------------------------------------------------------------------------------- /docs/CampaignCreation/4_CampaignPageToFundRaiser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/CampaignCreation/4_CampaignPageToFundRaiser.png -------------------------------------------------------------------------------- /docs/AbortingCampaign/2_Aborting_clickAfterReason.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/AbortingCampaign/2_Aborting_clickAfterReason.png -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()] 7 | }) 8 | -------------------------------------------------------------------------------- /docs/AbortingCampaign/4_Aborting_Backer'sWallet_After.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/AbortingCampaign/4_Aborting_Backer'sWallet_After.png -------------------------------------------------------------------------------- /docs/EndingCampaign/1_BeforeEndCampaignWalletBalance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/EndingCampaign/1_BeforeEndCampaignWalletBalance.png -------------------------------------------------------------------------------- /docs/EndingCampaign/3_WalletBalanceAfterSuccessfulEnd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/EndingCampaign/3_WalletBalanceAfterSuccessfulEnd.png -------------------------------------------------------------------------------- /docs/AbortingCampaign/3_Aborting_acceptingConfirmation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/AbortingCampaign/3_Aborting_acceptingConfirmation.png -------------------------------------------------------------------------------- /docs/EndingCampaign/2_ApproveEndCampaignWalletConfirmation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/EndingCampaign/2_ApproveEndCampaignWalletConfirmation.png -------------------------------------------------------------------------------- /docs/AbortingCampaign/0_Aborting_Backer'sWalletAfterContribution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Balaji-Ganesh/CrowdHelp-Blockchain-based-crowdfunding-platform/HEAD/docs/AbortingCampaign/0_Aborting_Backer'sWalletAfterContribution.png -------------------------------------------------------------------------------- /utils/contract/campaign.js: -------------------------------------------------------------------------------- 1 | import web3 from "../web3"; 2 | import Campaign from "../../artifacts/contracts/CrowdHelp.sol/Campaign.json"; 3 | 4 | export default (address) => { 5 | return new web3.eth.Contract(Campaign.abi, address); 6 | }; 7 | -------------------------------------------------------------------------------- /src/pages/campaigns/SetMileStones.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | function SetMileStones() { 4 | return ( 5 | <> 6 |
SetMileStones - this feature will be added later
7 | 8 | ); 9 | } 10 | 11 | export default SetMileStones; 12 | -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import App from "./App"; 4 | import "./index.css"; 5 | import "./config/firebase-config"; // for firebase. 6 | 7 | ReactDOM.createRoot(document.getElementById("root")).render( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /utils/contract/crowdHelp.js: -------------------------------------------------------------------------------- 1 | import web3 from "../web3"; 2 | import CrowdHelp from "../../artifacts/contracts/CrowdHelp.sol/CrowdHelp.json"; 3 | 4 | const crowdHelpContractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3"; 5 | const crowdHelp = new web3.eth.Contract( 6 | CrowdHelp.abi, 7 | crowdHelpContractAddress 8 | ); 9 | 10 | export default crowdHelp; 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | # hardhat 27 | cache 28 | deployments 29 | 30 | .env -------------------------------------------------------------------------------- /src/components/Copyright.jsx: -------------------------------------------------------------------------------- 1 | import { Link, Typography } from "@mui/material"; 2 | function Copyright() { 3 | return ( 4 | 5 | {"Copyright © "} 6 | 7 | CrowdHelp 8 | {" "} 9 | {new Date().getFullYear()} 10 | {"."} 11 | 12 | ); 13 | } 14 | 15 | export default Copyright; 16 | -------------------------------------------------------------------------------- /utils/web3.js: -------------------------------------------------------------------------------- 1 | import Web3 from "web3"; 2 | 3 | let web3; 4 | 5 | if (typeof window !== "undefined" && typeof window.web3 !== "undefined") { 6 | // we are in the browser and meta mask is installed 7 | web3 = new Web3(window.web3.currentProvider); 8 | } else { 9 | // we are on the server *OR* meta mask is not running 10 | // creating our own provider 11 | const provider = new Web3.providers.HttpProvider( 12 | "https://goerli.infura.io/v3/eaf842956c36444c8aaf54163a47e0d2" 13 | ); 14 | 15 | web3 = new Web3(provider); 16 | } 17 | 18 | export default web3; 19 | -------------------------------------------------------------------------------- /src/config/firebase-config.js: -------------------------------------------------------------------------------- 1 | import firebase from "firebase/compat/app"; 2 | 3 | const firebaseConfig = { 4 | apiKey: "AIzaSyCqkXQ1RXsNc4h1o-crilJ4kyk-kP2sELY", 5 | authDomain: "fir-experiments-16493.firebaseapp.com", 6 | projectId: "fir-experiments-16493", 7 | storageBucket: "fir-experiments-16493.appspot.com", 8 | messagingSenderId: "646710968437", 9 | appId: "1:646710968437:web:a04fd85f922b759ca0783c", 10 | }; 11 | 12 | // Initialize Firebase 13 | const app = firebase.initializeApp(firebaseConfig); 14 | export const auth = app.auth(); 15 | // export 📦 16 | export default app; 17 | -------------------------------------------------------------------------------- /src/components/AuthProtectedRoute.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Navigate } from "react-router-dom"; 3 | import { useAuth } from "../contexts/AuthContext"; 4 | 5 | // this going to work as a private router to actual router. 6 | // Why? to prevent from accessing certail pages. 7 | // i.e., without getting signed in, if trying to access profile page, what shall we show? 8 | const AuthProtectedRoute = ({ redirectPath = "/sign-in", children }) => { 9 | const { currentUserCredentials } = useAuth(); 10 | 11 | if (!currentUserCredentials) { 12 | return ; 13 | } 14 | 15 | return children; 16 | }; 17 | 18 | export default AuthProtectedRoute; 19 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | CrowdFund - Get Help from Crowd 8 | 12 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /artifacts/hardhat/console.sol/console.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "console", 4 | "sourceName": "hardhat/console.sol", 5 | "abi": [], 6 | "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122029ce6e039ea322c9fb75e8353f8ef45c3f4ff6aedf8833d58f1691ccfa56accb64736f6c63430008000033", 7 | "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122029ce6e039ea322c9fb75e8353f8ef45c3f4ff6aedf8833d58f1691ccfa56accb64736f6c63430008000033", 8 | "linkReferences": {}, 9 | "deployedLinkReferences": {} 10 | } 11 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | /* #root { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | 8 | .logo { 9 | height: 6em; 10 | padding: 1.5em; 11 | will-change: filter; 12 | } 13 | .logo:hover { 14 | filter: drop-shadow(0 0 2em #646cffaa); 15 | } 16 | .logo.react:hover { 17 | filter: drop-shadow(0 0 2em #61dafbaa); 18 | } 19 | 20 | @keyframes logo-spin { 21 | from { 22 | transform: rotate(0deg); 23 | } 24 | to { 25 | transform: rotate(360deg); 26 | } 27 | } 28 | 29 | @media (prefers-reduced-motion: no-preference) { 30 | a:nth-of-type(2) .logo { 31 | animation: logo-spin infinite 20s linear; 32 | } 33 | } 34 | 35 | .card { 36 | padding: 2em; 37 | } 38 | 39 | .read-the-docs { 40 | color: #888; 41 | } */ 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Balaji Ganesh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/Footer.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import CssBaseline from "@mui/material/CssBaseline"; 3 | import Box from "@mui/material/Box"; 4 | import Typography from "@mui/material/Typography"; 5 | import Container from "@mui/material/Container"; 6 | import Copyright from "./Copyright"; 7 | 8 | export default function Footer() { 9 | return ( 10 | 17 | 18 | 19 | 26 | theme.palette.mode === "light" 27 | ? theme.palette.grey[200] 28 | : theme.palette.grey[800], 29 | }} 30 | > 31 | 32 | 33 | CrowdHelp platform - [ONLY] Core functionalities done. 🚧. 34 | 35 | 36 | 37 | 38 | 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /contracts/CampaignSchemeEnums.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | uint constant SCHEMES_COUNT = 2; // Make sure to modify accordingly as per items in following enum. 5 | enum CampaignSchemeId { 6 | ALL_OR_NOTHING, // 0 7 | HALF_GOAL_WITHDRAW // 1 8 | // MILESTONES_BASED // upcoming.. 9 | } 10 | 11 | function getSchemeTitle(uint idx) pure returns (string memory title) { 12 | require(idx < SCHEMES_COUNT, "Index out of range"); 13 | if (idx == uint(CampaignSchemeId.ALL_OR_NOTHING)) return "All or Nothing"; 14 | if (idx == uint(CampaignSchemeId.HALF_GOAL_WITHDRAW)) return "Half goal withdraw"; 15 | return "Invalid scheme"; 16 | } 17 | 18 | function getAllSchemeTitles() pure returns (string[] memory) { 19 | string[] memory allSchemeTitles = new string[](SCHEMES_COUNT); 20 | for (uint i = 0; i < SCHEMES_COUNT; i++) { 21 | allSchemeTitles[i] = getSchemeTitle(i); 22 | } 23 | return allSchemeTitles; 24 | } 25 | 26 | function getSchemeId(uint id) pure returns (CampaignSchemeId) { 27 | require(id < SCHEMES_COUNT , "Index out of range"); 28 | if (id == uint(CampaignSchemeId.ALL_OR_NOTHING)) return CampaignSchemeId.ALL_OR_NOTHING; 29 | return CampaignSchemeId.HALF_GOAL_WITHDRAW; 30 | } 31 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | /* :root { 2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif; 3 | font-size: 16px; 4 | line-height: 24px; 5 | font-weight: 400; 6 | 7 | color-scheme: light dark; 8 | color: rgba(255, 255, 255, 0.87); 9 | background-color: #242424; 10 | 11 | font-synthesis: none; 12 | text-rendering: optimizeLegibility; 13 | -webkit-font-smoothing: antialiased; 14 | -moz-osx-font-smoothing: grayscale; 15 | -webkit-text-size-adjust: 100%; 16 | } 17 | 18 | a { 19 | font-weight: 500; 20 | color: #646cff; 21 | text-decoration: inherit; 22 | } 23 | a:hover { 24 | color: #535bf2; 25 | } 26 | 27 | body { 28 | margin: 0; 29 | display: flex; 30 | place-items: center; 31 | min-width: 320px; 32 | min-height: 100vh; 33 | } 34 | 35 | h1 { 36 | font-size: 3.2em; 37 | line-height: 1.1; 38 | } 39 | 40 | button { 41 | border-radius: 8px; 42 | border: 1px solid transparent; 43 | padding: 0.6em 1.2em; 44 | font-size: 1em; 45 | font-weight: 500; 46 | font-family: inherit; 47 | background-color: #1a1a1a; 48 | cursor: pointer; 49 | transition: border-color 0.25s; 50 | } 51 | button:hover { 52 | border-color: #646cff; 53 | } 54 | button:focus, 55 | button:focus-visible { 56 | outline: 4px auto -webkit-focus-ring-color; 57 | } 58 | 59 | @media (prefers-color-scheme: light) { 60 | :root { 61 | color: #213547; 62 | background-color: #ffffff; 63 | } 64 | a:hover { 65 | color: #747bff; 66 | } 67 | button { 68 | background-color: #f9f9f9; 69 | } 70 | } */ 71 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crowdhelp", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "preview": "vite preview" 9 | }, 10 | "dependencies": { 11 | "@emotion/react": "^11.10.5", 12 | "@emotion/styled": "^11.10.5", 13 | "@mui/icons-material": "^5.10.9", 14 | "@mui/lab": "^5.0.0-alpha.109", 15 | "@mui/material": "^5.10.11", 16 | "@nomiclabs/hardhat-ethers": "^2.2.1", 17 | "@truffle/hdwallet-provider": "^2.1.1", 18 | "axios": "^1.1.3", 19 | "dotenv": "^16.0.3", 20 | "firebase": "^9.13.0", 21 | "fs-extra": "^10.0.0", 22 | "moment": "^2.29.4", 23 | "react": "^18.2.0", 24 | "react-dom": "^18.2.0", 25 | "react-hook-form": "^7.39.5", 26 | "react-router-dom": "^6.4.3", 27 | "solc": "^0.8.0", 28 | "use-wallet": "0.10.0", 29 | "web3": "^1.3.5" 30 | }, 31 | "devDependencies": { 32 | "@ethersproject/providers": "^5.4.7", 33 | "@nomicfoundation/hardhat-chai-matchers": "^1.0.0", 34 | "@nomicfoundation/hardhat-network-helpers": "^1.0.0", 35 | "@nomicfoundation/hardhat-toolbox": "^2.0.0", 36 | "@nomiclabs/hardhat-etherscan": "^3.0.0", 37 | "@typechain/ethers-v5": "^10.1.0", 38 | "@typechain/hardhat": "^6.1.2", 39 | "@types/chai": "^4.2.0", 40 | "@types/mocha": "^9.1.0", 41 | "@types/react": "^18.0.22", 42 | "@types/react-dom": "^18.0.7", 43 | "@vitejs/plugin-react": "^2.2.0", 44 | "chai": "^4.2.0", 45 | "ethers": "^5.0.0", 46 | "hardhat": "^2.12.2", 47 | "hardhat-deploy": "^0.11.20", 48 | "hardhat-gas-reporter": "^1.0.8", 49 | "solidity-coverage": "^0.8.1", 50 | "ts-node": ">=8.0.0", 51 | "typechain": "^8.1.0", 52 | "typescript": ">=4.5.0", 53 | "vite": "^3.2.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config({ path: __dirname + "/.env.local" }); // When deploying -- be careful about this path.. 2 | require("@nomiclabs/hardhat-ethers"); 3 | require("hardhat-deploy"); 4 | require("@nomicfoundation/hardhat-toolbox"); 5 | 6 | console.log(process.env.INFURA_API_KEY); 7 | console.log(process.env.PRIVATE_KEY); 8 | 9 | module.exports = { 10 | solidity: { 11 | version: "0.8.0", 12 | settings: { 13 | optimizer: { 14 | enabled: true, 15 | runs: 200, 16 | }, 17 | // viaIR: true, 18 | }, 19 | }, 20 | mocha: { 21 | timeout: 90000, 22 | }, 23 | networks: { 24 | localhost: { 25 | url: "http://127.0.0.1:8545", 26 | }, 27 | hardhat: { 28 | initialBaseFeePerGas: 0, 29 | blockGasLimit: 18800000, 30 | chainId: 31337, 31 | }, 32 | // goerli_testnet: { 33 | // // url: `https://goerli.infura.io/v3/${process.env.INFURA_API_KEY}`, <<-- tried this way, its failing, so employed below way. 34 | // url: "https://goerli.infura.io/v3/eaf842956c36444c8aaf54163a47e0d2", 35 | // accounts: [process.env.PRIVATE_KEY], 36 | // gasPrice: 1000, 37 | // saveDeployments: true, 38 | // deploy: ["scripts/"], 39 | // }, 40 | }, 41 | }; 42 | 43 | /** 44 | * guide: https://docs.palm.io/HowTo/Deploy-using-Hardhat/ - as redirected by Infura (to deploy via HardHat) 45 | * $ npx hardhat compile 46 | * $ npx hardhat --network goerli_testnet deploy 47 | Nothing to compile 48 | Contract deployed to address: 0xB2B305a50121d6acC8c0F8951a6cdb41d3bB0C6D 49 | deploying "CrowdHelp" (tx: 0xe7a0301eae21ef759c24c188d2554d538cbe5e11d3ea1b9c6c385862d38df927)...: deployed at 0x5a61c16165e797bb770887F339f9DCb6608dce02 with 2316759 gas 50 | 51 | new deploy.. 52 | eaf842956c36444c8aaf54163a47e0d2 53 | 367d65fef68348fd92b6ba50e22b9bd63d45c7cf8c72072cedb6b8ae6ba7f8fc 54 | Nothing to compile 55 | Contract deployed to address: 0xB2B305a50121d6acC8c0F8951a6cdb41d3bB0C6D 56 | reusing "CrowdHelp" at 0x5a61c16165e797bb770887F339f9DCb6608dce02 57 | */ 58 | -------------------------------------------------------------------------------- /contracts/CrowdHelp.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./CampaignSchemeEnums.sol"; 5 | import "./Campaign.sol"; 6 | import "hardhat/console.sol"; 7 | 8 | contract CrowdHelp { 9 | // events 10 | event CampaignStarted( 11 | address projectContractAddress, 12 | address creator, 13 | uint256 minContribution, 14 | uint256 projectDeadline, 15 | uint256 goalAmount, 16 | uint256 currentAmount, 17 | uint256 noOfContributors, 18 | string title, 19 | string desc, 20 | uint currentState 21 | ); 22 | 23 | event ContributionReceived( 24 | address projectAddress, 25 | uint256 contributedAmount, 26 | address indexed contributor 27 | ); 28 | 29 | event CampaignCreationFailed(string reason); 30 | 31 | Campaign[] private deployedCampaigns; 32 | 33 | // @dev Anyone can start a fund rising 34 | // @return null 35 | 36 | function createCampaign( 37 | string memory projectTitle, 38 | string memory projectDesc, 39 | uint256 minimumContribution, 40 | uint256 targetContribution, 41 | uint256 deadline, 42 | string memory bannerUrl, 43 | uint campaignSchemeId 44 | ) public { 45 | console.log("Creating campaign with scheme:", uint(campaignSchemeId)); 46 | Campaign campaign = new Campaign( 47 | msg.sender, 48 | minimumContribution, 49 | deadline, 50 | targetContribution, 51 | projectTitle, 52 | projectDesc, 53 | bannerUrl, 54 | campaignSchemeId // passing directly like this.. 55 | ); 56 | 57 | console.log("Creating campaign with scheme:", uint(campaignSchemeId)); 58 | deployedCampaigns.push(campaign); 59 | } 60 | 61 | // @dev Get deployedCampaigns list 62 | // @return array 63 | 64 | function returnDeployedCampaigns() 65 | external 66 | view 67 | returns (Campaign[] memory) 68 | { 69 | return deployedCampaigns; 70 | } 71 | 72 | function getDeployedCampaigns() public view returns (address[] memory) { 73 | address[] memory campaignAddresses = new address[](deployedCampaigns.length); 74 | for (uint i = 0; i < deployedCampaigns.length; i++) { 75 | campaignAddresses[i] = address(deployedCampaigns[i]); 76 | } 77 | return campaignAddresses; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | // library and component imports.. 2 | import "./App.css"; 3 | 4 | // custom imports 5 | // import Feed from "./components/Feed"; 6 | import { Box } from "@mui/material"; 7 | import SignIn from "./pages/SignIn"; 8 | import SignUp from "./pages/SignUp"; 9 | import CreateCampaignWrapper from "./pages/campaigns/CreateCampaignWrapper"; 10 | import FillCampaignDetails from "./pages/campaigns/FillCampaignDetails"; 11 | import ReviewCampaignDetails from "./pages/campaigns/ReviewCampaignDetails"; 12 | import HomePage from "./pages/HomePage"; 13 | import ActiveCampaigns from "./pages/campaigns/ActiveCampaigns"; 14 | import AuthProvider from "./contexts/AuthContext"; 15 | import Profile from "./pages/Profile"; 16 | import ViewCampaign from "./pages/campaigns/ViewCampaign"; 17 | 18 | import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; 19 | import AuthProtectedRoute from "./components/AuthProtectedRoute"; 20 | import ForgotPassword from "./pages/ForgotPassword"; 21 | 22 | // For wallet connection & usage.. 23 | import { UseWalletProvider } from "use-wallet"; 24 | 25 | function App() { 26 | return ( 27 | 36 | 37 | 38 | 39 | } /> 40 | } /> 41 | } /> 42 | } /> 43 | 47 | 48 | 49 | } 50 | /> 51 | 55 | 56 | // {/* */} 57 | } 58 | /> 59 | } /> 60 | } /> 61 | 62 | 63 | 64 | 65 | ); 66 | } 67 | 68 | export default App; 69 | -------------------------------------------------------------------------------- /src/pages/campaigns/ReviewCampaignDetails.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | Button, 3 | Container, 4 | TextField, 5 | Typography, 6 | styled, 7 | Avatar, 8 | Link, 9 | List, 10 | ListItem, 11 | Box, 12 | Grid, 13 | ListItemText, 14 | } from "@mui/material"; 15 | import React from "react"; 16 | 17 | const addresses = [ 18 | "Keshav Memorial Institute of Technology", 19 | "Keshav Memorial Lane", 20 | "Narayanaguda", 21 | "Hyderabad", 22 | "TS", 23 | ]; 24 | const milestones = [ 25 | { name: "Milestone 1", detail: "1st Jan" }, 26 | { name: "Milestone 2", detail: "1st Feb" }, 27 | { name: "Milestone 3", detail: "1st March" }, 28 | ]; 29 | 30 | const campaignDetails = [ 31 | { name: "Campaign Title", detail: "Covid-19 help" }, 32 | { 33 | name: "Campaign Description", 34 | detail: "To help the people needy in covid-19 vaccine.", 35 | }, 36 | { name: "State", detail: "Telangana" }, 37 | { name: "City", detail: "Hyderabad" }, 38 | { name: "Category", detail: "Medical" }, 39 | { name: "Amount to be raised", detail: "50 ETH" }, 40 | { name: "Timeline", detail: "3rd March" }, 41 | ]; 42 | 43 | const StyledTypographyTitle = styled(Typography)(({ theme }) => ({ 44 | marginTop: theme.spacing(2), 45 | })); 46 | 47 | function ReviewCampaignDetails() { 48 | return ( 49 | <> 50 | 51 | Campaign Details 52 | 53 | 54 | {campaignDetails.map((campaignDetail) => ( 55 | 56 | 57 | {campaignDetail.name} 58 | 59 | 60 | {campaignDetail.detail} 61 | 62 | 63 | ))} 64 | 65 | 66 | 67 | 68 | Shipping 69 | 70 | Fund Raiser Name 71 | {addresses.join(", ")} 72 | 73 | 74 | 75 | Milestones summary 76 | 77 | 78 | {milestones.map((milestone) => ( 79 | 80 | 81 | {milestone.name} 82 | 83 | 84 | {milestone.detail} 85 | 86 | 87 | ))} 88 | 89 | 90 | 91 | 92 | ); 93 | } 94 | 95 | export default ReviewCampaignDetails; 96 | -------------------------------------------------------------------------------- /scripts/deploy.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | 3 | async function main() { 4 | const CrowdHelp = await hre.ethers.getContractFactory("CrowdHelp"); 5 | const crowdHelp = await CrowdHelp.deploy(); 6 | await crowdHelp.createCampaign( 7 | "Project X", 8 | "Desc", 9 | 100, 10 | 1000, 11 | 1212124, 12 | "bannerUrl", 13 | 0 14 | ); // Assuming scheme = 0 15 | 16 | // const [deployer] = await hre.ethers.getSigners(); 17 | 18 | // const Campaign = await hre.ethers.getContractFactory("Campaign"); 19 | 20 | // const campaign = await Campaign.deploy( 21 | // deployer.address, 22 | // 100, // minimum 23 | // 1713728020, // deadline timestamp 24 | // 1000, // target 25 | // "Test Project", // title 26 | // "This is a test", // desc 27 | // "http://banner.url", // banner 28 | // 0 // schemeId (assuming enum Basic) 29 | // ); 30 | 31 | await crowdHelp.deployed(); 32 | 33 | console.log("CrowdHelp deployed to:", crowdHelp.address); 34 | } 35 | 36 | main() 37 | .then(() => process.exit(0)) 38 | .catch((error) => { 39 | console.error("Deployment failed:", error); 40 | process.exit(1); 41 | }); 42 | 43 | // const hre = require("hardhat"); 44 | 45 | // async function main() { 46 | // // Deploy the factory contract 47 | // const CrowdHelp = await hre.ethers.getContractFactory("CrowdHelp"); 48 | // const crowdHelp = await CrowdHelp.deploy(); 49 | // await crowdHelp.deployed(); 50 | 51 | // console.log("CrowdHelp deployed to:", crowdHelp.address); 52 | 53 | // // Now create a campaign with VALID parameters 54 | // const minContribution = hre.ethers.utils.parseEther("0.01"); 55 | // const goal = hre.ethers.utils.parseEther("1"); 56 | // const deadline = Math.floor(Date.now() / 1000) + 86400; // 24 hours from now 57 | 58 | // const tx = await crowdHelp.createCampaign( 59 | // "Save the Forests", // projectTitle 60 | // "Planting 10,000 trees to fight climate change", // projectDesc 61 | // minContribution, 62 | // goal, 63 | // deadline, 64 | // "https://images.unsplash.com/photo-1503785640985-f62e3aeee448", // bannerUrl 65 | // 0 // campaignSchemeId - ✅ must be 0 or 1 only 66 | // ); 67 | 68 | // await tx.wait(); 69 | // console.log("Campaign created successfully!"); 70 | 71 | // // fetch the created campaign 72 | // const campaigns = await crowdHelp.returnDeployedCampaigns(); 73 | // console.log("Deployed campaigns:", campaigns); 74 | 75 | // console.log("Deploying campaign with:"); 76 | // console.log({ 77 | // projectTitle: "Some Title", 78 | // projectDesc: "Some Description", 79 | // minimumContribution: ethers.utils.parseEther("0.01").toString(), 80 | // targetContribution: ethers.utils.parseEther("1").toString(), 81 | // deadline: Math.floor(Date.now() / 1000) + 86400, 82 | // bannerUrl: "https://someurl.com/banner.jpg", 83 | // campaignSchemeId: 0, // or 1 ONLY 84 | // }); 85 | // } 86 | 87 | // // Standard error handler 88 | // main() 89 | // .then(() => process.exit(0)) 90 | // .catch((error) => { 91 | // console.error("Deployment failed:", error); 92 | // process.exit(1); 93 | // }); 94 | -------------------------------------------------------------------------------- /src/pages/campaigns/ActiveCampaigns.jsx: -------------------------------------------------------------------------------- 1 | // library and component imports.. 2 | import React, { useEffect } from "react"; 3 | import Button from "@mui/material/Button"; 4 | 5 | import Grid from "@mui/material/Grid"; 6 | import Stack from "@mui/material/Stack"; 7 | import Box from "@mui/material/Box"; 8 | import Typography from "@mui/material/Typography"; 9 | import Container from "@mui/material/Container"; 10 | import CircularProgress from "@mui/material/CircularProgress"; 11 | 12 | // local imports 13 | import CampaignCard from "../../components/CampaignCard"; 14 | import Footer from "../../components/Footer"; 15 | import NavBar from "../../components/NavBar"; 16 | 17 | // service imports.. 18 | import axios from "axios"; 19 | 20 | const api_url = "http://localhost:4000/api/"; 21 | 22 | function ActiveCampaigns() { 23 | // hooks.. 24 | const [activeCampaigns, setActiveCampaigns] = React.useState([]); 25 | 26 | useEffect(() => { 27 | console.log("useEffect called"); 28 | let ignore = false; 29 | // fetch the campaigns.. 30 | const fetchData = async () => { 31 | const response = await axios.get(api_url + "active-campaigns/10"); 32 | console.info(response.data); 33 | if (!ignore && response.status == 200) setActiveCampaigns(response.data); 34 | }; 35 | 36 | fetchData(); // call the function to fetch the data 37 | 38 | return () => { 39 | ignore = true; // to avoid rendering multiple times.. 40 | }; 41 | }, []); 42 | 43 | return ( 44 | <> 45 | 46 |
47 | {/* Hero unit */} 48 | 55 | 56 | 63 | Active Campaigns 64 | 65 | 71 | A list of active campaigns that are running currently and in need 72 | of contributors like you. Join hands with fund raisers to fulfill 73 | the noble cause. 74 | 75 | 76 | 77 | 78 | {/* End hero unit */} 79 | 80 | 81 | {activeCampaigns.map((activeCampaign, idx) => ( 82 | 83 | 84 | 85 | ))} 86 | 87 | {/* load as long as data is not fetched. */} 88 | {activeCampaigns.length == 0 && } 89 | 90 |
91 | 92 |