github.com/aeternity/aepp-sdk-go/v6@v6.0.0/cmd/account.go (about) 1 // Copyright © 2018 NAME HERE <EMAIL ADDRESS> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "fmt" 19 "regexp" 20 "runtime" 21 "sync" 22 23 "github.com/aeternity/aepp-sdk-go/v6/account" 24 "github.com/aeternity/aepp-sdk-go/v6/config" 25 "github.com/aeternity/aepp-sdk-go/v6/naet" 26 "github.com/aeternity/aepp-sdk-go/v6/transactions" 27 28 "github.com/spf13/cobra" 29 ) 30 31 var ( 32 waitForTx bool 33 spendTxPayload string 34 printPrivateKey bool 35 accountFileName string 36 password string 37 fee string // leave it as a string because viper cannot parse it directly into a BigInt 38 ttl uint64 39 nonce uint64 40 regex bool 41 ) 42 43 // accountCmd implements the account command 44 var accountCmd = &cobra.Command{ 45 Use: "account PRIVATE_KEY_PATH", 46 Short: "Interact with a account", 47 Long: ``, 48 } 49 50 // addressCmd implements the account address subcommand 51 var addressCmd = &cobra.Command{ 52 Use: "address ACCOUNT_KEYSTORE", 53 Short: "Print the aeternity account address", 54 Long: ``, 55 Args: cobra.ExactArgs(1), 56 RunE: addressFunc, 57 } 58 59 func getPassword() (p string, err error) { 60 if len(password) != 0 { 61 return password, nil 62 } 63 p, err = AskPassword("Enter the password to unlock the keystore: ") 64 if err != nil { 65 return "", err 66 } 67 return p, nil 68 } 69 70 func addressFunc(cmd *cobra.Command, args []string) error { 71 p, err := getPassword() 72 if err != nil { 73 return err 74 } 75 76 // load the account 77 account, err := account.LoadFromKeyStoreFile(args[0], p) 78 if err != nil { 79 return err 80 } 81 82 Pp("Account address", account.Address) 83 if printPrivateKey { 84 if AskYes("Are you sure you want to print your private key? This could be insecure.", false) { 85 Pp("Account private key", account.SigningKeyToHexString()) 86 } 87 } 88 89 return nil 90 } 91 92 // createCmd implements the account generate subcommand 93 var createCmd = &cobra.Command{ 94 Use: "create ACCOUNT_KEYSTORE", 95 Short: "Create a new account", 96 Long: ``, 97 Args: cobra.ExactArgs(1), 98 RunE: createFunc, 99 } 100 101 func createFunc(cmd *cobra.Command, args []string) (err error) { 102 acc, _ := account.New() 103 p, err := getPassword() 104 if err != nil { 105 return err 106 } 107 accountFileName = args[0] 108 109 // check if a name was given 110 f, err := account.StoreToKeyStoreFile(acc, p, accountFileName) 111 if err != nil { 112 return err 113 } 114 115 Pp( 116 "Wallet path", f, 117 "Account address", acc.Address, 118 ) 119 120 return nil 121 } 122 123 // balanceCmd implements the account balance subcommand 124 var balanceCmd = &cobra.Command{ 125 Use: "balance ACCOUNT_KEYSTORE", 126 Short: "Get the balance of an account", 127 Long: ``, 128 Args: cobra.ExactArgs(1), 129 RunE: func(cmd *cobra.Command, args []string) error { 130 node := newAeNode() 131 return balanceFunc(node, args) 132 }, 133 } 134 135 func balanceFunc(conn naet.GetAccounter, args []string) (err error) { 136 p, err := getPassword() 137 138 // load the account 139 account, err := account.LoadFromKeyStoreFile(args[0], p) 140 if err != nil { 141 return err 142 } 143 144 a, err := conn.GetAccount(account.Address) 145 if err != nil { 146 return err 147 } 148 149 PrintObject("account", a) 150 return nil 151 } 152 153 // signCmd implements the account sign subcommand 154 var signCmd = &cobra.Command{ 155 Use: "sign ACCOUNT_KEYSTORE UNSIGNED_TRANSACTION", 156 Short: "Sign the input (e.g. a transaction)", 157 Long: ``, 158 Args: cobra.ExactArgs(2), 159 RunE: signFunc, 160 } 161 162 func signFunc(cmd *cobra.Command, args []string) (err error) { 163 p, err := getPassword() 164 165 // load the account 166 account, err := account.LoadFromKeyStoreFile(args[0], p) 167 if err != nil { 168 return err 169 } 170 171 txUnsignedBase64 := args[1] 172 tx, err := transactions.DeserializeTxStr(txUnsignedBase64) 173 if err != nil { 174 return err 175 } 176 177 txSignedBase64, txHash, signature, err := transactions.SignHashTx(account, tx, config.Node.NetworkID) 178 if err != nil { 179 return err 180 } 181 182 Pp( 183 "Signing account address", account.Address, 184 "Signature", signature, 185 "Unsigned", txUnsignedBase64, 186 "Signed", txSignedBase64, 187 "Hash", txHash, 188 ) 189 return nil 190 } 191 192 // saveCmd implements the account save subcommand 193 var saveCmd = &cobra.Command{ 194 Use: "save ACCOUNT_KEYSTORE ACCOUNT_HEX_STRING", 195 Short: "Save an account from a hex string to a keystore file", 196 Long: ``, 197 Args: cobra.ExactArgs(2), 198 RunE: saveFunc, 199 } 200 201 func saveFunc(cmd *cobra.Command, args []string) (err error) { 202 accountFileName := args[0] 203 acc, err := account.FromHexString(args[1]) 204 if err != nil { 205 return err 206 } 207 208 p, err := getPassword() 209 210 f, err := account.StoreToKeyStoreFile(acc, p, accountFileName) 211 if err != nil { 212 return err 213 } 214 215 Pp("Keystore path ", f) 216 217 return nil 218 } 219 220 var vanityCmd = &cobra.Command{ 221 Use: "vanity", 222 Short: "Find an account that starts with or contains the user-specified text", 223 Long: ``, 224 Args: cobra.MinimumNArgs(1), 225 Run: vanityFunc, 226 } 227 228 func vanityFunc(cmd *cobra.Command, args []string) { 229 var searchString string 230 if regex { 231 searchString = args[0] 232 } else { 233 searchString = fmt.Sprintf("^%s", args[0]) 234 } 235 r, err := regexp.Compile(searchString) 236 if err != nil { 237 fmt.Println("Ouch! The search input ", searchString, "is not a valid regexp") 238 return 239 } 240 fmt.Println("The search for your account matching", searchString, "has begun") 241 242 var wg sync.WaitGroup 243 wg.Add(runtime.NumCPU()) 244 for i := 0; i < runtime.NumCPU(); i++ { 245 go func() { 246 for { 247 a, _ := account.New() 248 249 if r.MatchString(a.Address[3:]) { 250 fmt.Println("FOUND!") 251 fmt.Println("Secret: ", a.SigningKeyToHexString()) 252 fmt.Println("Address", a.Address) 253 } 254 } 255 }() 256 } 257 wg.Wait() 258 259 } 260 261 func init() { 262 RootCmd.AddCommand(accountCmd) 263 accountCmd.AddCommand(addressCmd) 264 accountCmd.AddCommand(createCmd) 265 accountCmd.AddCommand(saveCmd) 266 accountCmd.AddCommand(balanceCmd) 267 accountCmd.AddCommand(signCmd) 268 accountCmd.AddCommand(vanityCmd) 269 accountCmd.PersistentFlags().StringVar(&password, "password", "", "Read account password from stdin [WARN: this method is not secure]") 270 // account address flags 271 addressCmd.Flags().BoolVar(&printPrivateKey, "private-key", false, "Print the private key as hex string") 272 vanityCmd.Flags().BoolVar(®ex, "regex", false, "Search using a regular expression that can match anywhere within the address instead of a string that matches at the beginning") 273 }