找回密码
 立即注册

扫一扫,登录网站

首页 自媒体 查看内容
  • 1702
  • 0
  • 分享到

动手开发一个区块链投票DAPP

2018-9-25 11:18

来源: blockchainbrother



第一个区块链投票DAPP


前言


  • 我是一个菜鸟,所以在代码质量上可能不太好,欢迎指点。

  • 阅读本文可能需要一定的基础,有疑问欢迎留言。


本篇文章,将带读者用Truffle框架在ganache环境上



搭建一个属于自己的投票DAPP雏形,你可以在这基础上进行扩展。这里如果你对ganache不熟悉的可以使用testrpc环境也是一样的。


开发包对应版本


  • web3.js   v0.20.5

  • Truffle  v4.1.3

  • Solidity v0.4.2

  • Ganache 1.1.0


初始化工程


这里我们需要提前安装好 node 和 Truffle,如果不会的,可自行翻阅文档,网上很多资料。


  • 新建一个文件夹

  • 在新建的文件下执行下面的命令

truffle unbox pet-shop


这个命令是通过 truffle 的 unbox 工具初始化一个宠物DAPP,我们这里偷个懒,在官方的 pet-shop 项目上进行修改。


编写合约


在contracts文件夹下面新建一个 Election.sol 的合约文件,在这里我们进行合约编写。



合约内容如下:


pragma solidity ^0.4.2;

contract Election {    
    //结构体
    struct Candidate {
        uint id;
        string name;
        uint voteCount;
    }    //事件
    event votedEvent(
        uint indexed _candidateId
    );    //存储结构体
    mapping (uint => Candidate) public candidates;    //是否已经投票了
    mapping (address=>bool) public voters;    //总数量
    uint public candidateCount;    //构造函数
    function Election () public {
        addCandidate("张三);
        addCandidate("李四);
    }    //添加候选人
    function addCandidate(string _name) private {
        candidateCount ++;
        candidates[candidateCount] = Candidate(candidateCount, _name, 0);
    }    //投票
    function vote(uint _candidateId) public {        //过滤
        require(!voters[msg.sender]);
       require(_candidateId > 0 && _candidateId <= candidateCount);
               //记录用户已经投票了        voters[msg.sender] = true;        candidates[_candidateId].voteCount ++;        votedEvent(_candidateId);    } }


合约部分不赘述,如果有疑问可以留言。


部署合约


Truffle框架部署合约很简单,可以通过他的 migration 功能直接部署。


  • 在 migrations 文件夹下面,新建一个名为2_deploy_contract.js 的文件。

  • 在里面我们把我们的合约给加到 migration 里面,代码如下:

var Election = artifacts.require("./Election.sol);
module.exports = function(deployer) {  deployer.deploy(Election); };


这里说明下,如果你想偷懒,也可以直接在他下面的1_initial_migration.js文件里面导入Election.sol文件再加到 migration 里面。


  • 在一切准备就绪,只需要在终端上执行下面的命令

truffle migrate --reset


就能部署好了。为啥要加 --reset 如果你的合约第一次部署,可以不加,如果是迭代覆盖部署,就的加这个参数,好从新给你分配一个地址,否者会出现莫名其妙的问题,具体详细介绍,请查阅官方文档。


如果你这里使用的tesrpc环境,服务地址的端口是 8545 你需要去 修改下项目里面的 truffle.js文件里面的配置



编写html页面


由于我们是在 pet-shop 项目上进行修改的,所以我们只需要去修改 src/index.html 文件的内容就可以了。


我们把内容修改成如下内容:


             区块链投票        

     

       

         

区块链投票

         


         
         

           

Loading...

         

         

           

                                                                                                                                                                        
#NameVotes

           


                                 

             

                                           

                        

         

               


         


       

     

   

                


代码很简单,不用解释应该都能看懂哈。


编写js文件


js部分是DAPP比较麻烦的地方,也是最初学者迷惑的地方,我这里先把最终代码粘贴过来再解释:


App = {
  web3Provider: null,
  contracts: {},
  account: '0x0',

  init: function() {    return App.initWeb3();
  },

  initWeb3: function() {    if (typeof web3 !== 'undefined') {
      App.web3Provider = web3.currentProvider;
      console.warn("Meata);
    }else{
      App.web3Provider = new Web3.providers.HttpProvider('https://localhost:7545');
    }
    web3 = new Web3(App.web3Provider);    return App.initContract();
  },

  initContract: function() {
    
    $.getJSON("Election.json",function(election){
      
      App.contracts.Election = TruffleContract(election);
      App.contracts.Election.setProvider(App.web3Provider);

      App.listenForEvents();      return App.reander();
    })
    
  },

  reander: function(){    var electionInstance; 
  var $loader = $("#loader);    var $content = $("#content);    $loader.show();    $content.hide();    //获得账号信息    web3.eth.getCoinbase(function(err,account){      if(err === null){        App.account = account;        $("#accountAddress).html("您当前的账号: " + account);      }    });    //加载数据    App.contracts.Election.deployed().then(function(instance){      electionInstance = instance;      return electionInstance.candidateCount();    }).then(function(candidatesCount)
  {      var $candidatesResults = $("#candidatesResults);      $candidatesResults.empty();  
      var $cadidatesSelect = $("#cadidatesSelect);      $cadidatesSelect.empty();      for (var i=1;i<=candidatesCount;i++){        electionInstance.candidates(i).then(function(candidate)
  {          var id = candidate[0];          var name = candidate[1];
            var voteCount = candidate[2];
                     var candidateTemplate =
"";          $candidatesResults.append(candidateTemplate);          //投票          var cadidateOption = "
"+id+""+name+""+voteCount+"
  • initWeb3方法里面主要是对web3.js进行初始化,应该都能看懂。

  • initContract方法中

    • getJSON 方法是从本地读取json文件,在json文件读取成功后,再调用 Truffle 的 TruffleContract 方法进行合约初始化。

    • 初始化合约后,通过 setProvider 方法我这里理解是设置代理。


其他的都是调取的web3.js提供的api,除了api之外我觉得最有必要解释的是 App.contracts.Election.deployed().then(function(instance)... 这一串代码,这是实例化Election合约后会调取后面then 里面的方法同时,把实例化的变量通过 instance 带入到方法的参数里面。


同时在then里面有返回了一个方法 return instance.vote(candidateId,{from: App.account}); 这个方法又会执行,执行完后,又把执行的结果待会给下一个 then ,依次类推,这貌似是es6的链式语法。


如果我解释得不太明白,可以留言。


运行起来


上面的代码啥的一切准备就绪,现在只需要执行


npm run dev


项目就启动了,由于需要和testrpc或者Ganache交互,所有我们需要用到 MetaMask 插件,所以得要用谷歌浏览器,打开我们的项目,同时需要MetaMask 插件连接到我们的测试环境。



就能看到出来的效果了。


如果对MetaMask不了解的,可以在网上查阅相关资料。这里我的理解是,在DAPP中MetaMask充当的是一个桥梁作用,当我我们需要用到签名时,他会出现一个签名的界面让你确认,如下图:



其实就是一个轻钱包。


来源:简书 作者:_谦益

版权申明:本内容来自于互联网,属第三方汇集推荐平台。本文的版权归原作者所有,文章言论不代表链门户的观点,链门户不承担任何法律责任。如有侵权请联系QQ:3341927519进行反馈。
相关新闻
发表评论

请先 注册/登录 后参与评论

    回顶部