From 24ee8fab5c1166045df2131937a6342cde588065 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 22 Jul 2021 14:57:29 +0300 Subject: [PATCH] cli: move `wallet candidate getstate` into `query voter` This command has nothing to do with wallets. --- cli/candidate_test.go | 12 ++++---- cli/query/query.go | 66 +++++++++++++++++++++++++++++++++++++++++ cli/wallet/validator.go | 66 ----------------------------------------- docs/cli.md | 11 +++++++ 4 files changed, 83 insertions(+), 72 deletions(-) diff --git a/cli/candidate_test.go b/cli/candidate_test.go index d9093c51e..ffb0fd10b 100644 --- a/cli/candidate_test.go +++ b/cli/candidate_test.go @@ -79,9 +79,9 @@ func TestRegisterCandidate(t *testing.T) { e.checkEOF(t) // check state - e.Run(t, "neo-go", "wallet", "candidate", "getstate", + e.Run(t, "neo-go", "query", "voter", "--rpc-endpoint", "http://"+e.RPC.Addr, - "--address", validatorPriv.Address()) + validatorPriv.Address()) e.checkNextLine(t, "^\\s*Voted:\\s+"+validatorPriv.Address()) e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$") e.checkNextLine(t, "^\\s*Block\\s*:\\s*"+strconv.FormatUint(uint64(index), 10)) @@ -101,9 +101,9 @@ func TestRegisterCandidate(t *testing.T) { require.Equal(t, big.NewInt(0), vs[0].Votes) // check state - e.Run(t, "neo-go", "wallet", "candidate", "getstate", + e.Run(t, "neo-go", "query", "voter", "--rpc-endpoint", "http://"+e.RPC.Addr, - "--address", validatorPriv.Address()) + validatorPriv.Address()) e.checkNextLine(t, "^\\s*Voted:\\s+"+"null") // no vote. e.checkNextLine(t, "^\\s*Amount\\s*:\\s*"+b.String()+"$") e.checkNextLine(t, "^\\s*Block\\s*:\\s*"+strconv.FormatUint(uint64(index), 10)) @@ -125,6 +125,6 @@ func TestRegisterCandidate(t *testing.T) { vs, err = e.Chain.GetEnrollments() require.Equal(t, 0, len(vs)) - // getstate: missing address - e.RunWithError(t, "neo-go", "wallet", "candidate", "getstate") + // query voter: missing address + e.RunWithError(t, "neo-go", "query", "voter") } diff --git a/cli/query/query.go b/cli/query/query.go index 48ffacc3d..18ac8f0ba 100644 --- a/cli/query/query.go +++ b/cli/query/query.go @@ -10,10 +10,14 @@ import ( "strings" "text/tabwriter" + "github.com/nspcc-dev/neo-go/cli/flags" "github.com/nspcc-dev/neo-go/cli/options" + "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" + "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/urfave/cli" @@ -49,6 +53,12 @@ func NewCommands() []cli.Command { Action: queryTx, Flags: queryTxFlags, }, + { + Name: "voter", + Usage: "Print NEO holder account state", + Action: queryVoter, + Flags: options.RPC, + }, }, }} } @@ -189,3 +199,59 @@ func queryCommittee(ctx *cli.Context) error { } return nil } + +func queryVoter(ctx *cli.Context) error { + args := ctx.Args() + if len(args) == 0 { + return cli.NewExitError("No address specified", 1) + } + + addr, err := flags.ParseAddress(args[0]) + if err != nil { + return cli.NewExitError(fmt.Sprintf("wrong address: %s", args[0]), 1) + } + + gctx, cancel := options.GetTimeoutContext(ctx) + defer cancel() + c, exitErr := options.GetRPCClient(gctx, ctx) + if exitErr != nil { + return exitErr + } + + neoHash, err := c.GetNativeContractHash(nativenames.Neo) + if err != nil { + return cli.NewExitError(fmt.Errorf("failed to get NEO contract hash: %w", err), 1) + } + res, err := c.InvokeFunction(neoHash, "getAccountState", []smartcontract.Parameter{ + { + Type: smartcontract.Hash160Type, + Value: addr, + }, + }, nil) + if err != nil { + return cli.NewExitError(err, 1) + } + if res.State != "HALT" { + return cli.NewExitError(fmt.Errorf("invocation failed: %s", res.FaultException), 1) + } + if len(res.Stack) == 0 { + return cli.NewExitError("result stack is empty", 1) + } + st := new(state.NEOBalance) + err = st.FromStackItem(res.Stack[0]) + if err != nil { + return cli.NewExitError(fmt.Errorf("failed to convert account state from stackitem: %w", err), 1) + } + dec, err := c.NEP17Decimals(neoHash) + if err != nil { + return cli.NewExitError(fmt.Errorf("failed to get decimals: %w", err), 1) + } + voted := "null" + if st.VoteTo != nil { + voted = address.Uint160ToString(st.VoteTo.GetScriptHash()) + } + fmt.Fprintf(ctx.App.Writer, "\tVoted: %s\n", voted) + fmt.Fprintf(ctx.App.Writer, "\tAmount : %s\n", fixedn.ToString(&st.Balance, int(dec))) + fmt.Fprintf(ctx.App.Writer, "\tBlock: %d\n", st.BalanceHeight) + return nil +} diff --git a/cli/wallet/validator.go b/cli/wallet/validator.go index 0289ae47c..16f754ae4 100644 --- a/cli/wallet/validator.go +++ b/cli/wallet/validator.go @@ -7,14 +7,11 @@ import ( "github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/cli/options" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" - "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "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/fixedn" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpc/client" - "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" @@ -74,18 +71,6 @@ func newValidatorCommands() []cli.Command { }, }, options.RPC...), }, - { - Name: "getstate", - Usage: "print NEO holder account state", - UsageText: "getstate -a ", - Action: getAccountState, - Flags: append([]cli.Flag{ - flags.AddressFlag{ - Name: "address, a", - Usage: "Address to get state of", - }, - }, options.RPC...), - }, } } @@ -227,54 +212,3 @@ func getDecryptedAccount(ctx *cli.Context, wall *wallet.Wallet, addr util.Uint16 } return acc, nil } - -func getAccountState(ctx *cli.Context) error { - addrFlag := ctx.Generic("address").(*flags.Address) - if !addrFlag.IsSet { - return cli.NewExitError("address was not provided", 1) - } - - gctx, cancel := options.GetTimeoutContext(ctx) - defer cancel() - c, exitErr := options.GetRPCClient(gctx, ctx) - if exitErr != nil { - return exitErr - } - - neoHash, err := c.GetNativeContractHash(nativenames.Neo) - if err != nil { - return cli.NewExitError(fmt.Errorf("failed to get NEO contract hash: %w", err), 1) - } - res, err := c.InvokeFunction(neoHash, "getAccountState", []smartcontract.Parameter{ - { - Type: smartcontract.Hash160Type, - Value: addrFlag.Uint160(), - }, - }, nil) - if err != nil { - return cli.NewExitError(err, 1) - } - if res.State != "HALT" { - return cli.NewExitError(fmt.Errorf("invocation failed: %s", res.FaultException), 1) - } - if len(res.Stack) == 0 { - return cli.NewExitError("result stack is empty", 1) - } - st := new(state.NEOBalance) - err = st.FromStackItem(res.Stack[0]) - if err != nil { - return cli.NewExitError(fmt.Errorf("failed to convert account state from stackitem: %w", err), 1) - } - dec, err := c.NEP17Decimals(neoHash) - if err != nil { - return cli.NewExitError(fmt.Errorf("failed to get decimals: %w", err), 1) - } - voted := "null" - if st.VoteTo != nil { - voted = address.Uint160ToString(st.VoteTo.GetScriptHash()) - } - fmt.Fprintf(ctx.App.Writer, "\tVoted: %s\n", voted) - fmt.Fprintf(ctx.App.Writer, "\tAmount : %s\n", fixedn.ToString(&st.Balance, int(dec))) - fmt.Fprintf(ctx.App.Writer, "\tBlock: %d\n", st.BalanceHeight) - return nil -} diff --git a/docs/cli.md b/docs/cli.md index 0b3b6b8b5..dbc2fd359 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -533,6 +533,17 @@ Key Votes Com 03d8d58d2257ca6cb14522b76513d4783f7d481801695893794c2186515c6de76f 0 false false ``` +#### Voter data +`query voter` returns additional data about NEO holder: amount of NEO he has, +candidate he voted for (if any) and block number of the last transactions +involving NEO on this account: +``` +$ ./bin/neo-go query voter -r http://localhost:20332 Nj91C8TxQSxW1jCE1ytFre6mg5qxTypg1Y + Voted: 0214baf0ceea3a66f17e7e1e839ea25fd8bed6cd82e6bb6e68250189065f44ff01 (Nj91C8TxQSxW1jCE1ytFre6mg5qxTypg1Y) + Amount : 2000000 + Block: 3970 +``` + ### NEP-17 token functions `wallet nep17` contains a set of commands to use for NEP-17 tokens.