package cli import ( "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" "github.com/cosmos/cosmos-sdk/x/gov" "github.com/pkg/errors" ) const ( flagProposalID = "proposalID" flagTitle = "title" flagDescription = "description" flagProposalType = "type" flagDeposit = "deposit" flagProposer = "proposer" flagDepositer = "depositer" flagVoter = "voter" flagOption = "option" ) // submit a proposal tx func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "submit-proposal", Short: "Submit a proposal along with an initial deposit", RunE: func(cmd *cobra.Command, args []string) error { title := viper.GetString(flagTitle) description := viper.GetString(flagDescription) strProposalType := viper.GetString(flagProposalType) initialDeposit := viper.GetString(flagDeposit) // get the from address from the name flag from, err := sdk.GetAccAddressBech32(viper.GetString(flagProposer)) if err != nil { return err } amount, err := sdk.ParseCoins(initialDeposit) if err != nil { return err } proposalType, err := gov.StringToProposalType(strProposalType) if err != nil { return err } // create the message msg := gov.NewMsgSubmitProposal(title, description, proposalType, from, amount) err = msg.ValidateBasic() if err != nil { return err } // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } fmt.Printf("Committed at block:%d. Hash:%s.Response:%+v \n", res.Height, res.Hash.String(), res.DeliverTx) return nil }, } cmd.Flags().String(flagTitle, "", "title of proposal") cmd.Flags().String(flagDescription, "", "description of proposal") cmd.Flags().String(flagProposalType, "", "proposalType of proposal") cmd.Flags().String(flagDeposit, "", "deposit of proposal") cmd.Flags().String(flagProposer, "", "proposer of proposal") return cmd } // set a new Deposit transaction func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "deposit", Short: "deposit tokens for activing proposal", RunE: func(cmd *cobra.Command, args []string) error { // get the from address from the name flag depositer, err := sdk.GetAccAddressBech32(viper.GetString(flagDepositer)) if err != nil { return err } proposalID := viper.GetInt64(flagProposalID) amount, err := sdk.ParseCoins(viper.GetString(flagDeposit)) if err != nil { return err } // create the message msg := gov.NewMsgDeposit(depositer, proposalID, amount) err = msg.ValidateBasic() if err != nil { return err } // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } cmd.Flags().String(flagProposalID, "", "proposalID of proposal depositing on") cmd.Flags().String(flagDepositer, "", "depositer of deposit") cmd.Flags().String(flagDeposit, "", "amount of deposit") return cmd } // set a new Vote transaction func GetCmdVote(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "vote", Short: "vote for an active proposal, options: Yes/No/NoWithVeto/Abstain", RunE: func(cmd *cobra.Command, args []string) error { bechVoter := viper.GetString(flagVoter) voter, err := sdk.GetAccAddressBech32(bechVoter) if err != nil { return err } proposalID := viper.GetInt64(flagProposalID) option := viper.GetString(flagOption) byteVoteOption, err := gov.StringToVoteOption(option) if err != nil { return err } // create the message msg := gov.NewMsgVote(voter, proposalID, byteVoteOption) err = msg.ValidateBasic() if err != nil { return err } fmt.Printf("Vote[Voter:%s,ProposalID:%d,Option:%s]", bechVoter, msg.ProposalID, gov.VoteOptionToString(msg.Option)) // build and sign the transaction, then broadcast to Tendermint ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc)) res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil }, } cmd.Flags().String(flagProposalID, "", "proposalID of proposal voting on") cmd.Flags().String(flagVoter, "", "bech32 voter address") cmd.Flags().String(flagOption, "", "vote option {Yes, No, NoWithVeto, Abstain}") return cmd } // Command to Get a Proposal Information func GetCmdQueryProposal(storeName string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "query-proposal", Short: "query proposal details", RunE: func(cmd *cobra.Command, args []string) error { proposalID := viper.GetInt64(flagProposalID) ctx := context.NewCoreContextFromViper() res, err := ctx.QueryStore(gov.KeyProposal(proposalID), storeName) if len(res) == 0 || err != nil { return errors.Errorf("proposalID [%d] is not existed", proposalID) } var proposal gov.Proposal cdc.MustUnmarshalBinary(res, &proposal) proposalRest := gov.ProposalToRest(proposal) output, err := wire.MarshalJSONIndent(cdc, proposalRest) if err != nil { return err } fmt.Println(string(output)) return nil }, } cmd.Flags().String(flagProposalID, "", "proposalID of proposal being queried") return cmd } // Command to Get a Proposal Information func GetCmdQueryVote(storeName string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "query-vote", Short: "query vote", RunE: func(cmd *cobra.Command, args []string) error { proposalID := viper.GetInt64(flagProposalID) voterAddr, err := sdk.GetAccAddressBech32(viper.GetString(flagVoter)) if err != nil { return err } ctx := context.NewCoreContextFromViper() res, err := ctx.QueryStore(gov.KeyVote(proposalID, voterAddr), storeName) if len(res) == 0 || err != nil { return errors.Errorf("proposalID [%d] does not exist", proposalID) } var vote gov.Vote cdc.MustUnmarshalBinary(res, &vote) voteRest := gov.VoteToRest(vote) output, err := wire.MarshalJSONIndent(cdc, voteRest) if err != nil { return err } fmt.Println(string(output)) return nil }, } cmd.Flags().String(flagProposalID, "", "proposalID of proposal voting on") cmd.Flags().String(flagVoter, "", "bech32 voter address") return cmd }