您好,登錄后才能下訂單哦!
本篇文章為大家展示了以太坊區塊鏈怎樣使用NodeJs、Web3開發投票DApp,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
用戶可以查看到當前參與投票的候選人名單已經他們各自的目前所得票數,選擇其中一名進行投票,被投票的人所得票數對應增加。
本地NodeJs環境
Ganache測試環境
熟悉基礎的Web3-Api操作,安裝命令為: npm install web3
NodeJs安裝Solc編譯環境,安裝命令為:npm install solc
創建工作目錄 Voting-Node,在此目錄下新建 Voting.sol 智能合約文件,并在Remix中對此文件進行編輯,最后編輯完成后的文件內容如下:
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; } }
在Voting-Node目錄打開命令行并輸入node 命令,可以進入REPL環境,分步執行編譯部署命令,不過這種方式比較麻煩,不方便維護和修改,此處直接在Voting-Node目錄中編寫好了一個編譯、部署、測試 的 depoy.js文件,直接在Nodejs中運行就可以看到結果,內容如下:
//引入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'); //部署合約至區塊鏈節點 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; //調用VotingContract對象的new()方法來將投票合約部署到區塊鏈。new()方法參數列表應當與合約的 構造函數要求相一致。對于投票合約而言,new()方法的第一個參數是候選人名單。 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('0x99bdfb1f4c5d0c227d6cd98cf7a254bfc27c35cc'); //測試合約調用 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);
執行結果如下:
PS C:\Workspace\Ruoli-Code\Eth-Node> node .\deploy.js Initialization web3 complete,the first account is 0xa0b4360847bfe6c45f78103e97678dfa79aa9975 Compile Voting.sol complete deploy complete,deploy address is undefined --------------finish---------------- Rama's vote is 3 Nick's vote is 1 Jose's vote is 2 write ABI file complete .
最后結果符合預期,說明測試調用已經成功。
如果部署中出現 問題:TypeError: web3.eth.contract is not a function
則需要安裝 0.19版本的 web3,命令如下:
npm install web3@^0.19.0 --save
安裝完成后,問題修復。
在完成上面的編寫、編譯、部署、測試環節后,添加網頁交互那就很簡單了。
在Voting-Node目錄 打開命令行,執行初始化命令,如下:
npm init -y
會在此目錄下生成 package.json 文件,修改此文件內容如下:
{ "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 內容如下:
var http = require('http'); var fs = require('fs'); var url = require('url'); // 創建服務器 http.createServer( function (request, response) { // 解析請求,包括文件名 var pathname = url.parse(request.url).pathname; // 輸出請求的文件名 console.log("Request for " + pathname + " received."); // 從文件系統中讀取請求的文件內容 fs.readFile(pathname.substr(1), function (err, data) { if (err) { console.log(err); // HTTP 狀態碼: 404 : NOT FOUND // Content Type: text/plain response.writeHead(404, {'Content-Type': 'text/html'}); }else{ // HTTP 狀態碼: 200 : OK // Content Type: text/plain response.writeHead(200, {'Content-Type': 'text/html'}); // 響應文件內容 response.write(data.toString()); } // 發送響應數據 response.end(); }); }).listen(3000); // 控制臺會輸出以下信息 console.log('Server running at http://127.0.0.1:3000/index.html');
index.html 內容如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Voting DApp</title> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" > <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> <style type="text/css"> .vote-row{ margin-top: 45px; margin-bottom: 45px; } .vote-person{ height: 150px; width: 150px; border: 1px solid #ccc; border-radius: 10px; margin:0 auto; } .vote-person:hover{ background-color: #eee; } .vote-btn{ margin-top: 14px; width:100%; border-radius: 10px; border-top-left-radius:0em; border-top-right-radius:0em; } .vote-name{ font-size: 18px; margin-top:7px; } .vote-num{ width:50px; height:50px; border: 1px solid #ccc; border-radius: 50%; text-align: center; margin:10px auto 6px auto; padding-top: 10px; font-size: 18px; } </style> </head> <body class="container"> <h3 class="text-center">簡易投票 DApp</h3> <div class="row vote-row"> <div class="col-md-3 col-md-offset-1"> <div class="vote-person"> <div class="text-center vote-name">Rama</div> <div id="candidate-1" class="text-center vote-num"></div> <a href="#" class="btn btn-primary vote-btn">為TA投票</a> </div> </div> <div class="col-md-3"> <div class="vote-person"> <div class="text-center vote-name">Nick</div> <div id="candidate-2" class="text-center vote-num"></div> <a href="#" class="btn btn-primary vote-btn">為TA投票</a> </div> </div> <div class="col-md-3"> <div class="vote-person"> <div class="text-center vote-name">Jose</div> <div id="candidate-3" class="text-center vote-num"></div> <a href="#" class="btn btn-primary vote-btn">為TA投票</a> </div> </div> </div> </body> <script src="./web3.js"></script> <script src="./app.js"></script> </html>
app.js 內容如下:
注意:此處需要將之前保存的 ABI文件內容引入。
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('0x99bdfb1f4c5d0c227d6cd98cf7a254bfc27c35cc'); 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 name = candidateNames[i]; let val = contractInstance.totalVotesFor.call(name).toString() $("#"+candidates[name]).html(val); } //初始化事件 $(".vote-btn").click(function(){ //獲取投票人名稱 let voteName=$(this).prev().prev().text(); contractInstance.voteForCandidate(voteName, {from: web3.eth.accounts[0]}, function() { let div_id = candidates[voteName]; let vote_num=contractInstance.totalVotesFor.call(voteName).toString(); $("#"+div_id).fadeOut(400); $("#"+div_id).html(vote_num).fadeIn(800); }); }); });
至此所有開發已經完成。
執行如下命令啟動服務:
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
執行完成后 在瀏覽器中 訪問:http://127.0.0.1:3000/index.html
即可看到最開始的界面,至此所有開發完成。
上述內容就是以太坊區塊鏈怎樣使用NodeJs、Web3開發投票DApp,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。