github.com/aeternity/aepp-sdk-go@v1.0.3-0.20190606142815-1c0ffdc21fd9/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/aeternity" 24 25 "github.com/spf13/cobra" 26 ) 27 28 var ( 29 waitForTx bool 30 spendTxPayload string 31 printPrivateKey bool 32 accountFileName string 33 password string 34 fee string // leave it as a string because viper cannot parse it directly into a BigInt 35 ttl uint64 36 nonce uint64 37 regex bool 38 ) 39 40 // accountCmd implements the account command 41 var accountCmd = &cobra.Command{ 42 Use: "account PRIVATE_KEY_PATH", 43 Short: "Interact with a account", 44 Long: ``, 45 } 46 47 // addressCmd implements the account address subcommand 48 var addressCmd = &cobra.Command{ 49 Use: "address ACCOUNT_KEYSTORE", 50 Short: "Print the aeternity account address", 51 Long: ``, 52 Args: cobra.ExactArgs(1), 53 RunE: addressFunc, 54 } 55 56 func getPassword() (p string, err error) { 57 if len(password) != 0 { 58 return password, nil 59 } 60 p, err = AskPassword("Enter the password to unlock the keystore: ") 61 if err != nil { 62 return "", err 63 } 64 return p, nil 65 } 66 67 func addressFunc(cmd *cobra.Command, args []string) error { 68 p, err := getPassword() 69 if err != nil { 70 return err 71 } 72 73 // load the account 74 account, err := aeternity.LoadAccountFromKeyStoreFile(args[0], p) 75 if err != nil { 76 return err 77 } 78 79 aeternity.Pp("Account address", account.Address) 80 if printPrivateKey { 81 if AskYes("Are you sure you want to print your private key? This could be insecure.", false) { 82 aeternity.Pp("Account private key", account.SigningKeyToHexString()) 83 } 84 } 85 86 return nil 87 } 88 89 // createCmd implements the account generate subcommand 90 var createCmd = &cobra.Command{ 91 Use: "create ACCOUNT_KEYSTORE", 92 Short: "Create a new account", 93 Long: ``, 94 Args: cobra.ExactArgs(1), 95 RunE: createFunc, 96 } 97 98 func createFunc(cmd *cobra.Command, args []string) (err error) { 99 account, _ := aeternity.NewAccount() 100 p, err := getPassword() 101 if err != nil { 102 return err 103 } 104 accountFileName = args[0] 105 106 // check if a name was given 107 f, err := aeternity.StoreAccountToKeyStoreFile(account, p, accountFileName) 108 if err != nil { 109 return err 110 } 111 112 aeternity.Pp( 113 "Wallet path", f, 114 "Account address", account.Address, 115 ) 116 117 return nil 118 } 119 120 // balanceCmd implements the account balance subcommand 121 var balanceCmd = &cobra.Command{ 122 Use: "balance ACCOUNT_KEYSTORE", 123 Short: "Get the balance of an account", 124 Long: ``, 125 Args: cobra.ExactArgs(1), 126 RunE: balanceFunc, 127 } 128 129 func balanceFunc(cmd *cobra.Command, args []string) (err error) { 130 aeCli := NewAeCli() 131 p, err := getPassword() 132 133 // load the account 134 account, err := aeternity.LoadAccountFromKeyStoreFile(args[0], p) 135 if err != nil { 136 return err 137 } 138 139 a, err := aeCli.APIGetAccount(account.Address) 140 if err != nil { 141 return err 142 } 143 144 aeternity.PrintObject("account", a) 145 return nil 146 } 147 148 // signCmd implements the account sign subcommand 149 var signCmd = &cobra.Command{ 150 Use: "sign ACCOUNT_KEYSTORE UNSIGNED_TRANSACTION", 151 Short: "Sign the input (e.g. a transaction)", 152 Long: ``, 153 Args: cobra.ExactArgs(2), 154 RunE: signFunc, 155 } 156 157 func signFunc(cmd *cobra.Command, args []string) (err error) { 158 p, err := getPassword() 159 160 // load the account 161 account, err := aeternity.LoadAccountFromKeyStoreFile(args[0], p) 162 if err != nil { 163 return err 164 } 165 166 txUnsignedBase64 := args[1] 167 txSignedBase64, txHash, signature, err := aeternity.SignEncodeTxStr(account, txUnsignedBase64, aeternity.Config.Node.NetworkID) 168 if err != nil { 169 return err 170 } 171 172 aeternity.Pp( 173 "Signing account address", account.Address, 174 "Signature", signature, 175 "Unsigned", txUnsignedBase64, 176 "Signed", txSignedBase64, 177 "Hash", txHash, 178 ) 179 return nil 180 } 181 182 // saveCmd implements the account save subcommand 183 var saveCmd = &cobra.Command{ 184 Use: "save ACCOUNT_KEYSTORE ACCOUNT_HEX_STRING", 185 Short: "Save an account from a hex string to a keystore file", 186 Long: ``, 187 Args: cobra.ExactArgs(2), 188 RunE: saveFunc, 189 } 190 191 func saveFunc(cmd *cobra.Command, args []string) (err error) { 192 accountFileName := args[0] 193 account, err := aeternity.AccountFromHexString(args[1]) 194 if err != nil { 195 return err 196 } 197 198 p, err := getPassword() 199 200 f, err := aeternity.StoreAccountToKeyStoreFile(account, p, accountFileName) 201 if err != nil { 202 return err 203 } 204 205 aeternity.Pp("Keystore path ", f) 206 207 return nil 208 } 209 210 var vanityCmd = &cobra.Command{ 211 Use: "vanity", 212 Short: "Find an account that starts with or contains the user-specified text", 213 Long: ``, 214 Args: cobra.MinimumNArgs(1), 215 Run: vanityFunc, 216 } 217 218 func vanityFunc(cmd *cobra.Command, args []string) { 219 var searchString string 220 if regex { 221 searchString = args[0] 222 } else { 223 searchString = fmt.Sprintf("^%s", args[0]) 224 } 225 r, err := regexp.Compile(searchString) 226 if err != nil { 227 fmt.Println("Ouch! The search input ", searchString, "is not a valid regexp") 228 return 229 } 230 fmt.Println("The search for your account matching", searchString, "has begun") 231 232 var wg sync.WaitGroup 233 wg.Add(runtime.NumCPU()) 234 for i := 0; i < runtime.NumCPU(); i++ { 235 go func() { 236 for { 237 a, _ := aeternity.NewAccount() 238 239 if r.MatchString(a.Address[3:]) { 240 fmt.Println("FOUND!") 241 fmt.Println("Secret: ", a.SigningKeyToHexString()) 242 fmt.Println("Address", a.Address) 243 } 244 } 245 }() 246 } 247 wg.Wait() 248 249 } 250 251 func init() { 252 RootCmd.AddCommand(accountCmd) 253 accountCmd.AddCommand(addressCmd) 254 accountCmd.AddCommand(createCmd) 255 accountCmd.AddCommand(saveCmd) 256 accountCmd.AddCommand(balanceCmd) 257 accountCmd.AddCommand(signCmd) 258 accountCmd.AddCommand(vanityCmd) 259 accountCmd.PersistentFlags().StringVar(&password, "password", "", "Read account password from stdin [WARN: this method is not secure]") 260 // account address flags 261 addressCmd.Flags().BoolVar(&printPrivateKey, "private-key", false, "Print the private key as hex string") 262 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") 263 }