Added tx subcommands and automate manual testing
This commit is contained in:
parent
bae7cec3fa
commit
734b1073ba
|
@ -20,7 +20,7 @@ func GetCommands(cmds ...*cobra.Command) []*cobra.Command {
|
|||
// 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, "", "<host>:<port> to tendermint rpc interface for this chain")
|
||||
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
|
||||
|
@ -31,7 +31,7 @@ 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, "", "<host>:<port> to tendermint rpc interface for this chain")
|
||||
c.Flags().String(FlagNode, "tcp://localhost:46657", "<host>:<port> to tendermint rpc interface for this chain")
|
||||
}
|
||||
return cmds
|
||||
}
|
||||
|
|
|
@ -1,21 +1,9 @@
|
|||
package tx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
flagTags = "tag"
|
||||
flagAny = "any"
|
||||
)
|
||||
|
||||
// XXX: remove this when not needed
|
||||
func todoNotImplemented(_ *cobra.Command, _ []string) error {
|
||||
return errors.New("TODO: Command not yet implemented")
|
||||
}
|
||||
|
||||
// AddCommands adds a number of tx-query related subcommands
|
||||
func AddCommands(cmd *cobra.Command) {
|
||||
cmd.AddCommand(
|
||||
|
@ -23,23 +11,3 @@ func AddCommands(cmd *cobra.Command) {
|
|||
txCommand(),
|
||||
)
|
||||
}
|
||||
|
||||
func txSearchCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "txs",
|
||||
Short: "Search for all transactions that match the given tags",
|
||||
RunE: todoNotImplemented,
|
||||
}
|
||||
cmd.Flags().StringSlice(flagTags, nil, "Tags that must match (may provide multiple)")
|
||||
cmd.Flags().Bool(flagAny, false, "Return transactions that match ANY tag, rather than ALL")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func txCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "tx <hash>",
|
||||
Short: "Matches this txhash over all committed blocks",
|
||||
RunE: todoNotImplemented,
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package tx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/app"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
)
|
||||
|
||||
const (
|
||||
flagTags = "tag"
|
||||
flagAny = "any"
|
||||
)
|
||||
|
||||
func txSearchCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "txs",
|
||||
Short: "Search for all transactions that match the given tags",
|
||||
RunE: searchTx,
|
||||
}
|
||||
cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:46657", "Node to connect to")
|
||||
// TODO: change this to false when we can
|
||||
cmd.Flags().Bool(client.FlagTrustNode, true, "Don't verify proofs for responses")
|
||||
cmd.Flags().StringSlice(flagTags, nil, "Tags that must match (may provide multiple)")
|
||||
cmd.Flags().Bool(flagAny, false, "Return transactions that match ANY tag, rather than ALL")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func searchTx(cmd *cobra.Command, args []string) error {
|
||||
tags := viper.GetStringSlice(flagTags)
|
||||
if len(tags) == 0 {
|
||||
return errors.New("Must declare at least one tag to search")
|
||||
}
|
||||
// XXX: implement ANY
|
||||
query := strings.Join(tags, " AND ")
|
||||
|
||||
// get the node
|
||||
uri := viper.GetString(client.FlagNode)
|
||||
if uri == "" {
|
||||
return errors.New("Must define which node to query with --node")
|
||||
}
|
||||
node := client.GetNode(uri)
|
||||
|
||||
prove := !viper.GetBool(client.FlagTrustNode)
|
||||
res, err := node.TxSearch(query, prove)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err := formatTxResults(res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cdc := app.MakeTxCodec()
|
||||
output, err := cdc.MarshalJSON(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(output))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatTxResults(res []*ctypes.ResultTx) ([]txInfo, error) {
|
||||
var err error
|
||||
out := make([]txInfo, len(res))
|
||||
for i := range res {
|
||||
out[i], err = formatTxResult(res[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package tx
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/app" // XXX: not good
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
abci "github.com/tendermint/abci/types"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
)
|
||||
|
||||
func txCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "tx <hash>",
|
||||
Short: "Matches this txhash over all committed blocks",
|
||||
RunE: queryTx,
|
||||
}
|
||||
cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:46657", "Node to connect to")
|
||||
// TODO: change this to false when we can
|
||||
cmd.Flags().Bool(client.FlagTrustNode, true, "Don't verify proofs for responses")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func queryTx(cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 1 || len(args[0]) == 0 {
|
||||
return errors.New("You must provide a tx hash")
|
||||
}
|
||||
|
||||
// find the key to look up the account
|
||||
hexStr := args[0]
|
||||
hash, err := hex.DecodeString(hexStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// get the node
|
||||
uri := viper.GetString(client.FlagNode)
|
||||
if uri == "" {
|
||||
return errors.New("Must define which node to query with --node")
|
||||
}
|
||||
node := client.GetNode(uri)
|
||||
prove := !viper.GetBool(client.FlagTrustNode)
|
||||
|
||||
res, err := node.Tx(hash, prove)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := formatTxResult(res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cdc := app.MakeTxCodec()
|
||||
output, err := cdc.MarshalJSON(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(output))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatTxResult(res *ctypes.ResultTx) (txInfo, error) {
|
||||
height := res.Height
|
||||
result := res.TxResult
|
||||
// TODO: verify the proof if requested
|
||||
|
||||
tx, err := parseTx(res.Tx)
|
||||
if err != nil {
|
||||
return txInfo{}, err
|
||||
}
|
||||
|
||||
info := txInfo{
|
||||
Height: height,
|
||||
Tx: tx,
|
||||
Result: result,
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// txInfo is used to prepare info to display
|
||||
type txInfo struct {
|
||||
Height int64 `json:"height"`
|
||||
Tx sdk.Tx `json:"tx"`
|
||||
Result abci.ResponseDeliverTx `json:"result"`
|
||||
}
|
||||
|
||||
func parseTx(txBytes []byte) (sdk.Tx, error) {
|
||||
var tx sdk.StdTx
|
||||
cdc := app.MakeTxCodec()
|
||||
err := cdc.UnmarshalBinary(txBytes, &tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tx, nil
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Note: Bucky, I know you want to kill bash tests.
|
||||
# Please show me how to do an alternative to this.
|
||||
# I would rather get code running before I leave than
|
||||
# fight trying to invent some new test harness that
|
||||
# no one else will understand.
|
||||
#
|
||||
# Thus, I leave this as an exercise to the reader to
|
||||
# port into a non-bash version. And I don't do it proper...
|
||||
# just automate my manual tests
|
||||
|
||||
# WARNING!!!
|
||||
rm -rf ~/.basecoind ~/.basecli
|
||||
cd $GOPATH/src/github.com/cosmos/cosmos-sdk
|
||||
# make get_vendor_deps
|
||||
make build
|
||||
|
||||
# init stuff
|
||||
SEED=`./build/basecoind init | tail -1`
|
||||
PASS='some-silly-123'
|
||||
(echo $PASS; echo $SEED) | ./build/basecli keys add demo --recover
|
||||
ADDR=`./build/basecli keys show demo | cut -f3`
|
||||
echo "Recovered seed for demo:" $ADDR
|
||||
|
||||
# start up server
|
||||
./build/basecoind start > ~/.basecoind/basecoind.log 2>&1 &
|
||||
sleep 5
|
||||
PID_SERVER=$!
|
||||
|
||||
# query original state
|
||||
TO='ABCAFE00DEADBEEF00CAFE00DEADBEEF00CAFE00'
|
||||
echo; echo "My account:" $ADDR
|
||||
./build/basecli account $ADDR
|
||||
echo; echo "Empty account:" $TO
|
||||
./build/basecli account $TO
|
||||
|
||||
# send some money
|
||||
TX=`echo $PASS | ./build/basecli send --to=$TO --amount=1000mycoin --name=demo --seq=0`
|
||||
echo; echo "SendTx"; echo $TX
|
||||
HASH=`echo $TX | cut -d' ' -f6`
|
||||
echo "tx hash:" $HASH
|
||||
|
||||
# let some blocks come up....
|
||||
sleep 2
|
||||
|
||||
# balances change
|
||||
echo; echo "My account went down"
|
||||
./build/basecli account $ADDR
|
||||
echo; echo "Empty account got some cash"
|
||||
./build/basecli account $TO
|
||||
|
||||
# query original tx
|
||||
echo; echo "View tx"
|
||||
./build/basecli tx $HASH
|
||||
|
||||
# shutdown
|
||||
kill $PID_SERVER
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/app"
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/app" // XXX: not good
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
|
|
@ -39,6 +39,7 @@ func handleSendMsg(ctx sdk.Context, ck CoinKeeper, msg SendMsg) sdk.Result {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: add some tags so we can search it!
|
||||
return sdk.Result{} // TODO
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue