2018-09-04 23:41:17 -07:00
// nolint
package cli
import (
2019-05-18 16:06:08 -07:00
"fmt"
2019-02-06 16:15:37 -08:00
"strings"
2018-09-04 23:41:17 -07:00
2018-09-19 16:00:21 -07:00
"github.com/spf13/cobra"
2018-11-19 09:02:34 -08:00
"github.com/cosmos/cosmos-sdk/client"
2019-12-23 08:05:47 -08:00
"github.com/cosmos/cosmos-sdk/client/flags"
2020-05-21 14:29:34 -07:00
"github.com/cosmos/cosmos-sdk/client/tx"
2018-09-04 23:41:17 -07:00
sdk "github.com/cosmos/cosmos-sdk/types"
2019-05-18 16:06:08 -07:00
"github.com/cosmos/cosmos-sdk/version"
2019-02-04 16:45:18 -08:00
"github.com/cosmos/cosmos-sdk/x/distribution/client/common"
2018-09-19 21:53:48 -07:00
"github.com/cosmos/cosmos-sdk/x/distribution/types"
2020-06-13 02:07:51 -07:00
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
2018-09-04 23:41:17 -07:00
)
var (
flagOnlyFromValidator = "only-from-validator"
flagIsValidator = "is-validator"
2019-11-13 01:20:13 -08:00
flagCommission = "commission"
2019-05-23 16:00:26 -07:00
flagMaxMessagesPerTx = "max-msgs"
)
const (
MaxMessagesPerTxDefault = 5
2018-09-04 23:41:17 -07:00
)
2020-04-08 08:05:14 -07:00
// NewTxCmd returns a root CLI command handler for all x/distribution transaction commands.
2020-06-01 05:46:03 -07:00
func NewTxCmd ( clientCtx client . Context ) * cobra . Command {
2020-04-08 08:05:14 -07:00
distTxCmd := & cobra . Command {
Use : types . ModuleName ,
Short : "Distribution transactions subcommands" ,
DisableFlagParsing : true ,
SuggestionsMinimumDistance : 2 ,
RunE : client . ValidateCmd ,
}
distTxCmd . AddCommand ( flags . PostCommands (
2020-06-01 05:46:03 -07:00
NewWithdrawRewardsCmd ( clientCtx ) ,
NewWithdrawAllRewardsCmd ( clientCtx ) ,
NewSetWithdrawAddrCmd ( clientCtx ) ,
NewFundCommunityPoolCmd ( clientCtx ) ,
2020-04-08 08:05:14 -07:00
) ... )
return distTxCmd
}
2020-06-01 05:46:03 -07:00
type newGenerateOrBroadcastFunc func ( clientCtx client . Context , msgs ... sdk . Msg ) error
2020-04-08 08:05:14 -07:00
func newSplitAndApply (
newGenerateOrBroadcast newGenerateOrBroadcastFunc ,
2020-06-01 05:46:03 -07:00
clientCtx client . Context ,
2020-04-08 08:05:14 -07:00
msgs [ ] sdk . Msg ,
chunkSize int ,
) error {
if chunkSize == 0 {
2020-06-01 05:46:03 -07:00
return newGenerateOrBroadcast ( clientCtx , msgs ... )
2020-04-08 08:05:14 -07:00
}
// split messages into slices of length chunkSize
totalMessages := len ( msgs )
for i := 0 ; i < len ( msgs ) ; i += chunkSize {
sliceEnd := i + chunkSize
if sliceEnd > totalMessages {
sliceEnd = totalMessages
}
msgChunk := msgs [ i : sliceEnd ]
2020-06-01 05:46:03 -07:00
if err := newGenerateOrBroadcast ( clientCtx , msgChunk ... ) ; err != nil {
2020-04-08 08:05:14 -07:00
return err
}
}
return nil
}
2020-06-01 05:46:03 -07:00
func NewWithdrawRewardsCmd ( clientCtx client . Context ) * cobra . Command {
2020-04-08 08:05:14 -07:00
cmd := & cobra . Command {
Use : "withdraw-rewards [validator-addr]" ,
Short : "Withdraw rewards from a given delegation address, and optionally withdraw validator commission if the delegation address given is a validator operator" ,
Long : strings . TrimSpace (
fmt . Sprintf ( ` Withdraw rewards from a given delegation address ,
and optionally withdraw validator commission if the delegation address given is a validator operator .
Example :
$ % s tx distribution withdraw - rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj -- from mykey
$ % s tx distribution withdraw - rewards cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj -- from mykey -- commission
` ,
version . ClientName , version . ClientName ,
) ,
) ,
Args : cobra . ExactArgs ( 1 ) ,
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2020-06-01 05:46:03 -07:00
clientCtx := clientCtx . InitWithInput ( cmd . InOrStdin ( ) )
2020-04-08 08:05:14 -07:00
2020-06-01 05:46:03 -07:00
delAddr := clientCtx . GetFromAddress ( )
2020-04-08 08:05:14 -07:00
valAddr , err := sdk . ValAddressFromBech32 ( args [ 0 ] )
if err != nil {
return err
}
msgs := [ ] sdk . Msg { types . NewMsgWithdrawDelegatorReward ( delAddr , valAddr ) }
2020-07-06 03:12:00 -07:00
if commission , _ := cmd . Flags ( ) . GetBool ( flagCommission ) ; commission {
2020-04-08 08:05:14 -07:00
msgs = append ( msgs , types . NewMsgWithdrawValidatorCommission ( valAddr ) )
}
for _ , msg := range msgs {
if err := msg . ValidateBasic ( ) ; err != nil {
return err
}
}
2020-06-01 05:46:03 -07:00
return tx . GenerateOrBroadcastTx ( clientCtx , msgs ... )
2020-04-08 08:05:14 -07:00
} ,
}
2020-07-06 03:12:00 -07:00
2020-04-08 08:05:14 -07:00
cmd . Flags ( ) . Bool ( flagCommission , false , "also withdraw validator's commission" )
2020-05-21 14:29:34 -07:00
return cmd
2020-04-08 08:05:14 -07:00
}
2020-06-01 05:46:03 -07:00
func NewWithdrawAllRewardsCmd ( clientCtx client . Context ) * cobra . Command {
2020-04-08 08:05:14 -07:00
cmd := & cobra . Command {
Use : "withdraw-all-rewards" ,
Short : "withdraw all delegations rewards for a delegator" ,
Long : strings . TrimSpace (
fmt . Sprintf ( ` Withdraw all rewards for a single delegator .
Example :
$ % s tx distribution withdraw - all - rewards -- from mykey
` ,
version . ClientName ,
) ,
) ,
Args : cobra . NoArgs ,
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2020-06-01 05:46:03 -07:00
clientCtx := clientCtx . InitWithInput ( cmd . InOrStdin ( ) )
2020-04-08 08:05:14 -07:00
2020-06-01 05:46:03 -07:00
delAddr := clientCtx . GetFromAddress ( )
2020-04-08 08:05:14 -07:00
// The transaction cannot be generated offline since it requires a query
// to get all the validators.
2020-06-01 05:46:03 -07:00
if clientCtx . Offline {
2020-04-08 08:05:14 -07:00
return fmt . Errorf ( "cannot generate tx in offline mode" )
}
2020-06-01 05:46:03 -07:00
msgs , err := common . WithdrawAllDelegatorRewards ( clientCtx , types . QuerierRoute , delAddr )
2020-04-08 08:05:14 -07:00
if err != nil {
return err
}
2020-07-06 03:12:00 -07:00
chunkSize , _ := cmd . Flags ( ) . GetInt ( flagMaxMessagesPerTx )
2020-06-01 05:46:03 -07:00
return newSplitAndApply ( tx . GenerateOrBroadcastTx , clientCtx , msgs , chunkSize )
2020-04-08 08:05:14 -07:00
} ,
}
2020-06-09 03:18:44 -07:00
cmd . Flags ( ) . Int ( flagMaxMessagesPerTx , MaxMessagesPerTxDefault , "Limit the number of messages per tx (0 for unlimited)" )
2020-05-21 14:29:34 -07:00
return cmd
2020-04-08 08:05:14 -07:00
}
2020-06-01 05:46:03 -07:00
func NewSetWithdrawAddrCmd ( clientCtx client . Context ) * cobra . Command {
2020-04-08 08:05:14 -07:00
cmd := & cobra . Command {
Use : "set-withdraw-addr [withdraw-addr]" ,
Short : "change the default withdraw address for rewards associated with an address" ,
Long : strings . TrimSpace (
fmt . Sprintf ( ` Set the withdraw address for rewards associated with a delegator address .
Example :
$ % s tx distribution set - withdraw - addr cosmos1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p -- from mykey
` ,
version . ClientName ,
) ,
) ,
Args : cobra . ExactArgs ( 1 ) ,
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2020-06-01 05:46:03 -07:00
clientCtx := clientCtx . InitWithInput ( cmd . InOrStdin ( ) )
2020-04-08 08:05:14 -07:00
2020-06-01 05:46:03 -07:00
delAddr := clientCtx . GetFromAddress ( )
2020-04-08 08:05:14 -07:00
withdrawAddr , err := sdk . AccAddressFromBech32 ( args [ 0 ] )
if err != nil {
return err
}
msg := types . NewMsgSetWithdrawAddress ( delAddr , withdrawAddr )
if err := msg . ValidateBasic ( ) ; err != nil {
return err
}
2020-06-01 05:46:03 -07:00
return tx . GenerateOrBroadcastTx ( clientCtx , msg )
2020-04-08 08:05:14 -07:00
} ,
}
2020-05-21 14:29:34 -07:00
return cmd
2020-04-08 08:05:14 -07:00
}
2020-06-01 05:46:03 -07:00
func NewFundCommunityPoolCmd ( clientCtx client . Context ) * cobra . Command {
2020-04-08 08:05:14 -07:00
cmd := & cobra . Command {
2020-06-09 03:18:44 -07:00
Use : "fund-community-pool [amount]" ,
2020-04-08 08:05:14 -07:00
Args : cobra . ExactArgs ( 1 ) ,
2020-06-09 03:18:44 -07:00
Short : "Funds the community pool with the specified amount" ,
2020-04-08 08:05:14 -07:00
Long : strings . TrimSpace (
2020-06-09 03:18:44 -07:00
fmt . Sprintf ( ` Funds the community pool with the specified amount
2020-04-08 08:05:14 -07:00
Example :
2020-06-09 03:18:44 -07:00
$ % s tx distribution fund - community - pool 100 uatom -- from mykey
2020-04-08 08:05:14 -07:00
` ,
version . ClientName ,
) ,
) ,
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2020-06-01 05:46:03 -07:00
clientCtx := clientCtx . InitWithInput ( cmd . InOrStdin ( ) )
2020-04-08 08:05:14 -07:00
2020-06-01 05:46:03 -07:00
depositorAddr := clientCtx . GetFromAddress ( )
2020-04-08 08:05:14 -07:00
amount , err := sdk . ParseCoins ( args [ 0 ] )
if err != nil {
return err
}
msg := types . NewMsgFundCommunityPool ( amount , depositorAddr )
if err := msg . ValidateBasic ( ) ; err != nil {
return err
}
2020-06-01 05:46:03 -07:00
return tx . GenerateOrBroadcastTx ( clientCtx , msg )
2019-02-04 16:45:18 -08:00
} ,
}
2020-06-09 03:18:44 -07:00
2019-05-23 16:00:26 -07:00
return cmd
2019-02-04 16:45:18 -08:00
}
2019-05-21 03:02:10 -07:00
// GetCmdSubmitProposal implements the command to submit a community-pool-spend proposal
2020-06-01 05:46:03 -07:00
func GetCmdSubmitProposal ( clientCtx client . Context ) * cobra . Command {
2019-05-21 03:02:10 -07:00
cmd := & cobra . Command {
Use : "community-pool-spend [proposal-file]" ,
Args : cobra . ExactArgs ( 1 ) ,
Short : "Submit a community pool spend proposal" ,
Long : strings . TrimSpace (
fmt . Sprintf ( ` Submit a community pool spend proposal along with an initial deposit .
The proposal details must be supplied via a JSON file .
Example :
$ % s tx gov submit - proposal community - pool - spend < path / to / proposal . json > -- from = < key_or_address >
Where proposal . json contains :
{
"title" : "Community Pool Spend" ,
"description" : "Pay me some Atoms!" ,
"recipient" : "cosmos1s5afhd6gxevu37mkqcvvsj8qeylhn0rz46zdlq" ,
2020-03-11 10:06:39 -07:00
"amount" : "1000stake" ,
"deposit" : "1000stake"
2019-05-21 03:02:10 -07:00
}
` ,
version . ClientName ,
) ,
) ,
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2020-06-01 05:46:03 -07:00
clientCtx := clientCtx . InitWithInput ( cmd . InOrStdin ( ) )
2019-05-21 03:02:10 -07:00
2020-06-01 05:46:03 -07:00
proposal , err := ParseCommunityPoolSpendProposalJSON ( clientCtx . JSONMarshaler , args [ 0 ] )
2019-05-21 03:02:10 -07:00
if err != nil {
return err
}
2020-06-01 05:46:03 -07:00
from := clientCtx . GetFromAddress ( )
2019-05-21 03:02:10 -07:00
2020-03-11 10:03:47 -07:00
amount , err := sdk . ParseCoins ( proposal . Amount )
if err != nil {
return err
}
content := types . NewCommunityPoolSpendProposal ( proposal . Title , proposal . Description , proposal . Recipient , amount )
deposit , err := sdk . ParseCoins ( proposal . Deposit )
if err != nil {
return err
}
2020-06-13 02:07:51 -07:00
msg , err := govtypes . NewMsgSubmitProposal ( content , deposit , from )
2020-05-19 13:17:29 -07:00
if err != nil {
return err
}
2019-05-21 03:02:10 -07:00
if err := msg . ValidateBasic ( ) ; err != nil {
return err
}
2020-06-01 05:46:03 -07:00
return tx . GenerateOrBroadcastTx ( clientCtx , msg )
2019-05-21 03:02:10 -07:00
} ,
}
return cmd
}