With the storage ready to receive games, it is time to add a message to let players create games:
A game starts with an initial board and turn, as per the rules. The game creator does not choose how the initial pieces are placed.
A game needs an unused index to be created. For simplicity's sake, the index will be passed along with the message.
You are going to:
Create the message type.
Compile Protobuf.
Create a message server next to the keeper.
Handle the message.
Register the necessary elements in the module.
# The game creation object type and Protobuf service
These are defined together in a new file proto/alice/checkers/v1/tx.proto that you create:
Copy
syntax="proto3";package alice.checkers.v1;option go_package ="github.com/alice/checkers";import"cosmos/msg/v1/msg.proto";import"gogoproto/gogo.proto";import"alice/checkers/v1/types.proto";import"cosmos_proto/cosmos.proto";// Msg defines the module Msg service.serviceMsg{option(cosmos.msg.v1.service)=true;// CreateGame create a game.rpcCreateGame(MsgCreateGame)returns(MsgCreateGameResponse);}// MsgCreateGame defines the Msg/CreateGame request type.messageMsgCreateGame{option(cosmos.msg.v1.signer)="creator";// creator is the message sender.string creator =1;string index =2;string black =3[(cosmos_proto.scalar)="cosmos.AddressString"];string red =4[(cosmos_proto.scalar)="cosmos.AddressString"];}// MsgCreateGameResponse defines the Msg/CreateGame response type.messageMsgCreateGameResponse{} proto alice ... v1 tx.proto View source
MsgCreateGame does not mention Board or Turn as this (as mentioned) should not be under the control of the message sender.
The response is empty as there is no extra information to return. For instance, here the game index is known in advance.
option (cosmos.msg.v1.signer) identifies creator as the field that will serve as the signer. At compilation time, the SDK will automagically pick up the value of this annotation to have MsgCreateGame implement sdk.Msg.GetSigners.
Now that you have message types and server, you should register the types in the currently empty codec.go. Inspire yourself from what you find in minimal-module-example:
Copy
package checkers
import( types "github.com/cosmos/cosmos-sdk/codec/types"+ sdk "github.com/cosmos/cosmos-sdk/types"+"github.com/cosmos/cosmos-sdk/types/msgservice")// RegisterInterfaces registers the interfaces types with the interface registry.funcRegisterInterfaces(registry types.InterfaceRegistry){+ registry.RegisterImplementations((*sdk.Msg)(nil),+&MsgCreateGame{},+)+ msgservice.RegisterMsgServiceDesc(registry,&_Msg_serviceDesc)} codec.go View source
In module/module.go, register the new service. The lines were previously commented out:
At this stage, your module is able to handle messages passed to it by the app. However, you are not yet able to craft such messages in the first place. When working from the command line, this crafting is handled by the CLI client. The CLI client usually tells you what messages and transactions it can create when you run minid tx --help. Go ahead and check:
Copy
$ make install
$ minid tx --help
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:
Copy
import( autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"+ checkersv1 "github.com/alice/checkers/api/v1")func(am AppModule)AutoCLIOptions()*autocliv1.ModuleOptions {return&autocliv1.ModuleOptions{ Query:nil,- Tx:nil,+ Tx:&autocliv1.ServiceCommandDescriptor{+ Service: checkersv1.Msg_ServiceDesc.ServiceName,+ RpcCommandOptions:[]*autocliv1.RpcCommandOptions{+{+ RpcMethod:"CreateGame",+ Use:"create index black red",+ Short:"Creates a new checkers game at the index for the black and red players",+ PositionalArgs:[]*autocliv1.PositionalArgDescriptor{+{ProtoField:"index"},+{ProtoField:"black"},+{ProtoField:"red"},+},+},+},+},}} module autocli.go View source
Note that the create in "create index black red" is parsed out and used as the command in the minid tx checkers create command-line.
Back in the minimal chain, compile to see the command that was added:
Copy
$ make install
Now you should see the create command:
Copy
$ minid tx --help
Lists:
Copy
...
checkers Transactions commands for the checkers module
...
Copy
$ minid tx checkers --help
This returns:
Copy
...
Available Commands:
create Creates a new checkers game at the index for the black and red players
...
Copy
$ minid tx checkers create --help
This returns:
Copy
Creates a new checkers game at the index for the black and red players
Usage:
minid tx checkers create index black red [flags]
Flags:
...
Just like you did in the previous section, re-initialize and start it. You need to re-initialize because your genesis has changed once again:
Copy
$ make init
$ minid start
Now create a game from another shell. First list alice and bob's addresses as created by make init:
Copy
$ minid keys list --keyring-backend test
This returns something like:
Copy
- address: mini16ajnus3hhpcsfqem55m5awf3mfwfvhpp36rc7d
name: alice
pubkey: '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A0gUNtXpBqggTdnVICr04GHqIQOa3ZEpjAhn50889AQX"}'
type: local
- address: mini1hv85y6h5rkqxgshcyzpn2zralmmcgnqwsjn3qg
name: bob
pubkey: '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"ArXLlxUs2gEw8+clqPp6YoVNmy36PrJ7aYbV+W8GrcnQ"}'
type: local
With this information, you can send your first create game message:
If you run minid query --help, you can see that there is no checkers in the list of commands. So although you can create games, you cannot retrieve them yet without dumping the whole storage.