🐵15 DApp
[TOC]
DApp
以太坊社区将基于智能合约的应用称为去中心化的应用程序(Decentralized App,简称DApp)。DApp可以在一台与以太坊节点交互的中心化服务器上运行,也可以在任意一个以太坊平等节点上运行。
DApp 开发分两部分,首先要有提供服务接口的智能合约程序,而 DApp 是向用户提供友好 UI 操作界面。
形式上看来,智能合约开发像传统的后端开发,负责后端业务并向 DApp 提供服务接口,而 DApp 则是访问智能合约接口并向用户提供操作界面,负责客户端的业务开发。
智能合约
智能合约是部署在区块链上的服务程序,数据存储在区块链。传统的服务端程序(如JAVA后端)部署在私有服务器,数据往往存储在一些数据库服务程序,如 MySQL、Redis等。
智能合约也属于服务端程序,通过外部函数
external或公开函数public的方式向外暴露接口。客户端通过web3.js、ethers.js等使用 HTTP 或 IPC 连接和以太坊区块链节点交互,就是访问智能合约向外暴露的接口。

智能合约

传统的服务端程序
web3
DApp开发通常要用到
web3.js和 MetaMask 钱包,web3.js提供了一系列对区块链、智能合约、的操作API,而转账、支付 gas 等操作都需要调用到 MetaMask,DApp 的用户在默认下至少安装了一种或多种 MetaMask 这样的钱包插件。
web3.js
web3.js库是由以太坊基金会构建的开源 JavaScript 库(GNU Lesser General Public License 第 3 版),包括通过 JavaScript 对象表示法 - Remote Procedure Call (JSON-RPC) 协议与以太坊节点进行通信的函数。它是与以太坊区块链进行交互的 JavaScript 库。
Web3.js由一个主类web3和四个模块组成web3-eth、web3-shh、web3-bzz、web3-utils
web3-eth模块中包含函数,作用是让web3.js的用户可以与以太坊区块链进行交互。这些函数能够与智能合约、归外部所有的账户、节点、挖出的区块以及交易进行交互。
web3.eth.getBalance函数是获得指定区块的某个地址的以太坊余额
web3.eth.signTransaction函数是对交易签名
web3.eth.sendSignedTransaction函数是将签名的交易发送到以太坊区块链。
web3-shh模块的作用是使您可以与 Whisper 协议进行交互。Whisper 是一个消息传输协议,其目的是轻松广播消息以及进行低层异步通信。
web3.shh.post将 whisper 消息发布到网络
web3.shh.subscribe创建传入的 whisper 消息订阅
web3-bzz模块的作用是使您可以与 Swarm 交互。Swarm 是一个去中心化存储平台和内容分发服务,它可以用来为去中心化应用存储图片或视频等文件。
web3.bzz.upload的作用是使您可以将文件和文件夹上传到 Swarm
Web3.bzz.download的作用是使您可以从 Swarm 下载文件和文件夹
web3-utils包含实用程序函数,这些函数用于转换数字、验证值是否满足特定条件以及搜索数据集。
web3.utils.toWei将以太转换为 Wei
web3.utils.hexToNumberString将十六进制值转换为字符串
web3.utils.isAddress,校验特定字符串是否为有效的以太坊地址。
MetaMask API 的使用
MetaMask 提供了一些通过
web3.js直接操作它的函数。
MetaMask 文档 https://docs.metamask.io/guide/#why-metamask 。
另外,涉及转账的金额等数值操作需要用额外的库计算,因为智能合约中的
uint256这样巨大的数值在 JavaScript 中是难以表示的,所以要使用 https://github.com/indutny/bn.js 来操作具体的数值。
js 代码判断是否安装了 MetaMask ,必须通过 HTTP 协议才能完成这个判断,如果是 file 协议打开的 html 文件是无法完成这个判断的,其它 API 多少也有这种限制,因此在本地开发时应使用 HTTP 访问测试页面。
MetaMask 例子:https://github.com/PandaManPMC/dapp/blob/main/example/demo1/page/index.html
web3.js 基本使用
引入 web3.js 后连接上节点生成对象,可以使用对象调用 API。
web3.js 提供的功能很齐全,能够做各种功能的DApp开发,如创建账户、转账、交易查询等等。
web3.js 的转账函数如
web3.eth.sendTransaction需要私钥,这意味着用户要将私钥暴露给 DApp ,存在很高的风险的,所以除非是开发类似与 MetaMask 那样的钱包,否则不会直接使用这类函数,一般需要支付的场景会调用 MetaMask 这类钱包 DApp 授权支付,这样只有钱包 MetaMask 持有用户私钥,而不是用户使用的所有 DApp。
web3.js 连接节点的协议有 3 种,
http/https、WebSocketws/wss和ipc。
HttpProvider: HTTP 提供者,不支持订阅。
WebsocketProvider:Websocket 提供程序是在旧版浏览器中使用的标准。
IpcProvider:运行本地节点时使用 IPC 提供程序 node.js dapps。提供最安全的连接。
Provider
使用 Web3.givenProvider 会默认使用本地 MetaMask ,需要私钥签名的时候会调起 MetaMask 进行签名,就不需要在程序中进行签名,程序也无须保存私钥。
如果额外设置,例如使用自行搭建的节点,就需要另外配置,并且需要私钥签名。
web3.js 常用函数
web3 其它语言库
web3 库除了
web3.js还有其它语言库,如 web3j 是 java 语言库 https://github.com/web3j/web3j 。
Web3j 是一个轻量级、高度模块化、反应式、类型安全的 Java 和 Android 库,用于处理智能合约并与以太坊网络上的客户端(节点)集成。基于 HTTP 和 IPC的以太坊JSON-RPC客户端 API的完整实现,自动生成 Java 智能合约包装器,以从原生 Java 代码创建、部署、交易和调用智能合约(支持Solidity 和 Truffle 定义格式)。
引入 Web3j
基本函数的使用,除此之外,还有转账、部署合约、合约函数调用等API。
在 Web3j 的调试可以使用 Ganache 模拟一个本地节点。
投票 DApp
合约提供一些列函数接口,前端通过
web3.js调用合约接口。
投票合约
任何人可以自由调用合约发布投票项目,所有人在支付一定额度 ETH 后都可以参与投票,因此投票合约应该有增加投票项目的函数、投票函数、结束投票函数和合约拥有者可以转走投票收取的 ETH 的函数。
投票合约:https://github.com/PandaManPMC/VoteDAppExample/blob/main/ethereum/vote.sol
前端
前端通过
web3.js库实现与合约的交互,中间会调起MetaMask钱包支付 gas 或其它费用。
完整源码 https://github.com/PandaManPMC/VoteDAppExample 。
前端调用合约的函数用合约对象调用最为方便,创建合约对象需要
jsonInterface,remix 编译合约以后会生成vote_metadata.json文件,文件中output.abi就是这个jsonInterface。
web3.js的web3.eth.Contract对象调用合约函数的方式除了call、send还有其它函数,包括调用事件等,文档 https://web3js.readthedocs.io/en/v1.7.0/web3-eth-contract.html所有函数调用都是异步的,涉及修改合约数据的函数需要等待到打包完成才会回调。
jsonInterface
读取
jsonInterface创建合约对象
call 调用无须 gas 的函数
合约定义的函数
前端调用函数
send 调用需要支付或需要 gas 的函数
合约定义的函数
前端调用函数
有要支付的在
send()中增加value字段,无须支付就不需要加,但是from始终需要。
DAPP 登录的实现
DAPP 使用钱包作为会员账号,要在不知道用户钱包私钥的情况下确定操作登录的是用户本人,则可以调用 MateMask 这类保存了用户私钥的 DAPP 钱包提供的接口实现验证。
MetaMask 签名 personal_sign
MetaMask 这类遵循了 EIP-712 规范(类型化消息签名标准)的钱包 DAPP 提供有签名接口。
MetaMask 的签名接口会对程序传入的参数使用私钥进行签名,程序再通过公钥验证签名以确定操作钱包的是钱包拥有者。
签名操作是不需要支付 gas 费用的。
关于 MetaMask 签名的相关开发文档 https://docs.metamask.io/guide/signing-data.html#signing-data-with-metamask 。
签名的使用
DAPP 调用 MetaMask 进行签名。
在生产环境中,使用签名进行无密码登录,服务端通过公钥验证签名完成登录。

无密码登录流程
Last updated