DTeam 技术日志

Doer、Delivery、Dream

MetaMask 非权威开发指南

胡键 Posted at — Feb 26, 2022 阅读
<p>用户要想与以太坊交互就离不开钱包。同样的,为用户提供服务的以太坊 dapp 也必须实现与用户钱包交互的功能。否则,它算不上真正的 dapp,顶多成为一个以太坊数据的查看器。在众多钱包之中,不得不提及 <a href="https://metamask.io/">MetaMask</a>。不仅仅因为其是目前使用最多的钱包之一,而且还因为它是不少的 EIP 的参考实现。基本上,只要你的 dapp 可以正常跟 MetaMask 交互,那跟其他钱包交互也不会有多少大问题。因此,本文以 MetaMask 为例,谈谈 dapp 开发者必须了解的知识点。</p> <p>通过本文,你可以了解到:</p> <ul> <li>每个【Connect Wallet】都需要实现的基本功能</li> <li>支持多 provider</li> <li>应用加载后自动连接</li> <li>如何让地址旁出现跟 MM 一样的图标?</li> <li>理解 permission</li> <li>如何添加新网络?</li> <li>如何实现自动切换网络?</li> <li>如何添加新 Token?</li> <li>实现钱包登录的一般思路</li> <li>实现自己的钱包连接界面</li> <li>移动端和桌面端的差异</li> </ul> <p>同时,也请留意本文不会提及的内容:</p> <ul> <li>签名,请参见 <a href="https://mp.weixin.qq.com/s/vwhXB3ZmHQD5r_y-3BfRkg">Ethers.js 非权威开发指南(下)</a>的“签名”一节。</li> <li><a href="https://metamask.io/flask">MM Falsk</a> 相关内容,因为尚未发布稳定版,在这之前一切皆有可能变化。</li> </ul> <h2 id="每个connect-wallet都需要实现的基本功能">每个【Connect Wallet】都需要实现的基本功能</h2> <p>当 dapp 被(已装 MM 插件的)桌面浏览器或钱包浏览器加载后,后者会往页面注入钱包实例。此时,开发者所需完成的工作就是:</p> <ol> <li>连上它。</li> <li>得到当前实例连接到的网络和账户地址。</li> <li>注册必要的事件处理函数。</li> </ol> <p>以上三件事就是每个【Connect Wallet】必须实现的基本事项,至于其他的,比如说“若当前连接到的网络不符合预期则报错”,都属于锦上添花。这三件事对应下面的三段代码:</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-ts" data-lang="ts"><span style="display:flex;"><span><span style="color:#93a1a1;font-style:italic">// 获得实例 </span></span></span><span style="display:flex;"><span><span style="color:#93a1a1;font-style:italic"></span><span style="color:#268bd2">provider</span> = <span style="color:#cb4b16">window</span>.<span style="color:#268bd2">ethereum</span>; </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#93a1a1;font-style:italic">// 连接并获得当前账户地址 </span></span></span><span style="display:flex;"><span><span style="color:#93a1a1;font-style:italic"></span><span style="color:#859900">const</span> <span style="color:#268bd2">accounts</span> = <span style="color:#859900">await</span> <span style="color:#268bd2">ethereum</span>.<span style="color:#268bd2">request</span>({ <span style="color:#268bd2">method</span>: <span style="color:#2aa198">&#34;eth_requestAccounts&#34;</span> }); </span></span><span style="display:flex;"><span><span style="color:#859900">const</span> <span style="color:#268bd2">account</span> = <span style="color:#268bd2">accounts</span>[<span style="color:#2aa198;font-weight:bold">0</span>]; </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#93a1a1;font-style:italic">// 获得当前链接的 chain id </span></span></span><span style="display:flex;"><span><span style="color:#93a1a1;font-style:italic"></span><span style="color:#859900">const</span> <span style="color:#268bd2">chainId</span> = <span style="color:#859900">await</span> <span style="color:#268bd2">ethereum</span>.<span style="color:#268bd2">request</span>({ <span style="color:#268bd2">method</span>: <span style="color:#2aa198">&#34;eth_chainId&#34;</span> }); </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#93a1a1;font-style:italic">// 注册事件处理函数 </span></span></span><span style="display:flex;"><span><span style="color:#93a1a1;font-style:italic"></span><span style="color:#268bd2">provider</span> </span></span><span style="display:flex;"><span> .<span style="color:#268bd2">on</span>(<span style="color:#2aa198">&#34;connect&#34;</span>, <span style="color:#859900">async</span> (<span style="color:#268bd2">connectInfo</span>) =&gt; { </span></span><span style="display:flex;"><span> <span style="color:#93a1a1;font-style:italic">// 处理 </span></span></span><span style="display:flex;"><span><span style="color:#93a1a1;font-style:italic"></span> }) </span></span><span style="display:flex;"><span> .<span style="color:#268bd2">on</span>(<span style="color:#2aa198">&#34;disconnect&#34;</span>, (<span style="color:#268bd2">error</span>) =&gt; { </span></span><span style="display:flex;"><span> <span style="color:#93a1a1;font-style:italic">// 处理 </span></span></span><span style="display:flex;"><span><span style="color:#93a1a1;font-style:italic"></span> }) </span></span><span style="display:flex;"><span> .<span style="color:#268bd2">on</span>(<span style="color:#2aa198">&#34;accountsChanged&#34;</span>, (<span style="color:#268bd2">accounts</span>) =&gt; { </span></span><span style="display:flex;"><span> <span style="color:#93a1a1;font-style:italic">// 处理 </span></span></span><span style="display:flex;"><span><span style="color:#93a1a1;font-style:italic"></span> }) </span></span><span style="display:flex;"><span> .<span style="color:#268bd2">on</span>(<span style="color:#2aa198">&#34;chainChanged&#34;</span>, (<span style="color:#268bd2">chainId</span>) =&gt; { </span></span><span style="display:flex;"><span> <span style="color:#93a1a1;font-style:italic">// 处理 </span></span></span><span style="display:flex;"><span><span style="color:#93a1a1;font-style:italic"></span> }); </span></span></code></pre></div>

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

付费链接 (已付费:11)

友情链接


相关文章