第一个去中心化应用

本文内容来自熊丽兵老师在登链学院上的《以太坊Dapp开发实战》课程

简介

本文为一个简单的去中心化应用的开发,旨在了解以太坊Dapp开发流程。

应用效果图如下

第一个去中心化应用.png

应用的功能很简单

浅蓝色部分用来显示区块链上的姓名和年龄信息

浅绿色部分用来修改区块链上的姓名和年龄信息

开发流程

本例在Ubuntu系统下开发,据说在windows下会出现莫名其妙的问题,所以没用。

本开发示例没有使用任何框架,后续会写truffle框架开发示例

准备:选择以太坊网络节点、钱包连接节点、remix连接节点

后端:智能合约开发 -> 智能合约测试 -> 智能合约部署

前端:安装web服务器 -> 前端UI设计

交互:web3与智能合约交互

本例的工具选择

以太坊网络节点:ganache虚拟节点

钱包:metaMask

代码编辑器:Remix(以太坊在线IDE)

web服务器:lite-server

web3版本:web3.js

准备

选择一个以太坊网络节点,然后将钱包和remix跟此节点连接起来,打通环境

选择以太坊网络节点

以太坊的节点有很多种:主网、测试网络、geth私链节点、ganache模拟节点

因为每个交易都需要花钱,这在开发环境下非常不适合,所以开发时不要选择以太坊的主网,这会花费真实的以太币,也不要选择以太坊的测试网络,因为要等待区块的确认,这个过程会占用时间,而开发需要及时反馈。

这里选择ganache模拟节点

安装ganache

ganache有CLI和GUI两个版本,本文安装的是CLI版本。github地址:https://github.com/trufflesuite/ganache-cli

GUI版本地址:https://github.com/trufflesuite/ganache/releases ,如果想使用图形界面版,选择对应版本下载安装即可

sudo npm install -g ganache-cli //需要先安装nodejs
开启ganache

智能合约的测试部署需要在节点上进行,所以这里开启ganache节点。可以单独开一个终端运行ganache

ganache-cli

钱包连接ganache节点

以太坊Dapp交易需要花钱,钱存储在钱包里。所以,需要用到钱包。这里使用最常用的MetaMask钱包

MetaMask(官网:https://metamask.io/ )是一款浏览器插件钱包,不需下载安装客户端,只需添加至浏览器扩展程序即可使用。它不仅是一个简单的钱包,还可以很方便的调试和测试以太坊的智能合约。

安装MetaMask

安装可参考此链接:以太坊钱包MetaMask使用教程。基本的使用方法文章里都有介绍

连接ganache节点

点击MetaMask的NetWork栏,选择Private Network(ganache节点:localhost 8545),即可连接ganache节点

导入ganache账户

点击账户栏,选择 Import Account,输入私钥(启动ganache时会列出十个账户和对应的私钥,选择一个私钥复制过来)即可导入ganache自动创建的账户到MetaMask中。此账户中会默认有100ETH。用此账户来部署合约以及交易。

Remix连接ganache节点

Remix的Run界面的Environment选项里选择web3 Provider,弹出的窗口里输入ganache-cli的监听url(http://localhost:8545) ,即可连接上ganache节点

注意:remix中的使用的账户和MetaMask中使用的账户要一致
remix默认使用ganache创建的第一个账户,可以点击Account处更换
MetaMask导入账户时可直接导入第一个账户,就可与remix中的账户对应。

后端开发

智能合约开发使用以太坊的在线IDERemix

Remix使用请参考:教程 | 【Ethereum 智能合约开发笔记】使用 Remix

Remix编译版本要和智能合约的版本一致,否则会报错。
如智能合约使用0.4.24,那么remix也要选择0.4.24(Compile页面里选择)

智能合约开发

simple.sol

pragma solidity ^0.4.24;

contract simple{

    string name;
    uint age;

    //定义事件
    event Instructor(string name, uint age);

    function set(string _name, uint _age) public {
        name = _name;
        age = _age;

        //触发事件
        emit Instructor(name, age);
    }

    function get() public view returns(string, uint) {
        return (name, age);
    }
}

智能合约测试

这里不太好测试,后面用truffle时可以很方便的进行测试。要记住,Dapp开发一定要进行测试!这直接关系到钱!

智能合约部署

remix的Run页面里点击Deploy(create)按钮,即可把智能合约部署到节点上

在Deployed Contracts里会看到set和get函数。可以跟智能合约交互
set后面的输入框里输入"中本聪",18,然后点击set按钮。就将信息写入了区块链,然后点击get按钮,刚才输入的信息就会显示出来。

前端开发

项目目录结构

|-- simple  //项目根目录
    -- index.html
    -- index.css
    -- index.js

安装web服务器环境

项目开发中,环境的一致性非常重要,这里给项目本身安装web服务器(lite-server),而不需依赖外部的web服务器(如nginx)

npm install lite-server --save-dev

安装完后会在项目根目录下生成node_modules目录

|-- simple  //项目根目录
    -- index.html
    -- index.css
    -- index.js
    |-- node_modules

在终端开启服务

node_modules/lite-server/bin/lite-server

UI设计完后,开启服务后会自动打开网页,就会看到html内容

UI设计

基本的UI设计跟传统的App开发一样。

index.html



    
    
    
    第一个去中心化应用
    


    

第一个去中心化应用

index.css
body{background:#f0f0f0;}
#content{width:350px;margin:0 auto;}
#title{text-align: center;}
#info{padding:0.5em;background: lightblue;margin:1em 0;}
#update{padding:1em;background: lightgreen}
#name{border:none;}#age{border:none;}
button{margin:1em 0;}

web3与智能合约交互

这里是Dapp的关键部分,前端与智能合约使用RPC协议来交互。web3封装了RPC,提供了更友好的接口来调用.

web3有很多实现版本,用的最多的使web3.js。本例使用的就是web3.js。github地址:https://github.com/ethereum/web3.js ,详细信息可查看文档

大体步骤如下

获取web3对象 -> 得到智能合约实例 -> 调用智能合约方法来交互

修改html页面,在body最后引入js文件







index.js

//设置provider(web3连接到哪个节点)
if (typeof web3 !== 'undefined') {
    web3 = new Web3(web3.currentProvider);
} else {
    // Set the provider you want from Web3.providers
    web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}
//得到智能合约实例
//数组里是智能合约的abi。修改智能合约的话abi也会变化,需要更换
var infoContract = web3.eth.contract([
    {
        "anonymous": false,
        "inputs": [
            {
                "indexed": false,
                "name": "name",
                "type": "string"
            },
            {
                "indexed": false,
                "name": "age",
                "type": "uint256"
            }
        ],
        "name": "Instructor",
        "type": "event"
    },
    {
        "constant": false,
        "inputs": [
            {
                "name": "_name",
                "type": "string"
            },
            {
                "name": "_age",
                "type": "uint256"
            }
        ],
        "name": "set",
        "outputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [],
        "name": "get",
        "outputs": [
            {
                "name": "",
                "type": "string"
            },
            {
                "name": "",
                "type": "uint256"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    }
])

//地址为部署的智能合约的地址,重新部署的话地址就会改变,需要用新的合约地址
var simple = infoContract.at('0xa2eefd5ee8a78630d27e3b884b04b53315881942');

//调用合约的方法进行交互。交易是异步的,需要用回调函数来接收结果。结果在result里
simple.get.call(function(error,result){
    if(!error){
        $("#info").html(`我叫` + result[0] + `, 我今年` + result[1] + `岁了。`);
    }
});
//点击更新按钮,更新信息
$("#button").click(function(){
    $("#loader").show();
    simple.set.sendTransaction($("#name").val(),$("#age").val(),function(error,result){
        if(!error){
            console.log("set ok");
        }
    })
});
//监听事件,实时更新,而不是手动刷新浏览器更新。对应智能合约中自定义的event事件
var infoEvent = simple.Instructor();
infoEvent.watch(function(error,result){
    if(!error){
        $("#loader").hide();
        $("#info").html(`我叫` + result.args.name + `, 我今年` + result.args.age + `岁了。`);
    }else{
        $("#loader").hide();
        $("#info").html("Error:" + error);
    }
})

结语

这是一个简单的Dapp开发示例,目的是熟悉以太坊Dapp开发流程。
此方式有个很大的缺点,就是web3与智能合约交互太麻烦,修改智能合约后需要手动修改abi和地址信息。而且也不容易测试。

实际开发Dapp都是使用truffle框架来开发。后续会写truffle开发示例。

你可能感兴趣的:(第一个去中心化应用)