DApp开发者教程Dapp开发

两个简单的DApp, 宠物商店+投票

2018-08-19  本文已影响23人  rajs20222007

0x1 宠物商店

合约分析

宠物商店的合约内容如下, 其Dapp实现的是在宠物商店提供十六个宠物, 领养者可以选择一个进行领取. 合约使用solidity

pragma solidity ^ 0.4.18;

contract Adoption {
  address[16] public adopters;

  function adopt(uint petId) public returns(uint) {
    require(petId >= 0 && petId <= 15);
    adopters[petId] = msg.sender;
    return petId;
  }
  
  function getAdopters() public view returns(address[16]) {
    return adopters;
  }
}

<code>Adoption</code>就是合约名.
<code>address[16]</code>保存了领取宠物的用户地址, 16个宠物对应了十六个领取地址.

  function adopt(uint petId) public returns(uint) {
     //先判断宠物id是否在0~15, 宠物商店只提供16种宠物
    require(petId >= 0 && petId <= 15);
    //领养人的地址存储到对应的宠物领养位置
    //msg.sender是发起此方法的用户, 也就是领养用户发起的消息中的发起者
    adopters[petId] = msg.sender;
    //返回领取成功的宠物id
    return petId;
  }

<code>getAdopters</code>方法获取所有领养人.

宠物商店Web3

/scr/js目录下app.js文件内容如下:

App = {
  web3Provider: null,
  contracts: {},

  init: function() {
    // 加载宠物和其详细信息
    $.getJSON('../pets.json', function(data) {
      var petsRow = $('#petsRow');
      var petTemplate = $('#petTemplate');

      for (i = 0; i < data.length; i ++) {
        petTemplate.find('.panel-title').text(data[i].name);
        petTemplate.find('img').attr('src', data[i].picture);
        petTemplate.find('.pet-breed').text(data[i].breed);
        petTemplate.find('.pet-age').text(data[i].age);
        petTemplate.find('.pet-location').text(data[i].location);
        petTemplate.find('.btn-adopt').attr('data-id', data[i].id);

        petsRow.append(petTemplate.html());
      }
    });
     //返回加载后的实例
    return App.initWeb3();
  },

  initWeb3: function() {
     //如果有注入的web3, 则使用注入的web3
    if (typeof web3 !== 'undefined') {
      App.web3Provider = web3.currentProvider;
    } else {
      //如果没有注入的web3示例, 则在本地端口创建
      App.web3Provider = new Web3.providers.HttpProvider('http://localhost:8545');
    }
    web3 = new Web3(App.web3Provider);
    return App.initContract();
  },

  initContract: function() {
    $.getJSON('Adoption.json', function(data) {
      //用Adoption.json数据创建一个可交互的TruffleContract合约实例。
      var AdoptionArtifact = data;
      App.contracts.Adoption = TruffleContract(AdoptionArtifact);
      return App.markAdopted();
    });
    return App.bindEvents();
  },

  bindEvents: function() {
    $(document).on('click', '.btn-adopt', App.handleAdopt);
  },

  markAdopted: function(adopters, account) {
    var adoptionInstance;

    App.contracts.Adoption.deployed().then(function(instance) {
      adoptionInstance = instance;
      // 调用合约的getAdopters(), 用call读取信息不用消耗gas
      return adoptionInstance.getAdopters.call();
    }).then(function(adopters) {
      for (i = 0; i < adopters.length; i++) {
        if (adopters[i] !== '0x0000000000000000000000000000000000000000') {
          $('.panel-pet').eq(i).find('button').text('Success').attr('disabled', true);
        }
      }
    }).catch(function(err) {
      console.log(err.message);
    });
  },

  handleAdopt: function(event) {
    event.preventDefault();
    var petId = parseInt($(event.target).data('id'));
    var adoptionInstance;
    // 获取用户账号
    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }
      var account = accounts[0];
      App.contracts.Adoption.deployed().then(function(instance) {
        adoptionInstance = instance;
        // 发送交易领养宠物
        return adoptionInstance.adopt(petId, {from: account});
      }).then(function(result) {
        return App.markAdopted();
      }).catch(function(err) {
        console.log(err.message);
      });
    });
  }
};

$(function() {
  $(window).load(function() {
    App.init();
  });
});

0x2 投票

合约分析

投票Dapp实现了一个对候选人进行投票的系统.

pragma solidity ^0.4.18;
contract Voting {
  // 存储投票映射
  mapping (bytes32 => uint8) public votesReceived;
  // 存储投票候选人名单
  bytes32[] public candidateList;
  // 准备候选人名单
  function Voting(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;
   }
}

投票Web3

/scr/js目录下app.js文件内容如下:

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 = "<tr><th>"+id+"</th><td>"+name+"</td><td>"+voteCount+"</td></tr>";
          $candidatesResults.append(candidateTemplate); //投票 
          var cadidateOption = "<option value='"+id+"'>"+name+"</option>"; 
          $cadidatesSelect.append(cadidateOption);
        });
      } 
      return electionInstance.voters(App.account);
    }).then(function(hasVoted){ 
      if(hasVoted){
        $('form').hide();
      }
      $loader.hide();
      $content.show();
    }).catch(function(err){
      console.warn(err);
    });
  }, 
  
  //投票 
  castVote: function(){
    var $loader = $("#loader");
    var $content = $("#content"); 
    var candidateId = $('#cadidatesSelect').val(); 
    App.contracts.Election.deployed().then(function(instance){ 
      return instance.vote(candidateId,{
        from: App.account
      });
    }).then(function(result){ 
      $content.hide(); 
      $loader.show();
    }).catch(function(err){ 
      console.warn(err);
    });
  }, 
  
  //监听事件 
  listenForEvents: function(){ 
    App.contracts.Election.deployed().then(function(instance){
      instance.votedEvent({},{ 
        formBlock:0, toBlock: 'latest' 
      }).watch(function(error,event){ 
        console.log("event triggered",event); 
        App.reander(); 
      }); 
    }) 
  } 
};
$(function() {
  $(window).load(function() {
    App.init(); 
  }); 
});

0x3 总结

Dapp开发主要内容是合约的开发和Web端开发, 在合约设计实现时要根据自己的目标Dapp功能设计合适的外部接口, 在Dapp实现时合适的调用合约接口即可完成Dapp开发. 跟多定义关于合约的设计内容可以去Truffle boxes查找Demo.

群二维码
上一篇 下一篇

猜你喜欢

热点阅读