区块链投票应用:使用solidity+truffle+metamsk开发Dapp应用

Posted NUDT_林逸飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了区块链投票应用:使用solidity+truffle+metamsk开发Dapp应用相关的知识,希望对你有一定的参考价值。

参考教程:https://www.bilibili.com/video/BV14z4y1Z7Jd?p=8
本博客是学习Dapp开发过程的笔记,感谢令狐一冲老师精彩讲解。上述是老师B站视频链接。

Ganache

ganache是一个本地区块链环境,每次启动后会在内存中模拟一个区块链。

1.环境安装

1.安装Node.js

2.安装 ganache-cli(ganache也可以)

3.运行ganache

ganache-cli

!!Truffle

安装truffle

sudo npm install -g truffle

安装过程中可能出错,可能解决方式

//升级node.js
sudo npm install -g n
sudo n stable

安装完成之后检查安装

truffle -v  //版本

开发DApp(投票为例)

1.编写智能合约

投票合约

// SPDX-License-Identifier: SimPL-2.0
pragma solidity >=0.4.18 <0.8.0;

contract Voting{
    bytes32[] public candodateList;
    mapping(bytes32 => uint8) public votesReceived;
    
    
    constructor(bytes32[] memory _candidateListName) public {
        candodateList = _candidateListName;
    }
    
    function validateCan(bytes32 _candidate) internal view returns(bool) {
        for(uint8 i = 0; i< candodateList.length; i++) {
            if(candodateList[i] == _candidate)
                return true;
        }
        return false;
    }
     
    function voteForCan(bytes32 _candidate) public {
        votesReceived[_candidate] += 1;
    }
    
    function totalVotes(bytes32 _candidate)public view returns(uint8) {
        return votesReceived[_candidate];
    }
}

2.创建项目

mkdir Voting
cd Voting

truffle unbox webpack
//webpack 可以换成其他的模板文件,也可以换成init不用模板

//遇到问题了,
/*
✔ Preparing to download box
✖ Downloading
Unbox failed!
✖ Downloading
Unbox failed!
Error: Error connecting to github.com. Please check your internet connection and try again.
*/
//也可以通过如下方式获取
git clone https://github.com/truffle-box/webpack-box.git
$ cd truffle-init-webpack

3.修改合约部署脚本

1.启动ganache

删除模板里其他合约,将自己的合约部署到ganache上

2.修改合约部署脚本

修改migration中的2_deploy+contract.js(照着葫芦画瓢)

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

module.exports = function(deployer) {
    // deployer.deploy(ConvertLib);
    // deployer.link(ConvertLib, MetaCoin);
    // deployer.deploy(MetaCoin);
    deployer.deploy(Voting, [
        "0x4100000000000000000000000000000000000000000000000000000000000000",
        "0x4200000000000000000000000000000000000000000000000000000000000000"
    ]);
    //注意Voting部署时有参数
};

3.编译合约

wakin@ubuntu:~/Documents/course/truffle/vote1/webpack-box$ truffle compile

4.修改网络方式

修改truffle-conflig.js,改成ganach

(好像不用改)

module.exports = {
  networks: {
    development: {
      host: 'localhost',
      port: 8545,
      network_id: '*' // Match any network id
    }
  }
}

4.部署合约

truffle migrate
//注意有参数,并且还要是bytes32//部署成功之后,可以打开truffle自带的控制台来测试一下

4.编写前端界面

<!DOCTYPE html>
<html>

<head>
    <title>Voting</title>
</head>
<style>
    input {
        display: block;
        margin-bottom: 12px;
    }
</style>

<body>

    <h1>Voting App</h1>
    <p>Alice : <strong id="alice">loading...</strong> tickets</p>
    <p>Bob : <strong id="bob">loading...</strong> tickets</p>

    <label>VotoFor :</label>
    <input type="text" id="candidate" />
    <button onclick="App.voteForCan()">vote</button>
    <script src="index.js"></script>
</body>

</html>

必须在app目录下

sudo npm run dev//先到指定目录安装依赖npm install 

去浏览器看看一下界面

http://127.0.0.1:8080/

在这里插入图片描述

5.前端与区块链交互

编辑index.js

import Web3 from "web3";
//导入Voting.json
import votingArtifact from "../../build/contracts/Voting.json";
//定义两个值,方便传参
const aInBytes32 = "0x4100000000000000000000000000000000000000000000000000000000000000";
const bInBytes32 = "0x4200000000000000000000000000000000000000000000000000000000000000";

//定义了app
const App = {
    web3: null,
    account: null,
    voting: null, //定义一个voting的实例

    //启动时需要的
    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];
            //先刷新一下界面
            this.ready();

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

    //start函数后还应该有哪些函数呢
    //1.refresh展示最新票数
    refresh: async function(id, nameInBytes32) {
        const { totalVotes } = this.voting.methods;
        //从区块链拿到票数
        const tickets = await totalVotes(nameInBytes32).call();
        //写到页面上去,并更新最新票数
        const element = document.getElementById(id);
        element.innerHTML = tickets.toString();
    },

    //2.ready:当网页好的时候要把票数读出来
    ready: async function() {
        try {
            this.refresh("alice", aInBytes32);
            this.refresh("bob", bInBytes32);
        } catch (err) {
            console.log(err);
        }
    },

    //3.votingfor函数(中间需要展示票数的函数)
    voteForCan: async function() {
        try {
            //先获取到合约的方法
            const { voteForCan } = this.voting.methods;
            //再获取候选者名字:来自输入框
            const candidateName = document.getElementById("candidate").value;
            //拿到票数后对应加一
            if (candidateName == "Alice") {
                await voteForCan(aInBytes32).send({ from: this.account });
                this.refresh("alice", aInBytes32);
            } else if (candidateName == "Bob") {
                await voteForCan(bInBytes32).send({ from: this.account });
                this.refresh("bob", bInBytes32);
            }
        } catch (err) {
            //如果有err就打印一下
            console.log(err);
        }
    }

};

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();
});

6.metamask的使用(如遇问题,经常刷新)

1.通过私钥导入账户

在这里插入图片描述

2.链接到本地网络

Localhost 8545

3.连接账户

在这里插入图片描述

4.投票操作

在这里插入图片描述

总结

1.编写智能合约

2.编译

truffle compile

3.部署

truffle migrate

4.启动本地区块链

ganache -cli

5.编写Dapp(html和js)

6.(app目录下)启动Dapp

sudo npm run dev

7.http://127.0.0.1:8080/

查看界面,并于小狐狸交互

注意:每次都要重新进行2-6操作

以上是关于区块链投票应用:使用solidity+truffle+metamsk开发Dapp应用的主要内容,如果未能解决你的问题,请参考以下文章

区块链投票应用:使用solidity+truffle+metamsk开发Dapp应用

以太坊 DApp 开发入门实战! 用Node.js和truffle框架搭建——区块链投票系统!

以太坊开发完整去中心化应用 —— 区块链投票系统

区块链入门Truffle 项目实战,Solidity IDE, 智能合约部署

基于区块链的投票系统的设计与实现之环境的搭建

区块链测试 以太坊 truffle是什么 怎么用