发布文章

Dapp开发快速入门教程

作者
  • avatar
    作者
    Jack Chen @懒人码农

前言

Dapp是去中心化应用,它和我们平时使用的App(微信,支付宝等)只差了一个去中心化,如何理解这一去中心化?从体验层面来说:Dapp中并没有管理者,大家都是平等的,互相监督;而从技术层面来说:传统的App和部署在服务器的后端产生交互,而Dapp则是和部署在区块链上的智能合约产生交互。

去中心化应用Dapp是在去中心化网络上构建的应用程序,结合了智能合约和前端用户界面。请注意,以太坊智能合约具有可访问性和透明性,就像开放API一样,所以你的Dapp里甚至可以包含其他人写过的智能合约。

学前准备

  • 你要学会科学上网,这是必备的技能,我下面分享的一些链接有很多需要科学上网才能打开;
  • 你要有会Google的能力,搜索能力将是你后面最重要的能力,中文无法搜索到你要的结果,要学会英文搜索;
  • 要会使用github,各种大神的demo是我们学习的珍贵资料,一定要看要啃;
  • Metamask钱包与Google浏览器要下载要学会用。

前提条件

在学习Dapp之前,您应该了解区块链基础知识,并了解以太坊网络及其去中心化方式。

Web3.0是什么

现在很多人都说web3.0开发,那web3.0到底是什么呢?关于这个问题,我就不过多展开了。因为并没有定论,有的人认为web3.0很宽泛,涵盖了区块链、人工智能、大数据、DAO、元宇宙等等。也有人定义的很窄,差不多等同于Dapp应用。web3.0最基本的共识就是可读、可写、可拥有的互联网。

web1.0就是可读的互联网。当年的四大门户新浪、网易、搜狐、腾讯就是代表。网站自己生产新闻,用户只能阅读,不能参与。网站发什么,就只能看什么。

web2.0就是可读、可写的互联网论坛、微博、社区、短视频都是典型代表。网站的内容都是用户制作上传的,而不是经营者自己制作内容,专业术语是UGC,也就是用户生成内容。

web3.0就是可读、可写、可拥有的互联网,我们在抖音分享了日常精彩的生活片段,抖音平台就能得到流量,然后变现为广告收入。你在平台直播获得打赏或者带货收入,平台拿走大头,你只能拿点小头。所以你产生的数据,所有权并不归你。web3.0就是解决了这个痛点,我的就是我的,数据可拥有,细的内容不再展开。你大体对web3.0可能有所了解了。

Dapp是什么

Dapp就是web3.0范畴的产品,也就是去中心化的应用。因为没有中心控制,所以也就不存在被平台控制、被盘剥了。Dapp的核心是去中心化,一提到去中心化,我们就知道它必然使用了区块链技术。所以对于Dapp更为容易理解的说法,就是结合了区块链技术的应用程序。我们现在使用的应用程序,有的是桌面系统,有的是服务器系统,但我们日常使用最多的,还是web应用,大多数事情都可以通过互联网完成。Web是最友好、最方便、最经济的人机交互途径。Dapp也是这样,大多数Dapp其实就是加入了区块链技术的Web应用,为了能够有一个直观地感受,快速了解Dapp能干什么,下面会详细讲解一个竞猜类Dapp游戏案例,这也基本接近真实应用。

世界杯竞猜游戏,现实中的体彩就属于竞猜类的游戏,人人往往对竞猜类游戏持有不信任的态度。诟病的主要原因有两个,第一数据不透明,奖池总额有多少,有多少人参与了竞猜,最后的中奖人是不是真投了。第二开奖过程不信任,是不是有人会暗中操纵中奖结果,开奖全过程真实可信么。这两个问题在现实中无解的,即使请再多的公证人员,即使找的开奖人有多么的高尚,依然无法得到所有人的信任。在任何国家、任何地区都面临同样的问题。但是对于这类游戏来说,区块链就是最好的解决方案。区块链的数据公开透明,人人有一份完全相同的账本,中奖人投没投过,奖池有多少奖金,都一目了然。而且上链的数据具有不可篡改的特性,所以一经投出,再也无法事后更改。最重要的是中奖算法都写在区块链的智能合约中,源代码公开,人人可验证。开奖时智能合约会按照中奖算法自动执行,没有人可以干预这个过程。这是不是一个很好的解决方案呢。正应如此,所以竞猜类Dapp在所有Dapp应用中占比高。排名前4K的Dapp中有350个,我们来开发一个世界杯足球的竞猜游戏。假设这样的一个场景,2042年在北京举办的世界杯足球比赛中,中国队历史性的杀进了决赛,与巴西队争夺冠军。世界杯足球竞猜活动就此开始了。

Dapp系统架构

web3研习社

第一部分Dapp,运行在浏览器里,用户通过互联网可以使用。这个我们普通的Web程序没什么区别,比如网站的页面、小程序等等,都是这么工作的。它就是由一些HTML页面和JS组成,也就是我们通常所说的前端。

第二部分Server,这也跟传统的Web应用没有什么区别,它负责提供和处理数据,与前端的Dapp进行交互,通常负责数据库的读写,数据加工以及业务逻辑等工作。它可能是Java、Php、Go、Python等开发语言编写的,也就是我们通常所说的后台。以上两个部分合在一起,其实就是我们现在Web2.0应用的系统架构。

第三部分智能合约,Dapp架构与传统Web应用架构不同的地方就是多出来了智能合约这部分,智能合约是运行在区块链上的一段二进制代码,部分区块链是可以运行智能合约的。比如以太坊,差不多90%以上的智能合约都运行在以太坊上。所以你主要关注以太坊上的智能合约就行了。因为大多数的公链都是借鉴或者抄袭了以太坊。你开房的智能合约只要改两行代码。就可以移植到兼容EVM的区块链上,以太坊上的智能合约,通常使用solidity语言开发,编译之后,会成为一段二进制代码,然后部署到以太坊上,就可以进行调用了。这一部分通常称为链端,一般来说这三个部分就形成了一个完整的Dapp技术架构。

第四部分预言机,为什么架构后面还有一部分预言机呢,其实很多Dapp具有一些特殊的场景,需要一些辅助的数据,才能完成整个工作的闭环。比如预言机、Graph等就能提供一些辅助数据。

智能合约起名叫智能,其实并不能智能,它不能主动获取数据,只能被动接受数据。而且它也不会定时执行。撬动它执行的唯一方法,就是外部程序调用它的接口。更详细的内容会在后面讲解。

因为智能合约不智能,那么谁来通知智能合约比赛的结果呢。有人说智能合约开发一个功能,管理员点一下就能分奖。是的,这是一个解决方案,但有问题,第一,你啥时候点啊,你一辈子不点是不是奖金会永远不分配啊。第二,你是不是得输入比赛结果啊,明明阿根廷队赢了,你非得输入中国队赢了。那岂不被你玩死了。如何解决上面两个问题呢?是的,那就是预言机的工作。预言机会自动、实时的把比赛结果通知区块链上的智能合约让它执行分奖。至于原理后面会提到。这样整个系统就形成了一个闭环,自动执行所有的任务了,做到无人值守。

Dapp开发分工和职位

以上已讲清楚了Dapp系统的架构,接着说一下你可能关心的问题,那就是你能干哪块工作呢?咋干好呢?

第一部分,前端开发,Dapp前端开发岗位跟现在没有太大的区别,你只要会用两个JS库就可以了。一个是web3.js,一个是ethers.js,它们非常简单,其实你只要会其中之一就可以了。因为这俩货干得是同一件事,而且功能一模一样。就是写法上有点区别,不知道谁抄谁的。它们都是跟区块链交互的接口和对象。比如调用智能合约,查询账户余额等等。所以作为前端开发的你,只要会用其中一个库,你就可以理直气壮的说,我会开发Dapp了,我是一个Dapp前端开发工程师,工资上估计能上一个档次。但是,一个好的前端不能只会用现成的库,还应该知道为什么这么用,怎么用才最好。否则,你用不好的话,忽悠不到老板的钱。通常你应该了解一下区块链基本知识,不求深入,但求广泛。因为一个有知识的喷子才是好喷子

第二部分,后端开发,如果你以前是个后端开发工程师,你就啥都不用学,直接就可以说我会Dapp后端开发了。因为真的没你什么事,你就说我是一个Dapp开发后端工程师,没毛病,因为也没这个岗位。还叫后端开发工程师,所以你要想涨薪水,你得再学会前端或者链端才行。

第三部分,链端开发,这个是全新的岗位,工资会高点。因为会的人少,而且水平高的人更少。你起码得会熟练使用solidity,然后得会一堆常用代码库,还要注意安全。另外还得会使用几个框架,比如truffle、hardhat,但作为一个入门的初级开发者。还不需要掌握这么多,慢慢再提高。我会帮你一起从菜鸟成为一个合格的智能合约开发工程师。智能合约看起来简单,其实也没那么简单。因为这是直接跟钱打交道,稍有不慎连你老板都得跑路,所以你必须的学学智能合约的安全。

第四部分,辅助工具开发,指的就是预言机、Graph等使用和开发。通常就是由链端或后端开发人员来做,或者两者配合做。不同的业务场景,会有不同的分工。有一些公司,专做预言机,比如chainlink,竟然做到了所有Dapp应用的Top10,典型的挖金子的不赚钱,卖铲子的发了家。区块链领域中不缺机会,缺的是发现机会的眼睛。最后你四个部分全会,恭喜你。你改名叫Dapp全栈开发工程师,全都会。老板就会把四份工资加一块给你,然后乘以一个零点几的系数。

Dapp开发必备工具

我们已经了解了Dapp和传统App之间的区别,以及Dapp的系统架构。一个Dapp最核心的部分就是智能合约,Dapp通过智能合约实现了与区块链的交互。根据统计数据,目前运行在以太坊上的Dapp占据了所有Dapp的90%的份额。再加上兼容EVM的公链,比如TRON、BSC、BNB等上面的Dapp这个比例会更大。所以我介绍的内容多数是基于以太坊的Dapp开发,和产品设计的相关代码库、开发工具或辅助网站。

MetaMask钱包

官网访问地址:https://metamask.io

MetaMask是web3从业者必备的工具之一,也称之为小狐狸钱包。它提供了管理数字资产所需的一切功能,它是浏览器连接区块链的通道。无论是开发人员、产品经理、运营人员都需要使用钱包产品。钱包产品虽然有很多种,但MetaMask疑是使用量最大、最受信任的一个。它的源码都是开源的,接受一切审计。MetaMask是一个浏览器插件,在任何支持插件的浏览器都可以安装使用,比如谷歌chrome、火狐firefox、微软、Edge。凡是Dapp的从业者,无论是开发人员、产品经理、运营人员,无论是前端、链端还是后端。都应当安装和学会使用MetaMask钱包,它是进入web3.0的通道和起点。关于MetaMask安装和使用,看这里访问地址

Web3研习社

Ganache个人区块链

官网下载地址:https://trufflesuite.com/ganache

Ganache是准备从事开发工作的人,或者初级开发者。学习web3开发的必备工具之一。作为开发人员,在开发和调试程序过程中,不可能在以太坊主链上做测试。因为在主链上操作,需要花费真金白银,而且也不安全,搞不好会把钱包的资产搞没了。还有一个原因,区块确认可能会很慢,查询区块链信息和日志不方便。所以最好有一个本地的以太坊区块链环境,这样调试程序就会非常方便。

Ganache就是为了解决这个问题产生的,它模拟了以太坊主链的所有功能,可以快速启动一个个人以太坊区块链。它是集成开发框架truffle套件的一部分。准备从事Dapp开发工作的小伙伴或初级开发者,都应当安装和学会使用Ganache。关于Ganache的安装和使用,看这里访问地址

Web3研习社

Remix编译部署工具

官网访问地址:https://remix.ethereum.org

Remix是智能合约编译部署工具,智能合约是部署在区块链上的一段二进制代码。体积一般很小,有很多非常有名的智能合约,也就几百行代码,但就是这么少的代码,却是Dapp的核心所在,可能赚取了你想象不到的财富。我们通常使用更容易让人理解的solidity语言,来编写智能合约。然后将其编译为二进制代码,Remix就是用来编写和编译solidity语言的智能合约的工具。并且还能把智能合约部署到以太坊上进行测试和运行。Remix的优点是简单直观,可以在线使用,不需要在电脑上安装,所以remix非常适合于初级开发者学习使用。高级开发者也经常用它来做一些验证、实验工作等。准备从事Dapp开发工作的小伙伴或初级开发者,都应当使用Remix,作为产品设计和运营人员,需要具备智能合约的有关知识,并能够简单使用Remix。因为这会非常有助于你理解web3领域,知晓整个的工作流程。remix可以直接在线使用,无需安装。关于remix的使用,见下文。

Web3研习社

以上三个MetaMask、Ganache和Remix是进行Dapp开发的入门级工具和最基本的组合。我们的教程系列也只使用了这三个开发工具,

web3.js交互库

官网访问地址:https://web3js.readthedocs.io

web3.js是以太坊官方提供的一个JS库,由以太坊基金会开发维护。它封装了以太坊的JSON RPC API提供了一系列与区块链交互的JS对象和函数。Dapp前端和链端通常会使用web3.js库来连接以太坊网络。举个例子来说,我们通过浏览器使用一个Dapp,需要使用MetaMask钱包进行付款或转账交易。如何自动调出已安装的钱包,并完成这笔交易呢?那就是在前端的页面中嵌入web3.js库,通过web3.js库来操作钱包,调用智能合约与区块链进行交互。同样的,链端也往往有一些链上或链下工作,需要通过web3.js库与区块链进行交互。比如扫链、监听链上事件、预言机等等。web3.js是前端和链端开发人员必须熟练掌握和使用的JS库。产品设计和运营人员只需了解就可以了,这有助于你理解开发工作,便于衔接。尤其是对于产品经理而言,不要设计出前端根本无法实现的Dapp产品。web3.js其实非常简单,就像其它语言一样,10%的常用功能就能实现90%的需求。你需要掌握的接口函数就是常见的很少的几个,其它接口随用随学就可以。

Web3研习社

ethers.js交互库

github访问地址:https://github.com/ethers-io/ethers.js

ethers.js是非官方提供的一个JS库,它跟web3.js库的功能和使用方法基本相同。Dapp前端和链端,也经常会使用ethers.js库,代替web3.js库来连接以太坊网络。ethers.js的优势之处在于紧凑小巧,同时又包含大量测试案例,它提供了实用的新手入门文档。因此新手也可以使用,ethers.js使用起来简单、直观,并且该库在近2年越来越受欢迎,下载量和在项目中的使用量也不断增加。像Dapp开发集成环境hardhat,默认集成了ethers.js库。ethers.js包含JavaScript和TypeScript中实用程序的函数,以及以太坊钱包的所有功能。ehters.js也是前端和链端开发人员必须熟练掌握和使用的JS库。产品设计和运营人员只需了解就可以。

Web3研习社

OpenZeppelin智能合约库

github访问地址:https://github.com/OpenZeppelin

OpenZeppelin是一个非常有名的web3基础设施服务提供商,它提供了大名鼎鼎的开源OpenZeppelin智能合约库,这是开发安全、高效的智能合约基础库。OpenZeppelin库最早只是为了解决智能合约安全的一个库,比如SafeMath可以防止整数溢出漏洞攻击。有关智能合约的安全知识,见下文。OpenZeppelin库已经变得很强大,功能丰富,基本实现所有的ERC,开箱即用,不用开发人员再去造轮子了。比如:ERC20可用于发行同质化的代币,俗称发山寨币。ERC721可用于发行非同质化的代币,也就是NFT。OpenZeppelin目前已发展成为知名的基础服务提供商和安全审计公司,生意非常红火,基本是安全行业的NO.1,而且发展前景广阔。OpenZeppelin库是从事智能合约开发、智能合约审计、链端开发人员等必须掌握的一个库。产品设计人员和运营人员了解即可,关于web3基础设施开发是一个非常有前途的赛道,也诞生了很多知名公司。属于闷头发财型,专为挖金子的提供矿泉水、小镐头、国内的慢雾、派盾以及链安都属于这一类公司。OpenZeppelin库是一个开源项目。

Web3研习社

预言机Oracle

这里的Oracle不是指数据库公司甲骨文,而是一种第三方服务,中文翻译为预言机。预言机是将现实世界和区块链打通的一种机制,它监听区块链事件,为区块链注入数据。最典型的是喂价服务,随机数服务。比如自动化交易所,链上的智能合约进行交易撮合的时候,代币该如何定价呢?这个定价就必须得参考各大交易所的当前实时价格,这对区块链本身来说是办不到的,它跟现实世界是平行的,没有融合的。预言机就可以打通链上和链下,使两个世界融合,它就能为智能合约提供准实时的喂价服务。另外还提供随机数服务。这个问题非常有趣,智能合约安全之随机数攻击。这一细分领域也属于web3基础设施服务,代表公司就是知名的chainlink,专门提供预言机服务,占据90%的市场。这是一家很早就通过链上发行代币融资的初创公司,最终成为这一领域的领头羊。凡是web3领域从事DeFi有关的开发,都或多或少可能会使用它们服务和接口。当然向链上注入数据,其实就是一笔交易,需要花gas费的,所以这并不是一个免费服务。这部分内容产品设计人员和运营人员了解即可,但对于链端人员是必须掌握和熟练使用的一项技能。当然也非常简单,关于预言机的原理、使用和开发,见下文。

Web3研习社

区块浏览器Etherscan

官方访问地址:https://etherscan.io

区块链浏览器提供了区块链数据的可视化界面,通过区块链浏览器,你可以非常直观地查看区块链上的每一个区块,每一笔交易以及账户地址等信息。每一条公链都会有自己的区块链浏览器,比如以太坊、BSC、波场等都有自己的区块链浏览器。以太坊上的区块链浏览器,最为著名的就是Etherscan,它的使用频率非常之高。从Etherscan上除了可以查看每一个区块,每一笔交易信息,还能查看到平均GasPrice、以太实时价格、出块速度等信息。比如:GasPrice这项数据就非常重要,如果你提交的交易设置的太小,这笔交易就有可能永远不会被打包。得不到确认,也就是俗称的“被卡住了”。因为执行打包的验证者们,总会优先打包收益最高的交易。所以,交易中设置合理的GasPrice,既能够省钱,又可以尽快地被确认。Etherscan还有一个非常有用的功能,就是可以查看智能合约的源码,大多数知名的智能合约都是公开源码,接受大众审计的,因为只有源码公开,人们才会相信你的合约没有捣鬼。而且Etherscan还会进行审计,帮我们确认链上部署的合约和公开的源码是一致的。所以Etherscan对于开发人员非常重要,对于产品和运营人员查找一些数据也非常有用。开发人员可以在上面学习别人编写的合约,合约审计人员可以去审计这些合约,找找漏洞,报告给所有者,也许你能领取到一笔丰厚的奖金。当然,对于黑客、套利者、安全人员等更是一座宝藏。只要耐心研究这些数据,或许你从此会走上财务自由,币安的BSC、波场的Tron的区块链浏览器,这两个也是“土狗”项目和“科学家”们的财富源泉。

Web3研习社

Truffle

官方访问地址:https://trufflesuite.com

Truffle是Dapp开发、测试和部署的集成化环境,通常配合VSCode使用,这是Dapp开发前端、链端或者全栈开发人员的必备工具之一。前面我们介绍的Ganache,就是它的套件之一。这是Dapp开发人员使用的工具,产品经理、运营人员了解即可,无需学习使用。另外对于没有Dapp开发经验,没入门或者刚入门的小伙伴,可以使用上面讲到的三件套(MetaMask+Ganache+Remix)即可。有了一定经验之后,再学习Truffle就可以了,一切水到渠成。不要一开始就上难度,

Web3研习社

HardHat

官方访问地址:https://hardhat.org/

HardHat与Truffle的用途基本相同,也是Dapp开发、测试和部署的集成化环境。HardHat是一个基于JS和Solidity的开发框架,可以快速提升你的应用程序的开发速度。HardHat比Truffle集成度更高,目前看起来更受欢迎。这也是Dapp开发人员使用的工具,产品经理、运营人员了解即可,无需学习使用。一般的web3开发岗位的招聘要求中,都会有熟练使用Truffle或者HardHat,两个框架你都可以试用一下。至于应该选择哪一个,你可以自己把握,全凭个人喜好。

Web3研习社

Infura

官方访问地址:https://infura.io

我们知道去中心化的应用Dapp,最核心的能力就是能够与区块链进行交互,Dapp使用了web3.js或者ethers.js库访问钱包,进而通过钱包进入了以太坊网络。钱包的功能本质上有两个,第一个就是存储私钥,有了这个私钥,你才能处理你自己的加密资产。第二个就是封装了与以太坊节点交互的接口,也就是RPC API使用起来更方便,更易理解。Infura就是一个能够提供以太坊节点RPC API服务的厂商。而且是最大的,最有影响力的。事实上,MetaMask钱包链接以太坊主网,就是使用了Infura的服务。所以,MetaMask钱包的功能之一就是包装了一下Infura的接口,使得接入以太坊网络更容易使用。Infura不仅提供了免费的以太坊节点RPC API服务,还提供了IPFS API服务,以及整合了多个交易所的加密币行情API服务。Infura背后是自建了很多的节点,组成了一个以太坊节点集群。Infura自建的节点占以太坊网络全部节点的5%-10%,它要是咳嗽一声,以太坊网络全身都不舒坦,你可以免费或者付费使用Infura的节点。而不用自己搭建以太坊节点了,因为搭建以太坊节点的成本还是很高的,还得进行日常维护。Infura可以免费使用,如果你需要的话,可以去注册一下,生成属于自己的API。当然,对于大多数人来说可能并不需要,Infura也有付费服务,收费标准在每月50刀至1000刀不等。这也属于闷头发财型的区块链基础服务提供商。不过,对于需求较小的开发者或项目而言Infura还是十分友好的,开发者可以免费在Infura中创建3个项目。每日使用Infura的API服务提交10万次请求。Infura目前已经被小狐狸钱包MetaMask的母公司收购。所以,现在的Infura和MetaMask就是一家人,以上内容,大家了解即可。实际的Dapp设计、开发或者运营,大多数场景下可能用不到。

Web3研习社

DEMO实现步骤

创建和部署合约

首先我们打开本地以太坊仿真系统Ganache软件,Ganache就是为了方便开发Dapp,模拟了一个本地的以太坊区块链的节点,用于部署和测试智能合约。当我们开发的Dapp要正式上线运行,就需要将已经测试过的智能合约,重新部署到真正的以太坊主网上去。我们先来创建一个Ganache新的项目,用于本次Demo程序的开发,点击new workspace,名字设置为web3,当然任何名字都可以,然后点击保存。于是,系统为我们创建了10个新的账号,每一个账号里有100个以太币,这个位置的内容很重要,就是RPC SERVER。这里面的内容是一个URL地址,这个URL地址是外部程序用来连接Ganache的通道,外部的任何程序,只有通过这个地址才能使用Ganache,我们后面的Remix和MetaMask还会用到它。不要关掉这个程序,在我们做演示项目的时候,要一直运行着它。

我们再来做第二项工作,就是编写和部署智能合约。打开在线编写工具Remix。打开的过程可能有点慢,需要耐心等待。我们先编写一个简单的智能合约。点击新建按钮,新建一个文件hello.sol。我们先把版本注释和Solidity版本号写好,代码如下:

pragma solidity 0.8.18;
contract Hello {
    function greet() external pure returns(string memory) {
      return "Hello Web3";
    }
  }

创建一个智能合约,智能合约的名称为Hello,然后编写一个函数greet,它的可视范围是external,也就是外部可以调用。另外,它是一个pure函数,也就是不操作合约的状态变量。返回类型是一个字符串,再写实现部分,返回一个字符串"Hello Web3"。好了,我们的智能合约编写完成了。它的功能特别简单,只有一个函数greet调用后返回字符串"Hello Web3"。

编译这个合约,点击编译图标按钮,出现绿色小勾,说明编译成功。我们再来部署这个合约,这个合约我们要部署在Ganache上,我们需要更改一下部署的环境。点击下拉框选项,这里有很多项的部署环境,选择Ganache Provider这个选项,会弹出对话框为Ganache Provider的配置信息,这里有一个URL,目前是127.0.0.1,端口号是8545。回想一下前面介绍Ganache的时候,特意说了有一个非常重要的RPC URL,这里就是要修改为Ganache的RPC URL,Ganache的端口号是7545,所以弹出对话框这里需要修改为7545。修改完成后,点击OK按钮。可以看到这里出现了网络ID变更为5777。再看看这里的账户,已经变为Ganache里面的10个账户,每个账户有100个以太币。然后我们开始部署合约,点击Deploy按钮,部署完成,往下滚动就可以看到刚刚部署的合约。

点一下展开这个部署的合约,可以看到这个合约提供了一个可以调用的函数greet,我们点击调用一下试试。OK,输出了"Hello Web3",说明我们部署成功了。这时候整个合约已经部署在了Ganache。我们回到Ganache,就可以看到发生了一笔交易。这笔交易的性质是创建合约。好了,现在Remix和Ganache连通了。而且我们的Hello合约,也部署在了Ganache上。

下一步的工作,就是编写Dapp前端,调用我们刚刚编写的合约,这是一个Dapp典型的架构,我们需要做的工作,主要包含两个部分,第一部分,是Web App也就是HTML和JS开发的应用程序。第二部分,就是智能合约部署在区块链网络上面。目前我们的区块链网络,使用了以太坊的本地仿真软件Ganache。

Web3研习社

前面我们通过Remix编写和部署好了智能合约Hello,也就是这部分工作完成了。我们接着要做的工作就是这一部分,编写Web App,在这编写之前,我们先要把这部分工作完成,也就是小狐狸钱包Metamask要与Ganache对接。

打开谷歌或火狐浏览器,找到小狐狸Metamask插件,打开metamask点击网络位置,进入切换网络界面。点击添加网络,进入添加网络界面,输入网络名称Web3,填写RPC URL,这个URL就是Ganache的RPC URL了。如果记不住回到Ganache再查一下,是127.0.0.1,端口号7545。填写链ID,这个值也是Ganache里可以查。我们再回到MetaMask,继续填写链ID为5777。下一个数据项是货币符号,我们可以随意填写,比如填写mycoin,ok,填写完毕。点击保存按钮,网络已经自动切换为Web3,这正是我们刚才添加的网络。我们把Ganache中的一个账户导入到MetaMask钱包里面,后面会用到。再回到Ganache主界面,我们就选择导入第一个账户,找到后面的小钥匙图标,点击一下,进入到账户信息界面,把这个账户的私钥复制一下,后面会用到。

好的,我们再回到小狐狸钱包,打开小狐狸钱包,把网络切换到我们配置的Web3,也就是Ganache网络,点击这里,导入一个账户,选择导入账户,在这里填写私钥的位置,把从Ganache里复制的私钥,粘贴进去,点击导入按钮。ok,我们已经看到导入的账户了。

到这里,我们所欲的准备工作都已完成了,只剩下编写Web App前端代码了。以上的操作过程,请反复练习操作几次,直至熟练。您会更深入理解Remix、MetaMask钱包和Ganache的工作原理。如果有问题的话,可以加我微信lazycode520拉你进开发群一起学习交流讨论。

Dapp前端开发

前面介绍过,Dapp前端开发其实跟普通APP开发没有太大的区别。只是需要学习两个JS库,ethers.js和web3.js,这两个JS库作用基本是相同的。都是用来与区块链进行交互的工具库,学好任何一个就可以了。我们先来学习一下ethers.js库,在后面讲述其他案例的时候,在讲解web3.js库。我们为了搞清楚ethers.js与区块链的交互过程,先手工操作来验证一下,打开谷歌或火狐浏览器,然后随意访问一个网站,任何网站都可以。这里需要注意,只是打开一个空白的浏览器标签是不可以的,一定要打开一个网站,后面会解释其中的原因。然后点击鼠标右键,在弹出的菜单中,选择检查选项,或者英文的inspect选项。我们就可以进入控制台,我们也可以通过按F12快捷键进入控制台。这两种方法没有任何区别,切换到控制台页面,英文就是console页面。在这里我们可以执行JS语句与浏览器进行交互,就像在HTML页面执行JS的效果完全一样。我们在控制台中输入window然后回车,window对象代表当前的浏览器窗口。我们可以看到window对象内部包含很多成员变量和函数,我们在window对象后面,键入点E。window对象自动提示一个成员变量ethereum。这个ethereum对象,就等同于小狐狸钱包MetaMask,它是作为浏览器的扩展注入到了window对象。我们使用JS操作ethereum对象,就是在操作metamask。比如我们要使用metamask打开钱包中的一个账户,那么我们就可以这样写:

window.ethereum.request({ method: 'eth_requestAccounts' })

好了,我们回车一下,看看效果。metamask被调出来了。

如果我们不是打开一个网站,而是打开一个空白标签,或者打开一个本地的HTML文件,那将会是什么样的效果。我们打开一个新的标签页,然后调出右键菜单,选择检查,切换到控制台console,输入window.ethereum,然后回车,结果是未定义undefined。所以我们得出结论,ethereum只注入到了网站里。在一个空白页面,或者是打开本地的一个HTML文件,都不会注入ethereum对象的。

我们开始编写Dapp前端,首先打开VSCode,VSCode是微软免费的代码编辑器,写代码非常方便,是大多数Web程序员的首选。VSCode有很多可以选择安装的插件,通过这些插件可以扩展其功能,从而有效地提高开发程序的效率。进行Dapp前端开发,也通常使用VSCode作为代码编辑器,如果您还没安装VSCode,请安装后再继续学习。VSCode的使用也非常简单,稍微熟悉一下就可以上手。打开VSCode后,创建一个新的HTML文件,名字叫做dapp.html,然后保存到一个指定的目录。通常我们在编写Web前端的时候,都会使用一些框架,这样可以加快开发速度,编写的代码更容易维护。比如常用的有Vue和React,国内使用Vue的比较多,而国外使用React的比较多,其实两者的功能都差不多,使用哪个都可以。我们的DEMO为了简单起见,先不用框架,直接DIV+CSS,这样能看得更清楚。后面在编写世界杯竞猜游戏的时候,我会使用React框架。首先,我们来编写HTML页面,代码如下:

<html>
  <head>
    <meta charset="utf-8" />
    <title>Dapp Demo</title>
  </head>
  <body>
    <div style="text-align:center;margin-top:30px;">
      <div style="text-align:center">
        <button>连接钱包</button>
        <button>调用合约</button>
      </div>
      <div style="margin-top:10px" id="account">账户:</div>
      <div style="margin-top:10px;" id="contract">合约:</div>
    </div>
  </body>
</html>

运行以上HTML代码为一个网站,VSCode必须安装一个插件,叫做live server。点击左侧扩展图标按钮,输入live,就可以看到插件live server,点击安装,稍等一下即可安装完成。点击右键拉出一个快捷菜单,菜单中多出来一个选项open with live server,点击一下运行,浏览器自动打开了。好了,我们再回VSCode,编写JS代码,我们先编写连接钱包的函数,然后再编写调用智能合约的函数。我们在HTML代码中,先引入ethers.js库,这个JS库部署在CDN上,我们无需下载到本地,直接就可以引用。

开始编写连接钱包函数,第一步判断钱包metamask是否已经安装,也就是判断window.ethereum是不是未定义,如果没有安装就给出提示信息,然后返回。第二步调用window.ethereum.request方法,向用户申请授权metamask账号连接到本网站,返回的结果是一个账户数组,这个数组中包含了得到授权的全部用户账号。它通常只包含有一个账号,我们把第一个授权账号显示在HTML的对应位置。另外,ethereum.request方法是一个异步函数。我们用同步方式来使用它,所以前面加了await,按照JS语法,需要在包含它的函数前面声明为async。最后,把这个函数绑定到按钮上,事件名为onclick,也就是鼠标在点击的时候就调用这个函数,好了,编写完毕。我们再来运行它。代码如下:

<html>
  <head>
    <meta charset="utf-8" />
    <title>Dapp Demo</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ethers/6.6.2/ethers.min.js"></script>
  </head>
  <body>
    <div style="text-align:center;margin-top:30px;">
      <div style="text-align:center">
        <button onclick="connectWallet()">连接钱包</button>
        <button>调用合约</button>
      </div>
      <div style="margin-top:10px" id="account">账户:</div>
      <div style="margin-top:10px;" id="contract">合约:</div>
    </div>
    <script>
      async function connectWallet() {
        if (typeof window.ethereum === 'undefined') {
          alert('请先安装小狐狸钱包')
          return
        }

        let accounts = await window.ethereum.request({ method: 'eth_requestAccounts' })
        if (accounts.length > 0) {
          document.getElementById('account').innerText = '账号:' + accounts[0]
        }
      }
    </script>
  </body>
</html>

浏览器被打开后,点击连接钱包按钮,metamask被打开了,默认选中了第二个账户,点击下一步,点击连接。我们可以看到页面上已经可以显示账号地址了,这样连接钱包的功能,我们就完成了。

接下来,我们再来编写调用智能合约的功能,前端调用一个智能合约,就需要知道,这个合约的部署地址和应用接口。智能合约的应用接口,缩写为ABI,即应用二进制接口,我们在前面做了一个hello合约,我们的DEMO程序就是调用这个合约。我们要把这个智能合约的地址和接口,封装在一个JS文件中。新建一个JS文件,名字叫contract.js。先定义一个变量,合约地址contractAddress,再定义一个变量,合约接口contractAbi,我们切换到Remix,去查一下这两个变量的值,来到合约部署界面中。这是合约的地址,点击复制一下,把它粘贴到JS文件中。再切换到Remix,来到合约编译界面中,这是合约的ABI,点击复制一下,也把它粘贴到JS文件中。好了,这个JS文件完成了,保存一下。再回到dapp.html文件,定义一个运行合约函数runContract,复制一下检测是否安装钱包代码,在 标签内引入contract.js文件。然后继续编写函数runContract,首先定义一个provider变量,ethers.js库中的provider是对以太坊网络的抽象,前端的JS通过provider与后面的以太坊网络进行交互。有了provider对象,我们就可以创建一个智能合约对象了。合约对象需要传入合约地址,合约ABI和provider签名对象,现在就可以调用合约对象的函数了。我们调用智能合约的greet函数,返回结果放入变量result,将返回结果,显示在HTML的div元素中。最后,把这个函数runContract绑定到按钮上。事件名称为onclick,也就是在鼠标点击的时候,就调用这个函数,好了,编写完毕,我们再来运行它。代码如下:

<html>
  <head>
    <meta charset="utf-8" />
    <title>Dapp Demo</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ethers/6.6.2/ethers.min.js"></script>
    <script src="./js/contract.js"></script>
  </head>
  <body>
    <div style="text-align:center;margin-top:30px;">
      <div style="text-align:center">
        <button onclick="connectWallet()">连接钱包</button>
        <button onclick="runContract()">调用合约</button>
      </div>
      <div style="margin-top:10px" id="account">账户:</div>
      <div style="margin-top:10px;" id="contract">合约:</div>
    </div>
    <script>
      .....

      async function runContract() {
        if (typeof window.ethereum === "undefined") {
          alert("请先安装小狐狸钱包");
          return;
        }

        let provider = new ethers.providers.Web3Provider(window.ethereum);
        let contract = new ethers.Contract(contractAddress, contractAbi, provider.getSigner());
        let result = await contract.greet();
        document.getElementById("contract").innerText = result;
      }
    </script>
  </body>
</html>

先连接钱包功能,ok,我们得到了链接的账号地址。再调用运行智能合约函数,ok,我们得到了合约的返回结果"Hello Web3"。至此,我们已经得到了正确的结果,我们断开与metamask的链接,完整的再演示一遍。断开钱包账户的连接。刷新一下页面,运行连接钱包功能,然后调用运行智能合约函数,得到结果一样。这就是整个前端调用合约的过程。

相关教程