Blockchain 实战指南

FreeGuideOnline 最新 2026-07-15

区块链投票系统

```

5.4 app.js

// 合约 ABI(从 build/contracts/Voting.json 复制到此处)
const contractABI = []; // 粘贴完整的 ABI
const contractAddress = '部署后的合约地址'; // 从 Ganache 控制台或 truffle console 获取

let web3;
let votingContract;

window.addEventListener('load', async () => {
  // 现代浏览器需通过 MetaMask 注入
  if (window.ethereum) {
    web3 = new Web3(window.ethereum);
    await window.ethereum.request({ method: 'eth_requestAccounts' });
  } else {
    // 降级使用本地 Ganache 提供者
    web3 = new Web3('http://127.0.0.1:7545');
  }

  // 获取合约实例
  votingContract = new web3.eth.Contract(contractABI, contractAddress);

  // 渲染候选人和票数
  await renderCandidates();

  // 监听投票事件
  votingContract.events.votedEvent({ fromBlock: 'latest' }, (error, event) => {
    if (!error) {
      renderCandidates();
    }
  });
});

async function renderCandidates() {
  const count = await votingContract.methods.candidatesCount().call();
  const container = document.getElementById('candidates');
  container.innerHTML = '';

  for (let i = 1; i <= count; i++) {
    const candidate = await votingContract.methods.candidates(i).call();
    container.innerHTML += `
      <div>
        <strong>${candidate.name}</strong> - 票数: ${candidate.voteCount}
        <button onclick="vote(${candidate.id})">投票</button>
      </div>
    `;
  }
}

async function vote(candidateId) {
  const accounts = await web3.eth.getAccounts();
  try {
    await votingContract.methods.vote(candidateId).send({ from: accounts[0] });
    alert('投票成功!');
  } catch (err) {
    alert('投票失败: ' + err.message);
  }
}

5.5 获取合约 ABI 与地址

  • ABI:打开 build/contracts/Voting.json,找到 "abi" 字段,复制到 contractABI 数组中。
  • 地址:部署成功后,终端输出类似:
    Voting: 0x1234567890abcdef...
    
    或者在 Ganache 的 “Contracts” 页签中查看。

5.6 连接 MetaMask 测试

  1. 打开 MetaMask,添加自定义网络:
    • 网络名称:Localhost 7545
    • RPC URL:http://127.0.0.1:7545
    • 链 ID:1337
  2. 从 Ganache 导入一个测试账户的私钥到 MetaMask。
  3. 用浏览器打开 app/index.html(可使用 npx http-server ./app 启动简易服务器)。
  4. 页面会显示候选人及投票按钮,点击投票,MetaMask 弹出确认交易,确认后票数自动更新。

6. 部署到 Goerli 测试网(可选)

本地测试通过后,可将合约部署到公共测试网。

  1. 前往 Infura 注册,创建项目获取 Goerli 网络的 RPC URL。
  2. 从水龙头获取 Goerli 测试 ETH。
  3. 导出 MetaMask 账户的私钥,用于 Truffle 部署。
  4. 安装 @truffle/hdwallet-provider
npm install @truffle/hdwallet-provider
  1. 修改 truffle-config.js,新增网络配置:
const HDWalletProvider = require('@truffle/hdwallet-provider');

module.exports = {
  networks: {
    goerli: {
      provider: () => new HDWalletProvider({
        privateKeys: ['你的私钥'],
        providerOrUrl: '你的Infura_Gorli_RPC_URL'
      }),
      network_id: 5,
      gas: 5500000,
      confirmations: 2,
      timeoutBlocks: 200
    }
  }
};
  1. 部署:
truffle migrate --network goerli