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:
Verifies input sanity.
Creates a brand new game.
Saves it in storage.
Returns the ID of the new game.
For input sanity, your code can only accept or reject a message. You cannot fix a message, as that would change its content and break the signature. However, remember that your application is called via ABCI's CheckTx for each transaction that it receives. It is at this point that your application can statelessly sanitize inputs. For each message type, Ignite CLI isolates this concern into a ValidateBasic function:
What is a well-formatted MsgCreateGame? Eventually, you want the black and red players to be able to play moves. They will send and sign transactions for that. So, at the very least, you can check that the addresses passed are valid:
You should not try to check whether they have enough tokens to play as that would be a stateful check. Stateful checks are handled as part of the message handling behind ACBI's DeliverTx.
Copy
systemInfo, found := k.Keeper.GetSystemInfo(ctx)if!found {panic("SystemInfo not found")}
newIndex := strconv.FormatUint(systemInfo.NextId,10) x checkers keeper msg_server_create_game.go View source
You panic if you cannot find the SystemInfo object because there is no way to continue if it is not there. It is not like a user error, which would warrant returning an error.
.Red, and .Black need to be checked because they were copied as strings. You do not need to check .Creator because at this stage the message's signatures have been verified, and the creator is the signer.
Note that by returning an error, instead of calling panic, players cannot stall your blockchain. They can still spam but at a cost, because they will still pay the gas fee up to this point.
To test your additions to the message's ValidateBasic, you can simply add cases to the existing message_create_game_test.go(opens new window). You can verify that your additions have made the existing test fail:
Copy
$ go test github.com/alice/checkers/x/checkers/types
Copy
$ docker run --rm -it \
-v $(pwd):/checkers \
-w /checkers \
checkers_i \
go test github.com/alice/checkers/x/checkers/types
This should return:
Copy
--- FAIL: TestMsgCreateGame_ValidateBasic (0.00s)
--- FAIL: TestMsgCreateGame_ValidateBasic/valid_address (0.00s)
message_create_game_test.go:37:
Error Trace: /Users/alice/checkers/x/checkers/types/message_create_game_test.go:37
Error: Received unexpected error:
github.com/alice/checkers/x/checkers/types.(*MsgCreateGame).ValidateBasic
/Users/alice/checkers/x/checkers/types/message_create_game.go:50
github.com/alice/checkers/x/checkers/types.TestMsgCreateGame_ValidateBasic.func1
/Users/alice/checkers/x/checkers/types/message_create_game_test.go:32
invalid black address (empty address string is not allowed): invalid address
Test: TestMsgCreateGame_ValidateBasic/valid_address
First, change the file's package to types_test for consistency:
Moving on to the keeper, try the unit test you prepared in the previous section again:
Copy
$ go test github.com/alice/checkers/x/checkers/keeper
Copy
$ docker run --rm -it \
-v $(pwd):/checkers \
-w /checkers \
checkers_i \
go test github.com/alice/checkers/x/checkers/keeper
This should fail with:
Copy
panic: SystemInfo not found [recovered]
panic: SystemInfo not found
...
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:
A first good sign is that the output gas_used is slightly higher than it was before (gas_used: "52498"). After the transaction has been validated, confirm the current state.
Now your game is in the blockchain's storage. Notice how alice was given the black pieces and it is already her turn to play. As a note for the next sections, this is how to understand the board: