Truffle+Vue+MetaMask创建一个以太坊Dapp

参考资料

  • 使用 Web3 和 Vue.js 来创建你的第一个以太坊 dAPP
  • web3 1.0 API

开发环境

  • Windows10
  • web3 1.0

编写第一个Solidity智能合约

一个简单的例子是编写一个可以注册,保存社区成员信息和简单电子钱包功能的账户合约

pragma solidity ^0.4.24;
import "./SafeMath.sol";//开源的安全操作unit256的合约

contract Account{
    using SafeMath for uint256;
    //新成员创建事件
    event NewMember(string _name, string _avator);
    //成员信息结构
    struct Member {
        string name;//名字
        string avatar;//头像
        bool isExist;//是否注册
        uint256 balance;//可周转余额
    }
    //地址到成员信息的mapping
    mapping(address => Member) internal addressToMember;
    //限制调用的条件
    modifier onlyMemberOf(address _from){
        require(addressToMember[_from].isExist);
        _;
    }
    // 注册
    function registerMember(string _name, string _avatar) public {
        require(!isMemberOf());
        addressToMember[msg.sender] = Member(_name, _avatar, true, 0);
        emit NewMember(_name, _avatar);
    }

    // 判断是否注册
    function isMemberOf() public view returns (bool) {
        return addressToMember[msg.sender].isExist;
    }

    // 获取个人信息
    function getMemberInfo() public view onlyMemberOf(msg.sender) returns (string name, string avatar, uint256 balance) {
        return (addressToMember[msg.sender].name,addressToMember[msg.sender].avatar, addressToMember[msg.sender].balance);
    }
    //获取当前合约中的总余额
    function getTotalBalance() public view returns (uint256) {
        return address(this).balance;
    }
    //取出可周转余额
    function withdraw(uint256 amount) public onlyMemberOf(msg.sender) returns (uint256) {
        require(address(this).balance >= amount);
        addressToMember[msg.sender].balance = addressToMember[msg.sender].balance.sub(amount);
        msg.sender.transfer(amount);
        return addressToMember[msg.sender].balance;
    }
}
复制代码

在Remix上部署合约

  • 安装Ganache
  • 使用Ganache本地测试:安装MetaMask Chrome插件, 选择Custom RPC创建RPC连接到http://127.0.0.1:7545
  • 或者要部署到私有节点,可以使用命令行,然后选择Custom RPC创建RPC连接到http://127.0.0.1:8545
$ geth --identity "MY Etherum" --rpc --rpccorsdomain "*" --datadir data --port "8545" --rpcapi "db,eth,net,web3,personal" --networkid 666 console
复制代码
  • 打开Remix在线编译,在compile选择合适的编译版本编译,在run选择Deploy部署得到合约地址
  • 可以在Remix上测试我们的合约(注册后getMemberInfo可以用户信息,isMemberOf为true)
  • 合约部署和测试成功后,将ABI和Deployed Contracts复制保存到本地文件夹(注意Ganache得到的地址是临时的,下次打开就会失效)

配置Truffle+Vue项目

  • 环境配置
    在windows下需要先安装node.js, 建议使用Git Bash或者PowerShell执行命令:
    $ npm install -g -production windows-build-tools
    $ npm install -g ganache-cli
    $ npm install -g truffle
    $ npm install -g vue-cli
    复制代码
  • Vue项目安装
    $ vue init webpack ecourse // vue init webpach + 你的项目名
    $ cd ecourse
    $ npm install --save element-ui vue-router vuex [email protected] [email protected]
    复制代码
  • 添加文件及文件夹:① contracts放置.sol合约; ② store放置Vuex状态控制代码;③ util放置工具函数,util/constant放置上一步中编译好的合约地址和ABI,util/config放置一些配置

完善项目

具体的配置可以参考博客使用 Web3 和 Vue.js 来创建你的第一个以太坊 dAPP,这里我主要指出使用web3 1.0 标准的不同配置

  • getWeb3.js
import Web3 from 'web3'

let getWeb3 = new Promise(function (resolve, reject) {
  var web3js = window.web3;
  var web3Provider;
  if (typeof web3js !== 'undefined') {
  	web3Provider = web3js.currentProvider;
  } else {
  	web3Provider = new Web3.providers.HttpProvider('http://127.0.0.1:7545');
  }
  var web3 = new Web3(web3Provider);
  resolve({
  	injectedWeb3: web3.eth.net.isListening(), // 新的api
  	web3() {
  		return web3
  	}
  })
})
  .then(result => {
  	return new Promise(function (resolve, reject) {
  	  result.web3().eth.net.getId((err, networkId) => { // 新的api
  	  	if(err) {
  	  	  reject(new Error('Unable to retrieve network ID'))
  	  	} else {
  	  	  console.log('retrieve newworkId: ' + networkId)
  	  	  result = Object.assign({}, result, {networkId})
  	  	  resolve(result)
  	  	}
  	  })
  	})
  })
  .then(result => {
  	return new Promise(function (resolve, reject) {
  	  result.web3().eth.getCoinbase((err, coinbase) => {
  	  	if(err) {
  	  	reject(new Error('Unable to retrieve coinbase'))
  	  } else {
        coinbase = result.web3().utils.toChecksumAddress(coinbase);
  	  	console.log('retrieve coinbase: '+ coinbase);
  	  	result = Object.assign({}, result, {coinbase});
  	  	resolve(result)
  	  }})
  	})
  });

  export default getWeb3
复制代码
  • pollWeb3.js(web3 1.0 添加了新的api能够监听账户地址的变化,不需要使用setIntervel进行轮询)
import Web3 from 'web3'
import {store} from '../store/'

let web3 = window.web3;
web3 = new Web3(web3.currentProvider);
web3.currentProvider.publicConfigStore.on('update', ({selectedAddress, networkVersion}) => {
  store.dispatch('pollWeb3', {
    coinbase: selectedAddress
  })
});
复制代码
  • getContract.js
import Web3 from 'web3'
import {address, ABI} from './constant/ecourse_abi'
import {store} from '../store/'

let getContract = new Promise(function(resolve, reject) {
  let web3 = new Web3(window.web3.currentProvider);
  let ecourseContractInstance =  new web3.eth.Contract(ABI, address);//新的api
  if (!ecourseContractInstance) {
    reject("no contract instance build")
  }
  resolve(ecourseContractInstance);
});
export default getContract
复制代码

Dapp调用合约函数

  • App.vue(我们可以在入口文件注册web3和contract)
async beforeCreate() {
    if(!this.$store.state.web3.web3Instance) {
    await this.$store.dispatch('registerWeb3');
    await this.$store.dispatch('getContractInstance');
    }
},
复制代码
  • web3 1.0调用函数使用methods
// 为避免报错,可以在调用合约函数之前,进行一个判断
if(typeof this.$store.state.contractInstance !== "function") {
    await this.$store.dispatch('getContractInstance');
}
// 一个调用函数的例子
this.$store.state.contractInstance().methods.withdraw(this.formInline.balance)
    .send({from:this.$store.state.web3.coinbase, gas: 300000})
    .on('receipt', receipt => {
        this.$message('取款成功');
    })
    .on('error', error => {
        this.$message('取款失败');
    })
// 另一个调用函数的例子
this.$store.state.contractInstance().methods.getMemberInfo()
.call({from: state.web3.coinbase}) //注意!!!!!from不能省略,因为metamask默认的msg.sender是accounts[0]
.then(res => {
    console.log('account info: ' + res);
})
.catch(error => {
    console.log(error);
})
复制代码

其他

  • 之前没有学习过vue项目的,可以从一个最简单的Truffle PetShop项目学起,可以很快搭建并看到一个合约怎样调用。
  • 学习solidity的很好的网站:cryptozombies,大概两天可以把所有lesson过一遍,基本上编写合约就没什么问题了
  • 可以在truffle官网上找到很多框架,直接unbox使用,不过我觉得自己配置使用起来比较容易

我的项目地址:Github
有问题,可以随时提问

转载于:https://juejin.im/post/5c10b73d6fb9a049e82b5fff

你可能感兴趣的:(javascript,区块链,git)