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账户地址,需要:
先连接节点服务器
再连接WETH的智能合约
再调用这个合约的转账方法,创建一笔把1个WETH转给A地址的交易申请。
把这个交易申请发送到链上,配置参数:
from:发起者的账户地址,也就是要扣哪个地址的钱
to:这个交易申请发送到的合约地址,也就是由哪个合约去执行
data:上面那笔交易申请编译生成的code,包含交易信息。
...其他的类似 gasPrice、gasLimit等参数。
钱包会弹出签名确认框,用户点击确认后,会扣除对应的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-RPC 的 eth_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,就不用那么麻烦了,流程如下:
先连接节点服务器。
这个交易申请发送到链上,配置参数:
from:发起者的账户地址,也就是要扣哪个地址的钱
to:这个交易申请发送到的合约地址,也就是由哪个合约去执行
value:打算转账的ETH量,单位需要转为 wei。
...其他的类似 gasPrice、gasLimit等参数。
钱包会弹出签名确认框,用户点击确认后,会扣除对应的ETH + 要花费的作为手续费的少量ETH。
和调用合约的上链方法类似,上面的第2步也可以换用其他的多种方式。
根据交易hash查询交易结果
交易hash在发起交易时,通过传入的第二个参数回调函数来获取,也可以等待交易结果,在交易结果中的 transactionHash 就是此次交易的交易hash。
这个方法会得到当前这个hash对应的交易的状态,如果交易刚刚发生,可能查到的是null。
所以我们需要自己写轮询,半秒或一秒调一次,直到得到一个对象,读取对象中的 status 来判断交易是否成功。
Last updated
Was this helpful?