# Add Your First Query
In the previous section you added a message that lets you create new games. However, other than dumping the full storage, you cannot retrieve them yet as there is no query type defined. This section fixes that. You will:
- Add a query type to retrieve a game by index.
- Add all the necessary keeper and message server functions.
- Add CLI commands.
Note that you will only create a query to retrieve a single game, not a list of games, which would also be convenient. This other query is more complex and requires pagination.
# Add a game retrieval query
With the game storage indexed by game index, it is only natural to retrieve games by index. It is time to add a query to let anyone fetch games. You are going to:
- Create the query type.
- Compile Protobuf
- Create a query server next to the keeper.
- Handle the query.
- Register the necessary elements in the module.
# The game retrieval object type and Protobuf service
These are defined together in a new file proto/alice/checkers/v1/query.proto
that you create:
Note that the StoredGame
included in the response does not need to include the Index
field as it is implicit over the request's lifecycle.
# Compile Protobuf
Since you have defined a new query type and an associated service
, you should recompile everything:
In the new query.pg.go
(opens new window), you can find type QueryGetGameRequest struct
(opens new window) and type QueryServer interface
(opens new window). Now you can use them closer to the keeper.
# New query server
Create a new file keeper/query_server.go
and take inspiration from minimal-module-example
. It needs to:
- Implement the
GetGame
function. - Return the game if it is found.
- Return no games and no errors if it is not found.
- Return an error otherwise.
Note how the response's Game
is a pointer. This lets you define it as nil
in the case there is no game at the requested index.
With the query server defined, you now need to register it in the module.
# Register the types in the module
Now that you have message types and server, you should register the service in module/module.go
. Inspire yourself from what you find in minimal-module-example
. The lines were previously commented out:
# Add the CLI commands
At this stage, your module is able to handle queries passed to it by the app. But you are not yet able to craft such a query in the first place. When working from the command line, that crafting is handled by the CLI client. The CLI client usually tells you what queries it can create when you run minid query --help
. Go ahead and check:
You can see that checkers
is missing from the list of available commands. Fix that by entering your desired command in module/autocli.go
. Taking inspiration from minimal-module-example
:
Note that the get-game
in "get-game index"
is parsed out and used as the command in the minid query checkers get-game
command-line.
# Test again
Back in the minimal chain, compile to see the command that was added:
Now, you should see the get-game
command:
This time, adding a query did not change your genesis or storage, so you do not need to re-initialize. Start it:
Now query your previously created game:
This returns:
Try to get a non-existent game:
This should return:
Confirm this returned without any error:
This returns:
# Conclusion
You have started creating the first elements of a simple checkers blockchain, one where it is possible to create, and recall, games.
Compared to earlier versions, Cosmos SDK v0.50 allows you to create modules in a more modular and concise way.
If you still want to reduce the amount of work to do, in a way reminiscent of on Rails environments, you can use Ignite CLI. This is what you can learn in the next sections, where Ignite CLI is used to quickly create a checkers blockchain at an earlier (0.45) version of the Cosmos SDK.