1.开发环境准备:ganache+webjs+nodejs

2.创建一个文件夹Dapp

mkdir Dapp

3.安装ganache-cli,要求(nodejs>=V8)

npm install -g ganache-cli

ganache是 开发和测试的本地内存区块链。它模拟了真实的以太坊网络的功能,包括由测试以太币资助的多个账户的可用性。 4.安装web3js

npm install web3 -save

5.安装truffle

npm install -g truffle

truffle是节省程序员写多余代码的框架,通过truffle命令可以直接生成开发框架 安装过程如果出错建议更新一下nodejs 安装完成通过truffle -V检查版本 6.在remix中编写智能合约,并编译通过(新版本,需要翻墙: Remix – Ethereum IDE 旧版本: Remix – Ethereum IDE)

pragma solidity >=0.4.22  bool) public voters; //将投票人地址,映射成一个布尔值,用以判断该账户知否已经投过  struct Candidate { //定义一个结构体,包含候选人ID,名字,投票数    uint id;    string name;    uint voteCount;  }  mapping(uint => Candidate) public candidates; //通过ID来访问候选人   function addCandidate(string memory _name) private{ //定义添加候选人函数,并声明为私有的    candidatesCount ++; //添加一个就将候选人总数加一    candidates[candidatesCount] = Candidate(candidatesCount,_name,0); //将整个结构体赋予对应的候选人  }  constructor () public { //构造函数,添加候选人    addCandidate("张三");    addCandidate("李四");  }  function vote(uint _candidateId) public { //投票函数,传入输入框候选人对应的ID    require(!voters[msg.sender]); //检查该账户是否已投过票,msg.sender为调用合约地址    require(_candidateId > 0 && _candidateId <= candidatesCount); //检查所投的候选人是否在候选人名单中    voters[msg.sender] = true; //将调用合约账户设为已投    candidates[_candidateId].voteCount ++; //将所投候选人投票数加一    emit votedEvent(_candidateId);//发出事件  }  event votedEvent ( //定义事件,用以刷新界面    uint indexed _candidateId  ); }

7.在Dapp中创建模板工程

truffle unbox pet-port

此过程可能会出错,多试几次,大部分是因为网络问题 8.运行ganache-cli

ganache-cli

运行成功会生成10个合约账户以及对应的私钥,同时还有连接的本地端口 9.修改truffle-config.js 连接的端口和地址需要与ganache最终的一致 10.创建合约

vim Election.sol

将remix中的智能合约粘贴在这 11.编写前端页面,用以显示投票,修改src/index.html

    投票 DApp            

投票 DApp



Loading...

# 候选人 得票数


12.修改src/js/app.js代码

​App = { web3Provider: null, contracts: {}, account: '0x0', hasVoted: false, init: async function() {  return await App.initWeb3(); }, initWeb3: async function() {   if (window.ethereum) {    App.web3Provider = window.ethereum;    try {     await window.ethereum.enable();    } catch (error) {      console.error("User denied account access")    }   } else if (window.web3) {    App.web3Provider = window.web3.currentProvider;   }   else {    App.web3Provider = new Web3.providers.HttpProvider('http://localhost:8545');   }   web3 = new Web3(App.web3Provider);  return App.initContract(); }, initContract: function() {  $.getJSON("Election.json", function(election) {   App.contracts.Election = TruffleContract(election);   App.contracts.Election.setProvider(App.web3Provider);   App.listenForEvents();   return App.render();  }); }, listenForEvents: function() {  App.contracts.Election.deployed().then(function(instance) {   instance.votedEvent({}, {    fromBlock: 0,    toBlock: 'latest'   }).watch(function(error, event) {    console.log("event triggered", event)    App.render();   });  }); }, render: function() {  var electionInstance;  var loader = $("#loader");  var content = $("#content");  loader.show();  content.hide();  web3.eth.getCoinbase(function(err, account) {   if (err === null) {    App.account = account;    $("#accountAddress").html("Your Account: " + account);   }  });  App.contracts.Election.deployed().then(function(instance) {   electionInstance = instance;   return electionInstance.candidatesCount();  }).then(function(candidatesCount) {   var candidatesResults = $("#candidatesResults");   candidatesResults.empty();   var candidatesSelect = $('#candidatesSelect');   candidatesSelect.empty();   for (var i = 1; i <= candidatesCount; i++) {    electionInstance.candidates(i).then(function(candidate) {     var id = candidate[0];     var name = candidate[1];     var voteCount = candidate[2];     // Render candidate Result     var candidateTemplate = "" + id + "" + name + "" + voteCount + ""     candidatesResults.append(candidateTemplate);     // Render candidate ballot option     var candidateOption = "" + name + ""     candidatesSelect.append(candidateOption);    });   }   return electionInstance.voters(App.account);  }).then(function(hasVoted) {   if(hasVoted) {    $('form').hide();   }   loader.hide();   content.show();  }).catch(function(error) {   console.warn(error);  }); }, castVote: function() {  var candidateId = $('#candidatesSelect').val();  App.contracts.Election.deployed().then(function(instance) {   return instance.vote(candidateId, { from: App.account });  }).then(function(result) {   // Wait for votes to update   $("#content").hide();   $("#loader").show();  }).catch(function(err) {   console.error(err);  }); }};$(function() { $(window).load(function() {  App.init(); });});​

12.更新依赖

npm install

13.编译部署合约

truffle compiletruffle migrate

14.需要在谷歌浏览器中安装钱包插件, Releases · MetaMask/metamask-extension · GitHub直接下载对应的版本,如果出错,选不了网络,可以下载其他版本地址如下 链接: 百度网盘 请输入提取码https://pan.baidu.com/s/1qJTOKgFqXUXHRkAQAmcxZw 提取码:0w3n 解压添加到谷歌浏览器插件 15.在插件中导入账户,将ganache中生成的账户私钥输入 16.运行合约

npm run dev

17.在浏览器地址输入127.0.0.1:3000,会自动调出钱包,需要对钱包下一步即可