github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/cmd/account/accountdelete.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  	"bytes"
    10  	"fmt"
    11  	"os"
    12  	"path/filepath"
    13  	"strings"
    14  
    15  	"github.com/ethereum/go-ethereum/accounts/keystore"
    16  	"github.com/spf13/cobra"
    17  	"gopkg.in/yaml.v2"
    18  
    19  	"github.com/iotexproject/iotex-address/address"
    20  
    21  	"github.com/iotexproject/iotex-core/ioctl/cmd/alias"
    22  	"github.com/iotexproject/iotex-core/ioctl/config"
    23  	"github.com/iotexproject/iotex-core/ioctl/output"
    24  	"github.com/iotexproject/iotex-core/ioctl/util"
    25  )
    26  
    27  // Multi-language support
    28  var (
    29  	_deleteCmdShorts = map[config.Language]string{
    30  		config.English: "Delete an IoTeX account/address from wallet/config",
    31  		config.Chinese: "从 钱包/配置 中删除一个IoTeX的账户或地址",
    32  	}
    33  	_deleteCmdUses = map[config.Language]string{
    34  		config.English: "delete [ALIAS|ADDRESS]",
    35  		config.Chinese: "delete [别名|地址]",
    36  	}
    37  )
    38  
    39  // _accountDeleteCmd represents the account delete command
    40  var _accountDeleteCmd = &cobra.Command{
    41  	Use:   config.TranslateInLang(_deleteCmdUses, config.UILanguage),
    42  	Short: config.TranslateInLang(_deleteCmdShorts, config.UILanguage),
    43  	Args:  cobra.RangeArgs(0, 1),
    44  	RunE: func(cmd *cobra.Command, args []string) error {
    45  		cmd.SilenceUsage = true
    46  		arg := ""
    47  		if len(args) == 1 {
    48  			arg = args[0]
    49  		}
    50  		err := accountDelete(arg)
    51  		return output.PrintError(err)
    52  	},
    53  }
    54  
    55  func accountDelete(arg string) error {
    56  	addr, err := util.GetAddress(arg)
    57  	if err != nil {
    58  		return output.NewError(output.AddressError, "failed to get address", err)
    59  	}
    60  	account, err := address.FromString(addr)
    61  	if err != nil {
    62  		return output.NewError(output.ConvertError, "failed to convert string into address", nil)
    63  	}
    64  
    65  	var filePath string
    66  	if CryptoSm2 {
    67  		if filePath == "" {
    68  			filePath = filepath.Join(config.ReadConfig.Wallet, "sm2sk-"+account.String()+".pem")
    69  		}
    70  	} else {
    71  		ks := keystore.NewKeyStore(config.ReadConfig.Wallet,
    72  			keystore.StandardScryptN, keystore.StandardScryptP)
    73  		for _, v := range ks.Accounts() {
    74  			if bytes.Equal(account.Bytes(), v.Address.Bytes()) {
    75  				filePath = v.URL.Path
    76  				break
    77  			}
    78  		}
    79  	}
    80  
    81  	// check whether crypto file exists
    82  	_, err = os.Stat(filePath)
    83  	if err != nil {
    84  		return output.NewError(output.CryptoError, fmt.Sprintf("crypto file of account #%s not found", addr), err)
    85  	}
    86  
    87  	var confirm string
    88  	info := fmt.Sprintf("** This is an irreversible action!\n" +
    89  		"Once an account is deleted, all the assets under this account may be lost!\n" +
    90  		"Type 'YES' to continue, quit for anything else.")
    91  	message := output.ConfirmationMessage{Info: info, Options: []string{"yes"}}
    92  	fmt.Println(message.String())
    93  	if _, err := fmt.Scanf("%s", &confirm); err != nil {
    94  		return output.NewError(output.InputError, "failed to input yes", err)
    95  	}
    96  	if !strings.EqualFold(confirm, "yes") {
    97  		output.PrintResult("quit")
    98  		return nil
    99  	}
   100  
   101  	if err := os.Remove(filePath); err != nil {
   102  		return output.NewError(output.WriteFileError, "failed to remove keystore or pem file", err)
   103  	}
   104  
   105  	aliases := alias.GetAliasMap()
   106  	delete(config.ReadConfig.Aliases, aliases[addr])
   107  	out, err := yaml.Marshal(&config.ReadConfig)
   108  	if err != nil {
   109  		return output.NewError(output.SerializationError, "", err)
   110  	}
   111  	if err := os.WriteFile(config.DefaultConfigFile, out, 0600); err != nil {
   112  		return output.NewError(output.WriteFileError,
   113  			fmt.Sprintf("Failed to write to config file %s.", config.DefaultConfigFile), err)
   114  	}
   115  
   116  	output.PrintResult(fmt.Sprintf("Account #%s has been deleted.", addr))
   117  	return nil
   118  }