2019-06-15 05:34:11 -07:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2020-04-04 11:24:11 -07:00
|
|
|
"strings"
|
2019-06-15 05:34:11 -07:00
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/spf13/cobra"
|
2020-06-30 13:59:21 -07:00
|
|
|
"github.com/spf13/pflag"
|
2020-07-10 07:45:46 -07:00
|
|
|
"github.com/tendermint/tendermint/libs/cli"
|
2020-06-30 13:59:21 -07:00
|
|
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
2020-12-11 05:54:50 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
2020-07-07 08:40:46 -07:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2019-06-15 05:34:11 -07:00
|
|
|
)
|
|
|
|
|
2020-07-02 06:02:28 -07:00
|
|
|
// ClientContextKey defines the context key used to retrieve a client.Context from
|
|
|
|
// a command's Context.
|
2020-07-07 08:40:46 -07:00
|
|
|
const ClientContextKey = sdk.ContextKey("client.context")
|
2020-07-02 06:02:28 -07:00
|
|
|
|
|
|
|
// SetCmdClientContextHandler is to be used in a command pre-hook execution to
|
|
|
|
// read flags that populate a Context and sets that to the command's Context.
|
|
|
|
func SetCmdClientContextHandler(clientCtx Context, cmd *cobra.Command) (err error) {
|
|
|
|
clientCtx, err = ReadPersistentCommandFlags(clientCtx, cmd.Flags())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return SetCmdClientContext(cmd, clientCtx)
|
|
|
|
}
|
|
|
|
|
2019-06-15 05:34:11 -07:00
|
|
|
// ValidateCmd returns unknown command error or Help display if help flag set
|
|
|
|
func ValidateCmd(cmd *cobra.Command, args []string) error {
|
2020-04-04 11:24:11 -07:00
|
|
|
var unknownCmd string
|
|
|
|
var skipNext bool
|
2019-06-15 05:34:11 -07:00
|
|
|
|
|
|
|
for _, arg := range args {
|
2020-04-04 11:24:11 -07:00
|
|
|
// search for help flag
|
2019-06-15 05:34:11 -07:00
|
|
|
if arg == "--help" || arg == "-h" {
|
2020-04-04 11:24:11 -07:00
|
|
|
return cmd.Help()
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if the current arg is a flag
|
|
|
|
switch {
|
|
|
|
case len(arg) > 0 && (arg[0] == '-'):
|
|
|
|
// the next arg should be skipped if the current arg is a
|
|
|
|
// flag and does not use "=" to assign the flag's value
|
|
|
|
if !strings.Contains(arg, "=") {
|
|
|
|
skipNext = true
|
|
|
|
} else {
|
|
|
|
skipNext = false
|
|
|
|
}
|
|
|
|
case skipNext:
|
|
|
|
// skip current arg
|
|
|
|
skipNext = false
|
|
|
|
case unknownCmd == "":
|
|
|
|
// unknown command found
|
|
|
|
// continue searching for help flag
|
|
|
|
unknownCmd = arg
|
2019-06-15 05:34:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-04 11:24:11 -07:00
|
|
|
// return the help screen if no unknown command is found
|
|
|
|
if unknownCmd != "" {
|
|
|
|
err := fmt.Sprintf("unknown command \"%s\" for \"%s\"", unknownCmd, cmd.CalledAs())
|
2019-06-15 05:34:11 -07:00
|
|
|
|
|
|
|
// build suggestions for unknown argument
|
2020-04-04 11:24:11 -07:00
|
|
|
if suggestions := cmd.SuggestionsFor(unknownCmd); len(suggestions) > 0 {
|
2019-06-15 05:34:11 -07:00
|
|
|
err += "\n\nDid you mean this?\n"
|
|
|
|
for _, s := range suggestions {
|
|
|
|
err += fmt.Sprintf("\t%v\n", s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return errors.New(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return cmd.Help()
|
|
|
|
}
|
2020-06-30 13:59:21 -07:00
|
|
|
|
|
|
|
// ReadPersistentCommandFlags returns a Context with fields set for "persistent"
|
2020-07-30 09:44:22 -07:00
|
|
|
// or common flags that do not necessarily change with context.
|
|
|
|
//
|
|
|
|
// Note, the provided clientCtx may have field pre-populated. The following order
|
|
|
|
// of precedence occurs:
|
|
|
|
//
|
|
|
|
// - client.Context field not pre-populated & flag not set: uses default flag value
|
|
|
|
// - client.Context field not pre-populated & flag set: uses set flag value
|
|
|
|
// - client.Context field pre-populated & flag not set: uses pre-populated value
|
|
|
|
// - client.Context field pre-populated & flag set: uses set flag value
|
2020-06-30 13:59:21 -07:00
|
|
|
func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, error) {
|
2020-07-30 09:44:22 -07:00
|
|
|
if clientCtx.OutputFormat == "" || flagSet.Changed(cli.OutputFlag) {
|
2020-07-10 07:45:46 -07:00
|
|
|
output, _ := flagSet.GetString(cli.OutputFlag)
|
|
|
|
clientCtx = clientCtx.WithOutputFormat(output)
|
|
|
|
}
|
|
|
|
|
2021-03-18 01:27:03 -07:00
|
|
|
if !clientCtx.Simulate || flagSet.Changed(flags.FlagDryRun) {
|
|
|
|
dryRun, _ := flagSet.GetBool(flags.FlagDryRun)
|
|
|
|
clientCtx = clientCtx.WithSimulation(dryRun)
|
|
|
|
}
|
|
|
|
|
2020-10-08 10:41:35 -07:00
|
|
|
if clientCtx.KeyringDir == "" || flagSet.Changed(flags.FlagKeyringDir) {
|
|
|
|
keyringDir, _ := flagSet.GetString(flags.FlagKeyringDir)
|
|
|
|
|
|
|
|
// The keyring directory is optional and falls back to the home directory
|
|
|
|
// if omitted.
|
|
|
|
if keyringDir == "" {
|
|
|
|
keyringDir = clientCtx.HomeDir
|
|
|
|
}
|
|
|
|
|
|
|
|
clientCtx = clientCtx.WithKeyringDir(keyringDir)
|
|
|
|
}
|
|
|
|
|
2020-07-30 09:44:22 -07:00
|
|
|
if clientCtx.ChainID == "" || flagSet.Changed(flags.FlagChainID) {
|
2020-06-30 13:59:21 -07:00
|
|
|
chainID, _ := flagSet.GetString(flags.FlagChainID)
|
|
|
|
clientCtx = clientCtx.WithChainID(chainID)
|
|
|
|
}
|
|
|
|
|
2020-07-17 13:20:45 -07:00
|
|
|
if clientCtx.Keyring == nil || flagSet.Changed(flags.FlagKeyringBackend) {
|
2020-06-30 13:59:21 -07:00
|
|
|
keyringBackend, _ := flagSet.GetString(flags.FlagKeyringBackend)
|
|
|
|
|
2020-07-17 13:20:45 -07:00
|
|
|
if keyringBackend != "" {
|
2021-03-31 03:04:33 -07:00
|
|
|
kr, err := NewKeyringFromBackend(clientCtx, keyringBackend)
|
2020-07-17 13:20:45 -07:00
|
|
|
if err != nil {
|
|
|
|
return clientCtx, err
|
|
|
|
}
|
2020-06-30 13:59:21 -07:00
|
|
|
|
2020-07-17 13:20:45 -07:00
|
|
|
clientCtx = clientCtx.WithKeyring(kr)
|
|
|
|
}
|
2020-06-30 13:59:21 -07:00
|
|
|
}
|
|
|
|
|
2020-07-17 13:20:45 -07:00
|
|
|
if clientCtx.Client == nil || flagSet.Changed(flags.FlagNode) {
|
2020-06-30 13:59:21 -07:00
|
|
|
rpcURI, _ := flagSet.GetString(flags.FlagNode)
|
2020-07-17 13:20:45 -07:00
|
|
|
if rpcURI != "" {
|
|
|
|
clientCtx = clientCtx.WithNodeURI(rpcURI)
|
2020-10-28 06:31:22 -07:00
|
|
|
|
2021-03-31 03:04:33 -07:00
|
|
|
client, err := NewClientFromNode(rpcURI)
|
2020-10-28 06:31:22 -07:00
|
|
|
if err != nil {
|
|
|
|
return clientCtx, err
|
|
|
|
}
|
|
|
|
|
|
|
|
clientCtx = clientCtx.WithClient(client)
|
2020-07-17 13:20:45 -07:00
|
|
|
}
|
2020-06-30 13:59:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return clientCtx, nil
|
|
|
|
}
|
|
|
|
|
2020-12-14 14:09:51 -08:00
|
|
|
// readQueryCommandFlags returns an updated Context with fields set based on flags
|
2020-07-30 09:44:22 -07:00
|
|
|
// defined in AddQueryFlagsToCmd. An error is returned if any flag query fails.
|
|
|
|
//
|
|
|
|
// Note, the provided clientCtx may have field pre-populated. The following order
|
|
|
|
// of precedence occurs:
|
2020-06-30 13:59:21 -07:00
|
|
|
//
|
2020-07-30 09:44:22 -07:00
|
|
|
// - client.Context field not pre-populated & flag not set: uses default flag value
|
|
|
|
// - client.Context field not pre-populated & flag set: uses set flag value
|
|
|
|
// - client.Context field pre-populated & flag not set: uses pre-populated value
|
|
|
|
// - client.Context field pre-populated & flag set: uses set flag value
|
2020-12-14 14:09:51 -08:00
|
|
|
func readQueryCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, error) {
|
2020-07-30 09:44:22 -07:00
|
|
|
if clientCtx.Height == 0 || flagSet.Changed(flags.FlagHeight) {
|
|
|
|
height, _ := flagSet.GetInt64(flags.FlagHeight)
|
|
|
|
clientCtx = clientCtx.WithHeight(height)
|
|
|
|
}
|
2020-06-30 13:59:21 -07:00
|
|
|
|
2020-07-30 09:44:22 -07:00
|
|
|
if !clientCtx.UseLedger || flagSet.Changed(flags.FlagUseLedger) {
|
|
|
|
useLedger, _ := flagSet.GetBool(flags.FlagUseLedger)
|
|
|
|
clientCtx = clientCtx.WithUseLedger(useLedger)
|
|
|
|
}
|
2020-06-30 13:59:21 -07:00
|
|
|
|
|
|
|
return ReadPersistentCommandFlags(clientCtx, flagSet)
|
|
|
|
}
|
|
|
|
|
2020-12-14 14:09:51 -08:00
|
|
|
// readTxCommandFlags returns an updated Context with fields set based on flags
|
2020-07-30 09:44:22 -07:00
|
|
|
// defined in AddTxFlagsToCmd. An error is returned if any flag query fails.
|
2020-06-30 13:59:21 -07:00
|
|
|
//
|
2020-07-30 09:44:22 -07:00
|
|
|
// Note, the provided clientCtx may have field pre-populated. The following order
|
|
|
|
// of precedence occurs:
|
|
|
|
//
|
|
|
|
// - client.Context field not pre-populated & flag not set: uses default flag value
|
|
|
|
// - client.Context field not pre-populated & flag set: uses set flag value
|
|
|
|
// - client.Context field pre-populated & flag not set: uses pre-populated value
|
|
|
|
// - client.Context field pre-populated & flag set: uses set flag value
|
2020-12-14 14:09:51 -08:00
|
|
|
func readTxCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, error) {
|
2020-06-30 13:59:21 -07:00
|
|
|
clientCtx, err := ReadPersistentCommandFlags(clientCtx, flagSet)
|
|
|
|
if err != nil {
|
|
|
|
return clientCtx, err
|
|
|
|
}
|
|
|
|
|
2020-07-30 09:44:22 -07:00
|
|
|
if !clientCtx.GenerateOnly || flagSet.Changed(flags.FlagGenerateOnly) {
|
|
|
|
genOnly, _ := flagSet.GetBool(flags.FlagGenerateOnly)
|
|
|
|
clientCtx = clientCtx.WithGenerateOnly(genOnly)
|
|
|
|
}
|
2020-06-30 13:59:21 -07:00
|
|
|
|
2020-07-30 09:44:22 -07:00
|
|
|
if !clientCtx.Offline || flagSet.Changed(flags.FlagOffline) {
|
|
|
|
offline, _ := flagSet.GetBool(flags.FlagOffline)
|
|
|
|
clientCtx = clientCtx.WithOffline(offline)
|
|
|
|
}
|
2020-06-30 13:59:21 -07:00
|
|
|
|
2020-07-30 09:44:22 -07:00
|
|
|
if !clientCtx.UseLedger || flagSet.Changed(flags.FlagUseLedger) {
|
|
|
|
useLedger, _ := flagSet.GetBool(flags.FlagUseLedger)
|
|
|
|
clientCtx = clientCtx.WithUseLedger(useLedger)
|
|
|
|
}
|
2020-06-30 13:59:21 -07:00
|
|
|
|
2020-07-30 09:44:22 -07:00
|
|
|
if clientCtx.BroadcastMode == "" || flagSet.Changed(flags.FlagBroadcastMode) {
|
|
|
|
bMode, _ := flagSet.GetString(flags.FlagBroadcastMode)
|
|
|
|
clientCtx = clientCtx.WithBroadcastMode(bMode)
|
|
|
|
}
|
2020-06-30 13:59:21 -07:00
|
|
|
|
2020-07-30 09:44:22 -07:00
|
|
|
if !clientCtx.SkipConfirm || flagSet.Changed(flags.FlagSkipConfirmation) {
|
|
|
|
skipConfirm, _ := flagSet.GetBool(flags.FlagSkipConfirmation)
|
|
|
|
clientCtx = clientCtx.WithSkipConfirmation(skipConfirm)
|
2020-06-30 13:59:21 -07:00
|
|
|
}
|
|
|
|
|
2020-12-11 05:54:50 -08:00
|
|
|
if clientCtx.SignModeStr == "" || flagSet.Changed(flags.FlagSignMode) {
|
|
|
|
signModeStr, _ := flagSet.GetString(flags.FlagSignMode)
|
|
|
|
clientCtx = clientCtx.WithSignModeStr(signModeStr)
|
|
|
|
}
|
|
|
|
|
Add fee grant module (#8061)
* Add docs
* Add BasicFeeAllowance implementation
* Add expiration structs and complete basic fee
* Add delegation messages, add validation logic
* Add keeper and helper structs
* Add alias and handler to top level
* Add delegation module
* Add basic querier
* Add types tests
* Add types tests
* More internal test coverage
* Solid internal test coverage
* Expose Querier to top level module
* Add FeeAccount to auth/types, like StdTx, SignDoc
* Fix all tests in x/auth
* All tests pass
* Appease the Golang Linter
* Add fee-account command line flag
* Start on DelegatedDeductFeeDecorator
* Cleanup the Decorator
* Wire up delegation module in simapp
* add basic test for decorator (no delegation)
* Table tests for deduct fees
* Table tests over all conditions of delegated fee decorator
* Build full ante handler stack and test it
* Start genesis
* Implement Genesis
* Rename package delegation to subkeys
* Clarify antes test cases, handle empty account w/o fees
* Allow paying delegated fees with no account
* Pull mempool into delegated ante, for control on StdFee
* Use custom DelegatedTx, DelegatedFee for subkeys
* Revert all changes to x/auth.StdTx
* Appease scopelint
* Register DelegatedTx with codec
* Address PR comments
* Remove unnecessary DelegatedMempoolFeeDecorator
* Cleaned up errors in querier
* Clean up message sign bytes
* Minor PR comments
* Replace GetAllFees... with Iterator variants
* PrepareForExport adjusts grant expiration height
* Panic on de/serialization error in keeper
* Move custom ante handler chain to tests, update docs
* More cleanup
* More doc cleanup
* Renamed subkeys module to fee_grant
* Rename subkeys/delegation to fee grant in all strings
* Modify Msg and Keeper methods to use Grant not Delegate
* Add PeriodicFeeAllowance
* Update aliases
* Cover all accept cases for PeriodicFeeAllowance
* Et tu scopelint?
* Update docs as requested
* Remove error return from GetFeeGrant
* Code cleanup as requested by PR
* Updated all errors to use new sdk/errors package
* Use test suite for keeper tests
* Clean up alias.go file
* Define expected interfaces in exported, rather than importing from account
* Remove dependency on auth/ante
* Improve godoc, Logger
* Cleaned up ExpiresAt
* Improve error reporting with UseGrantedFee
* Enforce period limit subset of basic limit
* Add events
* Rename fee_grant to feegrant
* Ensure KeeperTestSuite actually runs
* Move types/tx to types
* Update alias file, include ante
* I do need nolint in alias.go
* Properly emit events in the handler. Use cosmos-sdk in amino types
* Update godoc
* Linting...
* Update errors
* Update pkg doc and fix ante-handler order
* Merge PR #5782: Migrate x/feegrant to proto
* fix errors
* proto changes
* proto changes
* fix errors
* fix errors
* genesis state changed to proto
* fix keeper tests
* fix test
* fixed tests
* fix tests
* updated expected keepers
* updated ante tests
* lint
* deleted alias.go
* tx updated to proto tx
* remove explicit signmode
* tests
* Added `cli/query.go`
* Added tx.go in cli
* updated `module.go`
* resolve errors in tx.go
* Add fee payer gentx func
* updated tx
* fixed error
* WIP: cli tests
* fix query error
* fix tests
* Unused types and funcs
* fix tests
* rename helper func to create tx
* remove unused
* update tx cfg
* fix cli tests
* added simulations
* Add `decoder.go`
* fix build fail
* added init genesis code
* update tx.go
* fixed LGTM alert
* modified cli
* remove gogoproto extensions
* change acc address type to string
* lint
* fix simulations
* Add gen simulations
* remove legacy querier
* remove legacy code
* add grpc queries tests
* fix simulations
* update module.go
* lint
* register feegrant NewSimulationManager
* fix sims
* fix sims
* add genesis test
* add periodic grant
* updated cmd
* changed times
* updated flags
* removed days as period clock
* added condition for period and exp
* add periodic fee cli tests
* udpated tests
* fix lint
* fix tests
* fix sims
* renaming to `fee_grant`
* review changes
* fix test
* add condition for duplicate grants
* fix tests
* add `genTxWithFeeGranter` in tests
* fix simulation
* one of changes & test fixes
* fix test
* fix lint
* changed package name `feegrant` to `fee_grant`
* review comments
* review changes
* review change
* review changes
* added fee-account in flags
* address review changes
* read fee granter from cli
* updated create account with mnemonic
* Address review comments
* move `simapp/ante` file to `feegrant/ante`
* update keeper logic to create account
* update docs
* fix tests
* update `serviceMsgClientConn` from `msgservice`
* review changes
* add test case for using more fees than allowed
* eliminate panic checks from keeper
* fix lint
* change store keys string to bytes
* fix tests
* review changes
* review changes
* udpate docs
* make spend limit optional
* fix tests
* fix tests
* review changes
* add norace tag
* proto-docs
* add docs
Co-authored-by: Ethan Frey <ethanfrey@users.noreply.github.com>
Co-authored-by: Alexander Bezobchuk <alexanderbez@users.noreply.github.com>
Co-authored-by: Aleksandr Bezobchuk <aleks.bezobchuk@gmail.com>
Co-authored-by: SaReN <sahithnarahari@gmail.com>
Co-authored-by: aleem1413 <aleem@vitwit.com>
Co-authored-by: MD Aleem <72057206+aleem1314@users.noreply.github.com>
Co-authored-by: Anil Kumar Kammari <anil@vitwit.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2021-01-29 11:54:51 -08:00
|
|
|
if clientCtx.FeeGranter == nil || flagSet.Changed(flags.FlagFeeAccount) {
|
|
|
|
granter, _ := flagSet.GetString(flags.FlagFeeAccount)
|
|
|
|
|
|
|
|
if granter != "" {
|
|
|
|
granterAcc, err := sdk.AccAddressFromBech32(granter)
|
|
|
|
if err != nil {
|
|
|
|
return clientCtx, err
|
|
|
|
}
|
|
|
|
|
|
|
|
clientCtx = clientCtx.WithFeeGranterAddress(granterAcc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-30 09:44:22 -07:00
|
|
|
if clientCtx.From == "" || flagSet.Changed(flags.FlagFrom) {
|
|
|
|
from, _ := flagSet.GetString(flags.FlagFrom)
|
2020-12-11 05:54:50 -08:00
|
|
|
fromAddr, fromName, keyType, err := GetFromFields(clientCtx.Keyring, from, clientCtx.GenerateOnly)
|
2020-07-30 09:44:22 -07:00
|
|
|
if err != nil {
|
|
|
|
return clientCtx, err
|
|
|
|
}
|
|
|
|
|
|
|
|
clientCtx = clientCtx.WithFrom(from).WithFromAddress(fromAddr).WithFromName(fromName)
|
2020-12-11 05:54:50 -08:00
|
|
|
|
|
|
|
// If the `from` signer account is a ledger key, we need to use
|
|
|
|
// SIGN_MODE_AMINO_JSON, because ledger doesn't support proto yet.
|
|
|
|
// ref: https://github.com/cosmos/cosmos-sdk/issues/8109
|
|
|
|
if keyType == keyring.TypeLedger && clientCtx.SignModeStr != flags.SignModeLegacyAminoJSON {
|
|
|
|
fmt.Println("Default sign-mode 'direct' not supported by Ledger, using sign-mode 'amino-json'.")
|
|
|
|
clientCtx = clientCtx.WithSignModeStr(flags.SignModeLegacyAminoJSON)
|
|
|
|
}
|
2020-07-30 09:44:22 -07:00
|
|
|
}
|
2020-06-30 13:59:21 -07:00
|
|
|
|
|
|
|
return clientCtx, nil
|
|
|
|
}
|
2020-07-02 06:02:28 -07:00
|
|
|
|
2021-09-09 13:22:55 -07:00
|
|
|
// ReadHomeFlag checks if home flag is changed. If this is a case, we update
|
|
|
|
// HomeDir field of Client Context.
|
2021-03-31 03:04:33 -07:00
|
|
|
func ReadHomeFlag(clientCtx Context, cmd *cobra.Command) Context {
|
|
|
|
if cmd.Flags().Changed(flags.FlagHome) {
|
|
|
|
rootDir, _ := cmd.Flags().GetString(flags.FlagHome)
|
|
|
|
clientCtx = clientCtx.WithHomeDir(rootDir)
|
|
|
|
}
|
|
|
|
|
|
|
|
return clientCtx
|
|
|
|
}
|
|
|
|
|
2020-12-14 14:09:51 -08:00
|
|
|
// GetClientQueryContext returns a Context from a command with fields set based on flags
|
|
|
|
// defined in AddQueryFlagsToCmd. An error is returned if any flag query fails.
|
|
|
|
//
|
|
|
|
// - client.Context field not pre-populated & flag not set: uses default flag value
|
|
|
|
// - client.Context field not pre-populated & flag set: uses set flag value
|
|
|
|
// - client.Context field pre-populated & flag not set: uses pre-populated value
|
|
|
|
// - client.Context field pre-populated & flag set: uses set flag value
|
|
|
|
func GetClientQueryContext(cmd *cobra.Command) (Context, error) {
|
|
|
|
ctx := GetClientContextFromCmd(cmd)
|
|
|
|
return readQueryCommandFlags(ctx, cmd.Flags())
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetClientTxContext returns a Context from a command with fields set based on flags
|
|
|
|
// defined in AddTxFlagsToCmd. An error is returned if any flag query fails.
|
|
|
|
//
|
|
|
|
// - client.Context field not pre-populated & flag not set: uses default flag value
|
|
|
|
// - client.Context field not pre-populated & flag set: uses set flag value
|
|
|
|
// - client.Context field pre-populated & flag not set: uses pre-populated value
|
|
|
|
// - client.Context field pre-populated & flag set: uses set flag value
|
|
|
|
func GetClientTxContext(cmd *cobra.Command) (Context, error) {
|
|
|
|
ctx := GetClientContextFromCmd(cmd)
|
|
|
|
return readTxCommandFlags(ctx, cmd.Flags())
|
|
|
|
}
|
|
|
|
|
2020-07-02 06:02:28 -07:00
|
|
|
// GetClientContextFromCmd returns a Context from a command or an empty Context
|
|
|
|
// if it has not been set.
|
|
|
|
func GetClientContextFromCmd(cmd *cobra.Command) Context {
|
|
|
|
if v := cmd.Context().Value(ClientContextKey); v != nil {
|
|
|
|
clientCtxPtr := v.(*Context)
|
|
|
|
return *clientCtxPtr
|
|
|
|
}
|
|
|
|
|
|
|
|
return Context{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetCmdClientContext sets a command's Context value to the provided argument.
|
|
|
|
func SetCmdClientContext(cmd *cobra.Command, clientCtx Context) error {
|
|
|
|
v := cmd.Context().Value(ClientContextKey)
|
|
|
|
if v == nil {
|
|
|
|
return errors.New("client context not set")
|
|
|
|
}
|
|
|
|
|
|
|
|
clientCtxPtr := v.(*Context)
|
|
|
|
*clientCtxPtr = clientCtx
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|