cosmos-sdk/client/keys/parse.go
Forostovec 2264024679
chore: remove dead String() methods in keys parse command (#25387)
Co-authored-by: Alex | Cosmos Labs <alex@cosmoslabs.io>
2025-10-07 11:32:09 -04:00

139 lines
3.0 KiB
Go

package keys
import (
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"strings"
"github.com/spf13/cobra"
"sigs.k8s.io/yaml"
"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/bech32"
)
func bech32Prefixes(config *sdk.Config) []string {
return []string{
config.GetBech32AccountAddrPrefix(),
config.GetBech32AccountPubPrefix(),
config.GetBech32ValidatorAddrPrefix(),
config.GetBech32ValidatorPubPrefix(),
config.GetBech32ConsensusAddrPrefix(),
config.GetBech32ConsensusPubPrefix(),
}
}
type hexOutput struct {
Human string `json:"human"`
Bytes string `json:"bytes"`
}
func newHexOutput(human string, bs []byte) hexOutput {
return hexOutput{Human: human, Bytes: fmt.Sprintf("%X", bs)}
}
type bech32Output struct {
Formats []string `json:"formats"`
}
func newBech32Output(config *sdk.Config, bs []byte) bech32Output {
bech32Prefixes := bech32Prefixes(config)
out := bech32Output{Formats: make([]string, len(bech32Prefixes))}
for i, prefix := range bech32Prefixes {
bech32Addr, err := bech32.ConvertAndEncode(prefix, bs)
if err != nil {
panic(err)
}
out.Formats[i] = bech32Addr
}
return out
}
// ParseKeyStringCommand parses an address from hex to bech32 and vice versa.
func ParseKeyStringCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "parse <hex-or-bech32-address>",
Short: "Parse address from hex to bech32 and vice versa",
Long: `Convert and print to stdout key addresses and fingerprints from
hexadecimal into bech32 cosmos prefixed format and vice versa.
`,
Args: cobra.ExactArgs(1),
RunE: parseKey,
}
return cmd
}
func parseKey(cmd *cobra.Command, args []string) error {
config, _ := sdk.GetSealedConfig(cmd.Context())
return doParseKey(cmd, config, args)
}
func doParseKey(cmd *cobra.Command, config *sdk.Config, args []string) error {
addr := strings.TrimSpace(args[0])
outstream := cmd.OutOrStdout()
if len(addr) == 0 {
return errors.New("couldn't parse empty input")
}
output, _ := cmd.Flags().GetString(flags.FlagOutput)
if !runFromBech32(outstream, addr, output) && !runFromHex(config, outstream, addr, output) {
return errors.New("couldn't find valid bech32 nor hex data")
}
return nil
}
// print info from bech32
func runFromBech32(w io.Writer, bech32str, output string) bool {
hrp, bz, err := bech32.DecodeAndConvert(bech32str)
if err != nil {
return false
}
displayParseKeyInfo(w, newHexOutput(hrp, bz), output)
return true
}
// print info from hex
func runFromHex(config *sdk.Config, w io.Writer, hexstr, output string) bool {
bz, err := hex.DecodeString(hexstr)
if err != nil {
return false
}
displayParseKeyInfo(w, newBech32Output(config, bz), output)
return true
}
func displayParseKeyInfo(w io.Writer, value any, output string) {
var (
err error
out []byte
)
switch output {
case flags.OutputFormatText:
out, err = yaml.Marshal(&value)
case flags.OutputFormatJSON:
out, err = json.Marshal(&value)
}
if err != nil {
panic(err)
}
_, _ = fmt.Fprintln(w, string(out))
}