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,会自动调出钱包,需要对钱包下一步即可