WEBアプリ上でNFTキャラクターを選ぶページを作ろう
🐱 NFT キャラクターをフロントエンドに表示する
前回のレッスンでは、Webアプリケーションからスマートコントラクトを呼び出すコードを実装し、 SelectCharacterコンポーネントを作成しました。
これから、スマートコントラクトからNFTキャラクターを取得してフロントエンドに表示させていきましょう。
👀 deploy.jsを整理する
Webアプリケーションの開発を進める前に、contract/scriptsにある、deploy.jsファイルを整理しましょう。
mintCharacterNFTやattackBoss関数を排除していきます。
もうすでに排除されている場合は、このプロセスをスキップして問題ありません。
deploy.jsが下記のようになっていることを確認したら、 次に進みましょう。
const main = async () => {
const gameContractFactory = await hre.ethers.getContractFactory("MyEpicGame");
const gameContract = await gameContractFactory.deploy(
["ZORO", "NAMI", "USOPP"], // キャラクターの名前
[
"https://i.imgur.com/TZEhCTX.png", // キャラクターの画像
"https://i.imgur.com/WVAaMPA.png",
"https://i.imgur.com/pCMZeiM.png",
],
[100, 200, 300],
[100, 50, 25],
"CROCODILE", // Bossの名前
"https://i.imgur.com/BehawOh.png", // Bossの画像
10000, // Bossのhp
50 // Bossの攻撃力
);
// ここでは、nftGame コントラクトが、
// ローカルのブロックチェーンにデプロイされるまで待つ処理を行っています。
const nftGame = await gameContract.deployed();
console.log("Contract deployed to:", nftGame.address);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
deploy.jsを整理することにより、フロントエンドにおける状態エラーを防ぐことができます。
deploy.jsを更新した後、もう一度スマートコントラクトをデプロイすると、これからWebアプリケーション上でNFTキャラクターをMintするプロセスがスムーズになります。
復習も兼ねて、下記を実行していきましょう。
1 . 再度、コントラクトをデプロイする。
yarn contract deployを実行する必要があります。
2 . フロントエンド( constants.js)のCONTRACT_ADDRESSを更新する。
3 . の ABI ファイルを更新する。
contract/artifacts/contracts/MyEpicGame.sol/MyEpicGame.jsonの中身を新しく作成するclient/src/utils/MyEpicGame.jsonの中に貼り付ける必要があります。
♻️ index.jsを更新する
client/src/Components/SelectCharacterにあるindex.jsは、プログラムの中で何度も登場する変数や関数をまとめているファイルです。
これから、index.jsの中身を更新していきます。
まず、index.jsのimportの部分を下記のように更新してください。
import React, { useEffect, useState } from "react";
import "./SelectCharacter.css";
import { ethers } from "ethers";
import { CONTRACT_ADDRESS, transformCharacterData } from "../../constants";
import myEpicGame from "../../utils/MyEpicGame.json";
次に、SelectCharacterを下記のように更新しましょう。
// SelectCharacter コンポーネントを定義しています。
const SelectCharacter = ({ setCharacterNFT }) => {
const [characters, setCharacters] = useState([]);
const [gameContract, setGameContract] = useState(null);
// ページがロードされた瞬間に下記を実行します。
useEffect(() => {
const { ethereum } = window;
if (ethereum) {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const gameContract = new ethers.Contract(
CONTRACT_ADDRESS,
myEpicGame.abi,
signer
);
// gameContract の状態を更新します。
setGameContract(gameContract);
} else {
console.log("Ethereum object not found");
}
}, []);
return (
<div className="select-character-container">
<h2>⏬ 一緒に戦う NFT キャラクターを選択 ⏬</h2>
</div>
);
};
export default SelectCharacter;
追加したコードを詳しく見ていきましょう。
const [characters, setCharacters] = useState([]);
const [gameContract, setGameContract] = useState(null);
ここでは、いくつかの状態変数を設定していきます。
-
characters: コントラクトから返されるNFTキャラクターのメタデータを保持するプロパティ。 -
setCharacters:charactersの状態を更新するプロパティ。 -
gameContract: コントラクトの状態を初期化して保存するプロパティ。プログラムの中でコントラクトは複数回呼び出されるので、いったん初期化した状態で保存し、コントラクト全体で使用できるようにします。
-
setGameContract:gameContractの状態を更新するプロパティ。
次に、下記のコードを見ていきましょう。
// ページがロードされた瞬間に下記を実行します。
useEffect(() => {
const { ethereum } = window;
if (ethereum) {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const gameContract = new ethers.Contract(
CONTRACT_ADDRESS,
myEpicGame.abi,
signer
);
// gameContract の状態を更新します。
setGameContract(gameContract);
} else {
console.log("Ethereum object not found");
}
}, []);
ここではuseEffectを使って、SelectCharacterコンポーネントが呼び出されたら、すぐにgameContractを作成して、使用できるようにしています。
この処理により、フロントエンドでNFTキャラクターを表示する準備が整います。