参考自(3条消息) 区块链投票应用:使用solidity+truffle+metamsk开发Dapp应用_一袋芋头的博客-CSDN博客下载了项目示例webpack之后
我们需要将里面的其他合约都删除,也可以直接删除这两个文件夹里的内容
然后就可以开始正片了(当然,你得先前就安装好环境)
开启ganache私链,
为了后续实验方便,这里我们通过指定数据存放目录来确保账号等数据保持不变,采用如下命令来启动ganache-cli私链:
#ganache-cli–db/root/MyGanacheData
然后我们需要去创建合约,编译部署至该私链上
首先在项目的合约目录,也就是/contract目录下创建sol文件
$ touch Voting.sol
$ gedit Voting.sol
// SPDX-License-Identifier: SimPL-2.0pragma solidity >=0.4.18 uint8) public votesReceived;constructor(bytes32[] memory _candidateListName) public {candodateList = _candidateListName;}function validateCan(bytes32 _candidate) internal view returns(bool) {for(uint8 i = 0; i< candodateList.length; i++) {if(candodateList[i] == _candidate)return true;}return false;} function voteForCan(bytes32 _candidate) public {votesReceived[_candidate] += 1;}function totalVotes(bytes32 _candidate)public view returns(uint8) {return votesReceived[_candidate];}}
然后我们进行编译,truffle compile,编译成功说明我们的.sol合约文件没有啥语法错误,并无卵用
然后基于这个sol文件来生成迁移文件 truffle create migration deploy_Voting,命令执行后会在migrations下生成迁移文件
前面一串数字是truffle部署时所用的ID,这里没有用,不用管,继续,我们需要更改这个js,需要传入参数
// const ConvertLib = artifacts.require("ConvertLib");// const MetaCoin = artifacts.require("MetaCoin");const Voting = artifacts.require("Voting");module.exports = function(deployer) {// deployer.deploy(ConvertLib);// deployer.link(ConvertLib, MetaCoin);// deployer.deploy(MetaCoin);deployer.deploy(Voting, ["0x4100000000000000000000000000000000000000000000000000000000000000","0x4200000000000000000000000000000000000000000000000000000000000000","0x4300000000000000000000000000000000000000000000000000000000000000"]);//注意Voting部署时有参数};
修改网络方式,修改truffle-conflig.js
module.exports = {networks: {development: {host: 'localhost',port: 8545,network_id: '*' // Match any network id}}}
下面我们就可以部署合约了,truffle migrate
这是合约部署 的详细情况
这是ganache私链的部署情况,因为一次部署就相当于是一次交易,所以会生成区块,会有交易哈希值产生,到此合约已经部署完毕,但是我们不好使用这个合约,所以我们需要写前端来方便我们使用它
在app/src/目录下写index.html和index.js文件
index.html
Voting input {display: block;margin-bottom: 12px;}Voting App
Alice : loading... tickets
Bob : loading... tickets
index.js
import Web3 from "web3";//导入Voting.jsonimport votingArtifact from "../../build/contracts/Voting.json";//定义两个值,方便传参const aInBytes32 = "0x4100000000000000000000000000000000000000000000000000000000000000";const bInBytes32 = "0x4200000000000000000000000000000000000000000000000000000000000000";const cInBytes32 = "0x4300000000000000000000000000000000000000000000000000000000000000";//定义了appconst App = {web3: null,account: null,voting: null, //定义一个voting的实例//启动时需要的start: async function() {const { web3 } = this;try {// get contract instanceconst networkId = await web3.eth.net.getId();//要改成自己的网络const deployedNetwork = votingArtifact.networks[networkId];this.voting = new web3.eth.Contract(votingArtifact.abi,deployedNetwork.address,);// get accountsconst accounts = await web3.eth.getAccounts();this.account = accounts[0];//先刷新一下界面this.ready();} catch (error) {console.error("Could not connect to contract or chain.");}},//start函数后还应该有哪些函数呢//1.refresh展示最新票数refresh: async function(id, nameInBytes32) {const { totalVotes } = this.voting.methods;//从区块链拿到票数const tickets = await totalVotes(nameInBytes32).call();//写到页面上去,并更新最新票数const element = document.getElementById(id);element.innerHTML = tickets.toString();},//2.ready:当网页好的时候要把票数读出来ready: async function() {try {this.refresh("alice", aInBytes32);this.refresh("bob", bInBytes32);this.refresh("clilly", cInBytes32);} catch (err) {console.log(err);}},//3.votingfor函数(中间需要展示票数的函数)voteForCan: async function() {try {//先获取到合约的方法const { voteForCan } = this.voting.methods;//再获取候选者名字:来自输入框const candidateName = document.getElementById("candidate").value;//拿到票数后对应加一if (candidateName == "Alice") {await voteForCan(aInBytes32).send({ from: this.account });this.refresh("alice", aInBytes32);} else {if (candidateName == "Bob") {await voteForCan(bInBytes32).send({ from: this.account });this.refresh("bob", bInBytes32);}else{if (candidateName == "Cilly") {await voteForCan(cInBytes32).send({ from: this.account });this.refresh("cilly", cInBytes32);}}}} catch (err) {//如果有err就打印一下console.log(err);}}};window.App = App;window.addEventListener("load", function() {if (window.ethereum) {// use MetaMask's providerApp.web3 = new Web3(window.ethereum);window.ethereum.enable(); // get permission to access accounts} else {console.warn("No web3 detected. Falling back to http://127.0.0.1:8545. You should remove this fallback when you deploy live",);// fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)App.web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"),);}App.start();});
然后运行
必须在App目录运行
npm run dev
额,报错了error:0308010C:digital envelope routines::unsupported,什么依托答辩,没办法,只好上网搜解答
export NODE_OPTIONS=--openssl-legacy-provider
临时解决问题,编译成功了,很牛逼,但是不知道为什么,用了再说
然后去自己浏览器打开http://localhost:8080/
可以开始使用,每次投票都会生成一个区块,保证了数据的不容篡改