From 7a6eee24627390708f209f6eff36df1c03c157e3 Mon Sep 17 00:00:00 2001 From: ccamel Date: Sat, 10 Feb 2024 20:28:39 +0100 Subject: [PATCH] feat(cli): add did output only to show key command --- client/keys/list.go | 16 ++++++----- client/keys/root.go | 16 ++--------- client/keys/show.go | 64 ++++++++++++++++++++++++++++++-------------- client/keys/utils.go | 49 ++++++++++++++++++++------------- 4 files changed, 87 insertions(+), 58 deletions(-) diff --git a/client/keys/list.go b/client/keys/list.go index 49762666..3f636adc 100644 --- a/client/keys/list.go +++ b/client/keys/list.go @@ -5,18 +5,22 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/keys" ) const ( flagListNames = "list-names" + listKeysCmd = "list" ) -// KeyOutput is the output format for keys when listing them. -// It is an improved copy of the KeyOutput from the keys module (github.com/cosmos/cosmos-sdk/client/keys/types.go). -type KeyOutput struct { - keys.KeyOutput - DID string `json:"did,omitempty" yaml:"did"` +// EnhanceListCmd replaces the original 'list' command implementation with our own 'list' command which +// will allow us to list did:key of the keys as well as the original keys. +func EnhanceListCmd(cmd *cobra.Command) { + for _, c := range cmd.Commands() { + if c.Name() == listKeysCmd { + c.RunE = runListCmd + break + } + } } // runListCmd retrieves all keys from the keyring and prints them to the console. diff --git a/client/keys/root.go b/client/keys/root.go index 65294670..7dc803a8 100644 --- a/client/keys/root.go +++ b/client/keys/root.go @@ -4,11 +4,6 @@ import ( "github.com/spf13/cobra" ) -const ( - listKeysCmd = "list" - showKeysCmd = "show" -) - // Enhance augment the given command which is assumed to be the root command of the 'list' command. // It will: // - add the 'did' command. @@ -19,15 +14,8 @@ func Enhance(cmd *cobra.Command) *cobra.Command { DIDCmd(), ) - for _, c := range cmd.Commands() { - switch c.Name() { - case listKeysCmd: - c.RunE = runListCmd - case showKeysCmd: - c.RunE = runShowCmd - default: - } - } + EnhanceListCmd(cmd) + EnhanceShowCmd(cmd) return cmd } diff --git a/client/keys/show.go b/client/keys/show.go index ab4abc95..0b248974 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" + "github.com/samber/lo" "github.com/spf13/cobra" errorsmod "cosmossdk.io/errors" @@ -20,9 +21,25 @@ import ( ) const ( + flagDID = "did" flagMultiSigThreshold = "multisig-threshold" + showKeysCmd = "show" ) +// EnhanceShowCmd replaces the original 'show' command implementation with our own 'show' command which +// will allow us to display the did:key of the key as well as the original key. +func EnhanceShowCmd(cmd *cobra.Command) { + for _, c := range cmd.Commands() { + if c.Name() == showKeysCmd { + c.RunE = runShowCmd + + f := c.Flags() + f.BoolP(flagDID, "k", false, "Output the did:key only (overrides --output)") + break + } + } +} + func runShowCmd(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { @@ -52,11 +69,7 @@ func runShowCmd(cmd *cobra.Command, args []string) error { return err } - if err := processOutput(cmd, clientCtx, keyRecord, bechKeyOut); err != nil { - return err - } - - return nil + return processOutput(cmd, clientCtx, keyRecord, bechKeyOut) } func fetchMultiSigKey(cmd *cobra.Command, clientCtx client.Context, args []string) (*keyring.Record, error) { @@ -85,12 +98,16 @@ func fetchMultiSigKey(cmd *cobra.Command, clientCtx client.Context, args []strin func checkFlagCompatibility(cmd *cobra.Command) error { isShowAddr, _ := cmd.Flags().GetBool(keys.FlagAddress) isShowPubKey, _ := cmd.Flags().GetBool(keys.FlagPublicKey) - if isShowAddr && isShowPubKey { - return errors.New("cannot use both --address and --pubkey at once") + isShowDid, _ := cmd.Flags().GetBool(flagDID) + + nbFlags := lo.Count([]bool{isShowAddr, isShowPubKey, isShowDid}, true) + + if nbFlags > 1 { + return errors.New("cannot use --address, --pubkey and --did at the same time") } isOutputSet := cmd.Flag(flags.FlagOutput) != nil && cmd.Flag(flags.FlagOutput).Changed - if isOutputSet && (isShowAddr || isShowPubKey) { + if isOutputSet && nbFlags > 0 { return errors.New("cannot use --output with --address or --pubkey") } @@ -100,27 +117,34 @@ func checkFlagCompatibility(cmd *cobra.Command) error { func processOutput(cmd *cobra.Command, clientCtx client.Context, k *keyring.Record, bechKeyOut bechKeyOutFn) error { isShowAddr, _ := cmd.Flags().GetBool(keys.FlagAddress) isShowPubKey, _ := cmd.Flags().GetBool(keys.FlagPublicKey) + isShowDid, _ := cmd.Flags().GetBool(flagDID) isShowDevice, _ := cmd.Flags().GetBool(keys.FlagDevice) - if isShowDevice { + switch { + case isShowDevice: return handleDeviceOutput(k) - } - - if isShowAddr || isShowPubKey { + case isShowAddr || isShowPubKey || isShowDid: ko, err := bechKeyOut(k) if err != nil { return err } - out := ko.Address - if isShowPubKey { + out := "" + switch { + case isShowAddr: + out = ko.Address + case isShowPubKey: out = ko.PubKey + case isShowDid: + out = ko.DID } + _, err = fmt.Fprintln(cmd.OutOrStdout(), out) return err - } - outputFormat := clientCtx.OutputFormat - return printKeyringRecord(cmd.OutOrStdout(), k, bechKeyOut, outputFormat) + default: + outputFormat := clientCtx.OutputFormat + return printKeyringRecord(cmd.OutOrStdout(), k, bechKeyOut, outputFormat) + } } func handleDeviceOutput(k *keyring.Record) error { @@ -169,11 +193,11 @@ func validateMultisigThreshold(k, nKeys int) error { func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) { switch bechPrefix { case sdk.PrefixAccount: - return keys.MkAccKeyOutput, nil + return toBechKeyOutFn(keys.MkAccKeyOutput), nil case sdk.PrefixValidator: - return keys.MkValKeyOutput, nil + return toBechKeyOutFn(keys.MkValKeyOutput), nil case sdk.PrefixConsensus: - return keys.MkConsKeyOutput, nil + return toBechKeyOutFn(keys.MkConsKeyOutput), nil } return nil, fmt.Errorf("invalid Bech32 prefix encoding provided: %s", bechPrefix) diff --git a/client/keys/utils.go b/client/keys/utils.go index fbe96826..6f2d62f2 100644 --- a/client/keys/utils.go +++ b/client/keys/utils.go @@ -14,10 +14,18 @@ import ( "github.com/okp4/okp4d/x/logic/util" ) -type bechKeyOutFn func(k *cryptokeyring.Record) (keys.KeyOutput, error) +// KeyOutput is the output format for keys when listing them. +// It is an improved copy of the KeyOutput from the keys module (github.com/cosmos/cosmos-sdk/client/keys/types.go). +type KeyOutput struct { + keys.KeyOutput + DID string `json:"did,omitempty" yaml:"did"` +} + +// bechKeyOutFn is a function that converts a record into a KeyOutput and returns an error if it fails. +type bechKeyOutFn func(k *cryptokeyring.Record) (KeyOutput, error) func printKeyringRecord(w io.Writer, k *cryptokeyring.Record, bechKeyOut bechKeyOutFn, output string) error { - ko, err := mkKeyOutput(k, bechKeyOut) + ko, err := bechKeyOut(k) if err != nil { return err } @@ -83,9 +91,9 @@ func printTextRecords(w io.Writer, kos []KeyOutput) error { func mkKeysOutput(records []*cryptokeyring.Record) ([]KeyOutput, error) { kos := make([]KeyOutput, len(records)) - + bechKeyOut := toBechKeyOutFn(keys.MkAccKeyOutput) for i, r := range records { - kko, err := mkKeyOutput(r, keys.MkAccKeyOutput) + kko, err := bechKeyOut(r) if err != nil { return nil, err } @@ -96,19 +104,24 @@ func mkKeysOutput(records []*cryptokeyring.Record) ([]KeyOutput, error) { return kos, nil } -func mkKeyOutput(record *cryptokeyring.Record, bechKeyOut bechKeyOutFn) (KeyOutput, error) { - kko, err := bechKeyOut(record) - if err != nil { - return KeyOutput{}, err - } - pk, err := record.GetPubKey() - if err != nil { - return KeyOutput{}, err - } - did, _ := util.CreateDIDKeyByPubKey(pk) +// toBechKeyOutFn converts a function that returns a KeyOutput and an error into a function that returns +// an extended KeyOutput and an error. +func toBechKeyOutFn(in func(k *cryptokeyring.Record) (keys.KeyOutput, error)) bechKeyOutFn { + return func(k *cryptokeyring.Record) (KeyOutput, error) { + ko, err := in(k) + if err != nil { + return KeyOutput{}, err + } + + pk, err := k.GetPubKey() + if err != nil { + return KeyOutput{}, err + } + did, _ := util.CreateDIDKeyByPubKey(pk) - return KeyOutput{ - KeyOutput: kko, - DID: did, - }, nil + return KeyOutput{ + KeyOutput: ko, + DID: did, + }, nil + } }