github.com/0chain/gosdk@v1.17.11/znft/keystore.go (about) 1 package znft 2 3 import ( 4 "fmt" 5 "os" 6 "path" 7 8 hdw "github.com/0chain/gosdk/zcncore/ethhdwallet" 9 "github.com/ethereum/go-ethereum/accounts" 10 "github.com/ethereum/go-ethereum/accounts/keystore" 11 "github.com/ethereum/go-ethereum/common" 12 "github.com/pkg/errors" 13 "gopkg.in/yaml.v2" 14 ) 15 16 // ListStorageAccounts List available accounts 17 func ListStorageAccounts(homedir string) []common.Address { 18 am := getAccountManager(homedir) 19 addresses := am.Accounts() 20 21 return addresses 22 } 23 24 // DeleteAccount deletes account from wallet 25 func DeleteAccount(homedir, address string) bool { 26 am := getAccountManager(homedir) 27 28 wallet, err := am.Find(accounts.Account{ 29 Address: common.HexToAddress(address), 30 }) 31 32 if err != nil && wallet == nil { 33 fmt.Printf("failed to find account %s, error: %s", address, err) 34 return false 35 } 36 37 return true 38 } 39 40 func getAccountManager(homedir string) *accounts.Manager { 41 keyDir := path.Join(homedir, WalletDir) 42 ks := keystore.NewKeyStore(keyDir, keystore.StandardScryptN, keystore.StandardScryptP) 43 config := &accounts.Config{InsecureUnlockAllowed: false} 44 am := accounts.NewManager(config, ks) 45 return am 46 } 47 48 // AccountExists checks if account exists 49 func AccountExists(homedir, address string) bool { 50 am := getAccountManager(homedir) 51 52 wallet, err := am.Find(accounts.Account{ 53 Address: common.HexToAddress(address), 54 }) 55 56 if err != nil && wallet == nil { 57 fmt.Printf("failed to find account %s, error: %s\n", address, err) 58 return false 59 } 60 61 status, _ := wallet.Status() 62 url := wallet.URL() 63 64 fmt.Printf("Account exists. Status: %s, Path: %s\n", status, url) 65 66 return true 67 } 68 69 // CreateKeyStorage create, restore or unlock key storage 70 func CreateKeyStorage(homedir, password string) error { 71 keyDir := path.Join(homedir, WalletDir) 72 ks := keystore.NewKeyStore(keyDir, keystore.StandardScryptN, keystore.StandardScryptP) 73 account, err := ks.NewAccount(password) 74 if err != nil { 75 return errors.Wrap(err, "failed to create keystore") 76 } 77 fmt.Printf("Created account: %s", account.Address.Hex()) 78 79 return nil 80 } 81 82 // UpdateClientEthereumAddress updates Ethereum address 83 func UpdateClientEthereumAddress(homedir, address string) (err error) { 84 configFile := path.Join(homedir, ConfigFile) 85 buf, err := os.ReadFile(configFile) 86 if err != nil { 87 return err 88 } 89 cfg := &Configuration{} 90 err = yaml.Unmarshal(buf, cfg) 91 if err != nil { 92 return err 93 } 94 95 cfg.WalletAddress = address 96 97 text, err := yaml.Marshal(cfg) 98 if err != nil { 99 return err 100 } 101 102 err = os.WriteFile(configFile, text, 0644) 103 104 return err 105 } 106 107 // ImportAccount imports account using mnemonic 108 // password is used to lock and unlock keystorage before signing transaction 109 func ImportAccount(homedir, mnemonic, password string) (string, error) { 110 // 1. Create storage and account if it doesn't exist and add account to it 111 keyDir := path.Join(homedir, WalletDir) 112 ks := keystore.NewKeyStore(keyDir, keystore.StandardScryptN, keystore.StandardScryptP) 113 114 // 2. Init wallet 115 wallet, err := hdw.NewFromMnemonic(mnemonic) 116 if err != nil { 117 return "", errors.Wrap(err, "failed to import from mnemonic") 118 } 119 120 // DefaultBaseDerivationPath is the base path from which custom derivation endpoints 121 // are incremented. As such, the first account will be at m/44'/60'/0'/0, the second 122 // at m/44'/60'/0'/1, etc 123 // from basic library: 124 // var DefaultBaseDerivationPath = accounts.DefaultBaseDerivationPath 125 // from the BIP44 specification, the HD derivation path is defined as 126 // m / purpose' / coin_type' / account' / change / address_index 127 // https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki 128 129 pathD := hdw.MustParseDerivationPath("m/44'/60'/0'/0/0") 130 account, err := wallet.Derive(pathD, true) 131 if err != nil { 132 return "", errors.Wrap(err, "failed parse derivation path") 133 } 134 135 key, err := wallet.PrivateKey(account) 136 if err != nil { 137 return "", errors.Wrap(err, "failed to get private key") 138 } 139 140 // 3. Find key 141 acc, err := ks.Find(account) 142 if err == nil { 143 fmt.Printf("Account already exists: %s\nPath: %s\n\n", acc.Address.Hex(), acc.URL.Path) 144 return acc.Address.Hex(), nil 145 } 146 147 // 4. Import the key if it doesn't exist 148 acc, err = ks.ImportECDSA(key, password) 149 if err != nil { 150 return "", errors.Wrap(err, "failed to get import private key") 151 } 152 153 fmt.Printf("Imported account %s to path: %s\n", acc.Address.Hex(), acc.URL.Path) 154 155 return acc.Address.Hex(), nil 156 }