🔖

MetaMask競合問題とEIP-6963: Multi Injected Provider Discovery

2023/06/14に公開

はじめに

僕は現在、N Suiteという秘密鍵管理のSaasの開発に携わっていて、MetaMaskに似たブラウザ拡張機能で動くウォレットの開発をしています。

https://nsuite.io/ja

ブラウザ拡張機能でEVM系のウォレットを作っていると、思わぬ問題に出くわします。それは、他のウォレットとぶつかること。どのウォレットも同じ window.ethereum にEthereum Providerを注入し、自分のウォレットをウェブページに知らせようとします。その際に複数のウォレットがあると、どれが最後に表示されるかはロードの順番次第。これはどうにかならないのでしょうか?ユーザーは自分でウォレットを選びたいはずです。開発者としても、自分のウォレットがちゃんと使われるようにしたい。特に人気のMetaMaskと競合する時、この問題は頭を悩ませます。

EIP-6963とは

この問題を解決するために、新しい提案が出てきました。それがEIP-6963です。

https://eips.ethereum.org/EIPS/eip-6963

これは、ウォレットを探すための新しい方法を提案しています。この方法では、ウォレットは window.ethereum に注入されるのではなく、JavaScriptの window イベントを使ってウェブページから検出されます。

これにより、ユーザーは一度に複数のウォレットを選ぶことができ、それぞれのウォレットが互いに競争することなく存在することができます。ウォレット提供者が公平に競争できるようにし、新しいウォレットの参入障壁を下げ、ユーザー体験も向上します。

実装方法

まず、各ウォレット提供者は EIP6963ProviderInfo というインターフェースを用いて自身を公開します。ここには、ウォレットのユニークなID、人間が読むことのできる名前、そしてアイコンへのURIが含まれます。これらの情報を使って、ウォレットは自己をユニークに識別し、ユーザーに見やすい形で自己を表示することができます。

interface EIP6963ProviderInfo {
  uuid: string;
  name: string;
  icon: string;
}

interface EIP6963ProviderDetail {
  info: EIP6963ProviderInfo;
  provider: EIP1193Provider;
}

さらに、ウォレットとDAppの間で、互いに存在を認識するためのイベントが発生します。これは window イベントを用いて行われ、二つの主要なイベント、 EIP6963AnnounceProviderEventEIP6963RequestProviderEvent が使用されます。

// Announce Event dispatched by a Wallet
interface EIP6963AnnounceProviderEvent extends CustomEvent {
  type: "eip6963:announceProvider";
  detail: EIP6963ProviderDetail;
}

// Request Event dispatched by a DApp
interface EIP6963RequestProviderEvent extends Event {
  type: "eip6963:requestProvider";
}

例えば、あなたのウォレットがウェブページにロードされたとき、次のように EIP6963AnnounceProviderEvent を発生させることができます。

const providerDetail = {
  info: {
    uuid: 'your-unique-id',
    name: 'YourWalletName',
    icon: 'your-icon-uri',
  },
  provider: yourEIP1193Provider,
};

const event = new CustomEvent('eip6963:announceProvider', {
  detail: Object.freeze(providerDetail),
});

window.dispatchEvent(event);

このイベントは、あなたのウォレットがページに存在することをDAppに通知します。そして、DAppは次のようにしてこのイベントを捕捉し、それに応答することができます。

window.addEventListener('eip6963:announceProvider', (event) => {
  const providerDetail = event.detail;
  // do something with providerDetail
});

実装の検証

当記事執筆時点ではMetaMaskはまだDraft段階で、実装されてはいないようです。

https://github.com/MetaMask/metamask-extension/pull/19320

そのため、正しく実装できたかどうかの確認は以下のサイトで行います。

https://eip6963.org/

正しく実装できていれば、このサイトにアクセスした時点で、ウォレットから送ったイベントをサイトが捕捉してウォレットを検出してくれます。


互いにイベントを送りあい、ウォレットが検出できた


接続も問題なくできた

まとめ

以上で新しい提案であるEIP-6963に対応することができました。これであとは各種DAppの対応がすすめば、MetaMaskと衝突する問題も減り、ユーザーが自分のウォレットを自由に選べるようにもなりますね。

最後に、N Suiteチームでは一緒に開発してくれる仲間を募集しています。

https://ja.careers.nsuite.io/

Discussion