以太坊DApp开发入门示例6,构建一个简单的投票DApp

OKX欧易app

OKX欧易app

欧易交易所app是全球排名第一的虚拟货币交易所,注册领取6万元盲盒礼包!

APP下载   官网注册

以太坊DApp开发入门示例6,构建一个简单的投票DApp

以太坊DApp开发入门示例6,构建一个简单的投票DApp

在前几个入门示例中,我们了解了以太坊账户、智能合约开发、Truffle框架以及前端交互的基础知识,本示例将带大家构建一个简单的投票DApp,涵盖智能合约设计、合约部署、前端界面开发及完整交互流程,这个示例将帮助开发者巩固Solidity编程、Truffle部署流程和Web3.js前端交互,同时理解DApp中“合约-前端-用户”的协同工作模式。

项目准备与环境搭建

在开始之前,请确保已完成以下环境配置:

  1. Node.js(建议版本≥14.0):用于运行前端框架和Truffle工具。
  2. Truffle:全局安装,命令为npm install -g truffle。
  3. Ganache:本地以太坊区块链,用于模拟区块链网络(提供10个测试账户,每个账户10000 ETH)。
  4. MetaMask:浏览器钱包插件,用于用户签名交易和管理私钥。
  5. 前端框架:本示例使用HTML + CSS + JavaScript(原生),也可结合React/Vue简化开发。

创建项目目录并初始化:

mkdir ethereum-voting-dapp
cd ethereum-voting-dapp
truffle init
npm install web3

智能合约设计:Voting.sol

投票DApp的核心是记录投票选项、统计票数、限制投票权限的智能合约,我们将其命名为Voting.sol,放在contracts/目录下。

合约功能需求

  • 支持多个候选人(投票选项)。
  • 每个地址只能投票一次(防止重复投票)。
  • 查看当前各候选人票数。
  • 合约所有者可结束投票(锁定投票功能)。

合约代码

// contracts/Voting.sol
pragma solidity ^0.8.0;
contract Voting {
    // 候选人结构体:姓名和票数
    struct Candidate {
        string name;
        uint voteCount;
    }
    // 候选人列表(固定数组,可根据需求改为动态数组)
    Candidate[] public candidates;
    // 记录地址是否已投票
    mapping(address => bool) public hasVoted;
    // 合约所有者(可结束投票)
    address public owner;
    // 构造函数:初始化候选人
    constructor(string[] memory candidateNames) {
        owner = msg.sender;
        for (uint i = 0; i < candidateNames.length; i++) {
            candidates.push(Candidate({
                name: candidateNames[i],
                voteCount: 0
            }));
        }
    }
    // 投票函数
    function vote(uint candidateIndex) public {
        require(!hasVoted[msg.sender], "You have already voted!");
        require(candidateIndex < candidates.length, "Invalid candidate index!");
        hasVoted[msg.sender] = true;
        candidates[candidateIndex].voteCount++;
    }
    // 获取候选人票数
    function getVoteCount(uint candidateIndex) public view returns (uint) {
        require(candidateIndex < candidates.length, "Invalid candidate index!");
        return candidates[candidateIndex].voteCount;
    }
    // 结束投票(仅所有者可调用)
    function endVoting() public {
        require(msg.sender == owner, "Only owner can end voting!");
        // 这里可以添加逻辑锁定投票(如设置状态变量),示例中简单清空候选人列表
        for (uint i = 0; i < candidates.length; i++) {
            candidates.pop();
        }
    }
}

配置Truffle:迁移合约

Truffle通过migrations/目录下的脚本管理合约部署,创建2_deploy_contracts.js文件:

// migrations/2_deploy_contracts.js
const Voting = artifacts.require("Voting");
module.exports = function (deployer) {
    // 部署合约时传入候选人列表
    const candidateNames = ["Alice", "Bob", "Charlie"];
    deployer.deploy(Voting, candidateNames);
};

部署合约到本地网络

  1. 启动Ganache(默认地址为http://127.0.0.1:7545)。
  2. 在项目目录下运行Truffle部署命令:
    truffle migrate --network development

    成功后,Ganache会显示交易详情,控制台会输出合约部署地址(如Voting deployed at: 0x123...)。

前端开发:连接合约与用户界面

创建前端文件结构

在项目根目录下创建src/文件夹,并添加以下文件:

  • index.html:投票界面。
  • style.css:样式文件。
  • app.js:前端逻辑(连接Web3、调用合约)。

编写HTML界面(index.html)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">以太坊投票DApp</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container">
        <h1>投票系统</h1>
        <div class="voting-section">
            <h2>选择候选人:</h2>
            <div id="candidates"></div>
            <button id="voteButton" disabled>投票</button>
        </div>
        <div class="results-section">
            <h2>投票结果:</h2>
            <div id="results"></div>
        </div>
        <div class="status" id="status"></div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/web3@1.8.0/dist/web3.min.js"></script>
    <script src="app.js"></script>
</body>
</html>

编写样式文件(style.css)

body {
    font-family: Arial, sans-serif;
    background-color: #f4f4f4;
    margin: 0;
    padding: 20px;
}
.container {
    max-width: 600px;
    margin: 0 auto;
    background: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
    text-align: center;
    color: #333;
}
.voting-section, .results-section {
    margin: 20px 0;
}
.candidate {
    margin: 10px 0;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 4px;
    cursor: pointer;
}
.candidate.selected {
    background-color: #e6f7ff;
    border-color: #1890ff;
}
button {
    width: 100%;
    padding: 10px;
    background-color: #1890ff;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 16px;
}
button:disabled {
    background-color: #d9d9d9;
    cursor: not-allowed;
}
.status {
    margin-top: 20px;
    padding: 10px;
    border-radius: 4px;
    text-align: center;
}
.status.success {
    background-color: #f6ffed;
    color: #52c41a;
}
.status.error {
    background-color: #fff2f0;
    color: #ff4d4f;
}

编写前端逻辑(app.js)

核心功能包括:连接Web3、加载候选人列表、监听用户投票、实时更新结果。

// src/app.js
document.addEventListener('DOMContentLoaded', () => {
    // 1. 初始化Web3
    let web3;
    let votingContract;
    let accounts;
    if (typeof window.ethereum !== 'undefined') {
        web3 = new Web3(window.ethereum);
        window.ethereum.request({ method: 'eth_requestAccounts' })
            .then(acc => {
                accounts = acc;
                initApp();
            })
            .catch(err => console.error("连接钱包失败:", err));
    } else {
        document.getElementById('status').innerHTML = 
            "<div class='status error'>请安装MetaMask钱包!</div>";
    }
    // 2. 初始化应用
    async function initApp() {
        const networkId = await web3.eth.net.getId();
        const contractAddress = "0x123..."; // 替换为实际部署的合约地址
        const contractAbi = [
            // 这里粘贴Voting.sol的ABI(可通过truffle compile生成)
            {
                "inputs": [],
                "name": "candidates",
                "outputs": [
                    {"internalType": "string", "name": "name", "type": "string"},
                    {"internalType": "uint256",

本文来自用户投稿,不代表币大大立场,如若转载,请注明出处:https://czxurui.com/jys/327919.html

上一篇 2026年10月01日
下一篇 2026年10月01日

相关推荐

  • 以太坊的攻坚战,持续加强力量,攻克核心难点

    以太坊的攻坚战,持续加强力量,攻克核心难点 以太坊,作为全球第二大加密货币和最具影响力的智能合约平台,自诞生以来便承载着构建去中心化互联网(Web3)的宏大愿景,这条通往未来的道路并非一帆风顺,其底层架构和生态发展在规模扩大和应用深化过程中,逐渐暴露出一系列亟

    2026-10-01 13:30:01
    1 0
  • V神八谈以太坊发展前景,从技术演进到生态繁荣的未来展望

    V神八谈以太坊发展前景,从技术演进到生态繁荣的未来展望 以太坊,作为全球第二大加密货币和最具影响力的智能合约平台,其发展前景一直是业界关注的焦点,而“V神”—— Vitalik Buterin,作为以太坊的联合创始人,他的观点更是被视为洞察以太坊未来走向的重要风向标,V神多次

    2026-10-01 13:30:01
    1 0
  • 以太坊合约地址,连接智能合约与数字世界的门牌号

    以太坊合约地址,连接智能合约与数字世界的门牌号 在以太坊乃至整个区块链世界中,我们频繁听到“地址”这个词,除了我们通常用于接收和发送加密货币的 externally owned account (EOA),即外部拥有账户之外,还有一类特殊的地址——合约地址(Contract Address),以太坊合约

    2026-10-01 13:30:01
    1 0
  • 以太坊对美元最新价格,波动中的机遇与挑战

    以太坊对美元最新价格,波动中的机遇与挑战 以太坊(ETH)作为全球第二大加密货币,其与美元(USD)的汇率走势一直是市场关注的焦点,截至最新数据,以太坊对美元价格在短期内呈现震荡调整态势,长期则受技术升级、宏观经济及行业生态等多重因素影响,展现出独特的投资价值与

    2026-10-01 13:30:01
    1 0
  • EOS是基于以太坊开发的吗?揭开两大公链的血缘与独立之路

    EOS是基于以太坊开发的吗?揭开两大公链的血缘与独立之路 在区块链行业的发展历程中,以太坊(Ethereum)无疑是一座里程碑式的存在,它作为首个实现智能合约功能的去中心化平台,为后续无数公链和DApp(去中心化应用)的诞生提供了土壤,而EOS作为曾被誉为“以太坊杀手”的明

    2026-10-01 13:30:01
    1 0
  • 50个以太坊是多少钱的?实时价格查询与影响因素解析

    50个以太坊是多少钱的?实时价格查询与影响因素解析 在加密货币市场,以太坊(Ethereum,简称ETH)作为市值第二大的数字资产,一直备受投资者关注,许多持有者或潜在投资者都会问:“50个以太坊现在值多少钱?”这个问题看似简单,实则涉及多个动态因素,本文将带你了解如何计

    2026-10-01 13:30:01
    1 0

发表回复

8206

评论列表(0条)

    暂无评论

binance币安交易所
已有2000万用户加入币安交易所

立即下载