Table of Contents
Recap
In part one I outlined the idea for a Tennis Manager simulation game on the Ethereum Blockchain. I created the ERC721 Token and the TrainableTennisPlayer
contract which enables owners to increase their player stats by training or resting.
Part two walked through the introduction of the CompetingTennisPlayer
contract, responsible for calculating the winners of matches between players.
Since then, Iโve written unit tests for those contracts. They are by no means complete, but I wanted to try building out a usable group of contracts as soon as possible to test out a basic front. If youโd like to help out with testing and building the application, check out the Github repo.
Iโve also altered the TennisPlayerBase
contract to extend ERC721Enumerable
, instead of the standard ERC721
token provided by Openzeppelin. This enables our game to retrieve all tokens owned by an address using _tokensOfOwner(address)
. Implementing this means not requiring the user to remember their token ID every time they log in.
As I mentioned in the previous article, Iโm looking forward to getting a rudimentary interface up and running to start interacting with the game.
Pulling It Together
Figure 1 shows a diagram of the contracts after the previous installment.
I want the game Dapp accessible through as few Smart Contracts as possible, so the front-end code doesnโt get too complicated. Hence the reason for SomethingHere
.
Iโve created a contract in place of SomethingHere
is called TennisPlayer
. This is shown in the following code.
Notice how myPlayers()
on line 9 uses the _tokensOfOwner()
function inherited from ERC721Enumerable
. As mentioned earlier, this allows the front-end to load all players owned by the user.
Creating New Players
In part one, I created the newPlayer()
function in TennisPlayerBase
with the custom access modifier onlyOwner
(inherited from Openzeppelinโs Ownable
contract). This means that only the owner of the token can create new players, and no one else. It has to be this way if the game is to be in control of setting the starting attributes of new players. Otherwise, a user can create a new player and max out the stats on immediately.
For this to work, we need an overarching Game
smart contract which itself creates the TennisPlayer
ERC721 token contract when it is deployed, hence becoming the owner.
The following smart contract which does this, Game.sol.
Notice the default attribute values from lines 11 to 16. Every new player starts with these. In the future, an element of randomness could be introduced so each new player has slightly different strengths and weaknesses. (although randomness is a sticking point)
The smart contract also stores an address called publicTokenAddress
representing the location of our ERC721 token on line 9. This is retrieved by the constructor when the token is created on line 19.
The newPlayer()
function is exposed publically on line 22, taking only the name, age, and height of the new player from the user. This is the entry point into the game Dapp.
At this stage, users can create new players through the Game
contract, and interact with functions in TennisPlayer
to train rest and compete against other players. This seems like a great place to start building the front end.
Front End
Truffle suite provides a bunch of Truffle boxes that come packaged with a framework of your choice. Iโm using the React box, with Redux (which I added in myself).
To enable our DApp to interact with the game, the Redux store needs to hold information about the Blockchain itโs connecting too, the Smart Contracts, and the account being used by the user.
I use this pattern to ensure all of this gets loaded correctly. Initially, it can look a bit overkill, but if something goes wrong in the loading phase, it helps to visualize it.
Displaying Players
To display all the players owned by the user, the DApp needs to call the myPlayers()
function in the TennisPlayer
contract, and store the results in the Redux store. From there, the component can select the data, and display it on the page.
Iโve written a component responsible for this called PlayerList
, shown in the following code.
PlayerList
renders a Bootstrap card with a title, a list of players, and a form to create a new player. Without any players, it looks like Figure 7, and once a player is created by the user, the list displays the ID, shown in figure 8.
This list is selectable. By clicking an item in the list the DApp retrieves the details of the player and stores them in the Redux store.
Displaying Player Details
Another component called PlayerDetails
is responsible for selecting player details from the Redux store and displaying them on the page.
The following shows the code for the PlayerDetails
component.
This component renders another Bootstrap card, and when active looks like Figure 10.
Pulled all together, Figure 11 shows the front end in its current state. Very basic, very clunky, and nowhere near finished. It doesnโt yet implement all of the features available in the Smart Contracts, but itโs a good start.
Next Steps
This project is in active development. At the time of writing, the current state of the code is as described in this article.
I want to be able to train, rest and compete with players against each other through the interface as soon as possible. Training and resting are going to be the next features I work on since they only require one player, where competing requires at least two so is slightly more compilated.
Once all available Smart Contract features are supported, Iโll look to expand the match logic, or jazz up the front-end to make it look more enticing and game-like.
Thereโs still a long way to go, but getting the full stack working together is a big step!
The code repo is on Github so itโs public and open to pull requests. If youโre interested in helping out please to contribute! Here is the repo.
Further Reading
If you want to learn more about the Crypto ecosystem, sign up for the weekly newsletter.