DTeam 技术日志

Doer、Delivery、Dream

Ethers.js 非权威开发指南(下)

胡键 Posted at — Jun 20, 2021 阅读
<p>本系列的<a href="./ethersjs-indefinitive-guide-part1.html">上篇</a>已经展示了连接钱包,调用合约和确定交易状态的全过程,对于一般的 dapp 开发已经完全足够。但对于有格调的开发者来讲,这些还不足以满足他们的胃口。那么,在下篇,你们将看到一些更加高级和特别的东西:</p> <ul> <li>如何处理以太坊的事件?</li> <li>如何监听特定合约的特定事件?</li> <li>如何查询以太坊的过往历史?</li> <li>如何获取导致交易产生的合约函数的输入参数?</li> <li>对于高阶合约函数(即,接受另一个合约的函数为输入值),该如何调用?</li> <li>如何实现签名(含 EIP712)?</li> <li>如何获得某个账户的公钥?</li> </ul> <p>相信以上这些重口味问题的答案应该不会让各位失望。</p> <h2 id="监听事件">监听事件</h2> <p>通常,事件监听的需求来自于朴素的诉求:及时得到状态更新的通知。这种需求不仅仅局限于异步方法的调用,对于稍微复杂的一些程序,事件机制的引入也会让整个应用的架构得到简化。</p> <p>Ethers.js 在 Provider 和 Contract 层面都提供了事件的支持,并且方法名称也有重叠。其中用得较多的方法如下:</p> <ul> <li><code>on</code>,对特定事件添加监听器。</li> <li><code>off</code>,移除某事件全部监听器。</li> <li><code>once</code>,添加事件监听器,并且在事件处理完成后自动移除。它和 <code>on</code> 的区别在于: <ul> <li><code>on</code> 没有移除事件监听器这一步骤,会继续监听后续事件;</li> <li><code>once</code> 处理完当前事件之后,不再监听,对后续到来的事件不再处理;</li> </ul> </li> </ul> <h3 id="dapp-典型的监听事件架构">dapp 典型的监听事件架构</h3> <p>虽然 Provider 和 Contract 提供了监听以太坊事件的方法,但要是不加区分到处引用这两个对象来添加事件处理函数,整个应用的代码仍不可避免地会陷入混乱。通常的做法都会结合前端框架的状态管理来做,实现上层业务代码和底层合约代码的解耦,同时又能及时得到通知。</p> <p>通常做法如下:</p> <ol> <li>定义状态管理涉及的业务对象,此过程类似 db 或者 domain 的设计。</li> <li>在事件处理函数内,基于所监听的事件,更新对应的状态对象。</li> <li>在业务代码部分订阅业务对象的更新事件,在该事件处理函数内完成页面状态更新。</li> </ol> <p>对于 Angular 来讲:</p> <ol> <li>状态更新部分涉及对象</li> </ol> <div class="highlight"><pre tabindex="0" style="color:#586e75;background-color:#eee8d5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>Provider / Contract EventListners &gt; Akita Service </span></span></code></pre></div><ol start="2"> <li>订阅状态更新涉及对象</li> </ol> <div class="highlight"><pre tabindex="0" style="color:#586e75;background-color:#eee8d5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>Akita Query &gt; Subscribers </span></span></code></pre></div><p>对于 Svelte 来讲,更简单,整个过程简化为:</p> <div class="highlight"><pre tabindex="0" style="color:#586e75;background-color:#eee8d5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>Provider / Contract EventListners &gt; Store &gt; Reactive 语句 / 变量 </span></span></code></pre></div><p>因为对 React 和 Vue 不熟,这里就此略过,但机制应该都是一样的。</p> <h3 id="使用-provider-监听">使用 Provider 监听</h3> <p>Provider 适合粗放型事件监听,值得注意的几个事件:</p> <ul> <li><code>block</code>,新区块生成</li> <li><code>error</code>,错误发生</li> <li><code>txHash 值</code>,tx 被确认</li> </ul> <p>其他事件请参见 Ethers.js 的文档。</p> <p>一般来讲,你不会需要上面的第三个事件(即<code>txHash 值</code>),采用<a href="./ethersjs-indefinitive-guide-part1.html">本系列上篇</a>中介绍的方法要更简单一些。</p> <p><code>block</code> 事件在你需要一口气跟踪多个状态时最为有效,比如一次交易的变化可能导致多个地方的状态发生变化:</p> <ul> <li>账户余额</li> <li>交易对内部双边余额的变化</li> <li>计价合约的参数变化</li> <li>……</li> </ul>

本文是付费文章,剩余内容请访问以下链接支付之后继续阅读:

付费链接 (已付费:27)

友情链接


相关文章