Table of Contents
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
CompetingTennisPlayercontract, 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
I’ve created a contract in place of
SomethingHere is called
TennisPlayer. This is shown in the following code.
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.
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.
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.
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
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.
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.
If you want to learn more about the Crypto ecosystem, sign up for the weekly newsletter.