Building a Full-Stack Tendermint & Cosmos SDK Application (Part 5): Integrating Cosmos SDK Modules
This is the fifth post in a series showing how to build a blockchain application using Tendermint platform & Cosmos-SDK. This blog post will discuss how to include an Cosmos-SDK module into your own application. The link to the previous post is here.
The Cosmos-SDK comes with a set of existing modules, implementing various important features in the blockchain ecosystem, ready to be integrated into our application. Some of them are:
- Auth — provides storage and management of user accounts
- Bank — allows maintaining balances and transferring different tokens
- Staking — implements a Delegated Proof of Stake
- Slashing — adds slashing feature to DPoS
- Governance — implements on-chain governance
- Mint — a utility to mint new tokens to arbitrary account
For our example tic-tac-toe app, we decided to use the auth module. It provides the implementation of user accounts and token balances. To showcase how to manage this, we will expand the functionality of our game to allow the players to bet a certain amount of tokens. The winner takes all of the tokens for himself.
The first thing to do when integrating with a module is to check its API. The API calls of the auth module that are interesting to us are the following:
- GetAccount — this returns the user account for a given address. If the account does not exist, it returns nil
- GetCoins — this account’s method returns current balance for every token
- SetCoins — this allows us to set a certain amount of tokens for a given account
- SetAccount — allows us to save a change that happened to an account
Having investigated the API, we can decide that the best way to implement this is to do the following:
- When a game is started, the amount of coins invested is deducted immediately from both accounts, if they both have enough. The state change is applied immediately.
- When a game is terminated, the winner’s balance is increased by the total amount invested
Obviously, this approach has some flows:
- The invitee has its balance reduced even if he has no desire to play the game whatsoever
- A single player can freeze both balances by simply not playing
These flows can be fixed, but for the sake of example and simplicity, we will not do that here.
So let’s see the implementation.
The modules are integrated together through their keepers. Each keeper holds the keepers of the modules it depends on. Hence our keeper will now look like this
Notice the accountKeeper field.
The MsgStartGame will contain an additional field, called Amount which holds the token count that are invested for the given game.
At the beginning of StartGame method that we showed in the previous post, we will add the following code:
It does a few things:
- First it ensures that both accounts exist in the case that the amount of tokens betted is not zero. If we don’t have accounts we cannot bet tokens
- It checks the tokens balance of both accounts, making sure they both have enough
- It subtracts the balances
- Save the new balances by calls to SetCoins and SetAccount
The second part of the logic is kicked off once there is a winner. In the method Play that we already showed in a previous post, at the end we add the following if statement and method call:
Method distributeReward looks like this:
At this point in time we do not need to ensure the validity of the state before doing any action, since we had done all of that at the beginning of the game. The only thing left to do is to update the winner account with the new, increased balance, and save it properly.
Integrating any module into the application structure consists of the following steps in our application:
- Its keys for key-value storage subdomains need to be instantiated and mounted
- Its keeper needs to be instantiated and passed to the keepers of other modules that depend on it — in our case only to tic-tac-toe keeper
- Its types need to be registered with Cosmos-SDK codec
The integration looks like this:
After doing this, and implementing the small but required changes in the CLI, handler, etc, regarding the amount field, we are ready to invest tokens to play tic-tac-toe!
In the next blog post we will demonstrate how we can actually build and run this