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 }