# Message Handler - Create and Save a Game Properly
Make sure you have everything you need before proceeding:
- You have Go installed.
- You have the checkers blockchain codebase with
MsgCreateGame
created by Ignite CLI. If not, follow the previous steps and check out the relevant version (opens new window).
In this section, you will:
- Add application rules - the rules of checkers.
- Add a Message Handler to create a game and return its ID.
In the previous section, you added the message to create a game along with its serialization and dedicated gRPC function with the help of Ignite CLI.
However, it does not create a game yet because you have not implemented the message handling. How would you do this?
# Some initial thoughts
Dwell on the following questions to guide you in the exercise:
- How do you sanitize your inputs?
- How do you avoid conflicts with past and future games?
- How do you use your files that implement the Checkers rules?
# Code needs
- No Ignite CLI is involved here, it is just Go.
- Of course, you need to know where to put your code - look for
TODO
. - How would you unit-test this message handling?
- How would you use Ignite CLI to locally run a one-node blockchain and interact with it via the CLI to see what you get?
For now, do not bother with niceties like gas metering or event emission.
You must add code that:
- Creates a brand new game.
- Saves it in storage.
- Returns the ID of the new game.
Ignite CLI isolated this concern into a separate file, x/checkers/keeper/msg_server_create_game.go
, for you to edit:
Ignite CLI has conveniently created all the message processing code for you. You are only required to code the key features.
# Coding steps
Given that you have already done a lot of preparatory work, what coding is involved? How do you replace // TODO: Handling the message
?
First,
rules
represents the ready-made file with the imported rules of the game:
Get the new game's ID with the
Keeper.GetNextGame
(opens new window) function created by theignite scaffold single nextGame...
command:Create the object to be stored:
Note the use of:
- The
rules.New()
(opens new window) command, which is part of the Checkers rules file you imported earlier. - The string content of the
msg *types.MsgCreateGame
, namely.Creator
,.Red
, and.Black
.
- The
Confirm that the values in the object are correct by checking the validity of the players' addresses:
.Creator
,.Red
, and.Black
need to be checked because they were copied as strings. The check on.Creator
is redundant because at this stage the message's signatures have been verified, and the creator is the signer.Save the
StoredGame
object using theKeeper.SetStoredGame
(opens new window) function created by theignite scaffold map storedGame...
command:Prepare the ground for the next game using the
Keeper.SetNextGame
(opens new window) function created by Ignite CLI:Return the newly created ID for reference:
# Unit tests
Try the unit test you prepared in the previous section again:
This should fail with:
Your keeper was initialized with an empty genesis. You must fix that one way or another.
You can fix this by always initializing the keeper with the default genesis. However such a default initialization may not always be desirable. So it is better to keep this default initialization closest to the tests. Copy the setupMsgServer
from msg_server_test.go
(opens new window) into your msg_server_create_game_test.go
. Modify it to also return the keeper:
Note the new import:
Unfortunately, this created an import cycle. To fix that, use the better practice of suffixing _test
to the package of your test files:
You should fix the package in all the (opens new window) other (opens new window) test (opens new window) files (opens new window) in your keeper folder. Afterward, run the tests again with the same command as before:
The error has changed, and you need to adjust the expected value as per the default genesis:
One unit test is good, but you can add more, in particular testing whether the values in storage are as expected when you create a single game:
Or when you create 3 (opens new window) games. Other tests could include whether the get all functionality works as expected after you have created 1 game (opens new window), or 3 (opens new window), or if you create a game in a hypothetical far future (opens new window). Also add games with badly formatted (opens new window) or missing input (opens new window).
# Interact via the CLI
Now you must confirm that the transaction creates a game. Start with:
Send your transaction as you did in the previous section:
A good sign is that the output gas_used
is slightly higher than it was before (gas_used: "50671"
). Confirm the current state:
Now your game is in the blockchain's storage. Notice how bob
was given the black pieces and it is already his turn to play. As a note for the next sections, this is how to understand the board:
Or if placed in a square:
You can also get this in a one-liner:
# Next up
You will modify this handling in the next sections by:
- Adding new fields to the stored information.
- Adding an event.
- Consuming some gas.
- Facilitating the eventual deadline enforcement.
- Adding money handling, including foreign tokens.
Now that a game is created, it is time to play it by adding moves. That is the subject of the next section.