From 8c93a6455b6f9c52afea1ba1b35ce9886230d5d2 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 22 Feb 2018 18:15:01 +0100 Subject: [PATCH] Implement query account without proofs --- client/node.go | 8 +++ examples/basecoin/cmd/basecli/client.go | 9 ++- examples/basecoin/cmd/basecli/commands.go | 77 +++++++++++++++++++++++ examples/basecoin/cmd/basecli/main.go | 12 +--- 4 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 client/node.go diff --git a/client/node.go b/client/node.go new file mode 100644 index 0000000000..5328f49d84 --- /dev/null +++ b/client/node.go @@ -0,0 +1,8 @@ +package client + +import rpcclient "github.com/tendermint/tendermint/rpc/client" + +// GetNode prepares a simple rpc.Client from the flags +func GetNode(uri string) rpcclient.Client { + return rpcclient.NewHTTP(uri, "/websocket") +} diff --git a/examples/basecoin/cmd/basecli/client.go b/examples/basecoin/cmd/basecli/client.go index 484ac73f74..736ce4b4e2 100644 --- a/examples/basecoin/cmd/basecli/client.go +++ b/examples/basecoin/cmd/basecli/client.go @@ -12,6 +12,7 @@ const ( flagCommit = "commit" flagValHash = "validator-set" + flagHeight = "height" flagSelect = "select" flagTags = "tag" flagAny = "any" @@ -51,7 +52,11 @@ func AddClientCommands(cmd *cobra.Command) { // GetCommands adds common flags to query commands func GetCommands(cmds ...*cobra.Command) []*cobra.Command { for _, c := range cmds { - c.Flags().Bool(flagTrustNode, false, "Don't verify proofs for responses") + // TODO: make this default false when we support proofs + c.Flags().Bool(flagTrustNode, true, "Don't verify proofs for responses") + c.Flags().String(flagChainID, "", "Chain ID of tendermint node") + c.Flags().String(flagNode, "", ": to tendermint rpc interface for this chain") + c.Flags().Int64(flagHeight, 0, "block height to query, omit to get most recent provable block") } return cmds } @@ -60,6 +65,8 @@ func GetCommands(cmds ...*cobra.Command) []*cobra.Command { func PostCommands(cmds ...*cobra.Command) []*cobra.Command { for _, c := range cmds { c.Flags().String(flagName, "", "Name of private key with which to sign") + c.Flags().String(flagChainID, "", "Chain ID of tendermint node") + c.Flags().String(flagNode, "", ": to tendermint rpc interface for this chain") } return cmds } diff --git a/examples/basecoin/cmd/basecli/commands.go b/examples/basecoin/cmd/basecli/commands.go index 2af60010d2..a1c2dd5d82 100644 --- a/examples/basecoin/cmd/basecli/commands.go +++ b/examples/basecoin/cmd/basecli/commands.go @@ -1,7 +1,20 @@ package main import ( + "encoding/hex" + "encoding/json" + "fmt" + + "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/spf13/viper" + + crypto "github.com/tendermint/go-crypto" + rpcclient "github.com/tendermint/tendermint/rpc/client" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/examples/basecoin/app" + "github.com/cosmos/cosmos-sdk/examples/basecoin/types" ) const ( @@ -21,3 +34,67 @@ func postSendCommand() *cobra.Command { cmd.Flags().String(flagFee, "", "Fee to pay along with transaction") return cmd } + +func getAccountCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "account
", + Short: "Query account balance", + RunE: getAccount, + } + return cmd +} + +func getAccount(cmd *cobra.Command, args []string) error { + if len(args) != 1 || len(args[0]) == 0 { + return errors.New("You must provide an account name") + } + + // find the key to look up the account + addr := args[0] + bz, err := hex.DecodeString(addr) + if err != nil { + return err + } + key := crypto.Address(bz) + + // TODO: make the store name a variable in getAccountCmd? + path := "/main/key" + + uri := viper.GetString(flagNode) + if uri == "" { + return errors.New("Must define which node to query with --node") + } + node := client.GetNode(uri) + + opts := rpcclient.ABCIQueryOptions{ + Height: viper.GetInt64(flagHeight), + // Trusted: viper.GetBool(flagTrustNode), + Trusted: true, + } + result, err := node.ABCIQueryWithOptions(path, key, opts) + if err != nil { + return err + } + resp := result.Response + if resp.Code != uint32(0) { + return errors.Errorf("Query failed: (%d) %s", resp.Code, resp.Log) + } + + // parse out the value + acct := new(types.AppAccount) + cdc := app.MakeTxCodec() + err = cdc.UnmarshalBinary(resp.Value, acct) + if err != nil { + return err + } + + // TODO: better + // fmt.Printf("Account: %#v\n", acct) + output, err := json.MarshalIndent(acct, "", " ") + // output, err := json.MarshalIndent(acct.BaseAccount.Coins, "", " ") + if err != nil { + return err + } + fmt.Println(string(output)) + return nil +} diff --git a/examples/basecoin/cmd/basecli/main.go b/examples/basecoin/cmd/basecli/main.go index 3a785124a6..5ba5450157 100644 --- a/examples/basecoin/cmd/basecli/main.go +++ b/examples/basecoin/cmd/basecli/main.go @@ -20,12 +20,6 @@ var ( } lineBreak = &cobra.Command{Run: func(*cobra.Command, []string) {}} - - getAccountCmd = &cobra.Command{ - Use: "account
", - Short: "Query account balance", - RunE: todoNotImplemented, - } ) func todoNotImplemented(_ *cobra.Command, _ []string) error { @@ -38,10 +32,10 @@ func main() { // generic client commands AddClientCommands(basecliCmd) - // query commands (custom to binary) + + // query/post commands (custom to binary) basecliCmd.AddCommand( - GetCommands(getAccountCmd)...) - // post tx commands (custom to binary) + GetCommands(getAccountCmd())...) basecliCmd.AddCommand( PostCommands(postSendCommand())...)