refactor client

This commit is contained in:
rigelrozanski 2018-03-03 19:07:50 +00:00
parent 131130b7a4
commit b6347db664
6 changed files with 186 additions and 57 deletions

127
client/builder/builder.go Normal file
View File

@ -0,0 +1,127 @@
package builder
import (
"fmt"
"github.com/pkg/errors"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/wire"
rpcclient "github.com/tendermint/tendermint/rpc/client"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
cmn "github.com/tendermint/tmlibs/common"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/keys"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Broadcast the transaction bytes to Tendermint
func BroadcastTx(tx []byte) (*ctypes.ResultBroadcastTxCommit, error) {
node, err := client.GetNode()
if err != nil {
return nil, err
}
res, err := node.BroadcastTxCommit(tx)
if err != nil {
return res, err
}
if res.CheckTx.Code != uint32(0) {
return res, errors.Errorf("CheckTx failed: (%d) %s",
res.CheckTx.Code,
res.CheckTx.Log)
}
if res.DeliverTx.Code != uint32(0) {
return res, errors.Errorf("DeliverTx failed: (%d) %s",
res.DeliverTx.Code,
res.DeliverTx.Log)
}
return res, err
}
// Query from Tendermint with the provided key and storename
func Query(key cmn.HexBytes, storeName string) (res []byte, err error) {
path := fmt.Sprintf("/%s/key", storeName)
node, err := client.GetNode()
if err != nil {
return res, err
}
opts := rpcclient.ABCIQueryOptions{
Height: viper.GetInt64(client.FlagHeight),
Trusted: viper.GetBool(client.FlagTrustNode),
}
result, err := node.ABCIQueryWithOptions(path, key, opts)
if err != nil {
return res, err
}
resp := result.Response
if resp.Code != uint32(0) {
return res, errors.Errorf("Query failed: (%d) %s", resp.Code, resp.Log)
}
return resp.Value, nil
}
// Get the from address from the name flag
func GetFromAddress() (from sdk.Address, err error) {
keybase, err := keys.GetKeyBase()
if err != nil {
return nil, err
}
name := viper.GetString(client.FlagName)
info, err := keybase.Get(name)
if err != nil {
return nil, errors.Errorf("No key for: %s", name)
}
return info.PubKey.Address(), nil
}
// sign and build the transaction from the msg
func SignAndBuild(msg sdk.Msg, cdc *wire.Codec) ([]byte, error) {
keybase, err := keys.GetKeyBase()
if err != nil {
return nil, err
}
name := viper.GetString(client.FlagName)
// sign and build
bz := msg.GetSignBytes()
buf := client.BufferStdin()
prompt := fmt.Sprintf("Password to sign with '%s':", name)
passphrase, err := client.GetPassword(prompt, buf)
if err != nil {
return nil, err
}
sig, pubkey, err := keybase.Sign(name, passphrase, bz)
if err != nil {
return nil, err
}
sigs := []sdk.StdSignature{{
PubKey: pubkey,
Signature: sig,
Sequence: viper.GetInt64(client.FlagSequence),
}}
// marshal bytes
tx := sdk.NewStdTx(msg, sigs)
return cdc.MarshalBinary(tx)
}
// sign and build the transaction from the msg
func SignBuildBroadcast(msg sdk.Msg, cdc *wire.Codec) (*ctypes.ResultBroadcastTxCommit, error) {
txBytes, err := SignAndBuild(msg, cdc)
if err != nil {
return nil, err
}
return BroadcastTx(txBytes)
}

View File

@ -9,6 +9,8 @@ const (
FlagHeight = "height"
FlagTrustNode = "trust-node"
FlagName = "name"
FlagSequence = "sequence"
FlagFee = "fee"
)
// LineBreak can be included in a command list to provide a blank line
@ -31,6 +33,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().Int64(FlagSequence, 0, "Sequence number to sign the tx")
c.Flags().String(FlagFee, "", "Fee to pay along with transaction")
c.Flags().String(FlagChainID, "", "Chain ID of tendermint node")
c.Flags().String(FlagNode, "tcp://localhost:46657", "<host>:<port> to tendermint rpc interface for this chain")
}

View File

@ -1,14 +1,10 @@
package client
import (
"fmt"
"github.com/pkg/errors"
"github.com/spf13/viper"
rpcclient "github.com/tendermint/tendermint/rpc/client"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
cmn "github.com/tendermint/tmlibs/common"
)
// GetNode prepares a simple rpc.Client from the flags
@ -19,53 +15,3 @@ func GetNode() (rpcclient.Client, error) {
}
return rpcclient.NewHTTP(uri, "/websocket"), nil
}
// Broadcast the transaction bytes to Tendermint
func BroadcastTx(tx []byte) (*ctypes.ResultBroadcastTxCommit, error) {
node, err := GetNode()
if err != nil {
return nil, err
}
res, err := node.BroadcastTxCommit(tx)
if err != nil {
return res, err
}
if res.CheckTx.Code != uint32(0) {
return res, errors.Errorf("CheckTx failed: (%d) %s",
res.CheckTx.Code,
res.CheckTx.Log)
}
if res.DeliverTx.Code != uint32(0) {
return res, errors.Errorf("DeliverTx failed: (%d) %s",
res.DeliverTx.Code,
res.DeliverTx.Log)
}
return res, err
}
// Query from Tendermint with the provided key and storename
func Query(key cmn.HexBytes, storeName string) (res []byte, err error) {
path := fmt.Sprintf("/%s/key", storeName)
node, err := GetNode()
if err != nil {
return res, err
}
opts := rpcclient.ABCIQueryOptions{
Height: viper.GetInt64(FlagHeight),
Trusted: viper.GetBool(FlagTrustNode),
}
result, err := node.ABCIQueryWithOptions(path, key, opts)
if err != nil {
return res, err
}
resp := result.Response
if resp.Code != uint32(0) {
return res, errors.Errorf("Query failed: (%d) %s", resp.Code, resp.Log)
}
return resp.Value, nil
}

View File

@ -0,0 +1,51 @@
package commands
import (
"fmt"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client/builder"
"github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/examples/basecoin/x/cool"
)
// SendTxCommand will create a send tx and sign it with the given key
func WhatCoolTxCmd(cdc *wire.Codec) *cobra.Command {
cmdr := commander{cdc}
return &cobra.Command{
Use: "whatcool [answer]",
Short: "What's cooler than being cool?",
RunE: cmdr.whatCoolTxCmd,
}
}
type commander struct {
cdc *wire.Codec
}
func (c commander) whatCoolTxCmd(cmd *cobra.Command, args []string) error {
if len(args) != 1 || len(args[0]) == 0 {
return errors.New("You must provide an answer")
}
// get the from address from the name flag
from, err := builder.GetFromAddress()
if err != nil {
return err
}
// create the message
msg := cool.NewWhatCoolMsg(from, args[0])
// build and sign the transaction, then broadcast to Tendermint
res, err := builder.SignBuildBroadcast(msg, c.cdc)
if err != nil {
return err
}
fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String())
return nil
}

View File

@ -8,7 +8,7 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/builder"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/auth"
@ -61,7 +61,7 @@ func (c commander) getAccountCmd(cmd *cobra.Command, args []string) error {
}
key := sdk.Address(bz)
res, err := client.Query(key, c.storeName)
res, err := builder.Query(key, c.storeName)
// parse out the value
account, err := c.parser(res)

View File

@ -9,6 +9,7 @@ import (
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/builder"
"github.com/cosmos/cosmos-sdk/client/keys"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
@ -48,7 +49,7 @@ func (c commander) sendTxCmd(cmd *cobra.Command, args []string) error {
return err
}
res, err := client.BroadcastTx(txBytes)
res, err := builder.BroadcastTx(txBytes)
if err != nil {
return err
}