外部EVMウォレット
@seams/walletは、秘密鍵を取り込まずに、既存のMetaMask、Rabby、PhantomのEVMアカウントに接続できます。 アプリが、検出したプロバイダーを選択します。アカウントへのアクセス許可と、すべての承認画面は、ウォレット拡張機能が管理します。
このコネクターはホスト側で動作し、Seamsのウォレットセッションを必要としません。 フレームワークに依存せずに使う場合は、@seams/wallet/external-evmからExternalEvmControllerをインポートします。 Reactアプリでは、以下のピッカーとフックを使えます。
React以外では、ホストUIのマウント時にcontroller.start(window)、アンマウント時にcontroller.dispose()を呼び出してください。
import { useMemo } from 'react';
import {
ExternalEvmController,
ExternalEvmWalletPicker,
useExternalEvm,
type ExternalEvmConnection,
} from '@seams/wallet/react';
function createExternalEvmController(): ExternalEvmController {
return new ExternalEvmController([
{
chainId: 11_155_111,
name: 'Sepolia testnet',
rpcUrl: 'https://rpc.sepolia.org',
},
]);
}
async function signExternalMessage(
controller: ExternalEvmController,
connection: ExternalEvmConnection,
): Promise<void> {
await controller.signMessage(connection, new TextEncoder().encode('Approve this application'));
}
export function ExternalWalletSection() {
const controller = useMemo(createExternalEvmController, []);
const externalEvm = useExternalEvm(controller);
const { connection } = externalEvm;
return (
<>
<ExternalEvmWalletPicker controller={controller} snapshot={externalEvm} />
{connection.kind === 'connected' ? (
<button type="button" onClick={signExternalMessage.bind(null, controller, connection)}>
Sign message
</button>
) : null}
</>
);
}コントローラーは、EIP-6963で通知されたプロバイダーを検出します。 Phantomの拡張機能がEIP-6963の通知を省く場合があるため、公式に定義されたwindow.phantom.ethereumも確認します。 共有のwindow.ethereumプロバイダーを選ぶことはありません。選択した各プロバイダーは、EIP-1193経由で呼び出します。 コントローラーは、アカウント、チェーン、切断のイベントを扱います。 要求の拒否、非対応のメソッドやネットワーク、不正なプロバイダー応答、古い接続、結果が不明な取引について、型付きの対処可能な失敗結果を返します。
最初のリリースは、デスクトップのEVM拡張機能、設定済みチェーンへの切り替え、personal_sign、 EIP-712のeth_signTypedData_v4、通常のeth_sendTransaction、設定済みRPC URLでのレシート確認に対応します。 各チェーンには、数値のEVMチェーンID、表示名、HTTPSまたはHTTPのJSON-RPCエンドポイントを設定してください。 コントローラーは、送信した取引を検証するためだけに、このRPCエンドポイントを使います。 署名とブロードキャストは、ウォレットプロバイダーが行います。
各操作には、対象のアカウントとチェーンのスナップショットとしてconnectionを使ってください。 アカウントやチェーンのイベント後に識別情報が古くなった場合、コントローラーはconnection_changedを返します。 新しいスナップショットを読み取り、ユーザーに再試行を求めてください。 返された取引ハッシュは、送信を行った証拠です。要求の送出後にプロバイダーが失敗した場合は、 submission_unknownを返し、自動的に再送することはありません。
切断すると、このアプリのプロバイダー用リスナーとローカル状態を解除します。 MetaMask、Rabby、Phantomにあるサイトのアクセス許可は取り消しません。 その許可は、ユーザーが外部ウォレットで管理します。
レシートを待つ
sendTransactionが送信成功の結果を返したら、 await controller.waitForReceipt(submission, { timeoutMs: 90_000, signal })を呼び出します。 コントローラーは設定済みRPCをポーリングし、レシートのチェーン、取引ハッシュ、アカウント、ステータス、ブロック番号を検証します。
結果はconfirmed、reverted、unresolvedのいずれかです。 confirmedは、1つのブロックに含まれたことを意味します。チェーンのファイナリティが必要なアプリでは、別途追跡してください。 タイムアウト、キャンセル、RPCの失敗、レシートを検証できない場合は、unresolvedを返します。 送信済みのハッシュを保持し、ユーザーが確認できるようにしてください。自動で再送しないでください。 キャンセル時は、進行中のRPC要求が完了するまで待つ場合があります。
拡張機能の動作確認
このコネクターを使うアプリを公開する前に、Console Liteの実装例で確認してください。
- 新規のデスクトップブラウザープロファイルで、MetaMask、Rabby、Phantom EVMを1つずつ有効にして実行します。
- インストールしたすべての拡張機能を同時に有効にして、再度確認します。
- ブラウザーと拡張機能のバージョンを記録します。
- 各ウォレットで、プロバイダーの検出、ウォレットの明示的な選択、アカウントの選択、設定済みネットワークへの切り替えを確認します。
- メッセージ署名、型付きデータへの署名、テストネット取引を確認します。
- 各承認を、一度ずつ拒否します。
- アプリ側で接続を解除します。
- 後続の試行で、新しい要求が開始されることを確認します。
- 取引の要求後に、プロバイダーとの通信を切断します。
- UIが結果不明の状態を表示し、自動で再送しないことを確認します。
外部アカウントは、Seamsの鍵管理や認証とは別のものです。 接続しても、Seamsへのログイン、ウォレットセッションの作成、Seamsウォレットの操作権限の付与は行いません。 モバイル向け接続、WalletConnect、Solana、アカウントのリンク、鍵管理用の秘密情報の取り込みは、このコネクターの対象外です。
EIP-6963、EIP-1193、 PhantomのEVMプロバイダードキュメントも参照してください。