Truffle+Vue+MetaMask建立一個以太坊Dapp

參考資料

開發環境

  • Windows10
  • web3 1.0

編寫第一個Solidity智能合約

一個簡單的例子是編寫一個能夠註冊,保存社區成員信息和簡單電子錢包功能的帳戶合約javascript

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 web3@1.0.0-beta.36 web3-net@1.0.0-beta.36
    複製代碼
  • 添加文件及文件夾:① contracts放置.sol合約; ② store放置Vuex狀態控制代碼;③ util放置工具函數,util/constant放置上一步中編譯好的合約地址和ABI,util/config放置一些配置

完善項目

具體的配置能夠參考博客使用 Web3 和 Vue.js 來建立你的第一個以太坊 dAPP,這裏我主要指出使用web3 1.0 標準的不一樣配置vue

  • 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
有問題,能夠隨時提問java

相關文章
相關標籤/搜索