package wallet import ( "bufio" "errors" "fmt" "os" "strings" "syscall" "github.com/CityOfZion/neo-go/pkg/wallet" "github.com/urfave/cli" "golang.org/x/crypto/ssh/terminal" ) var ( errNoPath = errors.New("target path where the wallet should be stored is mandatory and should be passed using (--path, -p) flags") errPhraseMismatch = errors.New("the entered pass-phrases do not match. Maybe you have misspelled them") ) // NewCommands returns 'wallet' command. func NewCommands() []cli.Command { return []cli.Command{{ Name: "wallet", Usage: "create, open and manage a NEO wallet", Subcommands: []cli.Command{ { Name: "create", Usage: "create a new wallet", Action: createWallet, Flags: []cli.Flag{ cli.StringFlag{ Name: "path, p", Usage: "Target location of the wallet file.", }, cli.BoolFlag{ Name: "account, a", Usage: "Create a new account", }, }, }, { Name: "dump", Usage: "check and dump an existing NEO wallet", Action: dumpWallet, Flags: []cli.Flag{ cli.StringFlag{ Name: "path, p", Usage: "Target location of the wallet file.", }, cli.BoolFlag{ Name: "decrypt, d", Usage: "Decrypt encrypted keys.", }, }, }, }, }} } func dumpWallet(ctx *cli.Context) error { path := ctx.String("path") if len(path) == 0 { return cli.NewExitError(errNoPath, 1) } wall, err := wallet.NewWalletFromFile(path) if err != nil { return cli.NewExitError(err, 1) } if ctx.Bool("decrypt") { fmt.Print("Wallet password: ") pass, err := terminal.ReadPassword(int(syscall.Stdin)) if err != nil { return cli.NewExitError(err, 1) } for i := range wall.Accounts { // Just testing the decryption here. err := wall.Accounts[i].Decrypt(string(pass)) if err != nil { return cli.NewExitError(err, 1) } } } fmtPrintWallet(wall) return nil } func createWallet(ctx *cli.Context) error { path := ctx.String("path") if len(path) == 0 { return cli.NewExitError(errNoPath, 1) } wall, err := wallet.NewWallet(path) if err != nil { return cli.NewExitError(err, 1) } if err := wall.Save(); err != nil { return cli.NewExitError(err, 1) } if ctx.Bool("account") { if err := createAccount(ctx, wall); err != nil { return cli.NewExitError(err, 1) } } fmtPrintWallet(wall) fmt.Printf("wallet successfully created, file location is %s\n", wall.Path()) return nil } func createAccount(ctx *cli.Context, wall *wallet.Wallet) error { var ( rawName, rawPhrase, rawPhraseCheck []byte ) buf := bufio.NewReader(os.Stdin) fmt.Print("Enter the name of the account > ") rawName, _ = buf.ReadBytes('\n') fmt.Print("Enter passphrase > ") rawPhrase, _ = terminal.ReadPassword(int(syscall.Stdin)) fmt.Print("\nConfirm passphrase > ") rawPhraseCheck, _ = terminal.ReadPassword(int(syscall.Stdin)) // Clean data var ( name = strings.TrimRight(string(rawName), "\n") phrase = strings.TrimRight(string(rawPhrase), "\n") phraseCheck = strings.TrimRight(string(rawPhraseCheck), "\n") ) if phrase != phraseCheck { return errPhraseMismatch } return wall.CreateAccount(name, phrase) } func fmtPrintWallet(wall *wallet.Wallet) { b, _ := wall.JSON() fmt.Println("") fmt.Println(string(b)) fmt.Println("") }