Before you start the migration, review the differences between v0.39 and v0.40 and later Stargate modules. This overview shows the differences for modules that are scaffolded with Starport:
One of the key differences is the integration of gRPC and protobuf in your application. Protobufs are an efficient method for serializing messages and the current industry standard.
In theory, you could copy a module from your existing application and make relevant changes based on the information in the App and Modules Migration(opens new window) documentation.
This tutorial uses Starport to generate fresh Stargate-compatible files and migrate the logic from a v0.39 application. You will also change some of the logic to make your application Stargate compatible.
The first step is to inspect the Claim type that is defined in your v0.39 application.
As Creator and ID are both default fields for Starport, we can use the starport type command to create our Claim type while defining the proof as a string -
Copy
$ starport type claim proof:string
🎉 Created a type `claim`.
Once this is done, you should see a few new files added to your application -
Compared to your v0.39 application, the key differences in type scaffolding is the addition of proto/pofe/claim.proto, x/pofe/keeper/grpc_query_claim.go, and x/pofe/types/query_pb.go files.
When you look inside the claim.proto file, you see the following file that contains transaction (tx) messages. It is safe to assume that these transaction messages mutate state.
You will also see a query.proto file, which contains messages used for querying the state of the blockchain. You will notice that there is a gRPC Query service defined.
Copy
// stargate/pofe/proto/pofe/query.proto
syntax ="proto3";package user.pofe.pofe;import"google/api/annotations.proto";import"cosmos/base/query/v1beta1/pagination.proto";// this line is used by starport scaffolding # 1import"pofe/claim.proto";
option go_package ="github.com/user/pofe/x/pofe/types";// Query defines the gRPC querier service.
service Query {// this line is used by starport scaffolding # 2
rpc Claim(QueryGetClaimRequest) returns (QueryGetClaimResponse){
option (google.api.http).get ="/user/pofe/pofe/claim/{id}";}
rpc ClaimAll(QueryAllClaimRequest) returns (QueryAllClaimResponse){
option (google.api.http).get ="/user/pofe/pofe/claim";}}// this line is used by starport scaffolding # 3
message QueryGetClaimRequest {string id =1;}
message QueryGetClaimResponse {
Claim Claim =1;}
message QueryAllClaimRequest {
cosmos.base.query.v1beta1.PageRequest pagination =1;}
message QueryAllClaimResponse {
repeated Claim Claim =1;
cosmos.base.query.v1beta1.PageResponse pagination =2;}
If you are unfamiliar with gRPC, a simple explanation is that each gRPC query is registered with a message structure that it receives, and the message structure of the response. For example, QueryGetClaimRequest would require an string id, and would return a Claim, which is defined in the claim.proto file in the same directory.
As a matter of fact, these messages will be used to generate the messages used in the application. You will notice this in x/pofe/types/claim.pb.go - take for example the Claim type. There will also be a few pre-generated helper functions including getters and marshaling methods for the messages.
Copy
// Code generated by protoc-gen-gogo. DO NOT EDIT.// source: pofe/claim.protopackage types
import(
fmt "fmt"_"github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits")// Reference imports to suppress errors if they are not otherwise used.var_= proto.Marshal
var_= fmt.Errorf
var_= math.Inf
// This is a compile-time assertion to ensure that this generated file// is compatible with the proto package it is being compiled against.// A compilation error at this line likely means your copy of the// proto package needs to be updated.const_= proto.GoGoProtoPackageIsVersion3 // please upgrade the proto packagetype Claim struct{
Creator string`protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"`
Id string`protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
Proof string`protobuf:"bytes,3,opt,name=proof,proto3" json:"proof,omitempty"`}func(m *Claim)Reset(){*m = Claim{}}func(m *Claim)String()string{return proto.CompactTextString(m)}func(*Claim)ProtoMessage(){}func(*Claim)Descriptor()([]byte,[]int){return fileDescriptor_6792804c00432dd8,[]int{0}}func(m *Claim)XXX_Unmarshal(b []byte)error{return m.Unmarshal(b)}func(m *Claim)XXX_Marshal(b []byte, deterministic bool)([]byte,error){if deterministic {return xxx_messageInfo_Claim.Marshal(b, m, deterministic)}else{
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)if err !=nil{returnnil, err
}return b[:n],nil}}func(m *Claim)XXX_Merge(src proto.Message){
xxx_messageInfo_Claim.Merge(m, src)}func(m *Claim)XXX_Size()int{return m.Size()}func(m *Claim)XXX_DiscardUnknown(){
xxx_messageInfo_Claim.DiscardUnknown(m)}var xxx_messageInfo_Claim proto.InternalMessageInfo
func(m *Claim)GetCreator()string{if m !=nil{return m.Creator
}return""}func(m *Claim)GetId()string{if m !=nil{return m.Id
}return""}func(m *Claim)GetProof()string{if m !=nil{return m.Proof
}return""}// MsgCreateClaim, MsgUpdateClaim, MsgDeleteClaim
Note that you can also generate these .pb.go files by running ./scripts/protocgen.
The same concept goes for the query methods - so updating the proto/pofe/query.proto file and running the script will update the contents of types/query.pb.go and query.pb.gw.go.
Now, we can continue to migrate our logic to Stargate!
If we compare the two files, we will notice that there is a difference in how the commands are defined. For instance, the Stargate version of the functions no longer require a codec as an argument - eg. func GetCmdXClaim(cdc *codec.Codec) vs func CmdXClaim(). In this case, we can remove cdc *codec.Codec from each of the functions as well as the "github.com/cosmos/cosmos-sdk/codec" import.
Another difference you will notice is how the application reads CLI commands. This includes reading the command, building the message, and Generating or broadcasting the command. For instance, the contents of the GetCmdCreateClaim command will be updated as such when following the updates generated by Starport and described in further detail here(opens new window).
Throughout this tutorial, you learned how to use Starport to migrate your application from v0.39 to v0.40 and later Stargate. Starport always generates the most up-to-date Cosmos SDK boilerplate code.
Although it is possible to manually change your application code, this tutorial minimizes the changes required to migrate an application. Instead of manually modifying each file that required updates, you migrated only the custom logic that was implemented. The generated boilerplate code also serves as a useful reference to examine the fundamental changes within the application.