Web3.0开发下-功能代码示例

title: Web3.0开发下-功能代码示例 id: de9c2c00b0da2d5d6185074dc3f2d060 tags:

  • Web3

  • 区块链

  • 智能合约 date: 2000/01/01 00:00:00 updated: 2023/11/24 17:30:24 isPublic: true --#|[分隔]|#--

Web3.0开发下-功能代码示例

以太坊官网:https://ethereum.org/zh/

web3官方教程:https://web3js.readthedocs.io/

以太坊区块链浏览器:https://etherscan.io/

以太坊开发文档:https://ethereum.org/zh/developers/docs/

以太坊JSON-RPC 应用程序接口:https://ethereum.org/zh/developers/docs/apis/json-rpc/

小狐狸(MetaMask)文档:https://docs.metamask.io/

币安钱包文档:https://docs.bnbchain.org/docs/wallet_api

:以下的前端界面使用vite + react开发,每次粘贴的都是片段。

实例化web3对象

实例化Web3的过程,就是给web3.js设置一个 服务提供者

服务提供者就是一个包含节点服务器的 RPC 地址的对象,web3和节点服务交互时,会把所有的请求给这个服务提供者,服务提供者再去和节点服务器交互。

所以实例化Web对象需要先生成服务提供者。

服务提供者

RPC有三种类型:HTTP、WebSocket、IPC,所以创建服务提供者也有三个方法:

但实际这一步可以省略不写,这部分主要是了解内部逻辑,原因见后续内容。

使用服务提供者实例化Web3

有了服务提供者,可以实例化web3了:

但其实,如果是使用RPC,我们不用手动创建服务提供者。

可以直接把RPC传给Web3来进行实例化,Web3会自动判断生成服务提供者并使用:

使用钱包作为服务提供者

当浏览器安装了小狐狸等钱包插件,那么我们可以直接使用钱包作为服务提供者。

如果刚刚安装了小狐狸,甚至还没有打开、没有配置过,那他默认配置的是以太坊主网络。

自动获取当前页面的服务提供者

在以太坊兼容的浏览器中使用 web3.js 时,Web3.givenProvider 将由该浏览器设置为当前的本机提供程序,否则为 null。

也就是说,如果浏览器已经安装了小狐狸,那么:

平时可以这样使用:

但如果这么使用,无法保证小狐狸当前连接的网络是自己需要的,还是要开发者判断。

查看和切换服务提供者

实例化web3后,可以随时查看当前的服务提供者对象:

如果当前的服务提供者是自己设置的 RPC,那么 currentProvider 对象为:

如果当前的服务提供者是钱包,那么 currentProvider 对象其实就是钱包对象:

我们可以直接给现有的web3实例切换服务提供者:

通过小狐狸钱包获取账户地址

现在页面开发,只把钱包作为服务提供者的只是少数,更多的是通过钱包,获取当前用户使用的账户地址,能省的用户手动在页面输入这一步。

下面的代码执行后,小狐狸好会弹出提示框,按提示确认后,即可允许某几个账户连接当前网站。

有的教程使用的可能是 window.ethereum.enable() 这个方法,这个方法已废弃,不再建议使用。

注意:钱包会为钱包中的每个账户,都记录「已连接的网站」列表,当用户允许某网站连接账户后,会自动把此网站地址放入「已连接的网站」列表中。

日后,这个页面再请求账户列表,小狐狸会直接返回一个数组,数组中只有一项,就是允许连接此网站的某个账户地址,优先返回用户当前正在使用的账户地址。

window.ethereum 作为服务提供者实例化 web3 后,可以使用 web3 的方法读取这个数组,如果没有账户连接过此页面,那得到的是空数组。

如果是使用 RPC 实例化的 web3,则只能获取到一个空数组。

监听小狐狸事件

监听小狐狸这个插件的一些事件,以便当用户修改了账户、断开了网站连接时做应对处理。

有些事件可以不连接小狐狸,页面就能监听触发;而有些在需要连接后再操作小狐狸,页面才能监听到。

调用小狐狸方法

调用小狐狸方法文档:RPC API

这里只列举两个可能常用的方法。

切换网络

可能用户当前连接的网络不是自己页面需要的,则需要调用小狐狸方法来切换。

小狐狸会弹出确认提示框,用户确认后切换成功。

注意,如果用户的小狐狸没有这个网络,则会报错,error.code 为 4902。

添加网络

可能用户的小狐狸钱包中,没有我们页面需要的网络,此时我们可以调小狐狸方法来添加。

小狐狸同样会弹框询问用户是否允许添加,添加完成后会要求用户切换到此网络。

下面的添加是不会成功的,因为小狐狸已经内置了这个官方的测试网络,下面的网络配置只是演示:

添加代币

可能用户的小狐狸钱包中,没有我们需要的某种代币,此时我们可以调小狐狸方法来给这个账户添加。

无论此账户当前是否有这种代币,调用方法后,小狐狸必然会弹框请求用户添加这一代币。

提前准备的工具方法js

下面两个方法在展示余额、发起交易时,非常常用。

因为以太坊世界的数量、余额使用的单位是wei,但平时展示给用户的都是以某币种为单位的,需要使用这个币种的精度来转换一下。

获取一些账户、余额、网络信息

网络ID(NetworkID),主要用来在网络层标识当前的区块链网络,NetworkId 不一致的两个节点无法建立连接。

以太坊本来只有网络ID,并没有链id(ChainId)。

但以太坊发生了分叉,为了避免一个交易在签名之后被重复在不同的链上提交,在EIP155引入了ChainID,通过在签名信息中加入ChainID避免了bug。

创建账户

创建账户,拿到新账户地址和私钥。

判断一个地址是否符合规范

当进行转账、查询余额时,偶尔需要用户输入地址,作为参数和区块链交互。

web3.js包含工具对象,可以使用里面的方法来校验地址是否合法,方法返回Boolean值。

因为这个工具对象和区块链无关,可以直接使用未实例化的 Web3 类。

web3 工具类的文档地址:web3.utils

签名消息字符串

签名消息是为了加密,签名的过程会使用账户地址和账户私钥进行加密,事后可以通过反向计算,算得该条加密字符串是否是某账户的私钥签名的。

调用钱包方法

连接小狐狸后,直接使用小狐狸进行消息签名,会调起小狐狸进行确认:

调用web3.js方法

这个需要先连接小狐狸,也是会调起小狐狸,和直接调用小狐狸的签名方法效果一样。

web3.js只是把钱包的签名方法进行了包装兼容而已。

币安钱包中的币安链(BEP2)网络的签名

币安链钱包比较特殊,币安链钱包中的BSC链(也是ERC20网络,币安钱包对ETH的兼容)可以仍然使用上面的 web3 调用。

但币安链BEP2网络,需要直接调用币安钱包对象的 BinanceChain.bnbSign 方法来进行签名(可至钱包文档页查看更详细内容):

验证签名

验证签名,需要拿到被加密的原信息字符串加密后的signature,使用web3.js的方法,能得到签名时的账户地址

判断这个账户地址是否是预期的账户,就可以验证了。

使用智能合约

以太坊中的所有代币、NFT,本质都是智能合约。

WETH这个代币,本质就是一个符合 ERC-20 的智能合约,它的地址就是合约地址。

哪个用户拥有多少WETH,都是这个合约去保存的,想要转账,也需要通知这个合约去交互。

连接合约

连接合约最简单,需要下面两个参数:

  • 合约地址:比如WETH就是这个代币的地址,也就是合约地址。

  • 合约ABI的json对象:合约中提供了很多属性、方法,这个ABI类似一个 TypeScript 中的接口文件,查看这个abi,就能看到这个合约支持那些属性、方法,方法要传入的参数和类型,已经返回的参数和类型。

调用合约方法简单示意

合约的方法都在 methods 中。

调用非上链方法

非上链方法基本都是只读方法,不需要上链、记账,调用起来比较简单,调用后直接再调用 .call() 即可。

比如 balanceOf 就是查询某用户拥有的代币余额的方法。

其他非上链方法同理,调用时传入响应的参数是,最后再调用 call() 即可。

调用上链方法

链上方法需要调用 send() 方法发送到链上。

需要给 send 传入参数,告知这笔交易的发起方、发送目标等,手续费也可以在这里配置,具体参数可见:methods.myMethod.send

因为上链方法比较复杂,且方式很多,下面依次举例介绍。

使用合约发出交易

下面就转账功能,进行具体的代码示例,调用合约的其他上链方法也都类似。

想要把1个WETH这种代币转给A账户地址,需要:

  1. 先连接节点服务器

  2. 再连接WETH的智能合约

  3. 再调用这个合约的转账方法,创建一笔把1个WETH转给A地址的交易申请。

  4. 把这个交易申请发送到链上,配置参数:

    • from:发起者的账户地址,也就是要扣哪个地址的钱

    • to:这个交易申请发送到的合约地址,也就是由哪个合约去执行

    • data:上面那笔交易申请编译生成的code,包含交易信息。

    • ...其他的类似 gasPrice、gasLimit等参数。

  5. 钱包会弹出签名确认框,用户点击确认后,会扣除对应的1WETH,和作为手续费的一定量的ETH。

注意,上面值转账某种代币,如果想转账此链的主币,比如ETH,则不需要使用合约,请见下一条「账户间转账ETH」教程。

使用web3.js发出交易

上面的第4步,发出交易,可以使用web3.js的 sendTransaction 方法替换,只不过需要把 transaction 这个交易单生成code,入参也有些变化。

sendTransaction 和合约方法无关,**sendTransaction **只是把某些请求发送到链上,基本所有上链操作都可以使用它。

具体可见教程:web3.eth.sendTransaction

以下代码,删除了前3步多余的注释:

使用钱包的 request 发出交易

钱包基本都会提供直接调用 JSON-RPC 的方法,小狐狸插件的话,就是使用小狐狸的 window.ethereum.request 方法,去调用 JSON-RPCeth_sendTransaction 方法。

小狐狸钱包的方法文档:window.ethereum.request(args)

JSON-RPC 的 eth_sendTransaction 文档:eth_sendTransaction

无需钱包-使用私钥签名再发送交易

发送交易很容易,合约、web3.js和钱包插件都有对应的方法,最关键的一步是签名,需要使用私钥签名的那一步。

之所以要连接钱包的一大原因,就是需要使用钱包让用户签名,方便用户操作。

但一些运行在服务端的服务,私钥就掌握在我们自己手里,这是就可以只用用私钥签名,无需钱包了,当然在前端页面里面也行,只要有私钥。

web3.js提供了 web3.eth.accounts.signTransaction 方法,允许用户传入交易对象和账户私钥来对交易进行签名。

但这个方法传入的交易对象中必填 gas 字段,我们可以自己配置,也可以调用 web3.eth.estimateGas 来进行一个 模拟调用,发起一个假的交易申请,方法会返回完成这笔交易需要花费的 gas,直接把这个 gas 添加到交易对象中,再去进行签名即可。

此外,因为要发送的交易已经签名过了,所以需要使用 web3.eth.sendSignedTransaction 方法来发送交易。

账户间转账ETH

上面使用的是合约转账,转的都是代币,需要连接代币的智能合约,让智能合约去操作。

但如果想转账此网络的官方主币,比如ETH,就不用那么麻烦了,流程如下:

  1. 先连接节点服务器。

  2. 这个交易申请发送到链上,配置参数:

    • from:发起者的账户地址,也就是要扣哪个地址的钱

    • to:这个交易申请发送到的合约地址,也就是由哪个合约去执行

    • value:打算转账的ETH量,单位需要转为 wei。

    • ...其他的类似 gasPrice、gasLimit等参数。

  3. 钱包会弹出签名确认框,用户点击确认后,会扣除对应的ETH + 要花费的作为手续费的少量ETH。

和调用合约的上链方法类似,上面的第2步也可以换用其他的多种方式。

根据交易hash查询交易结果

交易hash在发起交易时,通过传入的第二个参数回调函数来获取,也可以等待交易结果,在交易结果中的 transactionHash 就是此次交易的交易hash。

这个方法会得到当前这个hash对应的交易的状态,如果交易刚刚发生,可能查到的是null。

所以我们需要自己写轮询,半秒或一秒调一次,直到得到一个对象,读取对象中的 status 来判断交易是否成功。

Last updated

Was this helpful?