从上一篇起,一个关于 Ethers.js 开发的系列事实上诞生了。既然如此,我也乐得顺水推舟,干脆将其打造成一个使用 Ethers.js 开发以太坊应用的 Cookbook,以此来记录日常开发中的收获。于是乎,标题不再是上、下、续之类的麻烦字眼,直接替换成了自增数字,😄。
闲话说完,言归正传。通过本篇你可以了解到:
- transaction 的取消或加速
- EIP1559 对 GasPrice 的影响
- 什么是 HD Wallet 以及它的用途
- 对 contract 日志实现任意查询
- contract 方法调用的权限控制
如何取消或加速 Transaction
说到取消或加速 Transaction 的原因,有人可能会列出一大堆:
- 太慢了,希望快点结束;
- 后悔了,想取消;
- 市场变了,按原来的输入明显会失败,不如取消重来;
- ……
但在我看来,最大的原因还是迟迟不能被 confirm 的 Transaction 会影响当前 Wallet 的使用,导致整个 wallet 被堵住无法使用。如果它是个人用的,影响的也就是单个人而已;但如果它是被系统使用的服务器端 wallet,那影响面可想而知。
在介绍 Transaction 的取消和交易之前,必须先了解一个基本概念:nonce。单看字面意思,dapp 开发的初学者可能会摸不着头脑。但假如把它换成另一个词 sequence,相信就好懂多了。
简单讲,nonce 的基本作用:
- 表示当前地址已提交 transaction 的个数。它和 sequence 一样是自增的,每提交一次,个数加一。
- 防止重放攻击,由于每次提交之后都会变化且包含在 transaction 中,这样就杜绝了过往 transaction 签名被重用的可能性。
同时,transaction 只能按顺序执行,前面的不被确认,后面的就无法被执行,就算可以不断提交,但依旧也只是进入到等待队列,对于实际的活动帮助并不大,反而还会留下一大堆未来需要处理的麻烦事。
假如你的 dapp 只有前端且由用户负责发起 transaction ,典型如 uniswap,那么作为开发者,你是不必过于关心 nonce 或 wallet 是否被堵住这类琐碎的。这并不是说使用这类 dapp 的 wallet 并不会被堵住,而是说该操心的不是你的代码,而是使用者本身。
但倘若你的 dapp 涉及到服务端且存在服务端代码需要发起 transaction 时,你的麻烦就来了。
首先,你需要有办法知道服务端的 wallet 是否被堵住。这个简单,使用下面的代码就可以办到:
const [confirmedNonce, totalNonce] = await Promise.all([
provider.getTransactionCount(address),
provider.getTransactionCount(address, "pending"),
]);
既然 nonce 等于当前已提交的 transaction 个数,那么使用 Ethers 的 getTransactionCount
就可以获取其值。注意示例中的 pending
参数:
- 有它,表示将处于“待确认”的 transaction 也计入在内。
- 否则,表示“已提交”的个数
由此,判断一个 wallet 是否被堵住的方法也就简单了:
confirmedNonce === totalNonce;
接下来,另一个需要注意的就是并发性的问题。
...本文是付费文章
以上是此文章的预览内容