WEBアプリからNFTキャラクターを呼び出そう
👋 Web アプリケーションからスマート コントラクトを呼び出す
これまでのレッスンでは、スマートコントラクトのロジックの設定を行いました。
これからは、スマートコントラクトをWebアプリケーションから呼び出す機能を実装していきます。
下記のステップに沿って、Sepolia Test Networkにデプロイされたスマートコントラクトに、Webアプリケーションを接続させていきます。
1. デプロイされた最新のコントラクトアドレスをコピーし、Webアプリケーションに貼り付けます。
2. 最新のABIファイルをコピーして、Webアプリケーションのディレクトリに貼り付けます。ABIとは何かについては、のちほど詳しく説明します。
3. クライアント(=フロントエンド)からスマートコントラクト(=バックエンド)にアクセスするために、ethers.js
をインポートします。
🏠 最新のスマートコントラクトアドレスを取得する
あなたのスマートコントラクトのデプロイ先のアドレス(=スマートコントラクトアドレス)をApp.js
でも使用します。
deploy.js
スクリプトを実行するたびに、ターミナルに出力されていたアドレス(Contract deployed to: 0x..
)を覚えていますか?
0x..
が、あなたがデプロイしたスマートコントラクトアドレスになります。
ブロックチェーン上には、何百万ものコントラクトが存在しています。
クライアント(= Webアプリケーションのフロントエンド)に対して、どのコントラクトに接続するかを伝えるために、スマートコントラクトアドレスが必要です。
このアドレスは、さまざまなタイミングで使用する予定ですので、簡単にアクセスできるようにしましょう。
client/src
の中にconstants.js
ファイルを作成し、以下のコードを追加してください。
const CONTRACT_ADDRESS = "YOUR_CONTRACT_ADDRESS_GOES_HERE";
export { CONTRACT_ADDRESS };
YOUR_CONTRACT_ADDRESS_GOES_HERE
の部分にあなたのスマートコントラクトアドレスを貼り付けてください。
次に、App.js
ファイルに戻り、ファイルの先頭に下記をインポートして、constants.js
にアクセスできるようにしましょう。
import { CONTRACT_ADDRESS } from "./constants";
📁 最新の ABI ファイルを取得します。
ABI(Application Binary Interface)はコントラクトの取り扱い説明書のようなものです。
Webアプリケーションがコントラクトと通信するために必要な情報が、ABIファイルに含まれています。
コントラクト1つ1つにユニークなABIファイルが紐づいており、その中には下記の情報が含まれています。
1. そのコントラクトに使用されている関数の名前
2. それぞれの関数にアクセスするために必要なパラメータとその型
3. 関数の実行結果に対して返るデータ型の種類
ABIファイルは、コントラクトがコンパイルされた時に生成され、contract/artifacts
ディレクトリに自動的に格納されます。
ターミナルでcontract
ディレクトリに移動し、ls
を実行しましょう。
artifacts
ディレクトリの存在を確認してください。
ABIファイルの中身は、MyEpicGame.json
というファイルに格納されいます。
下記を実行して、ABIファイルをコピーしましょう。
1. ターミナル上でcontract
にいることを確認する(もしくは移動する)。
2. ターミナル上で下記を実行する。
code artifacts/contracts/MyEpicGame.sol/MyEpicGame.json
3. VS CodeでMyEpicGame.json
ファイルが開かれるので、中身をすべてコピーしましょう。
※ VS Codeのファインダーを使って、直接 MyEpicGame.json
を開くことも可能です。
次に、下記を実行して、ABIファイルをWebアプリケーションから呼び出せるようにしましょう。
1. ターミナル上でclient
にいることを確認する(もしくは移動する)。
2. 下記を実行して、client/src/
の中にutils
ディレクトリを作成する。
mkdir src/utils
3. 下記を実行して、utils
ディレクトリにMyEpicGame.json
ファイルを作成する。
touch src/utils/MyEpicGame.json
4. 下記を実行して、MyEpicGame.json
ファイルをVS Codeで開く。
code client/src/utils/MyEpicGame.json
5. 先ほどコピーしたcontract/artifacts/contracts/MyEpicGame.sol/MyEpicGame.json
の中身を新しく作成したclient/src/utils/MyEpicGame.json
の中に貼り付けてください。
ABIファイルの準備ができたので、App.js
にインポートしましょう。
下記をApp.js
の1行目に追加しましょう。
import myEpicGame from "./utils/MyEpicGame.json";
ここでは、先ほど取得した、ABIファイルを含むMyEpicGame.json
ファイルをインポートしています。
🚨 コントラクトを再びデプロイする際の注意点
コントラクトの中身を更新する場合、必ず下記3つのステップを実行することを忘れないようにしましょう。
1. 再度、コントラクトをデプロイする。
yarn contract deploy
を実行する必要があります。
2. フロントエンド(App.js
)のCONTRACT_ADDRESS
を更新する。
3. ABIファイルを更新する。
contract/artifacts/contracts/MyEpicGame.sol/MyEpicGame.json
の中身を新しく作成するclient/src/utils/MyEpicGame.json
の中に貼り付ける必要があります。
コントラクトを更新する際、必ずこの 3 つのステップを実行してください。
-
一度デプロイされたスマートコントラクトを変更することはできません。
-
コントラクトを変更するには、完全に再デプロイする必要があります。
-
新しくデプロイされたスマートコントラクトは、ブロックチェーン上で新しいコントラクトとして扱われるため、すべての変数はリセットされます。
-
つまり、コントラクトのコードを更新したい場合、すべての NFT データが失われます。
📞 ethers.js を使用する
スマートコントラクトをWBEアプリ ケーションに接続するために、必要なものがすべてそろいました。
これから、スマートコントラクトを呼び出すため、JavaScriptでオブジェクトを設定していきます。
まず、ethers.js が提供するライブラリをApp.js
にインポートします。
import { CONTRACT_ADDRESS } from './constants'
の直下に下記を追加しましょう。
import { ethers } from "ethers";
ここでは、フロントエンドとコントラクトを連携させるライブラリethers
をインポートしています。
🌐 ネットワークを確認する
次に 、ユーザーがSepolia Test Networkに接続しているか確認し、そうでない場合は、フロントエンド上でアラートを出す関数を実装していきます。
checkNetwork
関数をconst [characterNFT, setCharacterNFT] = useState(null);
の直下に追加してください。
// ユーザーがSepolia Network に接続されているか確認します。
// '11155111' は Sepolia のネットワークコードです。
const checkNetwork = async () => {
try {
if (window.ethereum.networkVersion !== "11155111") {
alert("Sepolia Test Network に接続してください!");
} else {
console.log("Sepolia に接続されています.");
}
} catch (error) {
console.log(error);
}
};
window.ethereum.networkVersion
では、ユーザーがどのイーサリアムネットワークを使用しているか確認しています。
イーサリアムネットワークには異なるチェーンIDが付与されており、SepoliaチェーンのIDは11155111
です。
したがって、ユーザーがSepolia Test Networkに接続されてないことをWebアプリケーションが検知したら、「Sepolia Test Networkに接続してください!」というアラートがフロントエンドに表示されます。
次に、App.js
を下記のように変更していきましょう。
-
checkNetwork()
をcheckIfWalletIsConnected
関数の中のsetCurrentAccount(account);
の直下に追加する。 -
connectWalletAction
関数を下記のように更新します。
// connectWallet メソッドを実装します。
const connectWalletAction = async () => {
try {
const { ethereum } = window;
if (!ethereum) {
alert("MetaMask を ダウンロードしてください!");
return;
}
// ユーザーがウォレットを持っているか確認します。
checkIfWalletIsConnected();
// ウォレットアドレスに対してアクセスをリクエストしています。
const accounts = await ethereum.request({
method: "eth_requestAccounts",
});
// ウォレットアドレスを currentAccount に紐付けます。
console.log("Connected", accounts[0]);
setCurrentAccount(accounts[0]);
// ユーザーが Sepolia に接続されているか確認します。
checkNetwork();
} catch (error) {
console.log(error);
}
};