既存プロジェクトに RainbowKit + wagmi を導入した時の覚書
Next.jsで作ったサイトにethersを使ってウォレット接続ボタンを置いてたんですが、RainbowKitってやつに変えてみました。すると、コントラクトの読み書きはwagmiに頼ることに。
公開済みのサイトは1つじゃないし今後また別のサイトに実装することもありそうなので、どうやったか書いておくことにします。
ぐぐってもサンプル全然出てこなくて時間かかっちゃった_(:3」z)_
下準備〜導入
基本的に👇ここ見ながらやりました。
- 既存プロジェクトをいじる前に、WalletConnectにサインインしてプロジェクトを作り、IDを入手しておく。
- これを既存プロジェクトで実行
npm install @rainbow-me/rainbowkit wagmi viem@2.x @tanstack/react-query
- コピペする(手順1で取得したプロジェクトIDを使用)
import { /* 任意のチェーン */ } from '@wagmi/core/chains'
import { getDefaultConfig } from '@rainbow-me/rainbowkit';
export const config = getDefaultConfig({
appName: "プロジェクト名",
projectId: "プロジェクトのID",
chains: [/* 任意のチェーン */],
ssr: true,
});
import '@rainbow-me/rainbowkit/styles.css';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { WagmiProvider } from 'wagmi';
import { /* 任意のチェーン */ } from 'wagmi/chains';
import { RainbowKitProvider } from '@rainbow-me/rainbowkit';
import { config } from '../wagmi/config'
const queryClient = new QueryClient();
チュートリアルだとconfigも_app.js
に書いてあるんですが、コントラクト読み書きする時に同じものが必要になるので外に出しといた方が良いです。
使えるチェーンはここ👇で探せます。
- Componentを次のように包む
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider initialChain={/* 接続と同時にネットワーク切り替えたい時はここで指定 */}>
{/* Component */}
</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
と、ここでエラーが出て動かない…
error - Error: No QueryClient set, use QueryClientProvider to set one
いろいろぐぐってもこれという解決法が見つからなかったんですけど、いろいろバージョン上げてるうちに出なくなりました。 なんだったのぉ(´・ω・`)
nodeのバージョンアップ方法👇
私の場合は n latest
で言うこと聞いてくれなかったので sudo n latest
ってしました。
あとは、node_modulesを丸ごと更新したりとか👇
npm update
他に何かしたっけ・・・?
一体何が幸いしたのか、もはやわかりません(´・ω・`)
ConnectWalletボタンを置く
資料こちら👇
改造したくなったらこちら👇
ここはコピペするだけで特に言及することないので、サラッと流します。
コントラクトからデータを取得
👇表示と同時にデータ取得したい時はuseReadContract
import { useReadContract } from 'wagmi'
import abi from '../abi.json';
const Test = () => {
const result = useReadContract({
abi,
address: 'コントラクトのアドレス',
functionName: '関数名',
args: [/*引数*/],
})
console.log("useReadContract:"+result.status);
return result.status == "success" ?
(<>入手したデータ:{ result.data }</>):
(<>読み込み中 または失敗</>);
};
export default Test;
👇ボタン押したタイミングとかにデータ取得したい時はreadContract
import { readContract } from '@wagmi/core'
import { config } from '../config' //下準備で作ったやつ
import abi from '../abi.json';
const Test2 = () => {
const readHandler = async () => {
await readContract(config, {
abi,
address: 'コントラクトのアドレス',
functionName: '関数名',
args: [/*引数*/],
}).then(result => {
console.log("success: "+result);
}).catch(error => {
console.log("error: "+error);
});
};
return (<><button onClick={readHandler}>Read Contract</button></>);
};
export default Test2;
コントラクトの処理を実行する
資料こちら👇
import { writeContract } from '@wagmi/core'
import { config } from '../config' //下準備で作ったやつ
import abi from '../abi.json';
const Test3 = () => {
const writeHandler = async () => {
await writeContract(config, {
abi,
address: 'コントラクトのアドレス',
functionName: '関数名',
args: [/*引数*/],
}).then(result => {
console.log("success: "+result);
}).catch(error => {
console.log("error: "+error);
});
}
return (<button onClick={writeHandler}>Write Contract</button>);
};
export default Test3;
別のやり方もあるみたいだけど試してないです👇
イベントを拾いたいときは
例えばこのような👇コントラクトがあって・・・
event sample_event(uint256 hyaku);
function sample_write() external {
emit sample_event(100);
}
「sample_write 実行後に sample_event で hyaku を受け取りたい!」なんて時は、writeContract
も使って、以下のように書きます。
import { writeContract,watchContractEvent } from '@wagmi/core'
import { config } from '../config' //下準備で作ったやつ
import abi from '../abi.json';
const Test4 = () => {
const writeHandler = async () => {
const unwatch = watchContractEvent(config, {
address: 'コントラクトのアドレス',
abi,
eventName: 'sample_event',
onLogs(logs) {
unwatch();//イベントを待つのをやめる
console.log("hyaku="+logs[0].args.hyaku);
},
onError(error) {
unwatch();//イベントを待つのをやめる
},
})
await writeContract(config, {
abi,
address: 'コントラクトのアドレス',
functionName: 'sample_write',
args: [],
}).then(result => {
console.log("success: "+result);
}).catch(error => {
console.log("error: "+error);
});
}
return (<button onClick={writeHandler}>Write Contract</button>);
};
export default Test4;
公式からそのままコピペすると watchContractEvent
実行直後にunwatch
呼んでますが、それ、完全に罠です!
「もうイベント待つのやめるわ」宣言するの早すぎぃ(´・ω・`) もうちょっと待と!
以上で、自分のやりたいことはできるようになりました。
また別のことを調べたら今回みたいにまとめるかもしれません。
Discussion