web3-frontend: フロントエンド Web3 統合スキル
フロントエンドアプリケーションからブロックチェーンと対話するための設計パターン、ライブラリ選択基準、実装ガイドを提供するスキル。viem / wagmi / RainbowKit を中心とした現代的な Web3 フロントエンドスタックを対象とする。
対象技術スタック
コアライブラリ
| ライブラリ | 役割 | 備考 |
|---|---|---|
| viem | 低レベル Ethereum クライアント | ethers.js の代替。TypeScript ファースト、tree-shakable |
| wagmi | React Hooks for Ethereum | viem ベース。React アプリの標準選択 |
| @tanstack/react-query | サーバー状態管理 | wagmi v2 の依存。キャッシュ・再検証を担当 |
| RainbowKit | ウォレット接続 UI | wagmi 統合済み。カスタマイズ性が高い |
| ConnectKit | ウォレット接続 UI(代替) | よりシンプルな API。小規模プロジェクト向け |
| WalletConnect v2 | マルチチェーンウォレット接続プロトコル | RainbowKit / ConnectKit の内部で使用 |
viem vs ethers.js 選択基準
| 判断基準 | viem 推奨 | ethers.js 推奨 |
|---|---|---|
| 新規プロジェクト | はい | — |
| TypeScript 型安全性 | 完全な型推論 | 部分的 |
| バンドルサイズ | tree-shakable(小さい) | モノリシック(大きい) |
| 既存の ethers.js コードベース | — | 移行コスト大 |
| wagmi との統合 | ネイティブ統合 | アダプター必要 |
| ドキュメント・コミュニティ | 成長中 | 成熟 |
判断ルール: 新規プロジェクトまたは wagmi 使用時は viem を推奨。既存 ethers.js プロジェクトの場合はユーザーに移行の意向を AskUserQuestion で確認する。
ワークフロー
Step 1: プロジェクト検出と技術スタック判定
- •
package.jsonを読み込み、以下の依存関係を確認する:- •
viem/ethers→ Ethereum クライアントの判定 - •
wagmi/@wagmi/core→ React hooks 使用有無 - •
@rainbow-me/rainbowkit/connectkit→ ウォレット UI の判定 - •
@tanstack/react-query→ 状態管理の確認 - •
next/react→ フレームワークの判定
- •
- •
tsconfig.jsonの存在で TypeScript プロジェクトか判定する。 - •既存のウォレット接続コードを Grep で検出する:
- •
createConfig,useAccount,useConnect→ wagmi 使用中 - •
ethers.providers,new ethers.Contract→ ethers.js 使用中
- •
検証ゲート: package.json が存在し、少なくとも 1 つの Web3 ライブラリが検出されること。Web3 ライブラリが未検出の場合は、AskUserQuestion で使用するスタックを確認する。
Step 2: スタック選択とリファレンス読み込み
Step 1 の結果に基づき、必要なリファレンスを選択して読み込む:
| 状況 | 読み込むリファレンス |
|---|---|
| コントラクト操作 | references/viem-patterns.md から操作パターンを読み込み、read/write/event の該当セクションを選択 |
| React コンポーネント開発 | references/wagmi-hooks.md から hooks パターンを読み込み、該当カテゴリ(接続・読取・書込)を選択 |
| ウォレット接続実装 | references/wallet-connection.md からプロバイダー統合パターンを読み込み、使用ライブラリに合わせて選択 |
| トランザクション送信 | references/transaction-ux.md から UX パターンを読み込み、楽観的更新・エラー表示の該当パターンを選択 |
判断が不明な場合: 複数のアプローチが考えられる場合は AskUserQuestion で要件を確認してからリファレンスを選択する。
検証ゲート: 少なくとも 1 つのリファレンスファイルが正常に読み込めること。
Step 3: コード生成
- •Step 2 で選択したパターンに基づきコードを生成する。
- •以下の共通原則を適用する:
- •TypeScript の型安全性を最大限活用する(ABI からの型推論を含む)
- •コントラクトアドレスはチェーン ID ごとに管理する
- •エラーハンドリングはユーザーフレンドリーなメッセージに変換する
- •ウォレット未接続状態を常に考慮する
- •ABI の取り扱い:
- •
as constアサーションで ABI を定義し、viem の型推論を有効にする - •ABI は
abi/ディレクトリに分離配置を推奨
- •
検証ゲート: 生成コードが TypeScript コンパイルを通ること(npx tsc --noEmit で確認可能)。
Step 4: テスト・動作確認
- •ユニットテスト:
- •hooks のテストは
@wagmi/testのモックプロバイダーを使用 - •コントラクト操作のテストは viem の
createTestClientを使用
- •hooks のテストは
- •統合テスト:
- •
anvil(Foundry のローカルノード)でローカルチェーンを起動してテスト - •
castでテストデータのセットアップ
- •
検証ゲート: テストが全件パスすること。テストフレームワーク未導入の場合は AskUserQuestion でテスト方針を確認する。
使用例
例 1: ウォレット接続の実装
ユーザー入力: 「RainbowKit でウォレット接続を実装して」
アクション:
- •Step 1:
package.jsonを確認 → wagmi + RainbowKit が依存に存在 - •Step 2:
references/wallet-connection.mdを読み込み → RainbowKit セクションを選択 - •Step 3: 以下を生成:
- •
wagmi.config.ts— チェーン設定、トランスポート定義 - •
providers.tsx— WagmiProvider + QueryClientProvider + RainbowKitProvider のラッピング - •
ConnectButtonコンポーネントの配置
- •
- •Step 4: ローカルで接続テスト
結果: RainbowKit のウォレット接続 UI が動作し、接続後にアドレスが表示される。
例 2: ERC20 トークン残高表示
ユーザー入力: 「ユーザーのウォレットにある USDC 残高を表示したい」
アクション:
- •Step 1: プロジェクト検出 → wagmi + viem を確認
- •Step 2:
references/viem-patterns.md(コントラクト読取)+references/wagmi-hooks.md(useReadContract)を読み込み - •Step 3: 以下を生成:
- •ERC20 ABI(balanceOf, decimals, symbol のみ)を
as constで定義 - •
useReadContractで balanceOf を呼び出すカスタム hook - •
formatUnitsでデシマル変換した表示コンポーネント
- •ERC20 ABI(balanceOf, decimals, symbol のみ)を
- •Step 4: テストクライアントでモック残高を設定してテスト
結果: 接続ウォレットの USDC 残高が正しいデシマルで表示される。
例 3: トランザクション送信 UX
ユーザー入力: 「NFT ミントのトランザクション送信画面を作って。進捗表示もほしい」
アクション:
- •Step 1: プロジェクト検出 → wagmi 確認
- •Step 2:
references/transaction-ux.md(トランザクションライフサイクル)+references/wagmi-hooks.md(useWriteContract)を読み込み - •Step 3: 以下を生成:
- •
useWriteContract+useWaitForTransactionReceiptを組み合わせたカスタム hook - •4 段階の進捗表示: idle → pending(署名待ち)→ confirming(ブロック確認待ち)→ success / error
- •ガス見積もりの事前表示(
estimateContractGas) - •エラー時のリトライボタンとユーザーフレンドリーなエラーメッセージ
- •
- •Step 4: anvil でミントコントラクトをデプロイしてテスト
結果: NFT ミントの全ライフサイクルが視覚的にフィードバックされる UI が完成。
トラブルシューティング
1. ウォレット接続が失敗する
症状: ConnectButton を押してもウォレットが接続されない / エラーが出る
原因と対策:
- •WalletConnect projectId 未設定: RainbowKit / ConnectKit は WalletConnect v2 の projectId が必須。
cloud.walletconnect.comでプロジェクトを作成し、環境変数で設定する。 - •チェーン設定の不一致:
wagmi.config.tsのチェーン設定がウォレットの接続チェーンと一致しない。chains配列を確認する。 - •SSR 環境での window 未定義: Next.js の SSR で
window.ethereumにアクセスしている。'use client'ディレクティブの付与と、動的インポートまたはmountedstate ガードを確認する。
2. チェーン切り替えが動作しない
症状: useSwitchChain が失敗する / ユーザーにチェーン追加プロンプトが出ない
原因と対策:
- •wagmi 設定にターゲットチェーン未追加:
chains配列にターゲットチェーンが含まれているか確認する。 - •カスタムチェーンの RPC URL 不正:
transportsでチェーン ID ごとに正しい RPC URL が設定されているか確認する。 - •ウォレット側の制限: 一部のウォレットはプログラマティックなチェーン追加をサポートしない。
switchChainのエラーをキャッチし、手動切り替えの案内を表示する。
3. コントラクト呼び出しが reverted する
症状: useWriteContract が ContractFunctionRevertedError を返す
原因と対策:
- •ABI の不一致: デプロイ済みコントラクトの ABI と定義した ABI が異なる。Etherscan / ブロックエクスプローラーから最新 ABI を取得する。
- •引数の型エラー: BigInt を期待する引数に Number を渡している。
parseEther,parseUnitsで正しく変換する。 - •ガス不足:
estimateContractGasで事前にガスを見積もり、十分な残高があるか確認する。 - •権限不足: コントラクトの
onlyOwner等の修飾子に引っかかっている。接続アドレスの権限を確認する。
4. RPC レート制限エラー
症状: 429 Too Many Requests または接続タイムアウト
原因と対策:
- •公開 RPC の制限: 本番では Alchemy / Infura 等の有料 RPC プロバイダーを使用する。
- •リクエストの過剰発行:
useReadContractのquery.refetchIntervalが短すぎる。適切な間隔(10-30秒)に設定する。 - •フォールバック RPC:
fallbackトランスポートで複数の RPC エンドポイントを設定し、フェイルオーバーを実装する。
5. TypeScript の型エラー
症状: ABI から型が推論されない / unknown 型になる
原因と対策:
- •ABI に
as constがない: ABI 定義にas constアサーションを付与する。外部ファイルからインポートする場合もsatisfies Abi+as constを使用する。 - •wagmi / viem のバージョン不整合:
wagmiとviemのメジャーバージョンが対応しているか確認する(wagmi v2 は viem v2 が必要)。
注意事項
- •秘密鍵をフロントエンドに含めない: 秘密鍵の管理はウォレット側の責務。フロントエンドでは
writeContractでトランザクションを構築し、ウォレットに署名を委譲する。 - •RPC エンドポイントの保護: 公開 RPC はレート制限あり。本番では API キー付きの RPC プロバイダーを使用し、サーバーサイドプロキシで API キーを隠蔽する。
- •チェーン ID の型安全性: viem はチェーン ID を型レベルで管理する。
mainnet,sepolia等の定義済みチェーンオブジェクトを使用し、マジックナンバーを避ける。 - •ethers.js v5 → v6 / viem への移行: 既存プロジェクトの移行は段階的に行う。viem は ethers.js と共存可能。
- •基盤的なスマートコントラクトの知識(Solidity 言語、セキュリティ、テスト)は
solidity-coreを参照する。 - •DeFi / NFT / ガバナンス等のドメイン固有パターンは対応する Solidity スキルを参照する。