github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/cmd/account/accountimport.go (about)

     1  // Copyright (c) 2019 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package account
     7  
     8  import (
     9  	"fmt"
    10  	"os"
    11  
    12  	"github.com/spf13/cobra"
    13  	"gopkg.in/yaml.v2"
    14  
    15  	"github.com/iotexproject/iotex-core/ioctl/config"
    16  	"github.com/iotexproject/iotex-core/ioctl/output"
    17  	"github.com/iotexproject/iotex-core/ioctl/util"
    18  	"github.com/iotexproject/iotex-core/ioctl/validator"
    19  )
    20  
    21  // Multi-language support
    22  var (
    23  	_importCmdShorts = map[config.Language]string{
    24  		config.English: "Import IoTeX private key or keystore into wallet",
    25  		config.Chinese: "将IoTeX的私钥或私钥库导入钱包",
    26  	}
    27  	_importKeyCmdShorts = map[config.Language]string{
    28  		config.English: "Import IoTeX private key into wallet",
    29  		config.Chinese: "将IoTeX的私钥导入钱包",
    30  	}
    31  	_importKeyCmdUses = map[config.Language]string{
    32  		config.English: "key ALIAS",
    33  		config.Chinese: "key 别名",
    34  	}
    35  	_importKeyStoreCmdShorts = map[config.Language]string{
    36  		config.English: "Import IoTeX keystore into wallet",
    37  		config.Chinese: "将IoTeX的私钥库导入钱包",
    38  	}
    39  	_importKeyStoreCmdUses = map[config.Language]string{
    40  		config.English: "keystore ALIAS FILEPATH",
    41  		config.Chinese: "keystore 别名 文件路径",
    42  	}
    43  	_importPemCmdShorts = map[config.Language]string{
    44  		config.English: "Import IoTeX key from pem file into wallet",
    45  		config.Chinese: "将IoTeX私钥从pem文件导入钱包",
    46  	}
    47  	_importPemCmdUses = map[config.Language]string{
    48  		config.English: "pem ALIAS FILEPATH",
    49  		config.Chinese: "pem 别名 文件路径",
    50  	}
    51  )
    52  var (
    53  	// _accountImportCmd represents the account import command
    54  	_accountImportCmd = &cobra.Command{
    55  		Use:   "import",
    56  		Short: config.TranslateInLang(_importCmdShorts, config.UILanguage),
    57  	}
    58  	// _accountImportKeyCmd represents the account import key command
    59  	_accountImportKeyCmd = &cobra.Command{
    60  		Use:   config.TranslateInLang(_importKeyCmdUses, config.UILanguage),
    61  		Short: config.TranslateInLang(_importKeyCmdShorts, config.UILanguage),
    62  		Args:  cobra.ExactArgs(1),
    63  		RunE: func(cmd *cobra.Command, args []string) error {
    64  			cmd.SilenceUsage = true
    65  			err := accountImportKey(args)
    66  			return output.PrintError(err)
    67  		},
    68  	}
    69  	// _accountImportKeyStoreCmd represents the account import keystore command
    70  	_accountImportKeyStoreCmd = &cobra.Command{
    71  		Use:   config.TranslateInLang(_importKeyStoreCmdUses, config.UILanguage),
    72  		Short: config.TranslateInLang(_importKeyStoreCmdShorts, config.UILanguage),
    73  		Args:  cobra.ExactArgs(2),
    74  		RunE: func(cmd *cobra.Command, args []string) error {
    75  			cmd.SilenceUsage = true
    76  			err := accountImportKeyStore(args)
    77  			return output.PrintError(err)
    78  		},
    79  	}
    80  	// _accountImportPemCmd represents the account import pem command
    81  	_accountImportPemCmd = &cobra.Command{
    82  		Use:   config.TranslateInLang(_importPemCmdUses, config.UILanguage),
    83  		Short: config.TranslateInLang(_importPemCmdShorts, config.UILanguage),
    84  		Args:  cobra.ExactArgs(2),
    85  		RunE: func(cmd *cobra.Command, args []string) error {
    86  			cmd.SilenceUsage = true
    87  			err := accountImportPem(args)
    88  			return output.PrintError(err)
    89  		},
    90  	}
    91  )
    92  
    93  func init() {
    94  	_accountImportCmd.AddCommand(_accountImportKeyCmd)
    95  	_accountImportCmd.AddCommand(_accountImportKeyStoreCmd)
    96  	_accountImportCmd.AddCommand(_accountImportPemCmd)
    97  }
    98  func validateAlias(alias string) error {
    99  	if err := validator.ValidateAlias(alias); err != nil {
   100  		return err
   101  	}
   102  	if addr, ok := config.ReadConfig.Aliases[alias]; ok {
   103  		return fmt.Errorf("alias \"%s\" has already used for %s", alias, addr)
   104  	}
   105  	return nil
   106  }
   107  func writeToFile(alias, addr string) error {
   108  	config.ReadConfig.Aliases[alias] = addr
   109  	out, err := yaml.Marshal(&config.ReadConfig)
   110  	if err != nil {
   111  		return output.NewError(output.SerializationError, "failed to marshal config", err)
   112  	}
   113  	if err := os.WriteFile(config.DefaultConfigFile, out, 0600); err != nil {
   114  		return output.NewError(output.WriteFileError,
   115  			fmt.Sprintf("failed to write to config file %s", config.DefaultConfigFile), err)
   116  	}
   117  	output.PrintResult(fmt.Sprintf("New account #%s is created. Keep your password, "+
   118  		"or you will lose your private key.", alias))
   119  	return nil
   120  }
   121  func readPasswordFromStdin() (string, error) {
   122  	password, err := util.ReadSecretFromStdin()
   123  	if err != nil {
   124  		return "", fmt.Errorf("failed to get password")
   125  	}
   126  	return password, nil
   127  }
   128  func accountImportKey(args []string) error {
   129  	// Validate inputs
   130  	alias := args[0]
   131  	err := validateAlias(alias)
   132  	if err != nil {
   133  		return output.NewError(output.ValidationError, "invalid alias", err)
   134  	}
   135  	output.PrintQuery(fmt.Sprintf("#%s: Enter your private key, "+
   136  		"which will not be exposed on the screen.", alias))
   137  	privateKey, err := readPasswordFromStdin()
   138  	privateKey = util.TrimHexPrefix(privateKey)
   139  	if err != nil {
   140  		return output.NewError(output.InputError, "failed to get password", err)
   141  	}
   142  	addr, err := newAccountByKey(alias, privateKey, config.ReadConfig.Wallet)
   143  	if err != nil {
   144  		return output.NewError(0, "", err)
   145  	}
   146  	return writeToFile(alias, addr)
   147  }
   148  func accountImportKeyStore(args []string) error {
   149  	// Validate inputs
   150  	alias := args[0]
   151  	err := validateAlias(alias)
   152  	if err != nil {
   153  		return output.NewError(output.ValidationError, "invalid alias", err)
   154  	}
   155  	_, err = os.Stat(args[1])
   156  	if err != nil {
   157  		return output.NewError(output.ReadFileError, "", err)
   158  	}
   159  
   160  	output.PrintQuery(fmt.Sprintf("#%s: Enter your password of keystore, "+
   161  		"which will not be exposed on the screen.", alias))
   162  	password, err := util.ReadSecretFromStdin()
   163  	if err != nil {
   164  		return output.NewError(output.InputError, "failed to get password", err)
   165  	}
   166  	addr, err := newAccountByKeyStore(alias, password, args[1], config.ReadConfig.Wallet)
   167  	if err != nil {
   168  		return output.NewError(0, "", err)
   169  	}
   170  	return writeToFile(alias, addr)
   171  }
   172  
   173  func accountImportPem(args []string) error {
   174  	// Validate inputs
   175  	alias := args[0]
   176  	err := validateAlias(alias)
   177  	if err != nil {
   178  		return output.NewError(output.ValidationError, "invalid alias", err)
   179  	}
   180  	_, err = os.Stat(args[1])
   181  	if err != nil {
   182  		return output.NewError(output.ReadFileError, "", err)
   183  	}
   184  
   185  	output.PrintQuery(fmt.Sprintf("#%s: Enter your password of pem file, "+
   186  		"which will not be exposed on the screen.", alias))
   187  	password, err := util.ReadSecretFromStdin()
   188  	if err != nil {
   189  		return output.NewError(output.InputError, "failed to get password", err)
   190  	}
   191  	addr, err := newAccountByPem(alias, password, args[1], config.ReadConfig.Wallet)
   192  	if err != nil {
   193  		return output.NewError(0, "", err)
   194  	}
   195  	return writeToFile(alias, addr)
   196  }