web3-frontend について
Web3 Frontendは、ウォレット接続やブロックチェーン操作を伴うdAppを開発する人向けのスキルです。wagmiとviemを使ったReactのパターンを扱い、トランザクション、署名、エラー処理を学べます。
主な機能
- 01ウォレット統合とネットワーク切り替え
- 02コントラクト書き込みとトランザクション状態の管理
- 03ガス見積もりとトランザクションエラー処理
- 04wagmiフックによるコントラクトデータ取得と操作
- 05EIP-712、SIWE、メッセージ署名の実装
活用シーン
- 01React dAppへのウォレット接続の追加
- 02コントラクトのミントや送金フローの構築
- 03トランザクション状態と手数料の表示
- 04ウォレットを使ったログインや承認の実装
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ pluginagentmarketplace/ custom-plugin-blockchain --skill web3-frontendインストール後、Claude Code で/web3-frontendを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/config.yamlschema.jsonreferences/GUIDE.mdPATTERNS.mdscripts/validate.py詳細
Web3 フロントエンドスキル
ウォレット統合、最新ライブラリ(viem/wagmi)、本番環境向け dApp パターンを習得し、Web3 フロントエンド開発をマスターしましょう。
クイックスタート
# Invoke this skill for Web3 frontend development
Skill("web3-frontend", topic="wallet", framework="react")
対応トピック
1. ウォレット統合
ユーザーを Web3 に接続します:
- RainbowKit:美しいウォレットモーダル
- WalletConnect:モバイル対応
- アカウント抽象化:ERC-4337
- マルチチェーン:ネットワーク切り替え
2. トランザクション管理
ブロックチェーンとのやり取りを処理します:
- 書き込み操作:コントラクトへの書き込み
- 状態追跡:保留中、確認済み
- ガス見積もり:手数料の表示
- エラー処理:ユーザーにわかりやすいメッセージ
3. 署名と認証
ユーザーの本人確認を行います:
- EIP-712:型付きデータへの署名
- SIWE:Ethereum によるサインイン
- Permit:ガス不要の承認
- メッセージ署名:個人署名
4. React フック
wagmi を使った最新のパターン:
- useAccount:接続状態
- useWriteContract:トランザクション
- useReadContract:データ取得
- useWaitForTransactionReceipt:確認
コード例
ウォレットの接続
'use client';
import { ConnectButton } from '@rainbow-me/rainbowkit';
import { useAccount } from 'wagmi';
export function WalletConnect() {
const { address, isConnected } = useAccount();
return (
<div>
<ConnectButton />
{isConnected && <p>Connected: {address}</p>}
</div>
);
}
コントラクトへの書き込み
import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi';
import { parseEther } from 'viem';
export function MintButton() {
const { writeContract, data: hash, isPending } = useWriteContract();
const { isLoading, isSuccess } = useWaitForTransactionReceipt({ hash });
const mint = () => {
writeContract({
address: '0x...',
abi: [...],
functionName: 'mint',
args: [1n],
value: parseEther('0.08'),
});
};
return (
<button onClick={mint} disabled={isPending || isLoading}>
{isPending ? 'Confirm in wallet...' :
isLoading ? 'Minting...' :
isSuccess ? 'Minted!' : 'Mint NFT'}
</button>
);
}
型付きデータへの署名(EIP-712)
import { useSignTypedData } from 'wagmi';
const DOMAIN = {
name: 'My App',
version: '1',
chainId: 1,
verifyingContract: '0x...',
};
export function useSignOrder() {
const { signTypedDataAsync } = useSignTypedData();
const sign = async (order: Order) => {
return await signTypedDataAsync({
domain: DOMAIN,
types: { Order: [...] },
primaryType: 'Order',
message: order,
});
};
return { sign };
}
エラー処理
export function parseError(error: unknown): string {
const msg = error instanceof Error ? error.message : String(error);
if (msg.includes('user rejected')) return 'Transaction cancelled';
if (msg.includes('insufficient funds')) return 'Insufficient balance';
if (msg.includes('execution reverted')) {
const reason = msg.match(/reason="([^"]+)"/)?.[1];
return reason || 'Transaction would fail';
}
return 'Transaction failed';
}
パッケージのセットアップ
npm install wagmi viem @rainbow-me/rainbowkit @tanstack/react-query
// providers/Web3.tsx
import { WagmiProvider } from 'wagmi';
import { RainbowKitProvider } from '@rainbow-me/rainbowkit';
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
import { config } from './config';
const queryClient = new QueryClient();
export function Web3Provider({ children }) {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider>{children}</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
);
}
よくあるパターン
| パターン | 用途 | フック |
|---|---|---|
| ウォレットを接続 | ユーザー認証 | useAccount |
| データを読み取る | 残高を表示 | useReadContract |
| トランザクションを書き込む | ミント、送金 | useWriteContract |
| トランザクションを待つ | 状態を確認 | useWaitForTransactionReceipt |
| メッセージに署名 | 認証、Permit | useSignMessage |
よくある落とし穴
| 落とし穴 | 問題 | 解決策 |
|---|---|---|
| ハイドレーションエラー | SSR の不一致 | dynamic と ssr: false を使用する |
| BigInt のシリアライズ | JSON.stringify | カスタムシリアライザー |
| 古いデータ | キャッシュの問題 | refetchInterval を使用する |
トラブルシューティング
「ウォレットが接続されない」
// Ensure client-side only
import dynamic from 'next/dynamic';
const ConnectButton = dynamic(
() => import('./ConnectButton'),
{ ssr: false }
);
「トランザクションがいつまでも保留中になる」
ガス設定を確認するか、処理を高速化してください:
await wallet.sendTransaction({
...tx,
maxFeePerGas: tx.maxFeePerGas * 120n / 100n,
});
セキュリティチェックリスト
- 秘密鍵を絶対に公開しない
- コントラクトアドレスを検証する
- ユーザー入力をサニタイズする
- 適切なエラーバウンダリーを使用する
- CSP ヘッダーを実装する
相互参照
- Bonded Agent:
05-web3-frontend - 関連スキル:
ethereum-development、solidity-development
バージョン履歴
| バージョン | 日付 | 変更内容 |
|---|---|---|
| 2.0.0 | 2025-01 | wagmi v2、viem を採用した本番環境向けの実装 |
| 1.0.0 | 2024-12 | 初回リリース |
コメント
Markdown 対応