【Web3/DeFi】DeFi領域のWallet接続機能のベストプラクティス
はじめに
今回、web3 DeFi領域のVaultsプラットフォーム開発に携わらせていただいている僕ですが、その開発で実装していたWallet接続にてバグが連発していて、コード自体にそこまで致命的な問題はなく、原因特定に難航していましたが、SolflareSDKを使用してWallet接続機能を実装していたことが原因だったので、この経験を記事にしてみます。
SolflareSDKを実装していたものをそのままWallet Adapterに移行したので結構な大工事になりました...
BackGraound
初期実装と問題発生の経緯
当初、僕ははSolflareSDKを利用してウォレット接続を実装していました。SolflareSDKには以下のようなメリットがありました。
- 直感的なAPI: 初期実装が容易で、直感的なAPI設計のため、迅速なプロトタイピングが可能でした。
- 軽量性: Phantomなど他のウォレットと比べても、軽量な実装が期待できました。
しかし、実際に運用していく中で、Phantomの接続に関しては問題なくDeposit機能などが動作する一方、Solflareの場合に特定のトランザクションでTransactionError
や接続エラーが頻発するという事実が判明しました。
なぜSolflareSDKではダメだったのか
SolflareSDKを利用していた場合、以下の問題点が浮上しました。
- エラーハンドリングの不安定さ: SolflareSDKでの接続時、特に新規ウォレットの場合、内部で予期せぬエラーが発生し、ユーザー登録処理に失敗することがありました。
- 公式サポートの欠如: SolflareSDKは便利な面もありましたが、公式が推奨しているのはWallet Adapterの利用であり、セキュリティやエラーハンドリング、トランザクションの安定性などの点で、公式のWallet Adapterの方が信頼性が高いと判断されました。
そのため、公式推奨のWallet Adapterへ移行することで、Phantomと同様にSolflareでも安定した接続が実現できると結論づけました。
Wallet機能実装の大工事
実装アーキテクチャ
以下は、今回の実装アーキテクチャの概要です。
- Reactアプリケーション: ユーザーインターフェースの実装全体を担います。
- ConnectWalletContext: ウォレットの状態(接続状態、アドレス、ウォレット種類)をグローバルに管理します。
- Wallet Adapter: 公式推奨のWallet Adapterを利用して、SolflareやPhantomなど複数のウォレットに対応します。
- バックエンドAPI: ユーザー登録やDeposit、Withdrawなどの各種リクエストを処理します。
コードの変更点
主な変更点は、以下の通りになります。
-
ConnectWalletContextの利用
以前はSolflareSDKを直接利用していましたが、現在はConnectWalletContextを通じてウォレットの状態を一元管理しています。
※ここで注意すべき点は、コンテキストからwalletType
も分割代入する必要があることです。// 修正前 const { walletConnected, walletAddress, setWalletConnected, setWalletAddress, setWalletType } = useContext(ConnectWalletContext); // 修正後 const { walletConnected, walletAddress, walletType, setWalletConnected, setWalletAddress, setWalletType } = useContext(ConnectWalletContext);
-
ユーザー登録処理の追加
接続後、registerUser(publicKey, walletType)
を呼び出して、新規ユーザーの場合にバックエンドへ登録リクエストを送信する処理を実装しました。
ただし、walletType
が未定義の場合は登録処理をスキップするようにし、エラーログも出力しています。if (connected && publicKey) { console.debug("DEBUG: Wallet connected using Wallet Adapter."); setWalletConnected(true); setWalletAddress(publicKey.toBase58()); // ...省略... if (walletType) { registerUser(publicKey, walletType) .then(() => { console.debug("DEBUG: User registration successful (or already registered)."); }) .catch((error) => { console.error("DEBUG: Error during user registration:", error); }); } else { console.warn("DEBUG: walletType is not defined. User registration skipped."); } }
-
Wallet Adapterの利用
公式が推奨するWallet Adapterに切り替えることで、エラーハンドリングや接続の安定性が向上しました。特にSolflareの場合、以前のSDKでは発生していたTransactionError
などの問題が解消されています。
※また、Solflare固有のセッション管理については、現段階では利用しない方針としています(後で安定性向上のために再検討可能)。 -
エラーハンドリングの強化
各API呼び出しや接続処理の際に、十分なログ出力とエラーメッセージを実装し、問題発生時の原因追及を容易にしました。
公式のドキュメントをしっかり読もう
Solflareのドキュメントは英語のみなのでなかなか敷居が高かったのですが、あまりにも問題が多発するため本当にSDKでの実装でいいのか確認するために重い腰を上げて公式ドキュメントを改めて最初から精読することにしました。
公式のDocsほど確実なものはないので、やはり大切に読むべき必要があります....
Wallet Adapterの利点
-
公式推奨による安心感
Wallet AdapterはSolana公式のウォレット接続ライブラリとして推奨されており、最新のセキュリティ基準やエラーハンドリングを備えています。 -
複数ウォレットの統一的なサポート
Phantomだけでなく、Solflareも含む複数のウォレットに対して一貫したAPIを提供するため、コードの保守性が向上します。 -
安定性の向上
実際にWallet Adapterに移行することで、以前SolflareSDKで発生していたトランザクションエラーや接続エラーが解消され、全体的なシステムの安定性が向上しました。
まとめ
今回、DeFiアプリケーションのウォレット接続機能について、SolflareSDKから公式のWallet Adapterへの移行を検討し、実装する過程で以下の点が明らかになりました。
- 課題: SolflareSDK使用時に新規ウォレットでDeposit処理を実施すると、ユーザー登録やトランザクション処理においてエラーが発生する。
- 背景: 当初は軽量で直感的なSolflareSDKを採用していたが、実際の運用では安定性に問題があったため、公式推奨のWallet Adapterへ移行する必要があった。
-
解決策: ConnectWalletContextを利用してウォレット状態を一元管理し、Wallet Adapter(PhantomおよびSolflare)を用いることで、エラーハンドリングと接続の安定性を確保した。特に、
walletType
の取り扱いを正しく行うために、ConnectWalletContextからwalletType
も分割代入するように修正し、エラー「walletType is not defined」を解消した。 - 結果: これにより、Solflareの接続時にもエラーなくDeposit/Withdraw機能が動作するようになり、ユーザー登録のバックエンドへのリクエストも正しく実行されるようになりました。
参考文献
この記事では、DeFiアプリケーションにおけるウォレット接続機能の実装課題とその解決方法について詳しく解説しました。SolflareSDKからWallet Adapterへの移行によって、ウォレット接続の安定性やエラーハンドリングが大幅に向上し、ユーザー体験の改善に寄与しています。これからDeFi領域でシステムを構築する方の参考になれば幸いです。
Discussion