github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/newcmd/hdwallet/hdwalletderive.go (about) 1 // Copyright (c) 2022 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 hdwallet 7 8 import ( 9 "fmt" 10 11 ecrypt "github.com/ethereum/go-ethereum/crypto" 12 "github.com/iotexproject/go-pkgs/crypto" 13 hdwallet "github.com/miguelmota/go-ethereum-hdwallet" 14 "github.com/pkg/errors" 15 "github.com/spf13/cobra" 16 17 "github.com/iotexproject/iotex-core/ioctl" 18 "github.com/iotexproject/iotex-core/ioctl/config" 19 "github.com/iotexproject/iotex-core/ioctl/util" 20 ) 21 22 // Multi-language support 23 var ( 24 _hdwalletDeriveCmdShorts = map[config.Language]string{ 25 config.English: "derive key from HDWallet", 26 config.Chinese: "查询HDWallet钱包的派生key地址", 27 } 28 ) 29 30 // NewHdwalletDeriveCmd represents the hdwallet derive command 31 func NewHdwalletDeriveCmd(client ioctl.Client) *cobra.Command { 32 short, _ := client.SelectTranslation(_hdwalletDeriveCmdShorts) 33 34 return &cobra.Command{ 35 Use: "derive id1/id2/id3", 36 Short: short, 37 Args: cobra.ExactArgs(1), 38 RunE: func(cmd *cobra.Command, args []string) error { 39 cmd.SilenceUsage = true 40 signer := "hdw::" + args[0] 41 account, change, index, err := util.ParseHdwPath(signer) 42 if err != nil { 43 return errors.Wrap(err, "invalid hdwallet key format") 44 } 45 46 cmd.Println("Enter password:") 47 password, err := client.ReadSecret() 48 if err != nil { 49 return errors.Wrap(err, "failed to get password") 50 } 51 52 addr, _, err := DeriveKey(client, account, change, index, password) 53 if err != nil { 54 return err 55 } 56 cmd.Printf("address: %s\n", addr) 57 return nil 58 }, 59 } 60 } 61 62 // DeriveKey derives the key according to path 63 func DeriveKey(client ioctl.Client, account, change, index uint32, password string) (string, crypto.PrivateKey, error) { 64 mnemonic, err := client.HdwalletMnemonic(password) 65 if err != nil { 66 return "", nil, err 67 } 68 wallet, err := hdwallet.NewFromMnemonic(mnemonic) 69 if err != nil { 70 return "", nil, err 71 } 72 73 derivationPath := fmt.Sprintf("%s/%d'/%d/%d", DefaultRootDerivationPath, account, change, index) 74 path := hdwallet.MustParseDerivationPath(derivationPath) 75 walletAccount, err := wallet.Derive(path, false) 76 if err != nil { 77 return "", nil, errors.Wrap(err, "failed to get account by derive path") 78 } 79 80 private, err := wallet.PrivateKey(walletAccount) 81 if err != nil { 82 return "", nil, errors.Wrap(err, "failed to get private key") 83 } 84 prvKey, err := crypto.BytesToPrivateKey(ecrypt.FromECDSA(private)) 85 if err != nil { 86 return "", nil, errors.Wrap(err, "failed to Bytes private key") 87 } 88 89 addr := prvKey.PublicKey().Address() 90 if addr == nil { 91 return "", nil, errors.Wrap(err, "failed to convert public key into address") 92 } 93 return addr.String(), prvKey, nil 94 }