diff --git a/frontend/src/App.js b/frontend/src/App.js index f1f8dc68..3f908df4 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -7,6 +7,7 @@ import LoadingIndicator from './Components/LoadingIndicator'; import SelectCharacter from './Components/SelectCharacter'; import { CONTRACT_ADDRESS, transformCharacterData } from './constants'; import GameContent from './utils/GameContent.json'; +import Arena from './Components/Arena'; // Eth -> JS imports import { ethers } from 'ethers'; @@ -158,6 +159,8 @@ const App = () => { // If user is connected and does not have a character NFT - show SelectCharacter component } else if (currentAccount && !characterNFT) { return ; + } else if (currentAccount && characterNFT) { // If user is connected and has a character NFT - show Arena component + return ; } }; diff --git a/frontend/src/Components/Arena/index.js b/frontend/src/Components/Arena/index.js new file mode 100644 index 00000000..db30deeb --- /dev/null +++ b/frontend/src/Components/Arena/index.js @@ -0,0 +1,133 @@ +import React, { useEffect, useState } from 'react'; +import { ethers } from 'ethers'; +import { CONTRACT_ADDRESS, transformCharacterData } from '../../constants'; +import gameContent from '../../utils/GameContent.json'; +import './Arena.css' +import SelectCharacter from '../SelectCharacter'; + +// Parse in characterNFT metadata +const Arena = ({ characterNFT }) => { + // State + const [gameContract, setGameContract] = useState(null); + // Boss Metadata state + const [boss, setBoss] = useState(null); + const [attackState, setAttackState] = useState(''); + const runAttackAction = async () => { + try { + if (gameContract) { + setAttackState('attacking...'); // Waiting for the attack transaction to finish + console.log('Attacking boss....') + const attackTxn = await gameContract.attackBoss(); + await attackTxn.wait(); + console.log('attackTxn:', attackTxn); + setAttackState('hit'); // When the character lands a hit on the boss + } + } catch (error) { + console.log('Error attacking boss:', error); + setAttackState(''); // Default state - nothing happens + } + }; + + // UseEffect + useEffect(() => { + const { ethereum } = window; + + if (ethereum) { + const provider = new ethers.providers.Web3Provider(ethereum); + const signer = provider.getSigner(); + const gameContract = new ethers.Contract( + CONTRACT_ADDRESS, + gameContent.abi, + signer + ); + + setGameContract(gameContract); + } else { + console.log('Ethereum object not found '); + } + + // Async function that gets the boss from the contract and sets it in state + const fetchBoss = async () => { + const bossTxn = await gameContract.getBoss(); + console.log('Boss:', bossTxn); + setBoss(transformCharacterData(bossTxn)); + }; + + // Attack setup logic when event is fired + const onAttackComplete = (newBossHp, newPlayerHp) => { + const bossHp = newBossHp.toNumber(); + const playerHp = newPlayerHp.toNumber(); + + console.log(`AttackComplete: Boss Hp: ${bossHp}, Player Hp: ${playerHp}`); + // Update player and boss hp + setBoss((prevState) => { + return { ...prevState, hp: bossHp }; + }); + + SelectCharacter((prevState) => { // I think this is supposed to be `setCharacterNFT` + return { ...prevState, hp: playerHp }; + }); + } + + if (gameContract) { + fetchBoss(); + gameContract.on('AttackComplete', onAttackComplete); + } + + return () => { + if (gameContract) { + gameContract.off('AttackComplete', onAttackComplete); + } + } + }, [gameContract]); // Is either `gameContent` or `gameContract` + + return ( +
+ {boss && ( +
+
+

{boss.name}

+
+ {`boss.name`} +
+ +

{`${boss.hp} / ${boss.maxHp} HP`}

+
+
+
+
+ +
+
+ )} + + {characterNFT && ( +
+
+

Your character

+
+
+

{characterNFT.name}

+ {`Character +
+ +

{`${characterNFT.hp} / ${characterNFT.maxHp} HP`}

+
+
+
+

{`⚔️ Attack Damage: ${characterNFT.attackDamage}`}

+
+
+
+
+ )} +
+ ); +}; + +export default Arena; \ No newline at end of file diff --git a/frontend/src/Components/SelectCharacter/index.js b/frontend/src/Components/SelectCharacter/index.js index 74166cd1..5d1fe4e9 100644 --- a/frontend/src/Components/SelectCharacter/index.js +++ b/frontend/src/Components/SelectCharacter/index.js @@ -56,6 +56,7 @@ const SelectCharacter = ({ setCharacterNFT }) => { const mintTxn = await gameContract.mintCharacterNFT(characterId); await mintTxn.wait(); console.log('mintTxn:', mintTxn); + //alert(`Your NFT has minted - see it here: https://testnets.opensea.io/assets/${CONTRACT_ADDRESS}/${tokenId.toNumber()}`); // hides loading indicator when done with Action setMintingCharacter(false); } @@ -109,7 +110,7 @@ const SelectCharacter = ({ setCharacterNFT }) => { return (
-

Mint Your Hero. Save El Barrio.

+

Mint Your Hero.

{characters.length > 0 && (
{renderCharacters()}
)}