From 519655805686df7e67905810b350699e399fae73 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 7 Dec 2021 19:36:02 +0300 Subject: [PATCH] cli/wallet: allow to read wallet from stdin where it's possible Unfortunately, testing this code is not possible without an additional wrapper in `input`, but adding it just to test this seems to be too excessive. Fixes --- cli/wallet/multisig.go | 2 +- cli/wallet/nep11.go | 2 +- cli/wallet/nep17.go | 8 ++++---- cli/wallet/validator.go | 4 ++-- cli/wallet/wallet.go | 30 +++++++++++++++++++++++++----- cli/wallet_test.go | 3 +++ docs/cli.md | 3 ++- 7 files changed, 38 insertions(+), 14 deletions(-) diff --git a/cli/wallet/multisig.go b/cli/wallet/multisig.go index c1c4b0104..6612e5c56 100644 --- a/cli/wallet/multisig.go +++ b/cli/wallet/multisig.go @@ -12,7 +12,7 @@ import ( ) func signStoredTransaction(ctx *cli.Context) error { - wall, err := openWallet(ctx.String("wallet")) + wall, err := readWallet(ctx.String("wallet")) if err != nil { return cli.NewExitError(err, 1) } diff --git a/cli/wallet/nep11.go b/cli/wallet/nep11.go index b22d30245..5ce8ea7b8 100644 --- a/cli/wallet/nep11.go +++ b/cli/wallet/nep11.go @@ -150,7 +150,7 @@ func removeNEP11Token(ctx *cli.Context) error { func getNEP11Balance(ctx *cli.Context) error { var accounts []*wallet.Account - wall, err := openWallet(ctx.String("wallet")) + wall, err := readWallet(ctx.String("wallet")) if err != nil { return cli.NewExitError(fmt.Errorf("bad wallet: %w", err), 1) } diff --git a/cli/wallet/nep17.go b/cli/wallet/nep17.go index bb6965122..2fec82629 100644 --- a/cli/wallet/nep17.go +++ b/cli/wallet/nep17.go @@ -142,7 +142,7 @@ func newNEP17Commands() []cli.Command { func getNEP17Balance(ctx *cli.Context) error { var accounts []*wallet.Account - wall, err := openWallet(ctx.String("wallet")) + wall, err := readWallet(ctx.String("wallet")) if err != nil { return cli.NewExitError(fmt.Errorf("bad wallet: %w", err), 1) } @@ -346,7 +346,7 @@ func printNEP17Info(ctx *cli.Context) error { } func printNEPInfo(ctx *cli.Context, standard string) error { - wall, err := openWallet(ctx.String("wallet")) + wall, err := readWallet(ctx.String("wallet")) if err != nil { return cli.NewExitError(err, 1) } @@ -403,7 +403,7 @@ func removeNEPToken(ctx *cli.Context, standard string) error { } func multiTransferNEP17(ctx *cli.Context) error { - wall, err := openWallet(ctx.String("wallet")) + wall, err := readWallet(ctx.String("wallet")) if err != nil { return cli.NewExitError(err, 1) } @@ -489,7 +489,7 @@ func transferNEP17(ctx *cli.Context) error { } func transferNEP(ctx *cli.Context, standard string) error { - wall, err := openWallet(ctx.String("wallet")) + wall, err := readWallet(ctx.String("wallet")) if err != nil { return cli.NewExitError(err, 1) } diff --git a/cli/wallet/validator.go b/cli/wallet/validator.go index a524be3a1..537d52211 100644 --- a/cli/wallet/validator.go +++ b/cli/wallet/validator.go @@ -83,7 +83,7 @@ func handleUnregister(ctx *cli.Context) error { } func handleCandidate(ctx *cli.Context, method string, sysGas int64) error { - wall, err := openWallet(ctx.String("wallet")) + wall, err := readWallet(ctx.String("wallet")) if err != nil { return cli.NewExitError(err, 1) } @@ -138,7 +138,7 @@ func handleCandidate(ctx *cli.Context, method string, sysGas int64) error { } func handleVote(ctx *cli.Context) error { - wall, err := openWallet(ctx.String("wallet")) + wall, err := readWallet(ctx.String("wallet")) if err != nil { return cli.NewExitError(err, 1) } diff --git a/cli/wallet/wallet.go b/cli/wallet/wallet.go index 772b5d8a5..9f34b8817 100644 --- a/cli/wallet/wallet.go +++ b/cli/wallet/wallet.go @@ -2,9 +2,11 @@ package wallet import ( "encoding/hex" + "encoding/json" "errors" "fmt" "io" + "os" "strings" "github.com/nspcc-dev/neo-go/cli/flags" @@ -23,12 +25,13 @@ import ( var ( errNoPath = errors.New("target path where the wallet should be stored is mandatory and should be passed using (--wallet, -w) flags") errPhraseMismatch = errors.New("the entered pass-phrases do not match. Maybe you have misspelled them") + errNoStdin = errors.New("can't read wallet from stdin for this command") ) var ( walletPathFlag = cli.StringFlag{ Name: "wallet, w", - Usage: "Target location of the wallet file.", + Usage: "Target location of the wallet file ('-' to read from stdin).", } wifFlag = cli.StringFlag{ Name: "wif", @@ -249,7 +252,7 @@ func NewCommands() []cli.Command { } func claimGas(ctx *cli.Context) error { - wall, err := openWallet(ctx.String("wallet")) + wall, err := readWallet(ctx.String("wallet")) if err != nil { return cli.NewExitError(err, 1) } @@ -332,7 +335,7 @@ func addAccount(ctx *cli.Context) error { } func exportKeys(ctx *cli.Context) error { - wall, err := openWallet(ctx.String("wallet")) + wall, err := readWallet(ctx.String("wallet")) if err != nil { return cli.NewExitError(err, 1) } @@ -560,7 +563,7 @@ func askForConsent(w io.Writer) bool { } func dumpWallet(ctx *cli.Context) error { - wall, err := openWallet(ctx.String("wallet")) + wall, err := readWallet(ctx.String("wallet")) if err != nil { return cli.NewExitError(err, 1) } @@ -582,7 +585,7 @@ func dumpWallet(ctx *cli.Context) error { } func dumpKeys(ctx *cli.Context) error { - wall, err := openWallet(ctx.String("wallet")) + wall, err := readWallet(ctx.String("wallet")) if err != nil { return cli.NewExitError(err, 1) } @@ -683,6 +686,23 @@ func openWallet(path string) (*wallet.Wallet, error) { if len(path) == 0 { return nil, errNoPath } + if path == "-" { + return nil, errNoStdin + } + return wallet.NewWalletFromFile(path) +} + +func readWallet(path string) (*wallet.Wallet, error) { + if len(path) == 0 { + return nil, errNoPath + } + if path == "-" { + w := &wallet.Wallet{} + if err := json.NewDecoder(os.Stdin).Decode(w); err != nil { + return nil, fmt.Errorf("js %s", err) + } + return w, nil + } return wallet.NewWalletFromFile(path) } diff --git a/cli/wallet_test.go b/cli/wallet_test.go index 5a7bb2ede..d3ee32da9 100644 --- a/cli/wallet_test.go +++ b/cli/wallet_test.go @@ -75,6 +75,9 @@ func TestWalletInit(t *testing.T) { }) t.Run("CreateAccount", func(t *testing.T) { + t.Run("stdin", func(t *testing.T) { + e.RunWithError(t, "neo-go", "wallet", "create", "--wallet", "-") + }) e.In.WriteString("testname\r") e.In.WriteString("testpass\r") e.In.WriteString("testpass\r") diff --git a/docs/cli.md b/docs/cli.md index cbd2adcc2..dce0bd573 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -83,7 +83,8 @@ see [compiler documentation](compiler.md). deploy` and `contract invokefunction`). Wallet management (creating wallet, adding addresses/keys to it) is available there as well as wallet-related functions like NEP-17 transfers, NEO votes, multi-signature signing and other -things. +things. For all commands requiring read-only wallet (like `dump-keys`) a +special `-` path can be used to read the wallet from the standard input. ### Wallet management