Merge PR #2842: Fix tx search
This commit is contained in:
commit
1a18a428a4
|
@ -3,6 +3,7 @@
|
|||
BREAKING CHANGES
|
||||
|
||||
* Gaia REST API (`gaiacli advanced rest-server`)
|
||||
* [gaia-lite] [\#2819](https://github.com/cosmos/cosmos-sdk/pull/2819) Txs query param format is now: `/txs?tag=value` (removed '' wrapping the query parameter `value`)
|
||||
|
||||
* Gaia CLI (`gaiacli`)
|
||||
* [cli] [\#2728](https://github.com/cosmos/cosmos-sdk/pull/2728) Seperate `tx` and `query` subcommands by module
|
||||
|
@ -56,10 +57,12 @@ FEATURES
|
|||
IMPROVEMENTS
|
||||
|
||||
* Gaia REST API (`gaiacli advanced rest-server`)
|
||||
* [gaia-lite] [\#2819](https://github.com/cosmos/cosmos-sdk/pull/2819) Tx search now supports multiple tags as query parameters
|
||||
* [\#2836](https://github.com/cosmos/cosmos-sdk/pull/2836) Expose LCD router to allow users to register routes there.
|
||||
|
||||
* Gaia CLI (`gaiacli`)
|
||||
* [\#2749](https://github.com/cosmos/cosmos-sdk/pull/2749) Add --chain-id flag to gaiad testnet
|
||||
* [\#2819](https://github.com/cosmos/cosmos-sdk/pull/2819) Tx search now supports multiple tags as query parameters
|
||||
|
||||
* Gaia
|
||||
- #2772 Update BaseApp to not persist state when the ante handler fails on DeliverTx.
|
||||
|
@ -78,7 +81,7 @@ IMPROVEMENTS
|
|||
- #2779 Introduce `ValidateBasic` to the `Tx` interface and call it in the ante
|
||||
handler.
|
||||
- #2825 More staking and distribution invariants
|
||||
* #2912 Print commit ID in hex when commit is synced.
|
||||
- #2912 Print commit ID in hex when commit is synced.
|
||||
|
||||
* Tendermint
|
||||
- #2796 Update to go-amino 0.14.1
|
||||
|
@ -95,7 +98,7 @@ BUG FIXES
|
|||
* Gaia
|
||||
* [\#2723] Use `cosmosvalcons` Bech32 prefix in `tendermint show-address`
|
||||
* [\#2742](https://github.com/cosmos/cosmos-sdk/issues/2742) Fix time format of TimeoutCommit override
|
||||
* [\#2898](https://github.com/cosmos/cosmos-sdk/issues/2898) Remove redundant '$' in docker-compose.yml
|
||||
* [\#2898](https://github.com/cosmos/cosmos-sdk/issues/2898) Remove redundant '$' in docker-compose.yml
|
||||
|
||||
* SDK
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -399,57 +400,39 @@ func TestTxs(t *testing.T) {
|
|||
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
|
||||
defer cleanup()
|
||||
|
||||
// query wrong
|
||||
res, body := Request(t, port, "GET", "/txs", nil)
|
||||
require.Equal(t, http.StatusBadRequest, res.StatusCode, body)
|
||||
var emptyTxs []tx.Info
|
||||
txs := getTransactions(t, port)
|
||||
require.Equal(t, emptyTxs, txs)
|
||||
|
||||
// query empty
|
||||
res, body = Request(t, port, "GET", fmt.Sprintf("/txs?tag=sender_bech32='%s'", "cosmos1jawd35d9aq4u76sr3fjalmcqc8hqygs90d0g0v"), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
require.Equal(t, "[]", body)
|
||||
txs = getTransactions(t, port, fmt.Sprintf("sender=%s", addr.String()))
|
||||
require.Equal(t, emptyTxs, txs)
|
||||
|
||||
// create TX
|
||||
// also tests url decoding
|
||||
txs = getTransactions(t, port, fmt.Sprintf("sender=%s", addr.String()))
|
||||
require.Equal(t, emptyTxs, txs)
|
||||
|
||||
txs = getTransactions(t, port, fmt.Sprintf("action=submit%%20proposal&proposer=%s", addr.String()))
|
||||
require.Equal(t, emptyTxs, txs)
|
||||
|
||||
// create tx
|
||||
receiveAddr, resultTx := doSend(t, port, seed, name, password, addr)
|
||||
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// check if tx is findable
|
||||
res, body = Request(t, port, "GET", fmt.Sprintf("/txs/%s", resultTx.Hash), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
var indexedTxs []tx.Info
|
||||
|
||||
// check if tx is queryable
|
||||
res, body = Request(t, port, "GET", fmt.Sprintf("/txs?tag=tx.hash='%s'", resultTx.Hash), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
require.NotEqual(t, "[]", body)
|
||||
|
||||
err := cdc.UnmarshalJSON([]byte(body), &indexedTxs)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(indexedTxs))
|
||||
|
||||
// XXX should this move into some other testfile for txs in general?
|
||||
// test if created TX hash is the correct hash
|
||||
require.Equal(t, resultTx.Hash, indexedTxs[0].Hash)
|
||||
txs = getTransactions(t, port, fmt.Sprintf("tx.hash=%s", resultTx.Hash))
|
||||
require.Len(t, txs, 1)
|
||||
require.Equal(t, resultTx.Hash, txs[0].Hash)
|
||||
|
||||
// query sender
|
||||
// also tests url decoding
|
||||
res, body = Request(t, port, "GET", fmt.Sprintf("/txs?tag=sender_bech32=%%27%s%%27", addr), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
err = cdc.UnmarshalJSON([]byte(body), &indexedTxs)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(indexedTxs), "%v", indexedTxs) // there are 2 txs created with doSend
|
||||
require.Equal(t, resultTx.Height, indexedTxs[0].Height)
|
||||
txs = getTransactions(t, port, fmt.Sprintf("sender=%s", addr.String()))
|
||||
require.Len(t, txs, 1)
|
||||
require.Equal(t, resultTx.Height, txs[0].Height)
|
||||
|
||||
// query recipient
|
||||
res, body = Request(t, port, "GET", fmt.Sprintf("/txs?tag=recipient_bech32='%s'", receiveAddr), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
err = cdc.UnmarshalJSON([]byte(body), &indexedTxs)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(indexedTxs))
|
||||
require.Equal(t, resultTx.Height, indexedTxs[0].Height)
|
||||
txs = getTransactions(t, port, fmt.Sprintf("recipient=%s", receiveAddr.String()))
|
||||
require.Len(t, txs, 1)
|
||||
require.Equal(t, resultTx.Height, txs[0].Height)
|
||||
}
|
||||
|
||||
func TestPoolParamsQuery(t *testing.T) {
|
||||
|
@ -534,6 +517,14 @@ func TestBonding(t *testing.T) {
|
|||
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
|
||||
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
|
||||
|
||||
// query tx
|
||||
txs := getTransactions(t, port,
|
||||
fmt.Sprintf("action=delegate&delegator=%s", addr),
|
||||
fmt.Sprintf("destination-validator=%s", operAddrs[0]),
|
||||
)
|
||||
require.Len(t, txs, 1)
|
||||
require.Equal(t, resultTx.Height, txs[0].Height)
|
||||
|
||||
acc := getAccount(t, port, addr)
|
||||
coins := acc.GetCoins()
|
||||
|
||||
|
@ -571,6 +562,14 @@ func TestBonding(t *testing.T) {
|
|||
coins = acc.GetCoins()
|
||||
require.Equal(t, int64(40), coins.AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||
|
||||
// query tx
|
||||
txs = getTransactions(t, port,
|
||||
fmt.Sprintf("action=begin-unbonding&delegator=%s", addr),
|
||||
fmt.Sprintf("source-validator=%s", operAddrs[0]),
|
||||
)
|
||||
require.Len(t, txs, 1)
|
||||
require.Equal(t, resultTx.Height, txs[0].Height)
|
||||
|
||||
unbonding := getUndelegation(t, port, addr, operAddrs[0])
|
||||
require.Equal(t, "30", unbonding.Balance.Amount.String())
|
||||
|
||||
|
@ -581,6 +580,15 @@ func TestBonding(t *testing.T) {
|
|||
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
|
||||
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
|
||||
|
||||
// query tx
|
||||
txs = getTransactions(t, port,
|
||||
fmt.Sprintf("action=begin-redelegation&delegator=%s", addr),
|
||||
fmt.Sprintf("source-validator=%s", operAddrs[0]),
|
||||
fmt.Sprintf("destination-validator=%s", operAddrs[1]),
|
||||
)
|
||||
require.Len(t, txs, 1)
|
||||
require.Equal(t, resultTx.Height, txs[0].Height)
|
||||
|
||||
// query delegations, unbondings and redelegations from validator and delegator
|
||||
delegatorDels = getDelegatorDelegations(t, port, addr)
|
||||
require.Len(t, delegatorDels, 1)
|
||||
|
@ -606,7 +614,7 @@ func TestBonding(t *testing.T) {
|
|||
// require.Equal(t, sdk.Unbonding, bondedValidators[0].Status)
|
||||
|
||||
// query txs
|
||||
txs := getBondingTxs(t, port, addr, "")
|
||||
txs = getBondingTxs(t, port, addr, "")
|
||||
require.Len(t, txs, 3, "All Txs found")
|
||||
|
||||
txs = getBondingTxs(t, port, addr, "bond")
|
||||
|
@ -639,6 +647,11 @@ func TestSubmitProposal(t *testing.T) {
|
|||
// query proposal
|
||||
proposal := getProposal(t, port, proposalID)
|
||||
require.Equal(t, "Test", proposal.GetTitle())
|
||||
|
||||
// query tx
|
||||
txs := getTransactions(t, port, fmt.Sprintf("action=submit-proposal&proposer=%s", addr))
|
||||
require.Len(t, txs, 1)
|
||||
require.Equal(t, resultTx.Height, txs[0].Height)
|
||||
}
|
||||
|
||||
func TestDeposit(t *testing.T) {
|
||||
|
@ -666,6 +679,11 @@ func TestDeposit(t *testing.T) {
|
|||
resultTx = doDeposit(t, port, seed, name, password, addr, proposalID, 5)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// query tx
|
||||
txs := getTransactions(t, port, fmt.Sprintf("action=deposit&depositor=%s", addr))
|
||||
require.Len(t, txs, 1)
|
||||
require.Equal(t, resultTx.Height, txs[0].Height)
|
||||
|
||||
// query proposal
|
||||
proposal = getProposal(t, port, proposalID)
|
||||
require.True(t, proposal.GetTotalDeposit().IsEqual(sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 10)}))
|
||||
|
@ -708,6 +726,11 @@ func TestVote(t *testing.T) {
|
|||
resultTx = doVote(t, port, seed, name, password, addr, proposalID)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// query tx
|
||||
txs := getTransactions(t, port, fmt.Sprintf("action=vote&voter=%s", addr))
|
||||
require.Len(t, txs, 1)
|
||||
require.Equal(t, resultTx.Height, txs[0].Height)
|
||||
|
||||
vote := getVote(t, port, proposalID, addr)
|
||||
require.Equal(t, proposalID, vote.ProposalID)
|
||||
require.Equal(t, gov.OptionYes, vote.Option)
|
||||
|
@ -866,7 +889,7 @@ func TestProposalsQuery(t *testing.T) {
|
|||
//_____________________________________________________________________________
|
||||
// get the account to get the sequence
|
||||
func getAccount(t *testing.T, port string, addr sdk.AccAddress) auth.Account {
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/auth/accounts/%s", addr), nil)
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/auth/accounts/%s", addr.String()), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var acc auth.Account
|
||||
err := cdc.UnmarshalJSON([]byte(body), &acc)
|
||||
|
@ -944,6 +967,22 @@ func doSend(t *testing.T, port, seed, name, password string, addr sdk.AccAddress
|
|||
return receiveAddr, resultTx
|
||||
}
|
||||
|
||||
func getTransactions(t *testing.T, port string, tags ...string) []tx.Info {
|
||||
var txs []tx.Info
|
||||
if len(tags) == 0 {
|
||||
return txs
|
||||
}
|
||||
queryStr := strings.Join(tags, "&")
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/txs?%s", queryStr), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
err := cdc.UnmarshalJSON([]byte(body), &txs)
|
||||
require.NoError(t, err)
|
||||
return txs
|
||||
}
|
||||
|
||||
// ============= IBC Module ================
|
||||
|
||||
func doIBCTransfer(t *testing.T, port, seed, name, password string, addr sdk.AccAddress) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||
// create receive address
|
||||
kb := client.MockKeyBase()
|
||||
|
@ -984,6 +1023,8 @@ func doIBCTransfer(t *testing.T, port, seed, name, password string, addr sdk.Acc
|
|||
return resultTx
|
||||
}
|
||||
|
||||
// ============= Slashing Module ================
|
||||
|
||||
func getSigningInfo(t *testing.T, port string, validatorPubKey string) slashing.ValidatorSigningInfo {
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/slashing/validators/%s/signing_info", validatorPubKey), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
@ -995,6 +1036,31 @@ func getSigningInfo(t *testing.T, port string, validatorPubKey string) slashing.
|
|||
return signingInfo
|
||||
}
|
||||
|
||||
func doUnjail(t *testing.T, port, seed, name, password string,
|
||||
valAddr sdk.ValAddress) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||
chainID := viper.GetString(client.FlagChainID)
|
||||
|
||||
jsonStr := []byte(fmt.Sprintf(`{
|
||||
"base_req": {
|
||||
"name": "%s",
|
||||
"password": "%s",
|
||||
"chain_id": "%s",
|
||||
"account_number":"1",
|
||||
"sequence":"1"
|
||||
}
|
||||
}`, name, password, chainID))
|
||||
|
||||
res, body := Request(t, port, "POST", fmt.Sprintf("/slashing/validators/%s/unjail", valAddr.String()), jsonStr)
|
||||
// TODO : fails with "401 must use own validator address"
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
var results []ctypes.ResultBroadcastTxCommit
|
||||
err := cdc.UnmarshalJSON([]byte(body), &results)
|
||||
require.Nil(t, err)
|
||||
|
||||
return results[0]
|
||||
}
|
||||
|
||||
// ============= Stake Module ================
|
||||
|
||||
func getDelegation(t *testing.T, port string, delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress) stake.Delegation {
|
||||
|
|
|
@ -209,14 +209,14 @@ paths:
|
|||
tags:
|
||||
- ICS0
|
||||
summary: Search transactions
|
||||
description: Search transactions by tag
|
||||
description: Search transactions by tag(s).
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- in: query
|
||||
name: tag
|
||||
type: string
|
||||
description: "transaction tag, for instance: sender_bech32=`'cosmos1g9ahr6xhht5rmqven628nklxluzyv8z9jqjcmc'`"
|
||||
description: "transaction tags such as 'action=submit-proposal' and 'proposer=cosmos1g9ahr6xhht5rmqven628nklxluzyv8z9jqjcmc' which results in the following endpoint: 'GET /txs?action=submit-proposal&proposer=cosmos1g9ahr6xhht5rmqven628nklxluzyv8z9jqjcmc'"
|
||||
required: true
|
||||
- in: query
|
||||
name: page
|
||||
|
@ -228,7 +228,7 @@ paths:
|
|||
type: integer
|
||||
responses:
|
||||
200:
|
||||
description: All Tx matching the provided tags
|
||||
description: All txs matching the provided tags
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
|
|
|
@ -9,18 +9,18 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
"github.com/cosmos/cosmos-sdk/client/utils"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/utils"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
)
|
||||
|
||||
const (
|
||||
flagTags = "tag"
|
||||
flagTags = "tags"
|
||||
flagAny = "any"
|
||||
)
|
||||
|
||||
|
@ -30,24 +30,35 @@ func SearchTxCmd(cdc *codec.Codec) *cobra.Command {
|
|||
Use: "txs",
|
||||
Short: "Search for all transactions that match the given tags.",
|
||||
Long: strings.TrimSpace(`
|
||||
Search for transactions that match the given tags. By default, transactions must match ALL tags
|
||||
passed to the --tags option. To match any transaction, use the --any option.
|
||||
Search for transactions that match exactly the given tags. For example:
|
||||
|
||||
For example:
|
||||
|
||||
$ gaiacli tendermint txs --tag test1,test2
|
||||
|
||||
will match any transaction tagged with both test1,test2. To match a transaction tagged with either
|
||||
test1 or test2, use:
|
||||
|
||||
$ gaiacli tendermint txs --tag test1,test2 --any
|
||||
$ gaiacli query txs --tags '<tag1>:<value1>&<tag2>:<value2>'
|
||||
`),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
tags := viper.GetStringSlice(flagTags)
|
||||
tagsStr := viper.GetString(flagTags)
|
||||
tagsStr = strings.Trim(tagsStr, "'")
|
||||
var tags []string
|
||||
if strings.Contains(tagsStr, "&") {
|
||||
tags = strings.Split(tagsStr, "&")
|
||||
} else {
|
||||
tags = append(tags, tagsStr)
|
||||
}
|
||||
|
||||
var tmTags []string
|
||||
for _, tag := range tags {
|
||||
if !strings.Contains(tag, ":") {
|
||||
return fmt.Errorf("%s should be of the format <key>:<value>", tagsStr)
|
||||
} else if strings.Count(tag, ":") > 1 {
|
||||
return fmt.Errorf("%s should only contain one <key>:<value> pair", tagsStr)
|
||||
}
|
||||
|
||||
keyValue := strings.Split(tag, ":")
|
||||
tag = fmt.Sprintf("%s='%s'", keyValue[0], keyValue[1])
|
||||
tmTags = append(tmTags, tag)
|
||||
}
|
||||
|
||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
||||
|
||||
txs, err := searchTxs(cliCtx, cdc, tags)
|
||||
txs, err := searchTxs(cliCtx, cdc, tmTags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -74,8 +85,7 @@ $ gaiacli tendermint txs --tag test1,test2 --any
|
|||
viper.BindPFlag(client.FlagChainID, cmd.Flags().Lookup(client.FlagChainID))
|
||||
cmd.Flags().Bool(client.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
|
||||
viper.BindPFlag(client.FlagTrustNode, cmd.Flags().Lookup(client.FlagTrustNode))
|
||||
cmd.Flags().StringSlice(flagTags, nil, "Comma-separated list of tags that must match")
|
||||
cmd.Flags().Bool(flagAny, false, "Return transactions that match ANY tag, rather than ALL")
|
||||
cmd.Flags().String(flagTags, "", "tag:value list of tags that must match")
|
||||
return cmd
|
||||
}
|
||||
|
||||
|
@ -139,45 +149,35 @@ func FormatTxResults(cdc *codec.Codec, res []*ctypes.ResultTx) ([]Info, error) {
|
|||
// Search Tx REST Handler
|
||||
func SearchTxRequestHandlerFn(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
tag := r.FormValue("tag")
|
||||
if tag == "" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte("You need to provide at least a tag as a key=value pair to search for. Postfix the key with _bech32 to search bech32-encoded addresses or public keys"))
|
||||
return
|
||||
}
|
||||
|
||||
keyValue := strings.Split(tag, "=")
|
||||
key := keyValue[0]
|
||||
|
||||
value, err := url.QueryUnescape(keyValue[1])
|
||||
var tags []string
|
||||
var txs []Info
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, sdk.AppendMsgToErr("could not decode address", err.Error()))
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, sdk.AppendMsgToErr("could not parse query parameters", err.Error()))
|
||||
return
|
||||
}
|
||||
if len(r.Form) == 0 {
|
||||
utils.PostProcessResponse(w, cdc, txs, cliCtx.Indent)
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasSuffix(key, "_bech32") {
|
||||
bech32address := strings.Trim(value, "'")
|
||||
prefix := strings.Split(bech32address, "1")[0]
|
||||
bz, err := sdk.GetFromBech32(bech32address, prefix)
|
||||
for key, values := range r.Form {
|
||||
value, err := url.QueryUnescape(values[0])
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, sdk.AppendMsgToErr("could not decode query value", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
tag = strings.TrimRight(key, "_bech32") + "='" + sdk.AccAddress(bz).String() + "'"
|
||||
tag := fmt.Sprintf("%s='%s'", key, value)
|
||||
tags = append(tags, tag)
|
||||
}
|
||||
|
||||
txs, err := searchTxs(cliCtx, cdc, []string{tag})
|
||||
txs, err = searchTxs(cliCtx, cdc, tags)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if len(txs) == 0 {
|
||||
w.Write([]byte("[]"))
|
||||
return
|
||||
}
|
||||
|
||||
utils.PostProcessResponse(w, cdc, txs, cliCtx.Indent)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
|
@ -277,7 +278,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
|
|||
require.NotZero(t, validatorDelegations[0].Shares)
|
||||
|
||||
// unbond a single share
|
||||
unbondStr := fmt.Sprintf("gaiacli tx stake unbond begin %v", flags)
|
||||
unbondStr := fmt.Sprintf("gaiacli tx stake unbond %v", flags)
|
||||
unbondStr += fmt.Sprintf(" --from=%s", "bar")
|
||||
unbondStr += fmt.Sprintf(" --validator=%s", sdk.ValAddress(barAddr))
|
||||
unbondStr += fmt.Sprintf(" --shares-amount=%v", "1")
|
||||
|
@ -354,6 +355,9 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
|||
executeWrite(t, spStr, app.DefaultKeyPass)
|
||||
tests.WaitForNextNBlocksTM(2, port)
|
||||
|
||||
txs := executeGetTxs(t, fmt.Sprintf("gaiacli query txs --tags='action:submit-proposal&proposer:%s' %v", fooAddr, flags))
|
||||
require.Len(t, txs, 1)
|
||||
|
||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||
require.Equal(t, int64(45), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||
|
||||
|
@ -398,6 +402,9 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
|||
fooAddr, flags))
|
||||
require.Equal(t, int64(15), deposit.Amount.AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||
|
||||
txs = executeGetTxs(t, fmt.Sprintf("gaiacli query txs --tags=action:deposit&depositor:%s %v", fooAddr, flags))
|
||||
require.Len(t, txs, 1)
|
||||
|
||||
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
|
||||
|
||||
require.Equal(t, int64(35), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
|
||||
|
@ -432,6 +439,9 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
|
|||
require.Equal(t, uint64(1), votes[0].ProposalID)
|
||||
require.Equal(t, gov.OptionYes, votes[0].Option)
|
||||
|
||||
txs = executeGetTxs(t, fmt.Sprintf("gaiacli query txs --tags=action:vote&voter:%s %v", fooAddr, flags))
|
||||
require.Len(t, txs, 1)
|
||||
|
||||
proposalsQuery, _ = tests.ExecuteT(t, fmt.Sprintf("gaiacli query gov proposals --status=DepositPeriod %v", flags), "")
|
||||
require.Equal(t, "No matching proposals found", proposalsQuery)
|
||||
|
||||
|
@ -736,6 +746,18 @@ func executeGetAccount(t *testing.T, cmdStr string) auth.BaseAccount {
|
|||
return acc
|
||||
}
|
||||
|
||||
//___________________________________________________________________________________
|
||||
// txs
|
||||
|
||||
func executeGetTxs(t *testing.T, cmdStr string) []tx.Info {
|
||||
out, _ := tests.ExecuteT(t, cmdStr, "")
|
||||
var txs []tx.Info
|
||||
cdc := app.MakeCodec()
|
||||
err := cdc.UnmarshalJSON([]byte(out), &txs)
|
||||
require.NoError(t, err, "out %v\n, err %v", out, err)
|
||||
return txs
|
||||
}
|
||||
|
||||
//___________________________________________________________________________________
|
||||
// stake
|
||||
|
||||
|
|
|
@ -183,10 +183,50 @@ gaiacli tx sign --validate-signatures signedSendTx.json
|
|||
|
||||
You can broadcast the signed transaction to a node by providing the JSON file to the following command:
|
||||
|
||||
```
|
||||
```bash
|
||||
gaiacli tx broadcast --node=<node> signedSendTx.json
|
||||
```
|
||||
|
||||
### Query Transactions
|
||||
|
||||
#### Matching a set of tags
|
||||
|
||||
You can use the transaction search command to query for transactions that match a specific set of `tags`, which are added on every transaction.
|
||||
|
||||
Each tag is conformed by a key-value pair in the form of `<tag>:<value>`. Tags can also be combined to query for a more specific result using the `&` symbol.
|
||||
|
||||
The command for querying transactions using a `tag` is the following:
|
||||
|
||||
```bash
|
||||
gaiacli query txs --tags='<tag>:<value>'
|
||||
```
|
||||
|
||||
And for using multiple `tags`:
|
||||
|
||||
```bash
|
||||
gaiacli query txs --tags='<tag1>:<value1>&<tag2>:<value2>'
|
||||
```
|
||||
|
||||
::: tip Note
|
||||
|
||||
You can find a list of available `tags` on each of the SDK modules:
|
||||
|
||||
- [Common tags](https://github.com/cosmos/cosmos-sdk/blob/d1e76221d8e28824bb4791cb4ad8662d2ae9051e/types/tags.go#L57-L63)
|
||||
- [Staking tags](https://github.com/cosmos/cosmos-sdk/blob/d1e76221d8e28824bb4791cb4ad8662d2ae9051e/x/stake/tags/tags.go#L8-L24)
|
||||
- [Governance tags](https://github.com/cosmos/cosmos-sdk/blob/d1e76221d8e28824bb4791cb4ad8662d2ae9051e/x/gov/tags/tags.go#L8-L22)
|
||||
- [Slashing tags](https://github.com/cosmos/cosmos-sdk/blob/d1e76221d8e28824bb4791cb4ad8662d2ae9051e/x/slashing/handler.go#L52)
|
||||
- [Distribution tags](https://github.com/cosmos/cosmos-sdk/blob/develop/x/distribution/tags/tags.go#L8-L17)
|
||||
- [Bank tags](https://github.com/cosmos/cosmos-sdk/blob/d1e76221d8e28824bb4791cb4ad8662d2ae9051e/x/bank/keeper.go#L193-L206)
|
||||
:::
|
||||
|
||||
#### Matching a transaction's hash
|
||||
|
||||
You can also query a single transaction by its hash using the following command:
|
||||
|
||||
```bash
|
||||
gaiacli query tx [hash]
|
||||
```
|
||||
|
||||
### Staking
|
||||
|
||||
#### Set up a Validator
|
||||
|
|
Loading…
Reference in New Issue