github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/gov/client/cli/tx.go (about) 1 package cli 2 3 import ( 4 "bufio" 5 "fmt" 6 "strconv" 7 "strings" 8 9 "github.com/spf13/cobra" 10 11 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client" 12 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/context" 13 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/flags" 14 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 15 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 16 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/version" 17 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth" 18 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/client/utils" 19 govutils "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/gov/client/utils" 20 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/gov/types" 21 ) 22 23 // Proposal flags 24 const ( 25 FlagTitle = "title" 26 FlagDescription = "description" 27 flagProposalType = "type" 28 FlagDeposit = "deposit" 29 flagVoter = "voter" 30 flagDepositor = "depositor" 31 flagStatus = "status" 32 FlagProposal = "proposal" 33 ) 34 35 type proposal struct { 36 Title string 37 Description string 38 Type string 39 Deposit string 40 } 41 42 // ProposalFlags defines the core required fields of a proposal. It is used to 43 // verify that these values are not provided in conjunction with a JSON proposal 44 // file. 45 var ProposalFlags = []string{ 46 FlagTitle, 47 FlagDescription, 48 flagProposalType, 49 FlagDeposit, 50 } 51 52 // GetTxCmd returns the transaction commands for this module 53 // governance ModuleClient is slightly different from other ModuleClients in that 54 // it contains a slice of "proposal" child commands. These commands are respective 55 // to proposal type handlers that are implemented in other modules but are mounted 56 // under the governance CLI (eg. parameter change proposals). 57 func GetTxCmd(storeKey string, cdc *codec.Codec, pcmds []*cobra.Command) *cobra.Command { 58 govTxCmd := &cobra.Command{ 59 Use: types.ModuleName, 60 Short: "Governance transactions subcommands", 61 DisableFlagParsing: true, 62 SuggestionsMinimumDistance: 2, 63 RunE: client.ValidateCmd, 64 } 65 66 cmdSubmitProp := GetCmdSubmitProposal(cdc) 67 for _, pcmd := range pcmds { 68 cmdSubmitProp.AddCommand(flags.PostCommands(pcmd)[0]) 69 } 70 71 govTxCmd.AddCommand(flags.PostCommands( 72 GetCmdDeposit(cdc), 73 GetCmdVote(cdc), 74 cmdSubmitProp, 75 )...) 76 77 return govTxCmd 78 } 79 80 // GetCmdSubmitProposal implements submitting a proposal transaction command. 81 func GetCmdSubmitProposal(cdc *codec.Codec) *cobra.Command { 82 cmd := &cobra.Command{ 83 Use: "submit-proposal", 84 Short: "Submit a proposal along with an initial deposit", 85 Long: strings.TrimSpace( 86 fmt.Sprintf(`Submit a proposal along with an initial deposit. 87 Proposal title, description, type and deposit can be given directly or through a proposal JSON file. 88 89 Example: 90 $ %s tx gov submit-proposal --proposal="path/to/proposal.json" --from mykey 91 92 Where proposal.json contains: 93 94 { 95 "title": "Test Proposal", 96 "description": "My awesome proposal", 97 "type": "Text", 98 "deposit": "10test" 99 } 100 101 Which is equivalent to: 102 103 $ %s tx gov submit-proposal --title="Test Proposal" --description="My awesome proposal" --type="Text" --deposit="10test" --from mykey 104 `, 105 version.ClientName, version.ClientName, 106 ), 107 ), 108 RunE: func(cmd *cobra.Command, args []string) error { 109 inBuf := bufio.NewReader(cmd.InOrStdin()) 110 txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) 111 cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc) 112 113 proposal, err := parseSubmitProposalFlags() 114 if err != nil { 115 return err 116 } 117 118 amount, err := sdk.ParseCoins(proposal.Deposit) 119 if err != nil { 120 return err 121 } 122 123 content := types.ContentFromProposalType(proposal.Title, proposal.Description, proposal.Type) 124 125 msg := types.NewMsgSubmitProposal(content, amount, cliCtx.GetFromAddress()) 126 if err := msg.ValidateBasic(); err != nil { 127 return err 128 } 129 130 return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) 131 }, 132 } 133 134 cmd.Flags().String(FlagTitle, "", "title of proposal") 135 cmd.Flags().String(FlagDescription, "", "description of proposal") 136 cmd.Flags().String(flagProposalType, "", "proposalType of proposal, types: text/parameter_change/software_upgrade") 137 cmd.Flags().String(FlagDeposit, "", "deposit of proposal") 138 cmd.Flags().String(FlagProposal, "", "proposal file path (if this path is given, other proposal flags are ignored)") 139 140 return cmd 141 } 142 143 // GetCmdDeposit implements depositing tokens for an active proposal. 144 func GetCmdDeposit(cdc *codec.Codec) *cobra.Command { 145 return &cobra.Command{ 146 Use: "deposit [proposal-id] [deposit]", 147 Args: cobra.ExactArgs(2), 148 Short: "Deposit tokens for an active proposal", 149 Long: strings.TrimSpace( 150 fmt.Sprintf(`Submit a deposit for an active proposal. You can 151 find the proposal-id by running "%s query gov proposals". 152 153 Example: 154 $ %s tx gov deposit 1 10stake --from mykey 155 `, 156 version.ClientName, version.ClientName, 157 ), 158 ), 159 RunE: func(cmd *cobra.Command, args []string) error { 160 inBuf := bufio.NewReader(cmd.InOrStdin()) 161 txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) 162 cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc) 163 164 // validate that the proposal id is a uint 165 proposalID, err := strconv.ParseUint(args[0], 10, 64) 166 if err != nil { 167 return fmt.Errorf("proposal-id %s not a valid uint, please input a valid proposal-id", args[0]) 168 } 169 170 // Get depositor address 171 from := cliCtx.GetFromAddress() 172 173 // Get amount of coins 174 amount, err := sdk.ParseCoins(args[1]) 175 if err != nil { 176 return err 177 } 178 179 msg := types.NewMsgDeposit(from, proposalID, amount) 180 err = msg.ValidateBasic() 181 if err != nil { 182 return err 183 } 184 185 return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) 186 }, 187 } 188 } 189 190 // GetCmdVote implements creating a new vote command. 191 func GetCmdVote(cdc *codec.Codec) *cobra.Command { 192 return &cobra.Command{ 193 Use: "vote [proposal-id] [option]", 194 Args: cobra.ExactArgs(2), 195 Short: "Vote for an active proposal, options: yes/no/no_with_veto/abstain", 196 Long: strings.TrimSpace( 197 fmt.Sprintf(`Submit a vote for an active proposal. You can 198 find the proposal-id by running "%s query gov proposals". 199 200 201 Example: 202 $ %s tx gov vote 1 yes --from mykey 203 `, 204 version.ClientName, version.ClientName, 205 ), 206 ), 207 RunE: func(cmd *cobra.Command, args []string) error { 208 inBuf := bufio.NewReader(cmd.InOrStdin()) 209 txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) 210 cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc) 211 212 // Get voting address 213 from := cliCtx.GetFromAddress() 214 215 // validate that the proposal id is a uint 216 proposalID, err := strconv.ParseUint(args[0], 10, 64) 217 if err != nil { 218 return fmt.Errorf("proposal-id %s not a valid int, please input a valid proposal-id", args[0]) 219 } 220 221 // Find out which vote option user chose 222 byteVoteOption, err := types.VoteOptionFromString(govutils.NormalizeVoteOption(args[1])) 223 if err != nil { 224 return err 225 } 226 227 // Build vote message and run basic validation 228 msg := types.NewMsgVote(from, proposalID, byteVoteOption) 229 err = msg.ValidateBasic() 230 if err != nil { 231 return err 232 } 233 234 return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) 235 }, 236 } 237 } 238 239 // DONTCOVER