投票系统dapp开发流程,前后端以及链端完整代码实现

  • A+
所属分类:以太坊ETH

chatGPT账号

下面我将通过一个简单的智能合约开发案例,详细说明使用Solidity进行智能合约开发的过程。我们将开发一个基本的投票系统,用户可以为候选人投票,并且投票结果会被记录在区块链上。

投票系统dapp开发流程,前后端以及链端完整代码实现

案例介绍:简单投票系统

1. 设置开发环境

安装工具

  • Node.js:用于运行JavaScript代码。
  • Truffle:Solidity开发框架。
  • Ganache:本地区块链模拟器。
  • MetaMask:用于与dApp进行交互的加密钱包。
npm install -g truffle
npm install -g ganache-cl

2. 创建Truffle项目

mkdir SimpleVoting
cd SimpleVoting
truffle init

3. 编写智能合约

contracts目录下创建一个新的文件Voting.sol

// Voting.sol
pragma solidity ^0.8.0;

contract Voting {
    struct Candidate {
        uint id;
        string name;
        uint voteCount;
    }

    mapping(address => bool) public voters;
    mapping(uint => Candidate) public candidates;
    uint public candidatesCount;

    event votedEvent(uint indexed candidateId);

    constructor() {
        addCandidate("Alice");
        addCandidate("Bob");
    }

    function addCandidate(string memory _name) private {
        candidatesCount++;
        candidates[candidatesCount] = Candidate(candidatesCount, _name, 0);
    }

    function vote(uint _candidateId) public {
        require(!voters[msg.sender], "You have already voted");
        require(_candidateId > 0 && _candidateId <= candidatesCount, "Invalid candidate ID");

        voters[msg.sender] = true;
        candidates[_candidateId].voteCount++;

        emit votedEvent(_candidateId);
    }
}

4. 编写迁移脚本

migrations目录下创建一个新的文件2_deploy_contracts.js

// 2_deploy_contracts.js
const Voting = artifacts.require("Voting");

module.exports = function (deployer) {
  deployer.deploy(Voting);
};

5. 配置Truffle

修改truffle-config.js,配置开发网络:

module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",
      port: 8545,
      network_id: "*" // 匹配任何网络id
    }
  },
  compilers: {
    solc: {
      version: "0.8.0"
    }
  }
};

6. 启动Ganache

ganache-cli

7. 部署智能合约

在新的终端窗口中执行以下命令:

truffle migrate --network development

8. 编写前端代码

创建client目录,并在其中初始化一个React应用:

npx create-react-app client
cd client
npm install web3

client/src目录下创建一个文件Voting.js,编写前端交互代码:

// Voting.js
import React, { useEffect, useState } from "react";
import Web3 from "web3";
import Voting from "./contracts/Voting.json";

const VotingApp = () => {
  const [account, setAccount] = useState("");
  const [candidates, setCandidates] = useState([]);
  const [voted, setVoted] = useState(false);

  useEffect(() => {
    const loadBlockchainData = async () => {
      const web3 = new Web3(Web3.givenProvider || "http://localhost:8545");
      const accounts = await web3.eth.requestAccounts();
      setAccount(accounts[0]);

      const networkId = await web3.eth.net.getId();
      const deployedNetwork = Voting.networks[networkId];
      const contract = new web3.eth.Contract(Voting.abi, deployedNetwork && deployedNetwork.address);

      const candidatesCount = await contract.methods.candidatesCount().call();
      const candidatesArray = [];
      for (let i = 1; i <= candidatesCount; i++) {
        const candidate = await contract.methods.candidates(i).call();
        candidatesArray.push(candidate);
      }
      setCandidates(candidatesArray);

      const hasVoted = await contract.methods.voters(accounts[0]).call();
      setVoted(hasVoted);

      // Listen for voted event
      contract.events.votedEvent({}, (error, event) => {
        console.log(event);
        setCandidates((prevCandidates) =>
          prevCandidates.map((candidate) =>
            candidate.id === event.returnValues.candidateId
              ? { ...candidate, voteCount: parseInt(candidate.voteCount) + 1 }
              : candidate
          )
        );
        setVoted(true);
      });
    };

    loadBlockchainData();
  }, []);

  const vote = async (candidateId) => {
    const web3 = new Web3(Web3.givenProvider || "http://localhost:8545");
    const networkId = await web3.eth.net.getId();
    const deployedNetwork = Voting.networks[networkId];
    const contract = new web3.eth.Contract(Voting.abi, deployedNetwork && deployedNetwork.address);

    await contract.methods.vote(candidateId).send({ from: account });
  };

  return (
    <div>
      <h2>Voting DApp</h2>
      <p>Your account: {account}</p>
      <h3>Candidates</h3>
      <ul>
        {candidates.map((candidate) => (
          <li key={candidate.id}>
            {candidate.name} - {candidate.voteCount} votes
            {!voted && <button onClick={() => vote(candidate.id)}>Vote</button>}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default VotingApp;

9. 运行前端应用

确保在client目录下,启动前端应用:

npm start

总结

通过上述步骤,我们创建了一个简单的投票系统,包括智能合约的编写、部署以及前端的交互。在实际项目中,可以根据需求进一步完善和扩展功能,例如用户身份验证、投票计时器等。在开发过程中,注重代码的安全性和最佳实践,可以确保智能合约的可靠性和安全性。

免责声明

发文时比特币价格:$71249

当前比特币价格:[crypto coins=”BTC” type=”text” show=”price”]

当前比特币涨幅:[crypto coins=”BTC” type=”text” show=”percent”]

免责声明:

本文不代表路远网立场,且不构成投资建议,请谨慎对待。用户由此造成的损失由用户自行承担,与路远网没有任何关系;

路远网不对网站所发布内容的准确性,真实性等任何方面做任何形式的承诺和保障;

网站内所有涉及到的区块链(衍生)项目,路远网对项目的真实性,准确性等任何方面均不做任何形式的承诺和保障;

网站内所有涉及到的区块链(衍生)项目,路远网不对其构成任何投资建议,用户由此造成的损失由用户自行承担,与路远网没有任何关系;

路远区块链研究院声明:路远区块链研究院内容由路远网发布,部分来源于互联网和行业分析师投稿收录,内容为路远区块链研究院加盟专职分析师独立观点,不代表路远网立场。

本文是全系列中第112 / 247篇:行业技术

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的电报
  • 这是我的电报扫一扫
  • weinxin
chatGPT账号
路远

发表评论

您必须登录才能发表评论!