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  }