# Add Your First Object
After the previous section, you have a somewhat empty checkers module integrated in a minimal app. It is now time to:
- Add a game storage type.
- Compile Protobuf.
- Add the necessary keeper functions.
# The game rules
A good start to developing a checkers blockchain is to define the rule set of the game. There are many versions of the rules. Choose a very simple set of basic rules (opens new window) to avoid getting lost in the rules of checkers or the proper implementation of the board state.
Use a ready-made implementation (opens new window) with the additional rule that the board is 8x8, is played on black cells, and black plays first. This code will not need adjustments. Copy this rules file into a new rules
folder inside the root folder of your checkers-minimal
module. Change its package from checkers
to rules
. You can do this by command-line:
# A stored game object
With the rules in place, begin with the minimum game information needed to be stored.
# The game object type
You need:
- Index: A string, so it can be identified and retrieved from storage.
- Black player: A string, the serialized address.
- Red player: A string, the serialized address.
- Board proper: A string, the board as it is serialized by the rules file.
- Player to play next: A string, specifying whose turn it is.
When you save strings, it makes it easier to understand what comes straight out of storage but at the expense of storage space. As an advanced consideration, you could store the same information in binary.
As ever, taking inspiration from minimal-module-example
, this can be described in proto/../types.proto
with:
Since Index is used to store and retrieve the stored game, it does not need to be saved to storage. This saves precious storage space.
Compile it:
Now that you have the individual stored game structure, you can define how it is kept in storage.
# The storage structure
The way that makes sense is to keep a map of games in storage (and controled by the keeper), and rely on the SDK's basic structures to optimize saving and retrieving.
However, the genesis takes a list, and in this list, the games need to be identified by their index.
To achieve that, you create a composed type that is used in the genesis state.
Update your GenesisState
in types.proto
:
Now recompile.
# Add validation
You can consider adding functions on the StoredGame
, for instance a Validate
one.
Additionally, you need to:
- Make sure that the
Index
byte count remains within reasonable bounds, for instance less than 256 bytes. - Make sure that the genesis does not pass games with conflicting indices.
Start with a new errors.go
file in the root folder of your checkers-minimal
module and a new stored-game.go
to contain relevant functions:
With these additions, you can validate the games in genesis.go
:
With the basics of genesis and validation handled, shift focus to the keeper to have it handle this storage too.
# Adjust the keeper files
In order to declare the stored games as a map, you first need to define a map key in keys.go
:
Then declare its type in the keeper struct in keeper/keeper.go
:
And then initialize the storage access, taking inspiration from minimal-module-example
:
What this initialization does is explained here (opens new window):
Collections is a library meant to simplify your experience with respect to module state handling.
The codec.CollValue
construct is covered in the documentation (opens new window).
Do not forget the genesis manipulation to and from storage in keeper/genesis.go
, again taking inspiration from minimal-module-example
:
# Test again
Just like you did in the previous section, compile the minimal chain, re-initialize, and start it. You need to re-initialize because your genesis has changed once again:
Now your minimal chain not only has a checkers module, but also a games storage area. After stopping it with CTRL-C, confirm this by calling up:
In there, you can find:
# Up next
You have an on-chain game storage area, but it is empty. In the next section, you will start populating it with the use of a transaction message.