DEV Community

Cover image for MetaMask API の使い方: dApp を Ethereum ウォレットに接続
Akira
Akira

Posted on • Originally published at apidog.com

MetaMask API の使い方: dApp を Ethereum ウォレットに接続

MetaMaskは何千万ものユーザーにとってEthereumへの主要な入り口であり、dApp開発者にとってMetaMask APIはUIとユーザーの署名キーを繋ぐ重要なインターフェースです。MetaMask APIは、EIP-1193で定義されたwindow.ethereumプロバイダーと、同インターフェースをモバイルやNode.jsに拡張するMetaMask SDKの2つで構成されます。このプロバイダーを理解すれば、Web3ウォレット統合の大半に対応できます。

Apidog を今すぐ試そう

このガイドでは、プロバイダーの検出、アカウントリクエスト、チェーンの取得、personal_signやEIP-712を利用した署名、トランザクション送信、チェーン追加・切替、さらにMetaMask SDKをブラウザ外で使う手順を解説します。ethers.js v6・viemとの組み合わせや、JSON-RPC呼び出しのテスト方法としてApidogを活用する方法も紹介します。

ウォレット関連の開発を行う際は、このガイドと最高の暗号ウォレットAPI解説も一緒にブックマークしておくと便利です。

要点

  • MetaMask APIはブラウザのwindow.ethereum(EIP-1193プロバイダー)と、モバイル/Node向けMetaMask SDKで構成。
  • eth_requestAccountsでユーザー接続、accountsChangedchainChangedで状態監視。
  • personal_signでメッセージ署名、eth_signTypedData_v4(EIP-712)で構造化データ署名。
  • wallet_switchEthereumChain(EIP-3326)でネットワーク切替、wallet_addEthereumChain(EIP-3085)で新規ネットワーク追加。
  • ethers.js v6、viem、wagmiなどの高レベルライブラリはプロバイダーをラップ、SnapsでMetaMask拡張も可能。
  • ApidogでJSON-RPCエンドポイントのテスト、トランザクション応答のモック、署名デバッグができる。

MetaMask APIとは?

MetaMask APIは、MetaMaskがWebページやアプリに提供するEVM互換チェーンと通信するための標準インターフェースです。ブラウザ拡張はwindow.ethereumを注入し、これはEIP-1193に準拠。EIP-1193対応dAppはMetaMask・Coinbase Wallet・Rabbyなど主要ウォレットすべてで動作します。

ブラウザ以外では、MetaMask SDKを使うことで、React NativeやNode.js、Electronアプリ、サーバーサイドスクリプトでも同じ方式で接続できます。SDKはディープリンクやQRコード経由でトランザクション署名をモバイルウォレットへ委譲可能。コードの共通化が容易です。

また、MetaMaskはSnapsというプラグインシステムも提供しており、サードパーティによる新チェーン追加・カスタムRPCメソッド・独自アカウントタイプの拡張が可能です(本記事では割愛)。

認証とセットアップ

MetaMaskプロバイダー自身にAPIキーは不要です。認証は、ユーザーが各リクエストごとにウォレットUIで承認ボタンを押す形になります。実装時のポイントは、プロバイダー検出とイベントリスナー追加です。

プロバイダーの検出

複数ウォレットが同時インストールされているケースもあるため、@metamask/detect-providerの利用が推奨されます。直接チェックも可能です。

// Vanilla JSでMetaMaskプロバイダーを検出
import detectEthereumProvider from '@metamask/detect-provider';

const provider = await detectEthereumProvider({ mustBeMetaMask: true });

if (!provider) {
  alert('Please install MetaMask');
} else {
  console.log('MetaMask detected');
}
Enter fullscreen mode Exit fullscreen mode

イベントリスナーの追加

アカウントやチェーンの切替イベントを必ずハンドリングしましょう。accountsChangedを無視するとバグの原因になります。

window.ethereum.on('accountsChanged', (accounts) => {
  if (accounts.length === 0) {
    console.log('User disconnected');
  } else {
    console.log('Active account:', accounts[0]);
  }
});

window.ethereum.on('chainChanged', (chainId) => {
  // ベストプラクティス: チェーン変更時はリロード
  window.location.reload();
});
Enter fullscreen mode Exit fullscreen mode

React環境ではwagmi等のライブラリがコネクタとして自動検出・管理してくれます。

主要エンドポイント

全てのリクエストはwindow.ethereum.request({ method, params })で行います。メソッドはJSON-RPCの文字列名、paramsは配列またはオブジェクトです。以下、主要なメソッドとサンプル実装例です。

アカウントリクエストとチェーン情報取得

// ユーザーに接続を促す
const accounts = await window.ethereum.request({
  method: 'eth_requestAccounts',
});
const account = accounts[0];

// 現在のチェーンIDを取得
const chainId = await window.ethereum.request({
  method: 'eth_chainId',
});

console.log(account, chainId); // 例: '0x...' '0x1'
Enter fullscreen mode Exit fullscreen mode

同じリクエストはcurlでも実行可能です。

curl https://mainnet.infura.io/v3/YOUR_KEY \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
Enter fullscreen mode Exit fullscreen mode

読み取りだけの場合はMetaMask不要で、AlchemyやInfura等のノードプロバイダー経由でもOKです。詳細はAlchemy APIガイドを参考に。

メッセージ署名(personal_sign)

const message = 'Sign in to Apidog at ' + new Date().toISOString();
const signature = await window.ethereum.request({
  method: 'personal_sign',
  params: [message, account],
});
Enter fullscreen mode Exit fullscreen mode

構造化データ署名(EIP-712, eth_signTypedData_v4)

const typedData = {
  domain: { name: 'Apidog Demo', version: '1', chainId: 1 },
  types: {
    EIP712Domain: [
      { name: 'name', type: 'string' },
      { name: 'version', type: 'string' },
      { name: 'chainId', type: 'uint256' },
    ],
    Login: [
      { name: 'wallet', type: 'address' },
      { name: 'nonce', type: 'uint256' },
    ],
  },
  primaryType: 'Login',
  message: { wallet: account, nonce: 42 },
};

const sig = await window.ethereum.request({
  method: 'eth_signTypedData_v4',
  params: [account, JSON.stringify(typedData)],
});
Enter fullscreen mode Exit fullscreen mode

トランザクション送信

const txHash = await window.ethereum.request({
  method: 'eth_sendTransaction',
  params: [{
    from: account,
    to: '0xRecipientAddressHere',
    value: '0x38d7ea4c68000', // 0.001 ETH (wei, hex)
  }],
});
Enter fullscreen mode Exit fullscreen mode

チェーン切り替え・新規追加

// Polygon(chainId 137 = 0x89)へ切り替え
try {
  await window.ethereum.request({
    method: 'wallet_switchEthereumChain',
    params: [{ chainId: '0x89' }],
  });
} catch (err) {
  if (err.code === 4902) {
    // 未追加の場合は新規追加
    await window.ethereum.request({
      method: 'wallet_addEthereumChain',
      params: [{
        chainId: '0x89',
        chainName: 'Polygon',
        rpcUrls: ['https://polygon-rpc.com'],
        nativeCurrency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 },
      }],
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

MetaMask SDKをReactで使う

SDKはデスクトップ拡張・モバイルディープリンク・アプリ内ブラウザ全対応のシングルパス統合が可能です。

import { MetaMaskProvider, useSDK } from '@metamask/sdk-react';

function Connect() {
  const { sdk, connected, account } = useSDK();
  return (
    <button onClick={() => sdk?.connect()}>
      {connected ? account : 'Connect MetaMask'}
    </button>
  );
}

export default function App() {
  return (
    <MetaMaskProvider sdkOptions={{ dappMetadata: { name: 'My dApp' } }}>
      <Connect />
    </MetaMaskProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

本番アプリでは、ethers.js v6やviemなどでラップし、型付きコントラクト呼び出しやエラーハンドリングを強化しましょう。メールやソーシャルログインを組み合わせる場合はPrivy APIガイドも参考に。

一般的なエラーとレート制限

MetaMaskは標準JSON-RPCエラーコードを返します。よくあるエラーは次の通りです。

  • 4001: ユーザーによるリクエスト拒否。再試行は避け、UIで「キャンセルされました」を表示。
  • 4100: 権限なし。アカウント未接続。まずeth_requestAccountsを呼ぶ。
  • 4200: 未サポートメソッド。ウォレット固有メソッド利用時はMetaMaskか確認。
  • 4902: 未追加チェーン。wallet_addEthereumChainで追加。
  • -32002: リクエスト保留中。二重クリック防止のデバウンス推奨。

プロバイダー自体にはレート制限はありませんが、背後のRPCノード(InfuraやAlchemy)はプランごとに制限されます。法定通貨変換などのフィアット連携にはフィアットオンランプAPIガイドも参照ください。

MetaMask APIの料金

MetaMask拡張とSDKは完全無料です。接続・署名・送信ごとの課金はありません。MetaMaskの収益はユーザーのスワップ手数料とカード事業からで、dApp開発者は無料で使えます。

かかるコストは、RPCエンドポイント(例:Alchemy/Infura)の利用分です。無料枠で小規模用途は十分ですが、本番運用では月額49~299ドル程度の専用プラン利用が一般的です。

ApidogでMetaMask APIをテストする

ブラウザベースの署名フローは、拡張・ページ・モバイルディープリンクの連携もありデバッグが難しい場合があります。Apidogを使えば、dAppで利用するJSON-RPCエンドポイントへ直接リクエストし、eth_chainIdeth_getBalanceの値確認、テストスイート化が容易です。

Ethereum JSON-RPC仕様をインポートし、ノードURLを環境変数で切替えれば、あらゆるEVMチェーンで再利用可能なコレクションを構築できます。Apidogは応答モック機能もあり、コントラクトが未監査でもフロント開発を進めたい場合に便利。CI環境では同コレクションをCLI実行してスキーマ変化検知も可能。Postmanの共有・同期に悩んでいるなら、PostmanなしのAPIテスト解説もおすすめです。

始めるには、Apidogをダウンロードしてください。

よくある質問

  • MetaMask APIはモバイルで使えますか?

    はい、MetaMask SDKで対応可能です。ディープリンクでモバイルウォレット署名を実現できます。インターフェースはブラウザ拡張と同一、コード修正不要です。モバイル用SDK比較はこちら

  • eth_signpersonal_signeth_signTypedData_v4の違いは?

    eth_signは生バイト署名で危険。personal_signは人間可読メッセージにプレフィックス、eth_signTypedData_v4(EIP-712)は構造化データ署名とUIでのフィールド表示。後者2つ推奨、eth_signは避けましょう。

  • MetaMask利用にAPIキーは必要?

    いいえ、MetaMaskプロバイダー自体は無料・キー不要。外部ノード利用時(Alchemy/Infura等)は別途APIキーが必要です。

  • ethers.jsやviemはMetaMaskと併用できる?

    どちらもwindow.ethereumをラップ。ethers v6はBrowserProvider(window.ethereum)、viemはcreateWalletClient({ transport: custom(window.ethereum) })で利用可能。多くのdAppがこれらを利用しています。

  • 複数ウォレットインストール時の挙動は?

    MetaMaskはEIP-6963対応済み。dAppはwindow.ethereumを取り合わず、全ウォレットの検出が可能。wagmi・RainbowKitは自動対応。

  • MetaMask Snapsは本番利用できる?

    2024年に一般公開済み。主に非EVMチェーン対応、カスタムトランザクションインサイト、ハードウェアウォレット統合に用いられています。

Top comments (0)