cosmos-sdk/x/feegrant/client/cli/tx.go
atheeshp a5128e7618
chore: update feegrant grant description (#10823)
## Description

Closes: #XXXX



---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed 
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
2021-12-22 09:49:02 +00:00

226 lines
6.4 KiB
Go

package cli
import (
"fmt"
"strings"
"time"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/feegrant"
)
// flag for feegrant module
const (
FlagExpiration = "expiration"
FlagPeriod = "period"
FlagPeriodLimit = "period-limit"
FlagSpendLimit = "spend-limit"
FlagAllowedMsgs = "allowed-messages"
)
// GetTxCmd returns the transaction commands for this module
func GetTxCmd() *cobra.Command {
feegrantTxCmd := &cobra.Command{
Use: feegrant.ModuleName,
Short: "Feegrant transactions subcommands",
Long: "Grant and revoke fee allowance for a grantee by a granter",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
feegrantTxCmd.AddCommand(
NewCmdFeeGrant(),
NewCmdRevokeFeegrant(),
)
return feegrantTxCmd
}
// NewCmdFeeGrant returns a CLI command handler for creating a MsgGrantAllowance transaction.
func NewCmdFeeGrant() *cobra.Command {
cmd := &cobra.Command{
Use: "grant [granter_key_or_address] [grantee]",
Short: "Grant Fee allowance to an address",
Long: strings.TrimSpace(
fmt.Sprintf(
`Grant authorization to pay fees from your address. Note, the'--from' flag is
ignored as it is implied from [granter].
Examples:
%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --expiration 2022-01-30T15:04:05Z or
%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --period 3600 --period-limit 10stake --expiration 2022-01-30T15:04:05Z or
%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --expiration 2022-01-30T15:04:05Z
--allowed-messages "/cosmos.gov.v1beta1.MsgSubmitProposal,/cosmos.gov.v1beta1.MsgVote"
`, version.AppName, feegrant.ModuleName, version.AppName, feegrant.ModuleName, version.AppName, feegrant.ModuleName,
),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
cmd.Flags().Set(flags.FlagFrom, args[0])
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
grantee, err := sdk.AccAddressFromBech32(args[1])
if err != nil {
return err
}
granter := clientCtx.GetFromAddress()
sl, err := cmd.Flags().GetString(FlagSpendLimit)
if err != nil {
return err
}
// if `FlagSpendLimit` isn't set, limit will be nil
limit, err := sdk.ParseCoinsNormalized(sl)
if err != nil {
return err
}
exp, err := cmd.Flags().GetString(FlagExpiration)
if err != nil {
return err
}
basic := feegrant.BasicAllowance{
SpendLimit: limit,
}
var expiresAtTime time.Time
if exp != "" {
expiresAtTime, err = time.Parse(time.RFC3339, exp)
if err != nil {
return err
}
basic.Expiration = &expiresAtTime
}
var grant feegrant.FeeAllowanceI
grant = &basic
periodClock, err := cmd.Flags().GetInt64(FlagPeriod)
if err != nil {
return err
}
periodLimitVal, err := cmd.Flags().GetString(FlagPeriodLimit)
if err != nil {
return err
}
// Check any of period or periodLimit flags set, If set consider it as periodic fee allowance.
if periodClock > 0 || periodLimitVal != "" {
periodLimit, err := sdk.ParseCoinsNormalized(periodLimitVal)
if err != nil {
return err
}
if periodClock <= 0 {
return fmt.Errorf("period clock was not set")
}
if periodLimit == nil {
return fmt.Errorf("period limit was not set")
}
periodReset := getPeriodReset(periodClock)
if exp != "" && periodReset.Sub(expiresAtTime) > 0 {
return fmt.Errorf("period (%d) cannot reset after expiration (%v)", periodClock, exp)
}
periodic := feegrant.PeriodicAllowance{
Basic: basic,
Period: getPeriod(periodClock),
PeriodReset: getPeriodReset(periodClock),
PeriodSpendLimit: periodLimit,
PeriodCanSpend: periodLimit,
}
grant = &periodic
}
allowedMsgs, err := cmd.Flags().GetStringSlice(FlagAllowedMsgs)
if err != nil {
return err
}
if len(allowedMsgs) > 0 {
grant, err = feegrant.NewAllowedMsgAllowance(grant, allowedMsgs)
if err != nil {
return err
}
}
msg, err := feegrant.NewMsgGrantAllowance(grant, granter, grantee)
if err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
flags.AddTxFlagsToCmd(cmd)
cmd.Flags().StringSlice(FlagAllowedMsgs, []string{}, "Set of allowed messages for fee allowance")
cmd.Flags().String(FlagExpiration, "", "The RFC 3339 timestamp after which the grant expires for the user")
cmd.Flags().String(FlagSpendLimit, "", "Spend limit specifies the max limit can be used, if not mentioned there is no limit")
cmd.Flags().Int64(FlagPeriod, 0, "period specifies the time duration(in seconds) in which period_limit coins can be spent before that allowance is reset (ex: 3600)")
cmd.Flags().String(FlagPeriodLimit, "", "period limit specifies the maximum number of coins that can be spent in the period")
return cmd
}
// NewCmdRevokeFeegrant returns a CLI command handler for creating a MsgRevokeAllowance transaction.
func NewCmdRevokeFeegrant() *cobra.Command {
cmd := &cobra.Command{
Use: "revoke [granter] [grantee]",
Short: "revoke fee-grant",
Long: strings.TrimSpace(
fmt.Sprintf(`revoke fee grant from a granter to a grantee. Note, the'--from' flag is
ignored as it is implied from [granter].
Example:
$ %s tx %s revoke cosmos1skj.. cosmos1skj..
`, version.AppName, feegrant.ModuleName),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
cmd.Flags().Set(flags.FlagFrom, args[0])
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
grantee, err := sdk.AccAddressFromBech32(args[1])
if err != nil {
return err
}
msg := feegrant.NewMsgRevokeAllowance(clientCtx.GetFromAddress(), grantee)
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlagsToCmd(cmd)
return cmd
}
func getPeriodReset(duration int64) time.Time {
return time.Now().Add(getPeriod(duration))
}
func getPeriod(duration int64) time.Duration {
return time.Duration(duration) * time.Second
}