cli: move input handling to a separate package
This commit is contained in:
parent
758a88a813
commit
0dda247719
5 changed files with 60 additions and 31 deletions
44
cli/input/input.go
Normal file
44
cli/input/input.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package input
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Terminal is a terminal used for input. If `nil`, stdin is used.
|
||||||
|
var Terminal *terminal.Terminal
|
||||||
|
|
||||||
|
// ReadLine reads line from the input without trailing '\n'
|
||||||
|
func ReadLine(w io.Writer, prompt string) (string, error) {
|
||||||
|
if Terminal != nil {
|
||||||
|
_, err := Terminal.Write([]byte(prompt))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
raw, err := Terminal.ReadLine()
|
||||||
|
return strings.TrimRight(raw, "\n"), err
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, prompt)
|
||||||
|
buf := bufio.NewReader(os.Stdin)
|
||||||
|
return buf.ReadString('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadPassword reads user password with prompt.
|
||||||
|
func ReadPassword(w io.Writer, prompt string) (string, error) {
|
||||||
|
if Terminal != nil {
|
||||||
|
return Terminal.ReadPassword(prompt)
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, prompt)
|
||||||
|
rawPass, err := terminal.ReadPassword(syscall.Stdin)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
fmt.Fprintln(w)
|
||||||
|
return strings.TrimRight(string(rawPass), "\n"), nil
|
||||||
|
}
|
|
@ -9,9 +9,9 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||||
|
"github.com/nspcc-dev/neo-go/cli/input"
|
||||||
"github.com/nspcc-dev/neo-go/cli/options"
|
"github.com/nspcc-dev/neo-go/cli/options"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/compiler"
|
"github.com/nspcc-dev/neo-go/pkg/compiler"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
|
@ -25,7 +25,6 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -680,8 +679,8 @@ func getAccFromContext(ctx *cli.Context) (*wallet.Account, error) {
|
||||||
return nil, cli.NewExitError(fmt.Errorf("wallet contains no account for '%s'", address.Uint160ToString(addr)), 1)
|
return nil, cli.NewExitError(fmt.Errorf("wallet contains no account for '%s'", address.Uint160ToString(addr)), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(ctx.App.Writer, "Enter account %s password > ", address.Uint160ToString(addr))
|
rawPass, err := input.ReadPassword(ctx.App.Writer,
|
||||||
rawPass, err := terminal.ReadPassword(syscall.Stdin)
|
fmt.Sprintf("Enter account %s password > ", address.Uint160ToString(addr)))
|
||||||
fmt.Fprintln(ctx.App.Writer)
|
fmt.Fprintln(ctx.App.Writer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, cli.NewExitError(err, 1)
|
return nil, cli.NewExitError(err, 1)
|
||||||
|
|
1
cli/testdata/testwallet.json
vendored
Normal file
1
cli/testdata/testwallet.json
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":"3.0","accounts":[{"address":"NNuJqXDnRqvwgzhSzhH4jnVFWB1DyZ34EM","key":"6PYT6enT6eh4gu4ew3Mx58pFFDQNhuR1qQPuU594Eo5u4sA2ZvE4MqJV12","label":"kek","contract":{"script":"DCECl3UyEIq6T5RRIXS6z4tNdZPTzQ7NvXyx7FwK05d9UyYLQZVEDXg=","parameters":[{"name":"parameter0","type":"Signature"}],"deployed":false},"lock":false,"isdefault":false}],"scrypt":{"n":16384,"r":8,"p":8},"extra":{"Tokens":null}}
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||||
|
"github.com/nspcc-dev/neo-go/cli/input"
|
||||||
"github.com/nspcc-dev/neo-go/cli/options"
|
"github.com/nspcc-dev/neo-go/cli/options"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
|
@ -178,7 +179,8 @@ func getDecryptedAccount(ctx *cli.Context, wall *wallet.Wallet, addr util.Uint16
|
||||||
return nil, fmt.Errorf("can't find account for the address: %s", address.Uint160ToString(addr))
|
return nil, fmt.Errorf("can't find account for the address: %s", address.Uint160ToString(addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
if pass, err := readPassword(ctx.App.Writer, "Password > "); err != nil {
|
if pass, err := input.ReadPassword(ctx.App.Writer, "Password > "); err != nil {
|
||||||
|
fmt.Println("ERROR", pass, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if err := acc.Decrypt(pass); err != nil {
|
} else if err := acc.Decrypt(pass); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
package wallet
|
package wallet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||||
|
"github.com/nspcc-dev/neo-go/cli/input"
|
||||||
"github.com/nspcc-dev/neo-go/cli/options"
|
"github.com/nspcc-dev/neo-go/cli/options"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
|
@ -18,7 +16,6 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -266,7 +263,7 @@ func convertWallet(ctx *cli.Context) error {
|
||||||
for _, acc := range wall.Accounts {
|
for _, acc := range wall.Accounts {
|
||||||
address.Prefix = address.NEO2Prefix
|
address.Prefix = address.NEO2Prefix
|
||||||
|
|
||||||
pass, err := readPassword(ctx.App.Writer, fmt.Sprintf("Enter passphrase for account %s (label '%s') > ", acc.Address, acc.Label))
|
pass, err := input.ReadPassword(ctx.App.Writer, fmt.Sprintf("Enter passphrase for account %s (label '%s') > ", acc.Address, acc.Label))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(err, -1)
|
return cli.NewExitError(err, -1)
|
||||||
} else if err := acc.Decrypt(pass); err != nil {
|
} else if err := acc.Decrypt(pass); err != nil {
|
||||||
|
@ -348,7 +345,7 @@ loop:
|
||||||
|
|
||||||
for _, wif := range wifs {
|
for _, wif := range wifs {
|
||||||
if decrypt {
|
if decrypt {
|
||||||
pass, err := readPassword(ctx.App.Writer, "Enter password > ")
|
pass, err := input.ReadPassword(ctx.App.Writer, "Enter password > ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(err, 1)
|
return cli.NewExitError(err, 1)
|
||||||
}
|
}
|
||||||
|
@ -518,9 +515,7 @@ func removeAccount(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func askForConsent(w io.Writer) bool {
|
func askForConsent(w io.Writer) bool {
|
||||||
fmt.Fprintln(w, "Are you sure? [y/N]: ")
|
response, err := input.ReadLine(w, "Are you sure? [y/N]: ")
|
||||||
reader := bufio.NewReader(os.Stdin)
|
|
||||||
response, err := reader.ReadString('\n')
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
response = strings.ToLower(strings.TrimSpace(response))
|
response = strings.ToLower(strings.TrimSpace(response))
|
||||||
if response == "y" || response == "yes" {
|
if response == "y" || response == "yes" {
|
||||||
|
@ -537,7 +532,7 @@ func dumpWallet(ctx *cli.Context) error {
|
||||||
return cli.NewExitError(err, 1)
|
return cli.NewExitError(err, 1)
|
||||||
}
|
}
|
||||||
if ctx.Bool("decrypt") {
|
if ctx.Bool("decrypt") {
|
||||||
pass, err := readPassword(ctx.App.Writer, "Enter wallet password > ")
|
pass, err := input.ReadPassword(ctx.App.Writer, "Enter wallet password > ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(err, 1)
|
return cli.NewExitError(err, 1)
|
||||||
}
|
}
|
||||||
|
@ -578,14 +573,12 @@ func createWallet(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func readAccountInfo(w io.Writer) (string, string, error) {
|
func readAccountInfo(w io.Writer) (string, string, error) {
|
||||||
buf := bufio.NewReader(os.Stdin)
|
rawName, _ := input.ReadLine(w, "Enter the name of the account > ")
|
||||||
fmt.Fprint(w, "Enter the name of the account > ")
|
phrase, err := input.ReadPassword(w, "Enter passphrase > ")
|
||||||
rawName, _ := buf.ReadBytes('\n')
|
|
||||||
phrase, err := readPassword(w, "Enter passphrase > ")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
phraseCheck, err := readPassword(w, "Confirm passphrase > ")
|
phraseCheck, err := input.ReadPassword(w, "Confirm passphrase > ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
@ -617,7 +610,7 @@ func newAccountFromWIF(w io.Writer, wif string) (*wallet.Account, error) {
|
||||||
// note: NEP2 strings always have length of 58 even though
|
// note: NEP2 strings always have length of 58 even though
|
||||||
// base58 strings can have different lengths even if slice lengths are equal
|
// base58 strings can have different lengths even if slice lengths are equal
|
||||||
if len(wif) == 58 {
|
if len(wif) == 58 {
|
||||||
pass, err := readPassword(w, "Enter password > ")
|
pass, err := input.ReadPassword(w, "Enter password > ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -655,16 +648,6 @@ func addAccountAndSave(w *wallet.Wallet, acc *wallet.Account) error {
|
||||||
return w.Save()
|
return w.Save()
|
||||||
}
|
}
|
||||||
|
|
||||||
func readPassword(w io.Writer, prompt string) (string, error) {
|
|
||||||
fmt.Fprint(w, prompt)
|
|
||||||
rawPass, err := terminal.ReadPassword(syscall.Stdin)
|
|
||||||
fmt.Fprintln(w)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return strings.TrimRight(string(rawPass), "\n"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func fmtPrintWallet(w io.Writer, wall *wallet.Wallet) {
|
func fmtPrintWallet(w io.Writer, wall *wallet.Wallet) {
|
||||||
b, _ := wall.JSON()
|
b, _ := wall.JSON()
|
||||||
fmt.Fprintln(w, "")
|
fmt.Fprintln(w, "")
|
||||||
|
|
Loading…
Reference in a new issue