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  }