准备工作

相关命令

  • mkdir simple_voting_dapp //创建文件夹
  • cd simple_voting_dapp //进入文件夹
  • npm init  //初始化npm包管理文件,输入ls 可以看到创建的package.json文件
  • npm intsall web3@0.20.1 //安装web3
  • npm install solc@0.4.25   //安装solc
  • npm install -g ganache-cli   //安装ganache-cli  参考文档
  • 输入ganache-cli 启动,出现如下界面,表示启动成功,列出10个账户以及各自的秘钥,每个账户都有100以太,这个类似dev私链的模式

Solidity合约

合约内容

  • 构造函数,用来初始化一些候选者
  • 用来投票的方法(对于票数加 1)
  • 返回候选者获得的总的票数的方法

合约代码

pragma solidity ^0.4.22;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;}}
}

合约编译

编译前测试

  • 查看安装的版本 npm list web3;npm list solc
  • node 进入命令行
  • var Web3 =  require('web3')
  • var web3 = new Web3(new Web3.providers.HttpProvider('Http://localhost:8545'))//这个需要和ganache-cli设置的一致,才可以连接上。
  • 使用web3.isConnected()//查看是否连接上,此时需要将ganache-cli启动
  • 使用命令web3.eth.accounts,获取目前的账户,需要注意每次启动ganache-cli都会产生全新的账号和秘钥

正式开始编译

  • var solc = require('solc')
  • 输入solc. 查看可以使用的命令
  • var sourceCode = fs.readFileSync('Voting.sol').toString()  //需要注意,必须给与文件读取权限
  • 输入sourceCode 可以查看编码文件
  • var compiledCode = solc.compile(sourceCode)  //这个就是正式的编译过程
  • 输入compiledCode可以查看字节码文件,编译结果如下图所示

  • 这是一个js对象,最关键的是bytecode(字节码)和interface接口(ABI),这两个文件是部署合约最关键的文件
  • 部署合约 var abi = JSON.parse(compiledCode.contracts[':Voting'].interface);    输入abi进行验证,是否取到正确的值,JSON.parse是为了Json格式化代码
  • var byteCode = compiledCode.contracts[':Voting'].bytecode 取到字节码     其中:Voting是合约名称
  • 创建合约对象 var VotingContract = web3.eth.contract(abi)
  • var deployTxObj = {data:byteCode,from:web3.eth.accounts[0],gas:30000000}  定义一笔交易
  • 定义合约实例 var contractInstance = VotingContract.new(["Alice","Bob","Cary"],deployTxObj);
  • contractInstance = VotingContract.new(["Alice","Bob","Cary"],{data:byteCode,from:web3.eth.accounts[0],gas:5000000});
  • 上面这一条命令是 定义合约实例 和 定义一笔交易的结合体,如果分开,有可能会报错
  • 取到合约实例的地址 contractInstance.address  这就将合约部署在区块链上,这个区块链是本地起的ganache-cli模拟区块链
  • contractInstance.vote("Alice",{from:web3.eth.accounts[0]})  账号0给Alice投出一票
  • contractINstance.totalVotesFor("Alice").toString()  查看Alice的总共的票数
  • contractINstance.totalVotesFor.call("Alice").toString() 查看
  • contractInstance.vote.sendTransaction("Alice",{from:web3.eth.accounts[0]})

页面交互

页面 index.html

<!DOCTYPE html>
<html><head><title>Voting DApp</title><link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' type='text/css'></head><body class="container"><h1>A Simple Voting Application</h1><div class="table-responsive"><table class="table table-bordered"><thead><tr><th>Candidate</th><th>Votes</th></tr></thead><tbody><tr><td>Alice</td><td id="candidate-1"></td></tr><tr><td>Bob</td><td id="candidate-2"></td></tr><tr><td>Cary</td><td id="candidate-3"></td></tr></tbody></table></div><input type="text" id="candidate" /><a href="#" onclick="voteForCandidate()" class="btn btn-primary">Vote</a></body><script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js"></script><script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script><script src="./index.js"></script></html>

注意

  • 不再需要引入web3对象,因为页面里面就包含了web3对象,https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js,打开这个链接之后,在页面的最下面会显示,

index.js

var web3 = new Web3(new Web3.providers.HttpProvider("Http://localhost:8545"));
var 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"}]');
// var contractAddr = "0x3577f4d4902f4766753056468bd08ef68df6c623";
var VotingContract = new web3.eth.Contract(abi);
// var contractInstance =new web3.eth.Contract(abi,contractAddr);
// contractInstance = VotingContract.at(contractAddr);
var contractInstance = VotingContract.at('0x3577f4d4902f4766753056468bd08ef68df6c623');
var candidates = {"Alice":"candidate-1","Bob":"candidate-2","Cary":"candidate-3"
};
function voteForCandidate(){let candidateName = $("#candidate").val();try{contractInstance.voteForCandidate(candidateName),{from:web3.eth.accounts[0]},(err,res)=>{if(err)console.log("Error:",err);else{let div_id = candidates[candidateName];let count = contractInstance.totalVotesFor(candidateName).toString();$("#" + id).html(count);}}}catch(err){}
};$(document).ready(function(){candidateNames = Object.keys(candidates);for(let i=0;i<candidateNames.length;i++){let name = candidateNames[i];let val = contractInstance.totalVotesFor.call(name).toString();$("#" + candidates[name]).html(val);}
});

报错

无解

  • at无法使用
  • 如果使用 var contractInstance =new web3.eth.Contract(abi,contractAddr);避免了at,但是无法使用call回调函数,依然报错

部署服务

server.js

  • 异步的方式启动,同步的会报错
var http = require('http');
var fs = require('fs');
var url = require('url');http.createServer(function(req,res){var pathName = url.parse(req.url).pathname;console.log("Request for:"+pathName + "received.");fs.readFile(pathName.substr(1),function(err,data){if(err){console.log(err);res.writeHead(400,{'Content-Type':"text/html"});}else{res.writeHead(200,{'Content-Type':"text/html"});res.write(data.toString());}res.end();});
}).listen(8888);
  • 使用命令 node server.js启动服务器
  • 浏览器输入 http://127.0.0.1:8888/index.html 查看

  • 如果报错 没有favicon.ico  直接创建一个就好,这个是图标文件

Dapp简单的投票小例子相关推荐

  1. python爬虫requests简单案例_Python小例子:一个最简单的爬虫

    学习编程的过程中总是有些枯燥.成天面对黑乎乎的窗口可能真的有些无聊.来,我们做点好玩的事情吧.比如 将网络上你喜欢的图片保存下来.不过千里之行 始于足下,在学习将网页上的图片下载下来之前.我们首先要学 ...

  2. 一个简单的定时任务小例子

    [强制]线程资源必须通过线程池提供,不允许在应用中自行显式创建线程. 说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资 源不足的问题.如果不使用线程池,有可能造成系统 ...

  3. Spring中的简单实现AOP小例子

    先说一下相应的知识作铺垫 Spring的AOP术语:          1)连接点(JointPoint):目标对象的每个方法     2)切入点(PontCut):切入了服务代码的连接点     3 ...

  4. 几个简单的正则小例子

     1 ^[\w]+[\w\.-]*@[\w]+[\w-]*(?<val>\.\w+){0,2}$ 电子邮件  2 ^http://([\w-]*\.)+([\w-]*)(/\w+)*([\ ...

  5. 网页爬虫(超超简单的一个小例子)

    (一) 目标:   在Uniprot中查询一系列基因编号(如图中第二列gene)对应的详细信息,基因编号以csv格式存储,输出的详细信息也存入csv中 (二) 思路:   查询了几个基因编号之后发现, ...

  6. 在Eclipse中写第一个hibernate小例子

    在hibernate自带的文档中,包含了一个很简单的小例子,不过这个小例子是基于ant的,而且说的不是很详细,不利于新手学习.在这里,我将在Eclipse中实现这个例子,并给出详细的实现步骤.     ...

  7. 一个整理桌面的python小例子

    不知和我一样喜欢把桌面堆满的人多不多,反正我是动不动就把桌面堆满了特别是忙得时候,windows的批处理总感觉比较乱,再加上一直希望看看脚本,在Perl,Python,Ruby的对比中选择了Pytho ...

  8. 基于vue-cli、elementUI的Vue超简单入门小例子

    基于vue-cli.elementUI的Vue超简单入门小例子 这个例子还是比较简单的,独立完成后,能大概知道vue是干嘛的,可以写个todoList的小例子. 开始写例子之前,先对环境的部署做点简单 ...

  9. r语言ggplot2一夜多图_R语言ggplot2画四方形的热图展示相关系数的简单小例子

    R语言里画热图通常会使用pheatmap这个包.如果想使用ggplot2这个包画热图的话需要借助geom_tile()这个函数.今天的内容就以相关系数的数据为例介绍一下ggplot2画热图的一个简单小 ...

最新文章

  1. ppk on JavaScript第二章:背景(完结篇)
  2. 什么是javadoc文档
  3. java睡眠后继续执行_Java线程只能有千个,而Go的Goroutine能有上百万个
  4. windows下安装及配置 golang 的Web框架Beego环境
  5. C#中使用SendMessage进行进程通信,可发送字符串,结构体(不能发送类类型)。
  6. 最佳实践:如何基于MNS和OSS实现无大小限制的消息传输
  7. 使用Vs code上传github需要输入密码和用户名解决
  8. jquery查找父窗体id_js/jquery如何获取父窗口的元素?
  9. ReportView使用
  10. [ZT]硬盘整数分区计算方法
  11. 电脑怎么让图片颜色反转?怎么调图片反色效果?
  12. TCP/IP协议漏洞实验
  13. 西游降魔之东去的西游
  14. java包裹邮费计算_猿实战16——承运商之搭建你的运费基石
  15. 交换机ftp将文件传到服务器,如何用FTP实现交换机间配置文件复制?
  16. redis关于hash的常用命令
  17. 利用AI强化学习训练50级比卡超单挑70级超梦!
  18. 超微服务器主板ipmi证书,超微主板的服务器使用IPMI远程安装操作系统教程
  19. 粉丝福利 | 秒 get 支付宝同款扫码组件
  20. STM32人脸识别系统设计(程序代码+论文)

热门文章

  1. python生成动态二维码实例_python生成动态个性二维码(示例代码)
  2. 登录不上_《盗贼之海》登录不上?还在傻傻等待,快来让我教教你
  3. 【转】Jenkins详细教程
  4. 【转】异步编程:.NET 4.5 基于任务的异步编程模型(TAP)
  5. 第十五节:深入理解async和await的作用及各种适用场景和用法
  6. 第十六节: EF的CodeFirst模式通过Fluent API修改默认协定
  7. python把矩阵堆叠成大矩阵_python numpy 矩阵堆叠实例
  8. hypixel服务器免费低延迟ip,国服hypixel服务器ip
  9. java中乐观锁_Java中乐观锁与悲观锁的实现
  10. 【HDU - 5012】Dice(模拟,bfs)