<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">"eth_requestAccounts"</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">"eth_chainId"</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">"connect"</span>, <span style="color:#859900">async</span> (<span style="color:#268bd2">connectInfo</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></span><span style="display:flex;"><span> .<span style="color:#268bd2">on</span>(<span style="color:#2aa198">"disconnect"</span>, (<span style="color:#268bd2">error</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></span><span style="display:flex;"><span> .<span style="color:#268bd2">on</span>(<span style="color:#2aa198">"accountsChanged"</span>, (<span style="color:#268bd2">accounts</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></span><span style="display:flex;"><span> .<span style="color:#268bd2">on</span>(<span style="color:#2aa198">"chainChanged"</span>, (<span style="color:#268bd2">chainId</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></span></code></pre></div>
本文是付费文章,剩余内容请访问以下链接支付之后继续阅读:
付费链接
(已付费:11)