-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #497 from cosmos/feature/sdk2-gaia-cli
REVIEW: Full-fledged gaia cli
- Loading branch information
Showing
56 changed files
with
2,488 additions
and
454 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package client | ||
|
||
import "github.com/spf13/cobra" | ||
|
||
// nolint | ||
const ( | ||
FlagChainID = "chain-id" | ||
FlagNode = "node" | ||
FlagHeight = "height" | ||
FlagTrustNode = "trust-node" | ||
FlagName = "name" | ||
) | ||
|
||
// LineBreak can be included in a command list to provide a blank line | ||
// to help with readability | ||
var LineBreak = &cobra.Command{Run: func(*cobra.Command, []string) {}} | ||
|
||
// GetCommands adds common flags to query commands | ||
func GetCommands(cmds ...*cobra.Command) []*cobra.Command { | ||
for _, c := range cmds { | ||
// 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, "tcp://localhost:46657", "<host>:<port> 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 | ||
} | ||
|
||
// PostCommands adds common flags for commands to post tx | ||
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, "tcp://localhost:46657", "<host>:<port> to tendermint rpc interface for this chain") | ||
} | ||
return cmds | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
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 | ||
func GetNode() (rpcclient.Client, error) { | ||
uri := viper.GetString(FlagNode) | ||
if uri == "" { | ||
return nil, errors.New("Must define node using --node") | ||
} | ||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package client | ||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/bgentry/speakeasy" | ||
isatty "github.com/mattn/go-isatty" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
// MinPassLength is the minimum acceptable password length | ||
const MinPassLength = 8 | ||
|
||
// BufferStdin is used to allow reading prompts for stdin | ||
// multiple times, when we read from non-tty | ||
func BufferStdin() *bufio.Reader { | ||
return bufio.NewReader(os.Stdin) | ||
} | ||
|
||
// GetPassword will prompt for a password one-time (to sign a tx) | ||
// It enforces the password length | ||
func GetPassword(prompt string, buf *bufio.Reader) (pass string, err error) { | ||
if inputIsTty() { | ||
pass, err = speakeasy.Ask(prompt) | ||
} else { | ||
pass, err = readLineFromBuf(buf) | ||
} | ||
if err != nil { | ||
return "", err | ||
} | ||
if len(pass) < MinPassLength { | ||
return "", errors.Errorf("Password must be at least %d characters", MinPassLength) | ||
} | ||
return pass, nil | ||
} | ||
|
||
// GetSeed will request a seed phrase from stdin and trims off | ||
// leading/trailing spaces | ||
func GetSeed(prompt string, buf *bufio.Reader) (seed string, err error) { | ||
if inputIsTty() { | ||
fmt.Println(prompt) | ||
} | ||
seed, err = readLineFromBuf(buf) | ||
seed = strings.TrimSpace(seed) | ||
return | ||
} | ||
|
||
// GetCheckPassword will prompt for a password twice to verify they | ||
// match (for creating a new password). | ||
// It enforces the password length. Only parses password once if | ||
// input is piped in. | ||
func GetCheckPassword(prompt, prompt2 string, buf *bufio.Reader) (string, error) { | ||
// simple read on no-tty | ||
if !inputIsTty() { | ||
return GetPassword(prompt, buf) | ||
} | ||
|
||
// TODO: own function??? | ||
pass, err := GetPassword(prompt, buf) | ||
if err != nil { | ||
return "", err | ||
} | ||
pass2, err := GetPassword(prompt2, buf) | ||
if err != nil { | ||
return "", err | ||
} | ||
if pass != pass2 { | ||
return "", errors.New("Passphrases don't match") | ||
} | ||
return pass, nil | ||
} | ||
|
||
// inputIsTty returns true iff we have an interactive prompt, | ||
// where we can disable echo and request to repeat the password. | ||
// If false, we can optimize for piped input from another command | ||
func inputIsTty() bool { | ||
return isatty.IsTerminal(os.Stdin.Fd()) || isatty.IsCygwinTerminal(os.Stdin.Fd()) | ||
} | ||
|
||
// readLineFromBuf reads one line from stdin. | ||
// Subsequent calls reuse the same buffer, so we don't lose | ||
// any input when reading a password twice (to verify) | ||
func readLineFromBuf(buf *bufio.Reader) (string, error) { | ||
pass, err := buf.ReadString('\n') | ||
if err != nil { | ||
return "", err | ||
} | ||
return strings.TrimSpace(pass), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package client | ||
|
||
import ( | ||
"github.com/tendermint/go-crypto/keys" | ||
"github.com/tendermint/go-crypto/keys/words" | ||
dbm "github.com/tendermint/tmlibs/db" | ||
) | ||
|
||
// GetKeyBase initializes a keybase based on the configuration | ||
func GetKeyBase(db dbm.DB) keys.Keybase { | ||
keybase := keys.New( | ||
db, | ||
words.MustLoadCodec("english"), | ||
) | ||
return keybase | ||
} | ||
|
||
// MockKeyBase generates an in-memory keybase that will be discarded | ||
// useful for --dry-run to generate a seed phrase without | ||
// storing the key | ||
func MockKeyBase() keys.Keybase { | ||
return GetKeyBase(dbm.NewMemDB()) | ||
} |
Oops, something went wrong.