千家信息网

以太坊区块链如何使用NodeJs、Web3开发投票DApp

发表于:2024-10-26 作者:千家信息网编辑
千家信息网最后更新 2024年10月26日,这篇文章将为大家详细讲解有关以太坊区块链如何使用NodeJs、Web3开发投票DApp,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1、开发完成后页面预览如下用户可
千家信息网最后更新 2024年10月26日以太坊区块链如何使用NodeJs、Web3开发投票DApp

这篇文章将为大家详细讲解有关以太坊区块链如何使用NodeJs、Web3开发投票DApp,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

1、开发完成后页面预览如下

用户可以查看到当前参与投票的候选人名单已经他们各自的目前所得票数,选择其中一名进行投票,被投票的人所得票数对应增加。

2、开发准备工作

  • 本地NodeJs环境

  • Ganache测试环境

  • 熟悉基础的Web3-Api操作,安装命令为: npm install web3@^0.20.0 --save

  • NodeJs安装Solc编译环境,安装命令为:npm install sol

  • 期间遇坑,安装Windows构建工具,安装命令为:npm install --global --production windows-build-tools

  • python27

3、编写智能合约

创建工作目录 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;   }}

4、编译、部署、测试 智能合约

在Voting-Node目录打开命令行并输入node 命令,可以进入REPL环境,分步执行编译部署命令,不过这种方式比较麻烦,不方便维护和修改,此处直接在Voting-Node目录中编写好了一个编译、部署、测试 的 depoy.js文件,直接在Nodejs中运行就可以看到结果,内容如下:

//引入web3模块let Web3 = require('web3');//初始化 web3let 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('0xa167fddc1c6d3d6187a748947b8f00b0dc4fc8db');///这里改为你自己的deployedContract.address//测试合约调用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、网页交互

在完成上面的编写、编译、部署、测试环节后,添加网页交互那就很简单了。

在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 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"));//这里导入你自己的ABIlet 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 内容如下:

     Voting DApp       

简易投票 DApp

app.js 内容如下:

注意:此处需要将之前保存的 ABI文件内容引入。

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);        }    });}

至此所有开发已经完成。

6、网页访问与测试

执行如下命令启动服务:

PS C:\Workspace\Ruoli-Code\Voting-Node> npm run dev> Voting-Node@1.0.0 dev C:\Workspace\Ruoli-Code\Voting-Node> node index.jsServer running at http://127.0.0.1:3000/index.html

执行完成后 在浏览器中 访问:http://127.0.0.1:3000/index.html

即可看到最开始的界面,至此所有开发完成。

关于"以太坊区块链如何使用NodeJs、Web3开发投票DApp"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

0