學(xué)習(xí)筆記vue + koa + mongodb集合開發(fā)以太坊Dapp

經(jīng)過好一段時(shí)間的折騰,還好搞出一個(gè)稍微有點(diǎn)含金量的的提升,在這里得感謝我的大飛哥的鼎力支持!阿里嘎多。。。

該demo涉及的技術(shù)點(diǎn)(僅供參考):

element-ui
koa2
MongoDB
Solidity
go-ethereum
IPFS星際文件系統(tǒng)
web3
truffle

輔助鏈接及工具:

Solidity在線編譯
MateMask
源碼地址: https://github.com/Jacky-MYD/vue-dapp-demo

至于開發(fā)環(huán)境的搭建應(yīng)該是比較繁瑣的,上述鏈接可以參考,當(dāng)然各技術(shù)點(diǎn)的官網(wǎng)會(huì)好一點(diǎn)。

項(xiàng)目目錄

image.png

內(nèi)置客戶端(client)和服務(wù)端(server),可以download項(xiàng)目
啟動(dòng)項(xiàng)目:
1.啟動(dòng):MongoDB

sudo mongod

2.cd到服務(wù)端:

cd serve 
npm install
npm run start // 默認(rèn)端口8081

3.cd到客戶端

cd client 
npm install
npm run dev // 默認(rèn)端口:8090

4.打開Ganache,默認(rèn)本地環(huán)境:http://127.0.0.1:7545
5.登錄MateMask
6.啟動(dòng)ipfs環(huán)境

ipfs daemon

7.瀏覽器訪問:http://127.0.0.1:8090
在各種環(huán)境都啟動(dòng)好之后,就可以通過合約進(jìn)行注冊(cè)用戶

demo簡(jiǎn)介
在編寫好服務(wù)端register的API以及客戶端代碼后(這里就不解釋了),
編寫合約:
Account.sol

pragma solidity ^0.5.8;
import "./SafeMath.sol";//開源的安全操作unit256的合約

contract Account{
    using SafeMath for uint256;
    //新成員創(chuàng)建事件
    event NewMember(string _name, string _avator);
    //成員信息結(jié)構(gòu)
    struct Member {
        string name;//名字
        string avatar;//頭像
        bool isExist;//是否注冊(cè)
        uint256 balance;//可周轉(zhuǎn)余額
    }
    //地址到成員信息的mapping
    mapping(address => Member) internal addressToMember;
    //限制調(diào)用的條件
    modifier onlyMemberOf(address _from){
        require(addressToMember[_from].isExist);
        _;
    }
    // 注冊(cè)
    function registerMember(string memory _name, string memory _avatar) public {
        require(!isMemberOf());
        addressToMember[msg.sender] = Member(_name, _avatar, true, 0);
        emit NewMember(_name, _avatar);
    }
  ...
}

通過truffle進(jìn)行合約編譯 ,編譯后會(huì)得一個(gè)Account.json文件,里面含有合約的ABI和合約地址等信息

const Account = artifacts.require("Account");

module.exports = function(deployer) {
  deployer.deploy(Account);
};

連接web3

import Web3 from 'web3'

let getWeb3 = new Promise((resolve, rejects) => {
    var web3js = window.web3;
    var web3Provider;
    if (typeof web3js !== 'undefined') {
        web3Provider = web3js.currentProvider;
    } else {
        // If no injected web3 instance is detected, fall back to Ganache
        web3Provider = new Web3.providers.HttpProvider('http://127.0.0.1:7545');
    }
    var web3 = new Web3(web3Provider);
    resolve({
        injectedWeb3: web3.eth.net.isListening(),
        web3() {
            return web3
        }
    })
}).then((result) => {
    return new Promise(function (resolve, reject) {
        result.web3().eth.net.getId((err, networkId) => {
            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

通過web3調(diào)用合約中的方法

import Web3 from 'web3'
import { address, ABI } from './comtractsAbi/Account'
import AccountContract from '../../build/contracts/Account'

let getContract = new Promise((resolve, rejects) => {
    let web3 = new Web3(window.web3.currentProvider)
    let MyContract = new web3.eth.Contract(AccountContract.abi, AccountContract.networks[5777].address)
    if (!MyContract) {
        reject("no contract instance build")
      }
      resolve(MyContract);
})

export default getContract

配置ipfs

import ipfsAPI from 'ipfs-api'
import util from './util'

let ipfs = ipfsAPI('localhost', '5001', {protocol: 'http'})

let ipfsPublic = {
    /**
     * set ipfs
     */
    add: (param) => {
        return new Promise(async (resolve, reject) => {
            const buffer = Buffer.from(param)
            await ipfs.add(buffer).then( rsp => {
                resolve(rsp[0].hash)
            }).catch(err => {
                console.error(err)
                reject (err)
            })
        })
        
    },
    /**
     * get ipfs buffer
     */
    getBuff: (hash) => {
        return new Promise(async (resolve, reject) => {
            await ipfs.cat(hash).then( buff => {
                resolve(buff)
            })
            .catch(err => {
                console.error(err)
                reject (err)
            })
        })
    },
    /**
     * buffer to utf-8 str
     */
    get: (hash) => {
        return new Promise(async (resolve, reject) => {
            await ipfs.cat(hash).then( buff => {
                let strContent = util.Utf8ArrayToStr(buff);
                resolve(strContent)
            })
            .catch(err => {
                console.error(err)
                reject (err)
            })
        })
    }
}

export default ipfsPublic

至于代碼詳情,可看源碼
項(xiàng)目流程簡(jiǎn)單說明
在合約部署后,項(xiàng)目啟動(dòng)完成時(shí),會(huì)得到一個(gè)合約地址(address:"0x07f417017aa903616eecc7fb4932b7f1383305a3")


image.png

在點(diǎn)擊注冊(cè)后,注冊(cè)信息會(huì)存儲(chǔ)到ipfs中,ipfs將返回一個(gè)hash值('QmT1QLKwUkgsR2uR8XFxhyoVp3SRnJFyxqHvdPG1RicUS6'),用于獲取相應(yīng)的信息
獲取hash后,通過合約地址調(diào)用合約中的registerMember方法,然后會(huì)自動(dòng)打開MateMask,進(jìn)行一筆交易


image.png

交易完整后,就會(huì)產(chǎn)生一個(gè)block(塊),這個(gè)block中含有一些信息,如:調(diào)用者(address:"0xd0922930b70f81777458aa965482bf6f28ea840a"),交易hash(transactionHash: "0xeddcf41eb0b35004bdc95daaeb31708a2634cc577e1bf13f69c5506d3ea69215"),區(qū)塊高度(blockNumber:33)等
image.png

最后,我在這里將一些相應(yīng)的字段信息同步到MongoDB中。
image.png

image.png

更多細(xì)節(jié)內(nèi)容,可以運(yùn)用你所能運(yùn)用的手段學(xué)習(xí)。
Over!??!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在整個(gè)加密貨幣市場(chǎng)的市值超過7000億美元之后,加密貨幣市場(chǎng)在過去幾個(gè)月太瘋狂了,但這只是一個(gè)開始。隨著區(qū)塊鏈系統(tǒng)...
    編程狂魔閱讀 1,638評(píng)論 0 2
  • 根據(jù)英文原版整理,內(nèi)容有增刪 1、開發(fā)語言、框架與工具 語言 Solidity - 官方推薦以太坊智能合約開發(fā)語言...
    Rakutens閱讀 988評(píng)論 0 2
  • 在我這一天拍的照片我覺得我喜歡我的家鄉(xiāng)是最美的! 家鄉(xiāng)是最美好的! 老家的天氣挺好的,我覺得在我眼里我老家的下...
    這小兵張嘎閱讀 185評(píng)論 0 0
  • 以前我總覺得愛情這種東西 都是無病呻吟的滿嘴謊話的東西 就算我一直以來都是在愛情這條路上裝作別人的良師益友可是我始...
    小太陽9264閱讀 240評(píng)論 0 0

友情鏈接更多精彩內(nèi)容