const ethers = require('ethers'); require('dotenv').config(); const express = require('express'); const jwt = require('jsonwebtoken'); const API_URL = process.env.API_URL; const PRIVATE_KEY = process.env.PRIVATE_KEY; const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS; const JWT_SECRET = process.env.JWT_SECRET; const provider = new ethers.providers.JsonRpcProvider(API_URL); const signer = new ethers.Wallet(PRIVATE_KEY, provider); const { abi } = require("./artifacts/contracts/Election.sol/Election.json"); const contractInstance = new ethers.Contract(CONTRACT_ADDRESS, abi, signer); const app = express(); app.use(express.json()); // Function to sign and send a transaction const sendTransaction = async (method, ...params) => { const tx = await contractInstance[method](...params); return tx.wait(); }; // Endpoint for login app.post('/login', async (req, res) => { const { voterId, password } = req.body; try { const [name, isLoginSuccessful] = await contractInstance.login(voterId, password); if (isLoginSuccessful) { const token = jwt.sign({ voterId }, JWT_SECRET, { expiresIn: '1h' }); res.json({ error: false, message: "success", loginResult: { userId: voterId, name: name, token: token } }); } else { res.status(401).json({ error: true, message: "Invalid credentials" }); } } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to add a new voter app.post('/voters', async (req, res) => { const { id, name, email, password } = req.body; try { const receipt = await sendTransaction('addVoter', id, name, email, password); res.json({ receipt }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to update a voter app.put('/voters/:id', async (req, res) => { const { id } = req.params; const { name, email, password } = req.body; try { const receipt = await sendTransaction('updateVoter', id, name, email, password); res.json({ receipt }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to delete a voter app.delete('/voters/:id', async (req, res) => { const { id } = req.params; try { const receipt = await sendTransaction('deleteVoter', id); res.json({ receipt }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to add a new candidate app.post('/candidates', async (req, res) => { const { id, name, visi, misi } = req.body; try { const receipt = await sendTransaction('addCandidate', id, name, visi, misi); res.json({ receipt }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to update a candidate app.put('/candidates/:id', async (req, res) => { const { id } = req.params; const { name, visi, misi } = req.body; try { const receipt = await sendTransaction('updateCandidate', id, name, visi, misi); res.json({ receipt }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to delete a candidate app.delete('/candidates/:id', async (req, res) => { const { id } = req.params; try { const receipt = await sendTransaction('deleteCandidate', id); res.json({ receipt }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get all voters app.get('/voters', async (req, res) => { try { const allVoters = await contractInstance.getAllVoters(); const response = { error: false, message: "Voters fetched successfully", voters: allVoters.map(voter => ({ id: voter.id, name: voter.name, email: voter.email, password: voter.password, hasVoted: voter.hasVoted, lastUpdated: voter.lastUpdated, transactionHash: voter.transactionHash, blockNumber: voter.blockNumber })) }; res.json(response); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get all candidates app.get('/candidates', async (req, res) => { try { const allCandidates = await contractInstance.getAllCandidates(); const response = { error: false, message: "Candidates fetched successfully", candidates: allCandidates.map(candidate => ({ id: candidate.id, name: candidate.name, visi: candidate.visi, misi: candidate.misi, voteCount: candidate.voteCount, lastUpdated: candidate.lastUpdated, transactionHash: candidate.transactionHash, blockNumber: candidate.blockNumber })) }; res.json(response); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get a specific voter by ID app.get('/voters/:id', async (req, res) => { const voterId = req.params.id; try { const voter = await contractInstance.voters(voterId); res.json({ id: voter.id, name: voter.name, email: voter.email, password: voter.password, hasVoted: voter.hasVoted, lastUpdated: voter.lastUpdated, transactionHash: voter.transactionHash, blockNumber: voter.blockNumber }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get a specific candidate by ID app.get('/candidates/:id', async (req, res) => { const candidateId = req.params.id; try { const candidate = await contractInstance.candidates(candidateId); res.json({ id: candidate.id, name: candidate.name, visi: candidate.visi, misi: candidate.misi, voteCount: candidate.voteCount, lastUpdated: candidate.lastUpdated, transactionHash: candidate.transactionHash, blockNumber: candidate.blockNumber }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to vote app.post('/vote', async (req, res) => { const { voterId, candidateId, password } = req.body; try { const receipt = await sendTransaction('vote', voterId, candidateId, password); res.json({ receipt }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get vote count for a candidate app.get('/vote-count/:id', async (req, res) => { const candidateId = req.params.id; try { const voteCount = await contractInstance.getVoteCount(candidateId); res.json({ voteCount }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get vote count for all candidates app.get('/vote-counts', async (req, res) => { try { const allCandidates = await contractInstance.getAllCandidates(); const voteCounts = allCandidates.map(candidate => ({ id: candidate.id, voteCount: candidate.voteCount })); res.json({ voteCounts }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get vote status of a user app.get('/voteStatus/:userId', async (req, res) => { const { userId } = req.params; try { const voter = await contractInstance.voters(userId); if (!voter.id) { return res.status(404).json({ hasVoted: false }); } res.json({ hasVoted: voter.hasVoted }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get voter history app.get('/voter-history/:id', async (req, res) => { const voterId = req.params.id; try { const history = await contractInstance.getVoterHistory(voterId); res.json(history); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get candidate history app.get('/candidate-history/:id', async (req, res) => { const candidateId = req.params.id; try { const history = await contractInstance.getCandidateHistory(candidateId); res.json(history); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get vote count history app.get('/vote-count-history/:id', async (req, res) => { const candidateId = req.params.id; try { const history = await contractInstance.getVoteCountHistory(candidateId); res.json(history); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get all voter histories app.get('/all-voter-histories', async (req, res) => { try { const allHistories = await contractInstance.getAllVoterHistories(); res.json(allHistories); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get all candidate histories app.get('/all-candidate-histories', async (req, res) => { try { const allHistories = await contractInstance.getAllCandidateHistories(); res.json(allHistories); } catch (error) { res.status(500).json({ error: error.message }); } }); // Endpoint to get all vote count histories app.get('/all-vote-count-histories', async (req, res) => { try { const allHistories = await contractInstance.getAllVoteCountHistories(); res.json(allHistories); } catch (error) { res.status(500).json({ error: error.message }); } }); app.listen(3000, () => { console.log('Election API listening at http://localhost:3000'); });