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