github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/distribution/client/cli/tx.go (about) 1 // nolint 2 package cli 3 4 import ( 5 "bufio" 6 "fmt" 7 "strings" 8 9 "github.com/spf13/cobra" 10 "github.com/spf13/viper" 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/client/flags" 15 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 16 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 17 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/version" 18 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth" 19 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/client/utils" 20 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/gov" 21 22 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/distribution/client/common" 23 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/distribution/types" 24 ) 25 26 var ( 27 flagOnlyFromValidator = "only-from-validator" 28 flagIsValidator = "is-validator" 29 flagCommission = "commission" 30 flagMaxMessagesPerTx = "max-msgs" 31 ) 32 33 const ( 34 MaxMessagesPerTxDefault = 5 35 ) 36 37 // GetTxCmd returns the transaction commands for this module 38 func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { 39 distTxCmd := &cobra.Command{ 40 Use: types.ModuleName, 41 Short: "Distribution transactions subcommands", 42 DisableFlagParsing: true, 43 SuggestionsMinimumDistance: 2, 44 RunE: client.ValidateCmd, 45 } 46 47 distTxCmd.AddCommand(flags.PostCommands( 48 GetCmdWithdrawRewards(cdc), 49 GetCmdSetWithdrawAddr(cdc), 50 GetCmdWithdrawAllRewards(cdc, storeKey), 51 GetCmdFundCommunityPool(cdc), 52 )...) 53 54 return distTxCmd 55 } 56 57 type generateOrBroadcastFunc func(context.CLIContext, auth.TxBuilder, []sdk.Msg) error 58 59 func splitAndApply( 60 generateOrBroadcast generateOrBroadcastFunc, 61 cliCtx context.CLIContext, 62 txBldr auth.TxBuilder, 63 msgs []sdk.Msg, 64 chunkSize int, 65 ) error { 66 67 if chunkSize == 0 { 68 return generateOrBroadcast(cliCtx, txBldr, msgs) 69 } 70 71 // split messages into slices of length chunkSize 72 totalMessages := len(msgs) 73 for i := 0; i < len(msgs); i += chunkSize { 74 75 sliceEnd := i + chunkSize 76 if sliceEnd > totalMessages { 77 sliceEnd = totalMessages 78 } 79 80 msgChunk := msgs[i:sliceEnd] 81 if err := generateOrBroadcast(cliCtx, txBldr, msgChunk); err != nil { 82 return err 83 } 84 } 85 86 return nil 87 } 88 89 // command to withdraw rewards 90 func GetCmdWithdrawRewards(cdc *codec.Codec) *cobra.Command { 91 cmd := &cobra.Command{ 92 Use: "withdraw-rewards [validator-addr]", 93 Short: "Withdraw rewards from a given delegation address, and optionally withdraw validator commission if the delegation address given is a validator operator", 94 Long: strings.TrimSpace( 95 fmt.Sprintf(`Withdraw rewards from a given delegation address, 96 and optionally withdraw validator commission if the delegation address given is a validator operator. 97 98 Example: 99 $ %s tx distribution withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj --from mykey 100 $ %s tx distribution withdraw-rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj --from mykey --commission 101 `, 102 version.ClientName, version.ClientName, 103 ), 104 ), 105 Args: cobra.ExactArgs(1), 106 RunE: func(cmd *cobra.Command, args []string) error { 107 inBuf := bufio.NewReader(cmd.InOrStdin()) 108 txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) 109 cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc) 110 111 delAddr := cliCtx.GetFromAddress() 112 valAddr, err := sdk.ValAddressFromBech32(args[0]) 113 if err != nil { 114 return err 115 } 116 117 msgs := []sdk.Msg{types.NewMsgWithdrawDelegatorReward(delAddr, valAddr)} 118 if viper.GetBool(flagCommission) { 119 msgs = append(msgs, types.NewMsgWithdrawValidatorCommission(valAddr)) 120 } 121 122 return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, msgs) 123 }, 124 } 125 cmd.Flags().Bool(flagCommission, false, "withdraw validator's commission") 126 return cmd 127 } 128 129 // command to withdraw all rewards 130 func GetCmdWithdrawAllRewards(cdc *codec.Codec, queryRoute string) *cobra.Command { 131 cmd := &cobra.Command{ 132 Use: "withdraw-all-rewards", 133 Short: "withdraw all delegations rewards for a delegator", 134 Long: strings.TrimSpace( 135 fmt.Sprintf(`Withdraw all rewards for a single delegator. 136 137 Example: 138 $ %s tx distribution withdraw-all-rewards --from mykey 139 `, 140 version.ClientName, 141 ), 142 ), 143 Args: cobra.NoArgs, 144 RunE: func(cmd *cobra.Command, args []string) error { 145 inBuf := bufio.NewReader(cmd.InOrStdin()) 146 txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) 147 cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc) 148 149 delAddr := cliCtx.GetFromAddress() 150 151 // The transaction cannot be generated offline since it requires a query 152 // to get all the validators. 153 if cliCtx.GenerateOnly { 154 return fmt.Errorf("command disabled with the provided flag: %s", flags.FlagGenerateOnly) 155 } 156 157 msgs, err := common.WithdrawAllDelegatorRewards(cliCtx, queryRoute, delAddr) 158 if err != nil { 159 return err 160 } 161 162 chunkSize := viper.GetInt(flagMaxMessagesPerTx) 163 return splitAndApply(utils.GenerateOrBroadcastMsgs, cliCtx, txBldr, msgs, chunkSize) 164 }, 165 } 166 167 cmd.Flags().Int(flagMaxMessagesPerTx, MaxMessagesPerTxDefault, "Limit the number of messages per tx (0 for unlimited)") 168 return cmd 169 } 170 171 // command to replace a delegator's withdrawal address 172 func GetCmdSetWithdrawAddr(cdc *codec.Codec) *cobra.Command { 173 return &cobra.Command{ 174 Use: "set-withdraw-addr [withdraw-addr]", 175 Short: "change the default withdraw address for rewards associated with an address", 176 Long: strings.TrimSpace( 177 fmt.Sprintf(`Set the withdraw address for rewards associated with a delegator address. 178 179 Example: 180 $ %s tx distribution set-withdraw-addr cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p --from mykey 181 `, 182 version.ClientName, 183 ), 184 ), 185 Args: cobra.ExactArgs(1), 186 RunE: func(cmd *cobra.Command, args []string) error { 187 188 inBuf := bufio.NewReader(cmd.InOrStdin()) 189 txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) 190 cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc) 191 192 delAddr := cliCtx.GetFromAddress() 193 withdrawAddr, err := sdk.AccAddressFromBech32(args[0]) 194 if err != nil { 195 return err 196 } 197 198 msg := types.NewMsgSetWithdrawAddress(delAddr, withdrawAddr) 199 return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) 200 }, 201 } 202 } 203 204 // GetCmdSubmitProposal implements the command to submit a community-pool-spend proposal 205 func GetCmdSubmitProposal(cdc *codec.Codec) *cobra.Command { 206 cmd := &cobra.Command{ 207 Use: "community-pool-spend [proposal-file]", 208 Args: cobra.ExactArgs(1), 209 Short: "Submit a community pool spend proposal", 210 Long: strings.TrimSpace( 211 fmt.Sprintf(`Submit a community pool spend proposal along with an initial deposit. 212 The proposal details must be supplied via a JSON file. 213 214 Example: 215 $ %s tx gov submit-proposal community-pool-spend <path/to/proposal.json> --from=<key_or_address> 216 217 Where proposal.json contains: 218 219 { 220 "title": "Community Pool Spend", 221 "description": "Pay me some Atoms!", 222 "recipient": "cosmos1s5afhd6gxevu37mkqcvvsj8qeylhn0rz46zdlq", 223 "amount": [ 224 { 225 "denom": "stake", 226 "amount": "10000" 227 } 228 ], 229 "deposit": [ 230 { 231 "denom": "stake", 232 "amount": "10000" 233 } 234 ] 235 } 236 `, 237 version.ClientName, 238 ), 239 ), 240 RunE: func(cmd *cobra.Command, args []string) error { 241 inBuf := bufio.NewReader(cmd.InOrStdin()) 242 txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) 243 cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc) 244 245 proposal, err := ParseCommunityPoolSpendProposalJSON(cdc, args[0]) 246 if err != nil { 247 return err 248 } 249 250 from := cliCtx.GetFromAddress() 251 content := types.NewCommunityPoolSpendProposal(proposal.Title, proposal.Description, proposal.Recipient, proposal.Amount) 252 253 msg := gov.NewMsgSubmitProposal(content, proposal.Deposit, from) 254 if err := msg.ValidateBasic(); err != nil { 255 return err 256 } 257 258 return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) 259 }, 260 } 261 262 return cmd 263 } 264 265 // GetCmdFundCommunityPool returns a command implementation that supports directly 266 // funding the community pool. 267 func GetCmdFundCommunityPool(cdc *codec.Codec) *cobra.Command { 268 return &cobra.Command{ 269 Use: "fund-community-pool [amount]", 270 Args: cobra.ExactArgs(1), 271 Short: "Funds the community pool with the specified amount", 272 Long: strings.TrimSpace( 273 fmt.Sprintf(`Funds the community pool with the specified amount 274 275 Example: 276 $ %s tx distribution fund-community-pool 100uatom --from mykey 277 `, 278 version.ClientName, 279 ), 280 ), 281 RunE: func(cmd *cobra.Command, args []string) error { 282 inBuf := bufio.NewReader(cmd.InOrStdin()) 283 txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) 284 cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc) 285 286 depositorAddr := cliCtx.GetFromAddress() 287 amount, err := sdk.ParseCoins(args[0]) 288 if err != nil { 289 return err 290 } 291 292 msg := types.NewMsgFundCommunityPool(amount, depositorAddr) 293 if err := msg.ValidateBasic(); err != nil { 294 return err 295 } 296 297 return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) 298 }, 299 } 300 }