使用truffle开发Dapp

介绍

Truffle 是一个在以太坊进行 DApp 开发的世界级开发环境、测试框架。

安装truffle

在安装truffle之前需要安装nodejs,安装后通过如下命令安装truffle:

sudo npm install -g truffle

安装过程中可能会报错,如果报错则执行如下命令升级nodejs:

sudo npm install -g n  
sudo n stable  

truffle安装完成后用如下命令检查:

truffle -v

写合约

我们写一个简单的投票合约,如下:

pragma solidity >=0.4.22 <0.6.0;

contract Voting {
    bytes32[] public candidateList;
    mapping(bytes32 => uint8) public votesReceived;
    constructor(bytes32[] memory candidateListName) public  {
        candidateList = candidateListName;
    }
    function validateCanditate(bytes32 candidateName)internal view returns(bool) {
        for (uint8 i =0; i < candidateList.length; i++) {
            if (candidateName == candidateList[i])
                return true;
        }
        return false;
    
    }
    function voteForCandidate(bytes32 candidateName) public {
        require(validateCanditate(candidateName));
        votesReceived[candidateName] += 1;
    }
    function totalVotesFor(bytes32 candidateName) view public returns(uint8) {
        require(validateCanditate(candidateName));
        return votesReceived[candidateName];
    }
}

先将上述合约在remix中调试通过。

创建工程

使用如下命令创建工程:

mkdir Vote
cd Vote
truffle unbox webpack

创建合约:

cd contracts
rm meta.sol
rm Lib.sol
vim Voting.sol

将上面的合约代码拷贝到Voting.sol中。

修改migrations/_deploy_contracts.js如下:

//const ConvertLib = artifacts.require("ConvertLib");
//const MetaCoin = artifacts.require("MetaCoin");
const Voting = artifacts.require("Voting.sol");

module.exports = function(deployer) {
  //deployer.deploy(ConvertLib);
  //deployer.link(ConvertLib, MetaCoin);
  //deployer.deploy(MetaCoin);
  //deployer.deploy(Voting, ['A', 'B']);//error,注意,要使用16进制 bytes32
  deployer.deploy(Voting, 
    ["0x4100000000000000000000000000000000000000000000000000000000000000",
    "0x4200000000000000000000000000000000000000000000000000000000000000"]);
};

编译合约

truffle compile

部署合约

启动ganache-cli:

ganache-cli//如果报错则重新安装下npm install -g ganache-cli

修改truffle-config.js如下:

module.exports = {
  /**
   * Networks define how you connect to your ethereum client and let you set the
   * defaults web3 uses to send transactions. If you don't specify one truffle
   * will spin up a development blockchain for you on port 9545 when you
   * run `develop` or `test`. You can ask a truffle command to use a specific
   * network from the command line, e.g
   *
   * $ truffle test --network <network-name>
   */

  networks: {
    development: {
     host: "127.0.0.1",     // Localhost (default: none)
     port: 8545,            // Standard Ethereum port (default: none)
     network_id: "*",       // Any network (default: none)
    },
    ...
}

部署:

truffle migrate

部署完后可以用truffle console进行测试:

truffle console//打开truffle控制台
let instance = await Voting.deployed()
instance

修改前端的页面

修改app/src/index.html如下:

<!DOCTYPE html>
<html>
  <head>
    <title>Vote Demo</title>
  </head>
  <body>
    <h1>Voting App</h1>
    <p>Alice: <strong id="alice">loading...</strong> votes </p>
    <p>Bob: <strong id="bob">loading...</strong> votes </p>
    <label for="vote">VoteFor:</label>
    <input type="text" id="candidate"/>
    <button onclick="App.voteForCandidate()">vote</button>
    <script src="index.js"></script>
  </body>
</html>

修改app/src/index.js如下:

import Web3 from 'web3';
import votingArtifact from '../../build/contracts/Voting.json'
const aInBytes32 = "0x4100000000000000000000000000000000000000000000000000000000000000";
const bInBytes32 = "0x4200000000000000000000000000000000000000000000000000000000000000";

const App = {
  web3: null,
  account: null,
  voting: null, 
  
  start: async function() {
    const { web3 } = this;

    try {
      // get contract instance
      const networkId = await web3.eth.net.getId();
      const deployedNetwork = votingArtifact.networks[networkId];
      this.voting = new web3.eth.Contract(
        votingArtifact.abi,
        deployedNetwork.address,
      );

      // get accounts
      const accounts = await web3.eth.getAccounts();
      this.account = accounts[0];
      // console.log("will ready +++++++ ");
      this.ready();
    } catch (error) {
      console.error("Could not connect to contract or chain.");
    }
  },
  
  refresh: async function(id, nameInBytes32) {
    const { totalVotesFor } = this.voting.methods;
    const tickets = await totalVotesFor(nameInBytes32).call();
    const element = document.getElementById(id);
    element.innerHTML = tickets.toString();
  },
  
  ready: async function() {
    try {
      this.refresh("alice", aInBytes32);
      this.refresh("bob", bInBytes32);
    } catch (err) {
      console.log(err);
    }
  },
  
  voteForCandidate: async function() {
    try {
      const { voteForCandidate } = this.voting.methods;
    
      const candidateName = document.getElementById("candidate").value;
      if (candidateName == "Alice") {
        await voteForCandidate(aInBytes32).send({ from: this.account });;  
        this.refresh("alice", aInBytes32);
      } else if (candidateName == "Bob") {
        await voteForCandidate(bInBytes32).send({ from: this.account });;
        this.refresh("bob", bInBytes32);
      }
    } catch (err) {
      console.log(err);
    }
  },
}

window.App = App;

window.addEventListener("load", function() {
  // console.log("load+++++");
  if (window.ethereum) {
    // use MetaMask's provider
    App.web3 = new Web3(window.ethereum);
    window.ethereum.enable(); // get permission to access accounts
  } else {
    console.warn(
      "No web3 detected. Falling back to http://127.0.0.1:8545. You should remove this fallback when you deploy live",
    );
    // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
    App.web3 = new Web3(
      new Web3.providers.HttpProvider("http://127.0.0.1:8545"),
    );
  }

  App.start();
});

运行

npm run dev

打开浏览器,输入127.0.0.1:8080

  • 13
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值