新聞中心
這篇文章將為大家詳細講解有關以太坊區(qū)塊鏈如何使用NodeJs、Web3開發(fā)投票DApp,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
公司主營業(yè)務:成都做網(wǎng)站、網(wǎng)站制作、移動網(wǎng)站開發(fā)等業(yè)務。幫助企業(yè)客戶真正實現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)是一支青春激揚、勤奮敬業(yè)、活力青春激揚、勤奮敬業(yè)、活力澎湃、和諧高效的團隊。公司秉承以“開放、自由、嚴謹、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領域給我們帶來的挑戰(zhàn),讓我們激情的團隊有機會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出香河免費做網(wǎng)站回饋大家。
1、開發(fā)完成后頁面預覽如下
用戶可以查看到當前參與投票的候選人名單已經(jīng)他們各自的目前所得票數(shù),選擇其中一名進行投票,被投票的人所得票數(shù)對應增加。
2、開發(fā)準備工作
本地NodeJs環(huán)境
Ganache測試環(huán)境
熟悉基礎的Web3-Api操作,安裝命令為: npm install web3@^0.20.0 --save
NodeJs安裝Solc編譯環(huán)境,安裝命令為:npm install sol
期間遇坑,安裝Windows構建工具,安裝命令為:npm install --global --production windows-build-tools
python27
3、編寫智能合約
創(chuàng)建工作目錄 Voting-Node,在此目錄下新建 Voting.sol 智能合約文件,并在Remix中對此文件進行編輯,最后編輯完成后的文件內(nèi)容如下:
pragma solidity ^0.4.18; contract Voting { mapping (bytes32 => uint8) public votesReceived; bytes32[] public candidateList; constructor (bytes32[] candidateNames) public { candidateList = candidateNames; } function totalVotesFor(bytes32 candidate) view public returns (uint8) { require(validCandidate(candidate)); return votesReceived[candidate]; } function voteForCandidate(bytes32 candidate) public { require(validCandidate(candidate)); votesReceived[candidate] += 1; } function validCandidate(bytes32 candidate) view public returns (bool) { for(uint i = 0; i < candidateList.length; i++) { if (candidateList[i] == candidate) { return true; } } return false; } }
4、編譯、部署、測試 智能合約
在Voting-Node目錄打開命令行并輸入node 命令,可以進入REPL環(huán)境,分步執(zhí)行編譯部署命令,不過這種方式比較麻煩,不方便維護和修改,此處直接在Voting-Node目錄中編寫好了一個編譯、部署、測試 的 depoy.js文件,直接在Nodejs中運行就可以看到結果,內(nèi)容如下:
//引入web3模塊 let Web3 = require('web3'); //初始化 web3 let web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:7545")); //輸出初始化結果 console.log('Initialization web3 complete,the first account is '+ web3.eth.accounts[0]); let fs = require('fs'); let code = fs.readFileSync('Voting.sol').toString(); let solc = require('solc'); //編譯合約為ABI文件 let compiledCode = solc.compile(code); console.log('Compile Voting.sol complete'); //部署合約至區(qū)塊鏈節(jié)點 let abiDefinition = JSON.parse(compiledCode.contracts[':Voting'].interface); //寫入ABI文件至本地文件目錄 fs.writeFile('Voting.json',JSON.stringify(abiDefinition), {}, function(err) { console.log('write ABI file [Voting.json] complete . '); }); let VotingContract = web3.eth.contract(abiDefinition); let byteCode = compiledCode.contracts[':Voting'].bytecode; //調(diào)用VotingContract對象的new()方法來將投票合約部署到區(qū)塊鏈。new()方法參數(shù)列表應當與合約的 構造函數(shù)要求相一致。對于投票合約而言,new()方法的第一個參數(shù)是候選人名單。 let deployedContract = VotingContract.new(['Rama','Nick','Jose'],{data: byteCode, from: web3.eth.accounts[0], gas: 4700000}); //輸出合約 地址,如果此處沒有返回地址,可以在Ganache日志中查看到 console.log('deploy complete,deploy address is '+ deployedContract.address); //let contractInstance = VotingContract.at(deployedContract.address); let contractInstance = VotingContract.at('0xa167fddc1c6d3d6187a748947b8f00b0dc4fc8db');///這里改為你自己的deployedContract.address //測試合約調(diào)用 contractInstance.voteForCandidate('Rama', {from: web3.eth.accounts[0]}); contractInstance.voteForCandidate('Rama', {from: web3.eth.accounts[0]}); contractInstance.voteForCandidate('Rama', {from: web3.eth.accounts[0]}); contractInstance.voteForCandidate('Nick', {from: web3.eth.accounts[0]}); contractInstance.voteForCandidate('Jose', {from: web3.eth.accounts[0]}); contractInstance.voteForCandidate('Jose', {from: web3.eth.accounts[0]}); console.log("--------------finish----------------"); let RamaVote=contractInstance.totalVotesFor.call('Rama'); let NickVote=contractInstance.totalVotesFor.call('Nick'); let JoseVote=contractInstance.totalVotesFor.call('Jose'); console.log("Rama's vote is "+RamaVote); console.log("Nick's vote is "+NickVote); console.log("Jose's vote is "+JoseVote);
5、網(wǎng)頁交互
在完成上面的編寫、編譯、部署、測試環(huán)節(jié)后,添加網(wǎng)頁交互那就很簡單了。
在Voting-Node目錄 打開命令行,執(zhí)行初始化命令,如下:
npm init -y
會在此目錄下生成 package.json 文件,修改此文件內(nèi)容如下:
{ "name": "Voting-Node", "version": "1.0.0", "description": "", "main": "index.js", "dependencies": { "solc": "^0.4.23", "web3": "^0.19.0" }, "devDependencies": {}, "scripts": { "dev": "node index.js" }, "keywords": [], "author": "Ruoli", "license": "ISC" }
在目錄下新建 index.js 、 index.html、app.js 文件,如下所示。
index.js 內(nèi)容如下:
var express = require('express'); var app = express(); var server = require('http').createServer(app); var Web3 = require("web3"); app.use(express.static('.')); let web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545")); //這里導入你自己的ABI let abi = JSON.parse('[{"constant":true,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"totalVotesFor","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"validCandidate","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"votesReceived","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"candidateList","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"voteForCandidate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"candidateNames","type":"bytes32[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]') let VotingContract = web3.eth.contract(abi); //這里要替換成你自己的地址 let contractInstance = VotingContract.at('0xcadcaf0cf38ad0adc259b8426b723bb31faa899d'); app.get("/totalVotesFor", function(req, res) { var voteName = req.query.voteName; var vote_num=contractInstance.totalVotesFor.call(voteName).toString(); console.log(vote_num); res.send(vote_num); }); app.get("/voteForCandidate", function(req, res) { var voteName = req.query.voteName; contractInstance.voteForCandidate(voteName, {from: web3.eth.accounts[0]}); var vote_num=contractInstance.totalVotesFor.call(voteName).toString(); res.send(vote_num); }); server.listen(3000); // 控制臺會輸出以下信息 console.log('Server running at http://127.0.0.1:3000/index.html');
index.html 內(nèi)容如下:
Voting DApp 簡易投票 DApp
app.js 內(nèi)容如下:
注意:此處需要將之前保存的 ABI文件內(nèi)容引入。
let candidates = {"Rama": "candidate-1", "Nick": "candidate-2", "Jose": "candidate-3"} $(document).ready(function() { //初始化余額 candidateNames = Object.keys(candidates); for (var i = 0; i < candidateNames.length; i++) { let voteName = candidateNames[i]; totalVotesFor(voteName); } //初始化事件 $(".vote-btn").click(function(){ //獲取投票人名稱 let voteName=$(this).prev().prev().text(); voteForCandidate(voteName); }); }); function totalVotesFor(voteName) { $.get("/totalVotesFor?voteName=" + voteName, function(data) { if(data == "Error") { alert('提示', '500'); } else { $("#"+candidates[voteName]).html(data); } }); } function voteForCandidate(voteName) { $.get("/voteForCandidate?voteName=" + voteName, function(data) { if(data == "Error") { alert('提示', '500'); } else { let div_id = candidates[voteName]; var vote_num = totalVotesFor(voteName); $("#"+div_id).html(data);//.fadeIn(800); $("#"+div_id);//.fadeOut(400); } }); }
至此所有開發(fā)已經(jīng)完成。
6、網(wǎng)頁訪問與測試
執(zhí)行如下命令啟動服務:
PS C:\Workspace\Ruoli-Code\Voting-Node> npm run dev > Voting-Node@1.0.0 dev C:\Workspace\Ruoli-Code\Voting-Node > node index.js Server running at http://127.0.0.1:3000/index.html
執(zhí)行完成后 在瀏覽器中 訪問:http://127.0.0.1:3000/index.html
即可看到最開始的界面,至此所有開發(fā)完成。
關于“以太坊區(qū)塊鏈如何使用NodeJs、Web3開發(fā)投票DApp”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
當前題目:以太坊區(qū)塊鏈如何使用NodeJs、Web3開發(fā)投票DApp
標題網(wǎng)址:http://biofuelwatch.net/article/pioeig.html