【完全保存版】thirdwebでユーザー名からスマートウォレットを作成するプロジェクトを作ろう!
0 はじめに
今回は、こちらのYouTubeを元に、thirdwebを使って、「名前」と「パスワード」からスマートウォレットを作成します。
1 準備をしよう
1 git clone
まずは、git cloneを行います。
git clone https://github.com/thirdweb-example/unilogin.git
2 依存関係のインストール
ディレクトリを移動し、依存関係をインストールします。
cd unilogin
yarn install
3 client IDの設定
次に、「env.local.example」ファイルをコピーし、「env.local」を作成します。
その上で、下のように、「NEXT_PUBLIC_THIRDWEB_CLIENT_ID」を設定します。
なお、クライアントIDについてご不明の場合は、こちらをご参照ください。
4 立ち上げを行う
設定できましたら、下のように立ち上げます。
yarn dev
2 やってみよう
1 スマートウォレットの作成
「localhost:3000」を確認すると、下のように立ち上がりました。
任意のユーザー名とパスワードを設定し、ログインします。
なお、すでにテストをしている他の人と被らないようなユーザー名にする必要があります。
このように、処理が進んでいます。
現在は、暗号化されたアドレスをIPFSにアップロードしています。
ここでは、スマートウォレットをデプロイし、そのユーザー名を登録しています。
すると、このようになりました。
「0x49…Db」の部分が今回作られたスマートウォレットです。
2 スマートウォレットからのNFTの取得
では、このスマートウォレットでERC1155のNFTを取得してみます。
「Claim」を選択します。
すると、このようにClaim中となります。
このように、Claimが成功したようです。
先ほどまで「14399」となっていたClaim数も一つ増えています。
このようにNFTを取得できました。
3 スマートウォレットの確認
次に作成した、スマートウォレットのアドレスを選択してみましょう。
こちらが、今回作成したスマートウォレットです。
ちなみに、「Base Goerli Testnet」というチェーンで作成していたということもここで分かりました。
「Account」を見てみると、下のように、取得したNFTを確認できました。
ちなみに、上の画像を選択すると、「ERC1155」であることも確認できました。
4 スマートウォレットの再入力
では、再度同じユーザー名で入れるかも確認してみましょう。
ユーザー名とパスワードを入れ、進みます。
このように、ユーザー名が存在していることが確認されました。
すると、このように、先ほどのスマートウォレットのページに行くことができました。
5 パスワードが違う場合の流れ
では、パスワードが違う場合も確かめてみましょう。
下では、違うパスワードを入れて、進んでみます。
すると、このように、パスワードが異なる旨のエラーが想定通り出ました。
3 構成を理解しよう
では、どのような処理が行われているのかを見てみましょう。
下のように、青がクライアント側、赤がオンチェーン、緑がIPFS関連です。
ユーザー名とパスワードの入力
まずはユーザー名とパスワードを入力します。
そのユーザー名に対応するアカウントがFactoryコントラクトに存在するかを確認し、分岐します。
4 ユーザー名が「Facrtory」コントラクトに存在しない場合
以下、存在しなかった場合の分岐です。
1 ローカルウォレットの作成
まずは、新しいローカルウォレットを作成します。
2 ローカルウォレットの暗号化
次に、このローカルウォレットをパスワードを使って、暗号化します。
3 暗号化されたローカルウォレットの保存
この暗号化されたローカルウォレットをIPFSにアップロードします。
4 スマートウォレットのデプロイ
一方、そのスマートウォレットをデプロイします。
5 Factoryコントラクトへの登録
次に、このユーザー名とIPFSにアップロード済みのメタデータのURLを登録します。
6 ローカルウォレットとスマートウォレットの接続
これで、スマートウォレットに接続できました。
5 ユーザー名が「Facrtory」コントラクトに存在する場合
次はアカウントが存在する場合の流れです。
1 メタデータのURIの取得
まず、スマートウォレットに保管してある、IPFS内のメタデータのURIを取得します。
2 ローカルウォレットのダウンロード
そのURIを元に、暗号化されているローカルウォレットをダウンロードします。
なお、実際のメタデータはこのようになっていました。
3 ローカルウォレットの復号
暗号化されているローカルウォレットを復号化します。
4 ローカルウォレットのインポート
復号化したウォレットをインポートします。
なお、コード上は、インポート時に、暗号化されたウォレットとパスワードを渡しています。
5 ローカルウォレットとスマートウォレットの接続
最後に、スマートウォレットとローカルウォレットを結びつけています。
なお、スマートウォレットは、チェーンやfactoryアドレス、クライアントIDなどから生成されます。
6 コードを見てみよう
では、コードも見てみましょう。
まずは、ログイン部分を見てみます。
1 ウォレット接続について
こちらの「connectWallet」関数でウォレット接続を行っています。
まずは、ユーザー名とパスワードが入力されているかを確認しています。
2 スマートウォレットとの接続について
その上で、「connectToSmartWallet」関数で、スマートウォレットと接続します。
ここは後ほど、重点的に扱います。
スマートウォレットの署名者を抽出します。
抽出した署名者を「singner」に設定しています。
また、読み取りが完了したので、ローディングも「false」に設定しています。
また、こちらでエラーが発生した場合の処理が書かれています。
3 ウォレットファイルについて
次に、「wallet.ts」ファイルを確認します。
こちらが今回のメインで、次の3つの関数が存在します。
4 スマートウォレットの作成について
まずは、「createSmartWallet」関数です。
その名の通り、スマートウォレットを作成しています。
ウォレットをどのチェーン(chain)で作るかやどのコントラクトから作るか(FactoryAddress)を設定しています。
5 設定ファイルについて
なお、チェーンやFactoryアドレスなどは、「consants.ts」で設定しています。
下のように「factory」アドレスや「openEditionContract」もこちらで設定しています。
なお、「openEditionContract」は今回配布する、ERC1155のコントラクトアドレスです。
また、スマートウォレットのABIも格納しています。
ABIについてご不明な場合は、こちらもご参照ください。
では、戻ります。
スマートウォレット作成時に、ガスレスにするか否か、クライアントIDも設定しています。
6 ウォレットアドレスの取得について
次に、「getWalletAddressForUser」関数を確認します。
まずは、thirdwebSDKの「getContract」関数を使って、アカウントに接続しています。
参考までに、こちらが公式のドキュメントです。
接続ができたので、「factory」コントラクトの「accountOfUsername」関数を実行します。
これで、ユーザー名に対するアカウントを取得します。
下のように確認すると、イメージが湧きやすいかもしれません。
7 スマートウォレットの作成について
では、最後に「connectToSmartWallet」関数を見てみましょう。
こちらは少し長いので、章立てにしました。
1 ステータスの表示について
まずは、こちらの「statusCallback」関数を見てみましょう。
オプションとして、引数に設定しているようです。
実際の使用場面では、下のように、「setLoadingStatus」 を設定し、表示しているようです。
2 ユーザー名の確認について
具体的な処理を見ると、下のように、sdkを作成しています。
また、上で定義した「getWalletAddressForUser」関数で「Factrory」コントラクトからユーザー名のウォレットアドレスを取得しています。
その後、「isContractDeployed」関数を使い、そのアドレスがデプロイ済みかを確認します。
さらに、上で定義した、「createSmartWallet」関数でスマートウォレットを取得しています。
その上で、ローカルウォレットのインスタンスも生成しています。
3 ユーザー名が存在する場合
以下は、「Factory」コントラクト内のユーザー名に対応するコントラクトウォレットがデプロイ済みの場合です。
3ー1 オンチェーンデータへのアクセスについて
まずは、「statusCallback」関数で、ユーザー名が存在し、オンチェーンデータにアクセス中の旨を表示します。
続いて、「スマートウォレット」に接続し、メタデータを取得しています。
また、メタデータ内の「encryptedWallet」(暗号化済みのウォレット)を取得しています。
なお、メタデータの取得などについては、この辺りが公式の部分です。
「encryptedWallet」がない場合は、エラーを出します。
3ー2 ローカルウォレットの復号化について
次に、「import」関数を使って、暗号化済みのウォレットとそのパスワードからローカルウォレットを作成します。
下のように、「import」は秘密鍵などからローカルウォレットを作成する関数のようです。
3ー3 スマートウォレットとの接続について
次に、スマートウォレットとローカルウォレットを接続します。
4 ユーザー名が存在しない場合
では、「Factory」コントラクト内にユーザー名が登録されていない場合も見てみましょう。
4ー1 ローカルウォレットの作成
まずは、下のように、ローカルウォレットを作成します。
「generate」関数は、下のように、ランダムなウォレットを作成するときに用いられます。
4ー2 ローカルウォレットの暗号化について
次に、「export」関数を用いて、暗号化を行います。
「strategy」でエクスポート方法を示し、「password」を使って暗号化をしているようです。
なお、「export」については、このように記載されています。
4ー3 スマートウォレットとの接続について
続いて、スマートウォレットとローカルウォレットを接続しています。
4ー4 IPFSへのアップロードについて
次に、IPFS上に、暗号化したローカルウォレットを格納します。
下のように、「ユーザー名」と「暗号化ウォレット」をIPFSにアップロードしています。
なお、IPFSへのアップロードについては、この辺りが公式になります。
4ー5 Factoryコントラクトへの登録について
では、最後に、「Factory」コントラクトへの登録部分を見てみましょう。
「smartWallet.execute」で以下に続くトランザクションを実行します。
そして、「Transaction.fromContractInfo」でトランザクションのオブジェクトを作成しています。
以下の部分で、スマートウォレットのアドレスや署名者などを渡しています。
また、メソッドは「register」で、引数として、ユーザー名とメタデータのURIを渡しています。
せっかくなので、「register」関数も見てみましょう。
下のように、「Factory」コントラクトで登録を行なっています。
また、下のように、内部関数で、メタデータも設定しています。
「contractURI」も見ると、下のようになっていました。
「IPFS」を確認すると、下のように名前や暗号化されたウォレットの情報を確認することができました。
今回は以上です。