用truffle构建dapp

###### 一、成功的环境配置:

​        truffle v5.1.50

​        solc:0.5.16

​        web3:1.2.9

        "devDependencies": {
    "copy-webpack-plugin": "^5.0.5",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.9.0"

  },
  "dependencies": {
    "truffle-contract": "^4.0.31",
    "web3": "^1.2.4"
  }

###### 二、构建webpack

​    ![image-20201026220148763](https://s1.ax1x.com/2020/10/26/BK0Oqx.png)

###### 三、清理配置webpack的内容

在contracts目录下删除多余的合约文件

![image-20201026222915475](https://s1.ax1x.com/2020/10/26/BKBfld.png)

修改truffle-config.js文件如下:

![image-20201026220344670](https://s1.ax1x.com/2020/10/26/BK07RJ.png)

###### 四、编写智能合约和网页,js文件

```js
pragma solidity >0.2.4;

// We have to specify what version of compiler this code will compile with

contract Voting {

  /* mapping field below is equivalent to an associative array or hash.

  The key of the mapping is candidate name stored as type bytes32 and value is

  an unsigned integer to store the vote count

  */

  

  mapping (bytes32 => uint256) public votesReceived;

  

  /* Solidity doesn't let you pass in an array of strings in the constructor (yet).

  We will use an array of bytes32 instead to store the list of candidates

  */

  

  bytes32[] public candidateList;

  /* This is the constructor which will be called once when you

  deploy the contract to the blockchain. When we deploy the contract,

  we will pass an array of candidates who will be contesting in the election

  */

  constructor(bytes32[] memory candidateNames) public {

    candidateList = candidateNames;

  }

  // This function returns the total votes a candidate has received so far

  function totalVotesFor(bytes32 candidate) view public returns (uint256) {

    require(validCandidate(candidate));

    return votesReceived[candidate];

  }

  // This function increments the vote count for the specified candidate. This

  // is equivalent to casting a vote

  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;

  }

}
```

index.html

```html
<!DOCTYPE html>
<html>
<head>
 <title>Hello World 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 Hello World 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>Rama</td>
     <td id="candidate-1"></td>
    </tr>
    <tr>
     <td>Nick</td>
     <td id="candidate-2"></td>
    </tr>
    <tr>
     <td>Jose</td>
     <td id="candidate-3"></td>
    </tr>
   </tbody>
  </table>
 </div>
 <input type="text" id="candidate" />
 <a href="#" οnclick="App.voteForCandidate()" class="btn btn-primary">Vote</a>
</body>
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js@1.0.0-beta.37/dist/web3.min.js"></script>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script>
<script src="./index.js"></script>

```

index.js

```js
import Web3 from "web3";
import votingArtifact from "../../build/contracts/Voting.json";

let candidates = {"Rama": "candidate-1", "Nick": "candidate-2", "Jose": "candidate-3"}

const App = {
  web3: null,
  account: null,
  voting: null,

  start: async function() {
    const { web3 } = this;

    try {
      /* Get the network we are connected to and then read the build/contracts/Voting.json and instantiate a contract object to use
      */

      // 
      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];

      this.loadCandidatesAndVotes();
    } catch (error) {
      console.error("Could not connect to contract or chain.");
    }
  },

  loadCandidatesAndVotes: async function() {
    const { totalVotesFor } = this.voting.methods;
    //const { sendCoin } = this.meta.methods;
    //await sendCoin(receiver, amount).send({ from: this.account });
    let candidateNames = Object.keys(candidates);
    for (var i = 0; i < candidateNames.length; i++) {
      let name = candidateNames[i];
      var count = await totalVotesFor(this.web3.utils.asciiToHex(name)).call();
      $("#" + candidates[name]).html(count);
    }
  },

  voteForCandidate: async function() {
    let candidateName = $("#candidate").val();
    $("#msg").html("Vote has been submitted. The vote count will increment as soon as the vote is recorded on the blockchain. Please wait.")
    $("#candidate").val("");

    const { totalVotesFor, voteForCandidate } = this.voting.methods;
    

    /* Voting.deployed() returns an instance of the contract. Every call
     * in Truffle returns a promise which is why we have used then()
     * everywhere we have a transaction call
     */
    await voteForCandidate(this.web3.utils.asciiToHex(candidateName)).send({gas: 140000, from: this.account});
    let div_id = candidates[candidateName];
    var count = await totalVotesFor(this.web3.utils.asciiToHex(candidateName)).call();
    $("#" + div_id).html(count);
    $("#msg").html("");
  }
  
};

window.App = App;

window.addEventListener("load", function() {
  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();
});
```

五、部署,运行

首先需要一个本地的私有链作为合约部署的目的链。

使用truffle develop 来启动一个私有区块链用于测试。

![image-20201026220917705](https://s1.ax1x.com/2020/10/26/BK0Ls1.png)

有了区块链,之后就可以把合约部署在链上了。

修改migrates下的2_deploy_contracts.js文件

指定我们自己的合约文件:

```javascript
const Voting = artifacts.require("Voting");

module.exports = function(deployer) {

  deployer.deploy(Voting, ['Rama', 'Nick', 'Jose'].map(name => web3.utils.asciiToHex(name)));

};
```

在项目根路径下执行truffle migrate .

![image-20201026221045996](https://s1.ax1x.com/2020/10/26/BK0qMR.png)

说明合约部署成功。

在app路径下执行npm install 用于安装package.json中定义的依赖。

执行npm run dev.

打开浏览器 输入 http://localhost:8080即可看到页面

![image-20201026221451128](https://s1.ax1x.com/2020/10/26/BK0jZ6.png)

测试一下功能,至此就使用truffle框架搭建起一个简单的dapp。

遇到问题:实际上遇到的最大的问题还是环境配置的问题,由于webpack 和webpack-dev-server版本不相兼容的问题是最让人头疼的。

还有由于web3版本1.x与0.20.x的区别,在与合约进行交互的时候也要注意要使用恰当的写法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值