github.com/cosmos/cosmos-sdk@v0.50.10/client/keys/parse.go (about) 1 package keys 2 3 import ( 4 "encoding/hex" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "io" 9 "strings" 10 11 "github.com/spf13/cobra" 12 "sigs.k8s.io/yaml" 13 14 "github.com/cosmos/cosmos-sdk/client/flags" 15 sdk "github.com/cosmos/cosmos-sdk/types" 16 "github.com/cosmos/cosmos-sdk/types/bech32" 17 ) 18 19 func bech32Prefixes(config *sdk.Config) []string { 20 return []string{ 21 config.GetBech32AccountAddrPrefix(), 22 config.GetBech32AccountPubPrefix(), 23 config.GetBech32ValidatorAddrPrefix(), 24 config.GetBech32ValidatorPubPrefix(), 25 config.GetBech32ConsensusAddrPrefix(), 26 config.GetBech32ConsensusPubPrefix(), 27 } 28 } 29 30 type hexOutput struct { 31 Human string `json:"human"` 32 Bytes string `json:"bytes"` 33 } 34 35 func (ho hexOutput) String() string { 36 return fmt.Sprintf("Human readable part: %v\nBytes (hex): %s", ho.Human, ho.Bytes) 37 } 38 39 func newHexOutput(human string, bs []byte) hexOutput { 40 return hexOutput{Human: human, Bytes: fmt.Sprintf("%X", bs)} 41 } 42 43 type bech32Output struct { 44 Formats []string `json:"formats"` 45 } 46 47 func newBech32Output(config *sdk.Config, bs []byte) bech32Output { 48 bech32Prefixes := bech32Prefixes(config) 49 out := bech32Output{Formats: make([]string, len(bech32Prefixes))} 50 51 for i, prefix := range bech32Prefixes { 52 bech32Addr, err := bech32.ConvertAndEncode(prefix, bs) 53 if err != nil { 54 panic(err) 55 } 56 57 out.Formats[i] = bech32Addr 58 } 59 60 return out 61 } 62 63 func (bo bech32Output) String() string { 64 out := make([]string, len(bo.Formats)) 65 66 for i, format := range bo.Formats { 67 out[i] = fmt.Sprintf(" - %s", format) 68 } 69 70 return fmt.Sprintf("Bech32 Formats:\n%s", strings.Join(out, "\n")) 71 } 72 73 // ParseKeyStringCommand parses an address from hex to bech32 and vice versa. 74 func ParseKeyStringCommand() *cobra.Command { 75 cmd := &cobra.Command{ 76 Use: "parse <hex-or-bech32-address>", 77 Short: "Parse address from hex to bech32 and vice versa", 78 Long: `Convert and print to stdout key addresses and fingerprints from 79 hexadecimal into bech32 cosmos prefixed format and vice versa. 80 `, 81 Args: cobra.ExactArgs(1), 82 RunE: parseKey, 83 } 84 85 return cmd 86 } 87 88 func parseKey(cmd *cobra.Command, args []string) error { 89 config, _ := sdk.GetSealedConfig(cmd.Context()) 90 return doParseKey(cmd, config, args) 91 } 92 93 func doParseKey(cmd *cobra.Command, config *sdk.Config, args []string) error { 94 addr := strings.TrimSpace(args[0]) 95 outstream := cmd.OutOrStdout() 96 97 if len(addr) == 0 { 98 return errors.New("couldn't parse empty input") 99 } 100 101 output, _ := cmd.Flags().GetString(flags.FlagOutput) 102 if !(runFromBech32(outstream, addr, output) || runFromHex(config, outstream, addr, output)) { 103 return errors.New("couldn't find valid bech32 nor hex data") 104 } 105 106 return nil 107 } 108 109 // print info from bech32 110 func runFromBech32(w io.Writer, bech32str, output string) bool { 111 hrp, bz, err := bech32.DecodeAndConvert(bech32str) 112 if err != nil { 113 return false 114 } 115 116 displayParseKeyInfo(w, newHexOutput(hrp, bz), output) 117 118 return true 119 } 120 121 // print info from hex 122 func runFromHex(config *sdk.Config, w io.Writer, hexstr, output string) bool { 123 bz, err := hex.DecodeString(hexstr) 124 if err != nil { 125 return false 126 } 127 128 displayParseKeyInfo(w, newBech32Output(config, bz), output) 129 130 return true 131 } 132 133 func displayParseKeyInfo(w io.Writer, stringer fmt.Stringer, output string) { 134 var ( 135 err error 136 out []byte 137 ) 138 139 switch output { 140 case flags.OutputFormatText: 141 out, err = yaml.Marshal(&stringer) 142 143 case flags.OutputFormatJSON: 144 out, err = json.Marshal(&stringer) 145 } 146 147 if err != nil { 148 panic(err) 149 } 150 151 _, _ = fmt.Fprintln(w, string(out)) 152 }