github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/client/keys/parse.go (about)

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