Merge PR #6525: x/bank: Refactor CLI & Tests

This commit is contained in:
Alexander Bezobchuk 2020-06-30 16:59:21 -04:00 committed by GitHub
parent 56af94e6ab
commit d5049413ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 665 additions and 561 deletions

View File

@ -63,6 +63,7 @@ older clients.
### API Breaking Changes
* (client) [\#6525](https://github.com/cosmos/cosmos-sdk/pull/6525) Removed support for `indent` in JSON responses. Clients should consider piping to an external tool such as `jq`.
* (x/staking) [\#6451](https://github.com/cosmos/cosmos-sdk/pull/6451) `DefaultParamspace` and `ParamKeyTable` in staking module are moved from keeper to types to enforce consistency.
* [\#6409](https://github.com/cosmos/cosmos-sdk/pull/6409) Rename all IsEmpty methods to Empty across the codebase and enforce consistency.
* [\#6231](https://github.com/cosmos/cosmos-sdk/pull/6231) Simplify `AppModule` interface, `Route` and `NewHandler` methods become only `Route`

View File

@ -6,6 +6,9 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/cosmos/cosmos-sdk/client/flags"
)
// ValidateCmd returns unknown command error or Help display if help flag set
@ -55,3 +58,95 @@ func ValidateCmd(cmd *cobra.Command, args []string) error {
return cmd.Help()
}
// ReadPersistentCommandFlags returns a Context with fields set for "persistent"
// flags that do not necessarily change with context. These must be checked if
// the caller explicitly changed the values.
func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, error) {
if flagSet.Changed(flags.FlagChainID) {
chainID, _ := flagSet.GetString(flags.FlagChainID)
clientCtx = clientCtx.WithChainID(chainID)
}
if flagSet.Changed(flags.FlagTrustNode) {
trustNode, _ := flagSet.GetBool(flags.FlagTrustNode)
clientCtx = clientCtx.WithTrustNode(trustNode)
}
if flagSet.Changed(flags.FlagKeyringBackend) {
keyringBackend, _ := flagSet.GetString(flags.FlagKeyringBackend)
kr, err := newKeyringFromFlags(clientCtx, keyringBackend)
if err != nil {
return clientCtx, err
}
clientCtx = clientCtx.WithKeyring(kr)
}
if flagSet.Changed(flags.FlagNode) {
rpcURI, _ := flagSet.GetString(flags.FlagNode)
clientCtx = clientCtx.WithNodeURI(rpcURI)
}
return clientCtx, nil
}
// ReadQueryCommandFlags returns an updated Context with fields set based on flags
// defined in GetCommands. An error is returned if any flag query fails.
//
// Certain flags are naturally command and context dependent, so for these flags
// we do not check if they've been explicitly set by the caller. Other flags can
// be considered "persistent" (e.g. KeyBase or Client) and these should be checked
// if the caller explicitly set those.
func ReadQueryCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, error) {
height, _ := flagSet.GetInt64(flags.FlagHeight)
clientCtx = clientCtx.WithHeight(height)
useLedger, _ := flagSet.GetBool(flags.FlagUseLedger)
clientCtx = clientCtx.WithUseLedger(useLedger)
return ReadPersistentCommandFlags(clientCtx, flagSet)
}
// ReadTxCommandFlags returns an updated Context with fields set based on flags
// defined in PostCommands. An error is returned if any flag query fails.
//
// Certain flags are naturally command and context dependent, so for these flags
// we do not check if they've been explicitly set by the caller. Other flags can
// be considered "persistent" (e.g. KeyBase or Client) and these should be checked
// if the caller explicitly set those.
func ReadTxCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, error) {
clientCtx, err := ReadPersistentCommandFlags(clientCtx, flagSet)
if err != nil {
return clientCtx, err
}
genOnly, _ := flagSet.GetBool(flags.FlagGenerateOnly)
clientCtx = clientCtx.WithGenerateOnly(genOnly)
dryRun, _ := flagSet.GetBool(flags.FlagDryRun)
clientCtx = clientCtx.WithSimulation(dryRun)
offline, _ := flagSet.GetBool(flags.FlagOffline)
clientCtx = clientCtx.WithOffline(offline)
useLedger, _ := flagSet.GetBool(flags.FlagUseLedger)
clientCtx = clientCtx.WithUseLedger(useLedger)
bMode, _ := flagSet.GetString(flags.FlagBroadcastMode)
clientCtx = clientCtx.WithBroadcastMode(bMode)
skipConfirm, _ := flagSet.GetBool(flags.FlagSkipConfirmation)
clientCtx = clientCtx.WithSkipConfirmation(skipConfirm)
from, _ := flagSet.GetString(flags.FlagFrom)
fromAddr, fromName, err := GetFromFields(clientCtx.Keyring, from, clientCtx.GenerateOnly)
if err != nil {
return clientCtx, err
}
clientCtx = clientCtx.WithFrom(from).WithFromAddress(fromAddr).WithFromName(fromName)
return clientCtx, nil
}

View File

@ -43,21 +43,18 @@ type Context struct {
Simulate bool
GenerateOnly bool
Offline bool
Indent bool
SkipConfirm bool
TxGenerator TxGenerator
AccountRetriever AccountRetriever
// TODO: API and CLI interfaces are migrating to a single binary (i.e be part of
// the same process of the application). We need to groom through these fields
// and remove any that no longer make sense.
NodeURI string
Verifier tmlite.Verifier
NodeURI string
Verifier tmlite.Verifier
// TODO: Deprecated (remove).
Codec *codec.Codec
}
// TODO: Remove all New* and Init* methods.
// NewContextWithInputAndFrom returns a new initialized Context with parameters from the
// command line using Viper. It takes a io.Reader and and key name or address and populates
// the FromName and FromAddress field accordingly. It will also create Tendermint verifier
@ -127,33 +124,29 @@ func (ctx Context) InitWithInputAndFrom(input io.Reader, from string) Context {
ctx.BroadcastMode = viper.GetString(flags.FlagBroadcastMode)
ctx.Simulate = viper.GetBool(flags.FlagDryRun)
ctx.Offline = offline
ctx.Indent = viper.GetBool(flags.FlagIndentResponse)
ctx.SkipConfirm = viper.GetBool(flags.FlagSkipConfirmation)
ctx.HomeDir = viper.GetString(flags.FlagHome)
ctx.GenerateOnly = viper.GetBool(flags.FlagGenerateOnly)
homedir := viper.GetString(flags.FlagHome)
genOnly := viper.GetBool(flags.FlagGenerateOnly)
backend := viper.GetString(flags.FlagKeyringBackend)
if len(backend) == 0 {
backend = keyring.BackendMemory
}
kr, err := newKeyringFromFlags(backend, homedir, input, genOnly)
kr, err := newKeyringFromFlags(ctx, backend)
if err != nil {
panic(fmt.Errorf("couldn't acquire keyring: %v", err))
}
fromAddress, fromName, err := GetFromFields(kr, from, genOnly)
fromAddress, fromName, err := GetFromFields(kr, from, ctx.GenerateOnly)
if err != nil {
fmt.Printf("failed to get from fields: %v\n", err)
os.Exit(1)
}
ctx.HomeDir = homedir
ctx.Keyring = kr
ctx.FromAddress = fromAddress
ctx.FromName = fromName
ctx.GenerateOnly = genOnly
if offline {
return ctx
@ -290,6 +283,12 @@ func (ctx Context) WithSimulation(simulate bool) Context {
return ctx
}
// WithOffline returns a copy of the context with updated Offline value.
func (ctx Context) WithOffline(offline bool) Context {
ctx.Offline = offline
return ctx
}
// WithFromName returns a copy of the context with an updated from account name.
func (ctx Context) WithFromName(name string) Context {
ctx.FromName = name
@ -310,6 +309,13 @@ func (ctx Context) WithBroadcastMode(mode string) Context {
return ctx
}
// WithSkipConfirmation returns a copy of the context with an updated SkipConfirm
// value.
func (ctx Context) WithSkipConfirmation(skip bool) Context {
ctx.SkipConfirm = skip
return ctx
}
// WithTxGenerator returns the context with an updated TxGenerator
func (ctx Context) WithTxGenerator(generator TxGenerator) Context {
ctx.TxGenerator = generator
@ -335,6 +341,7 @@ func (ctx Context) PrintOutput(toPrint interface{}) error {
if ctx.OutputFormat == "text" {
// handle text format by decoding and re-encoding JSON as YAML
var j interface{}
err = json.Unmarshal(out, &j)
if err != nil {
return err
@ -344,18 +351,9 @@ func (ctx Context) PrintOutput(toPrint interface{}) error {
if err != nil {
return err
}
} else if ctx.Indent {
// To JSON indent, we re-encode the already encoded JSON given there is no
// error. The re-encoded JSON uses the standard library as the initial encoded
// JSON should have the correct output produced by ctx.JSONMarshaler.
out, err = codec.MarshalIndentFromJSON(out)
if err != nil {
return err
}
}
writer := ctx.Output
// default to stdout
if writer == nil {
writer = os.Stdout
}
@ -409,9 +407,10 @@ func GetFromFields(kr keyring.Keyring, from string, genOnly bool) (sdk.AccAddres
return info.GetAddress(), info.GetName(), nil
}
func newKeyringFromFlags(backend, homedir string, input io.Reader, genOnly bool) (keyring.Keyring, error) {
if genOnly {
return keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, homedir, input)
func newKeyringFromFlags(ctx Context, backend string) (keyring.Keyring, error) {
if ctx.GenerateOnly {
return keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, ctx.HomeDir, ctx.Input)
}
return keyring.New(sdk.KeyringServiceName(), backend, homedir, input)
return keyring.New(sdk.KeyringServiceName(), backend, ctx.HomeDir, ctx.Input)
}

View File

@ -106,36 +106,16 @@ func TestContext_PrintOutput(t *testing.T) {
buf := &bytes.Buffer{}
ctx = ctx.WithOutput(buf)
ctx.OutputFormat = "json"
ctx.Indent = false
err = ctx.PrintOutput(hasAnimal)
require.NoError(t, err)
require.Equal(t,
`{"animal":{"@type":"/cosmos_sdk.codec.v1.Dog","size":"big","name":"Spot"},"x":"10"}
`, string(buf.Bytes()))
// json indent
buf = &bytes.Buffer{}
ctx = ctx.WithOutput(buf)
ctx.OutputFormat = "json"
ctx.Indent = true
err = ctx.PrintOutput(hasAnimal)
require.NoError(t, err)
require.Equal(t,
`{
"animal": {
"@type": "/cosmos_sdk.codec.v1.Dog",
"name": "Spot",
"size": "big"
},
"x": "10"
}
`, string(buf.Bytes()))
// yaml
buf = &bytes.Buffer{}
ctx = ctx.WithOutput(buf)
ctx.OutputFormat = "text"
ctx.Indent = false
err = ctx.PrintOutput(hasAnimal)
require.NoError(t, err)
require.Equal(t,
@ -156,41 +136,16 @@ x: "10"
buf = &bytes.Buffer{}
ctx = ctx.WithOutput(buf)
ctx.OutputFormat = "json"
ctx.Indent = false
err = ctx.PrintOutput(hasAnimal)
require.NoError(t, err)
require.Equal(t,
`{"type":"testdata/HasAnimal","value":{"animal":{"type":"testdata/Dog","value":{"size":"big","name":"Spot"}},"x":"10"}}
`, string(buf.Bytes()))
// json indent
buf = &bytes.Buffer{}
ctx = ctx.WithOutput(buf)
ctx.OutputFormat = "json"
ctx.Indent = true
err = ctx.PrintOutput(hasAnimal)
require.NoError(t, err)
require.Equal(t,
`{
"type": "testdata/HasAnimal",
"value": {
"animal": {
"type": "testdata/Dog",
"value": {
"name": "Spot",
"size": "big"
}
},
"x": "10"
}
}
`, string(buf.Bytes()))
// yaml
buf = &bytes.Buffer{}
ctx = ctx.WithOutput(buf)
ctx.OutputFormat = "text"
ctx.Indent = false
err = ctx.PrintOutput(hasAnimal)
require.NoError(t, err)
require.Equal(t,

View File

@ -57,7 +57,6 @@ const (
FlagDryRun = "dry-run"
FlagGenerateOnly = "generate-only"
FlagOffline = "offline"
FlagIndentResponse = "indent"
FlagOutputDocument = "output-document" // inspired by wget -O
FlagSkipConfirmation = "yes"
FlagProve = "prove"
@ -77,13 +76,13 @@ var (
// GetCommands adds common flags to query commands
func GetCommands(cmds ...*cobra.Command) []*cobra.Command {
for _, c := range cmds {
c.Flags().Bool(FlagIndentResponse, false, "Add indent to JSON response")
c.Flags().Bool(FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device")
c.Flags().String(FlagNode, "tcp://localhost:26657", "<host>:<port> to Tendermint RPC interface for this chain")
c.Flags().Int64(FlagHeight, 0, "Use a specific height to query state at (this can error if the node is pruning state)")
c.Flags().String(FlagKeyringBackend, DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
// TODO: REMOVE VIPER CALLS!
viper.BindPFlag(FlagTrustNode, c.Flags().Lookup(FlagTrustNode))
viper.BindPFlag(FlagUseLedger, c.Flags().Lookup(FlagUseLedger))
viper.BindPFlag(FlagNode, c.Flags().Lookup(FlagNode))
@ -100,7 +99,6 @@ func GetCommands(cmds ...*cobra.Command) []*cobra.Command {
// PostCommands adds common flags for commands to post tx
func PostCommands(cmds ...*cobra.Command) []*cobra.Command {
for _, c := range cmds {
c.Flags().Bool(FlagIndentResponse, false, "Add indent to JSON response")
c.Flags().String(FlagFrom, "", "Name or address of private key with which to sign")
c.Flags().Uint64P(FlagAccountNumber, "a", 0, "The account number of the signing account (offline mode only)")
c.Flags().Uint64P(FlagSequence, "s", 0, "The sequence number of the signing account (offline mode only)")
@ -120,10 +118,15 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command {
c.Flags().String(FlagSignMode, "", "Choose sign mode (direct|amino-json), this is an advanced feature")
// --gas can accept integers and "simulate"
//
// TODO: Remove usage of var in favor of string as this is technical creating
// a singleton usage pattern and can cause issues in parallel tests.
c.Flags().Var(&GasFlagVar, "gas", fmt.Sprintf(
"gas limit to set per-transaction; set to %q to calculate required gas automatically (default %d)",
GasFlagAuto, DefaultGasLimit,
))
// TODO: REMOVE VIPER CALLS!
viper.BindPFlag(FlagTrustNode, c.Flags().Lookup(FlagTrustNode))
viper.BindPFlag(FlagUseLedger, c.Flags().Lookup(FlagUseLedger))
viper.BindPFlag(FlagNode, c.Flags().Lookup(FlagNode))
@ -137,8 +140,6 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command {
return cmds
}
// Gas flag parsing functions
// GasSetting encapsulates the possible values passed through the --gas flag.
type GasSetting struct {
Simulate bool

View File

@ -78,7 +78,6 @@ the flag --nosort is set.
cmd.Flags().Uint32(flagCoinType, sdk.GetConfig().GetCoinType(), "coin type number for HD derivation")
cmd.Flags().Uint32(flagAccount, 0, "Account number for HD derivation")
cmd.Flags().Uint32(flagIndex, 0, "Address index number for HD derivation")
cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response")
cmd.Flags().String(flagKeyAlgo, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for")
return cmd
@ -311,18 +310,13 @@ func printCreate(cmd *cobra.Command, info keyring.Info, showMnemonic bool, mnemo
out.Mnemonic = mnemonic
}
var jsonString []byte
if viper.GetBool(flags.FlagIndentResponse) {
jsonString, err = KeysCdc.MarshalJSONIndent(out, "", " ")
} else {
jsonString, err = KeysCdc.MarshalJSON(out)
}
jsonString, err := KeysCdc.MarshalJSON(out)
if err != nil {
return err
}
cmd.PrintErrln(string(jsonString))
default:
return fmt.Errorf("invalid output format %s", output)
}

View File

@ -20,7 +20,7 @@ func ListKeysCmd() *cobra.Command {
along with their associated name and address.`,
RunE: runListCmd,
}
cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response")
cmd.Flags().BoolP(flagListNames, "n", false, "List names only")
return cmd
}

View File

@ -16,7 +16,6 @@ import (
"github.com/cosmos/cosmos-sdk/types/bech32"
"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -85,7 +84,6 @@ hexadecimal into bech32 cosmos prefixed format and vice versa.
Args: cobra.ExactArgs(1),
RunE: parseKey,
}
cmd.Flags().Bool(flags.FlagIndentResponse, false, "Indent JSON output")
return cmd
}
@ -145,11 +143,7 @@ func displayParseKeyInfo(w io.Writer, stringer fmt.Stringer) {
out, err = yaml.Marshal(&stringer)
case OutputFormatJSON:
if viper.GetBool(flags.FlagIndentResponse) {
out, err = KeysCdc.MarshalJSONIndent(stringer, "", " ")
} else {
out = KeysCdc.MustMarshalJSON(stringer)
}
out, err = KeysCdc.MarshalJSON(stringer)
}
if err != nil {

View File

@ -49,7 +49,6 @@ consisting of all the keys provided by name and multisig threshold.`,
cmd.Flags().BoolP(FlagPublicKey, "p", false, "Output the public key only (overrides --output)")
cmd.Flags().BoolP(FlagDevice, "d", false, "Output the address in a ledger device")
cmd.Flags().Uint(flagMultiSigThreshold, 1, "K out of N required signatures")
cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response")
return cmd
}

View File

@ -9,7 +9,6 @@ import (
"github.com/tendermint/tendermint/libs/cli"
"gopkg.in/yaml.v2"
"github.com/cosmos/cosmos-sdk/client/flags"
cryptokeyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
)
@ -45,13 +44,7 @@ func printKeyInfo(w io.Writer, keyInfo cryptokeyring.Info, bechKeyOut bechKeyOut
printTextInfos(w, []cryptokeyring.KeyOutput{ko})
case OutputFormatJSON:
var out []byte
var err error
if viper.GetBool(flags.FlagIndentResponse) {
out, err = KeysCdc.MarshalJSONIndent(ko, "", " ")
} else {
out, err = KeysCdc.MarshalJSON(ko)
}
out, err := KeysCdc.MarshalJSON(ko)
if err != nil {
panic(err)
}
@ -71,18 +64,11 @@ func printInfos(w io.Writer, infos []cryptokeyring.Info) {
printTextInfos(w, kos)
case OutputFormatJSON:
var out []byte
var err error
if viper.GetBool(flags.FlagIndentResponse) {
out, err = KeysCdc.MarshalJSONIndent(kos, "", " ")
} else {
out, err = KeysCdc.MarshalJSON(kos)
}
out, err := KeysCdc.MarshalJSON(kos)
if err != nil {
panic(err)
}
fmt.Fprintf(w, "%s", out)
}
}

View File

@ -64,10 +64,6 @@ func getBlock(clientCtx client.Context, height *int64) ([]byte, error) {
}
}
if clientCtx.Indent {
return legacy.Cdc.MarshalJSONIndent(res, "", " ")
}
return legacy.Cdc.MarshalJSON(res)
}

View File

@ -28,7 +28,6 @@ func StatusCommand() *cobra.Command {
cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
viper.BindPFlag(flags.FlagNode, cmd.Flags().Lookup(flags.FlagNode))
cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response")
return cmd
}
@ -53,12 +52,7 @@ func printNodeStatus(_ *cobra.Command, _ []string) error {
return err
}
var output []byte
if clientCtx.Indent {
output, err = legacy.Cdc.MarshalJSONIndent(status, "", " ")
} else {
output, err = legacy.Cdc.MarshalJSON(status)
}
output, err := legacy.Cdc.MarshalJSON(status)
if err != nil {
return err
}

View File

@ -56,15 +56,18 @@ func ValidatorCommand(cdc *codec.Codec) *cobra.Command {
cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
viper.BindPFlag(flags.FlagNode, cmd.Flags().Lookup(flags.FlagNode))
cmd.Flags().Bool(flags.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
viper.BindPFlag(flags.FlagTrustNode, cmd.Flags().Lookup(flags.FlagTrustNode))
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
viper.BindPFlag(flags.FlagKeyringBackend, cmd.Flags().Lookup(flags.FlagKeyringBackend))
cmd.Flags().Bool(flags.FlagIndentResponse, false, "indent JSON response")
viper.BindPFlag(flags.FlagIndentResponse, cmd.Flags().Lookup(flags.FlagIndentResponse))
cmd.Flags().Int(flags.FlagPage, 0, "Query a specific page of paginated results")
viper.BindPFlag(flags.FlagPage, cmd.Flags().Lookup(flags.FlagPage))
cmd.Flags().Int(flags.FlagLimit, 100, "Query number of results returned per page")
viper.BindPFlag(flags.FlagLimit, cmd.Flags().Lookup(flags.FlagLimit))
return cmd
}

View File

@ -3,6 +3,7 @@ package tx
import (
"io"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
@ -35,7 +36,47 @@ const (
signModeAminoJSON = "amino-json"
)
func NewFactoryFromCLI(input io.Reader) Factory {
func NewFactoryCLI(clientCtx client.Context, flagSet *pflag.FlagSet) Factory {
signModeStr, _ := flagSet.GetString(flags.FlagSignMode)
signMode := signing.SignMode_SIGN_MODE_UNSPECIFIED
switch signModeStr {
case signModeDirect:
signMode = signing.SignMode_SIGN_MODE_DIRECT
case signModeAminoJSON:
signMode = signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON
}
accNum, _ := flagSet.GetUint64(flags.FlagAccountNumber)
accSeq, _ := flagSet.GetUint64(flags.FlagSequence)
gasAdj, _ := flagSet.GetFloat64(flags.FlagGasAdjustment)
memo, _ := flagSet.GetString(flags.FlagMemo)
f := Factory{
txGenerator: clientCtx.TxGenerator,
accountRetriever: clientCtx.AccountRetriever,
keybase: clientCtx.Keyring,
chainID: clientCtx.ChainID,
gas: flags.GasFlagVar.Gas,
simulateAndExecute: flags.GasFlagVar.Simulate,
accountNumber: accNum,
sequence: accSeq,
gasAdjustment: gasAdj,
memo: memo,
signMode: signMode,
}
feesStr, _ := flagSet.GetString(flags.FlagFees)
f = f.WithFees(feesStr)
gasPricesStr, _ := flagSet.GetString(flags.FlagGasPrices)
f = f.WithGasPrices(gasPricesStr)
return f
}
// TODO: Remove in favor of NewFactoryCLI
func NewFactoryFromDeprecated(input io.Reader) Factory {
kb, err := keyring.New(
sdk.KeyringServiceName(),
viper.GetString(flags.FlagKeyringBackend),
@ -57,12 +98,12 @@ func NewFactoryFromCLI(input io.Reader) Factory {
f := Factory{
keybase: kb,
chainID: viper.GetString(flags.FlagChainID),
accountNumber: viper.GetUint64(flags.FlagAccountNumber),
sequence: viper.GetUint64(flags.FlagSequence),
gas: flags.GasFlagVar.Gas,
gasAdjustment: viper.GetFloat64(flags.FlagGasAdjustment),
simulateAndExecute: flags.GasFlagVar.Simulate,
chainID: viper.GetString(flags.FlagChainID),
memo: viper.GetString(flags.FlagMemo),
signMode: signMode,
}

View File

@ -9,6 +9,7 @@ import (
"strings"
"github.com/gogo/protobuf/jsonpb"
"github.com/spf13/pflag"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
@ -20,10 +21,19 @@ import (
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
)
// GenerateOrBroadcastTxCLI will either generate and print and unsigned transaction
// or sign it and broadcast it returning an error upon failure.
func GenerateOrBroadcastTxCLI(clientCtx client.Context, flagSet *pflag.FlagSet, msgs ...sdk.Msg) error {
txf := NewFactoryCLI(clientCtx, flagSet)
return GenerateOrBroadcastTxWithFactory(clientCtx, txf, msgs...)
}
// GenerateOrBroadcastTx will either generate and print and unsigned transaction
// or sign it and broadcast it returning an error upon failure.
//
// TODO: Remove in favor of GenerateOrBroadcastTxCLI
func GenerateOrBroadcastTx(clientCtx client.Context, msgs ...sdk.Msg) error {
txf := NewFactoryFromCLI(clientCtx.Input).WithTxGenerator(clientCtx.TxGenerator).WithAccountRetriever(clientCtx.AccountRetriever)
txf := NewFactoryFromDeprecated(clientCtx.Input).WithTxGenerator(clientCtx.TxGenerator).WithAccountRetriever(clientCtx.AccountRetriever)
return GenerateOrBroadcastTxWithFactory(clientCtx, txf, msgs...)
}

View File

@ -9,49 +9,49 @@ option go_package = "github.com/cosmos/cosmos-sdk/x/bank/types";
// Query provides defines the gRPC querier service
service Query {
// Balance queries the balance of a single coin for a single account
rpc Balance (QueryBalanceRequest) returns (QueryBalanceResponse) { }
// Balance queries the balance of a single coin for a single account
rpc Balance(QueryBalanceRequest) returns (QueryBalanceResponse) {}
// AllBalances queries the balance of all coins for a single account
rpc AllBalances (QueryAllBalancesRequest) returns (QueryAllBalancesResponse) { }
// AllBalances queries the balance of all coins for a single account
rpc AllBalances(QueryAllBalancesRequest) returns (QueryAllBalancesResponse) {}
// TotalSupply queries the total supply of all coins
rpc TotalSupply (QueryTotalSupplyRequest) returns (QueryTotalSupplyResponse) { }
// TotalSupply queries the total supply of all coins
rpc TotalSupply(QueryTotalSupplyRequest) returns (QueryTotalSupplyResponse) {}
// SupplyOf queries the supply of a single coin
rpc SupplyOf (QuerySupplyOfRequest) returns (QuerySupplyOfResponse) { }
// SupplyOf queries the supply of a single coin
rpc SupplyOf(QuerySupplyOfRequest) returns (QuerySupplyOfResponse) {}
}
// QueryBalanceRequest is the request type for the Query/Balance RPC method
message QueryBalanceRequest {
// address is the address to query balances for
bytes address = 1 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
// address is the address to query balances for
bytes address = 1 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
// denom is the coin denom to query balances for
string denom = 2;
// denom is the coin denom to query balances for
string denom = 2;
}
// QueryBalanceResponse is the response type for the Query/Balance RPC method
message QueryBalanceResponse {
// balance is the balance of the coin
cosmos.Coin balance = 1;
// balance is the balance of the coin
cosmos.Coin balance = 1;
}
// QueryBalanceRequest is the request type for the Query/AllBalances RPC method
message QueryAllBalancesRequest {
// address is the address to query balances for
bytes address = 1 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
// address is the address to query balances for
bytes address = 1 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
cosmos.query.PageRequest req = 2;
cosmos.query.PageRequest req = 2;
}
// QueryAllBalancesResponse is the response type for the Query/AllBalances RPC method
message QueryAllBalancesResponse {
// balances is the balances of the coins
repeated cosmos.Coin balances = 1 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
// balances is the balances of the coins
repeated cosmos.Coin balances = 1
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
cosmos.query.PageResponse res = 2;
cosmos.query.PageResponse res = 2;
}
// QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC method
@ -59,17 +59,19 @@ message QueryTotalSupplyRequest {}
// QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC method
message QueryTotalSupplyResponse {
// supply is the supply of the coins
repeated cosmos.Coin supply = 1 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
// supply is the supply of the coins
repeated cosmos.Coin supply = 1
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
}
// QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method
message QuerySupplyOfRequest {
string denom = 1;
string denom = 1;
}
// QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method
message QuerySupplyOfResponse {
// amount is the supply of the coin
string amount = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false];
// amount is the supply of the coin
cosmos.Coin amount = 1
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Coin", (gogoproto.nullable) = false];
}

View File

@ -107,6 +107,7 @@ func queryCmd(config simappparams.EncodingConfig) *cobra.Command {
clientCtx = clientCtx.
WithJSONMarshaler(config.Marshaler).
WithCodec(cdc)
simapp.ModuleBasics.AddQueryCommands(queryCmd, clientCtx)
return queryCmd

View File

@ -26,6 +26,7 @@ import (
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/api"
@ -39,12 +40,8 @@ import (
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
var (
_, cdc = simapp.MakeCodecs()
// package-wide network lock to only allow one test network at a time
lock = new(sync.Mutex)
)
// package-wide network lock to only allow one test network at a time
var lock = new(sync.Mutex)
// AppConstructor defines a function which accepts a network configuration and
// creates an ABCI Application to provide to Tendermint.
@ -61,39 +58,47 @@ func NewSimApp(val Validator) server.Application {
// Config defines the necessary configuration used to bootstrap and start an
// in-process local testing network.
type Config struct {
AppConstructor AppConstructor // the ABCI application constructor
GenesisState map[string]json.RawMessage // custom gensis state to provide
TimeoutCommit time.Duration // the consensus commitment timeout
ChainID string // the network chain-id
NumValidators int // the total number of validators to create and bond
BondDenom string // the staking bond denomination
MinGasPrices string // the minimum gas prices each validator will accept
Passphrase string // the passphrase provided to the test keyring
AccountTokens sdk.Int // the amount of unique validator tokens (e.g. 1000node0)
StakingTokens sdk.Int // the amount of tokens each validator has available to stake
BondedTokens sdk.Int // the amount of tokens each validator stakes
PruningStrategy string // the pruning strategy each validator will have
EnableLogging bool // enable Tendermint logging to STDOUT
CleanupDir bool // remove base temporary directory during cleanup
Codec codec.Marshaler
TxGenerator client.TxGenerator
AccountRetriever client.AccountRetriever
AppConstructor AppConstructor // the ABCI application constructor
GenesisState map[string]json.RawMessage // custom gensis state to provide
TimeoutCommit time.Duration // the consensus commitment timeout
ChainID string // the network chain-id
NumValidators int // the total number of validators to create and bond
BondDenom string // the staking bond denomination
MinGasPrices string // the minimum gas prices each validator will accept
Passphrase string // the passphrase provided to the test keyring
AccountTokens sdk.Int // the amount of unique validator tokens (e.g. 1000node0)
StakingTokens sdk.Int // the amount of tokens each validator has available to stake
BondedTokens sdk.Int // the amount of tokens each validator stakes
PruningStrategy string // the pruning strategy each validator will have
EnableLogging bool // enable Tendermint logging to STDOUT
CleanupDir bool // remove base temporary directory during cleanup
}
// DefaultConfig returns a sane default configuration suitable for nearly all
// testing requirements.
func DefaultConfig() Config {
encCfg := simapp.MakeEncodingConfig()
return Config{
AppConstructor: NewSimApp,
GenesisState: simapp.ModuleBasics.DefaultGenesis(cdc),
TimeoutCommit: 2 * time.Second,
ChainID: "chain-" + tmrand.NewRand().Str(6),
NumValidators: 4,
BondDenom: sdk.DefaultBondDenom,
MinGasPrices: fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom),
Passphrase: clientkeys.DefaultKeyPass,
AccountTokens: sdk.TokensFromConsensusPower(1000),
StakingTokens: sdk.TokensFromConsensusPower(500),
BondedTokens: sdk.TokensFromConsensusPower(100),
PruningStrategy: storetypes.PruningOptionNothing,
CleanupDir: true,
Codec: encCfg.Marshaler,
TxGenerator: encCfg.TxGenerator,
AccountRetriever: authtypes.NewAccountRetriever(encCfg.Marshaler),
AppConstructor: NewSimApp,
GenesisState: simapp.ModuleBasics.DefaultGenesis(encCfg.Marshaler),
TimeoutCommit: 2 * time.Second,
ChainID: "chain-" + tmrand.NewRand().Str(6),
NumValidators: 4,
BondDenom: sdk.DefaultBondDenom,
MinGasPrices: fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom),
Passphrase: clientkeys.DefaultKeyPass,
AccountTokens: sdk.TokensFromConsensusPower(1000),
StakingTokens: sdk.TokensFromConsensusPower(500),
BondedTokens: sdk.TokensFromConsensusPower(100),
PruningStrategy: storetypes.PruningOptionNothing,
CleanupDir: true,
}
}
@ -279,14 +284,23 @@ func NewTestNetwork(t *testing.T, cfg Config) *Network {
signedTx, err := txBldr.SignStdTx(nodeDirName, tx, false)
require.NoError(t, err)
txBz, err := cdc.MarshalJSON(signedTx)
txBz, err := cfg.Codec.MarshalJSON(signedTx)
require.NoError(t, err)
require.NoError(t, writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz))
srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), appCfg)
clientCtx := client.Context{}.
WithKeyring(kb).
WithHomeDir(tmCfg.RootDir).
WithChainID(cfg.ChainID).
WithJSONMarshaler(cfg.Codec).
WithTxGenerator(cfg.TxGenerator).
WithAccountRetriever(cfg.AccountRetriever)
network.Validators[i] = &Validator{
AppConfig: appCfg,
ClientCtx: clientCtx,
Ctx: ctx,
Dir: filepath.Join(network.BaseDir, nodeDirName),
NodeID: nodeID,

View File

@ -13,7 +13,6 @@ import (
"github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server/api"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
@ -60,10 +59,7 @@ func startInProcess(cfg Config, val *Validator) error {
}
if val.APIAddress != "" {
val.ClientCtx = client.Context{}.
WithHomeDir(tmCfg.RootDir).
WithChainID(cfg.ChainID).
WithJSONMarshaler(cdc).
val.ClientCtx = val.ClientCtx.
WithClient(val.RPCClient).
WithTrustNode(true)
@ -110,7 +106,7 @@ func collectGenFiles(cfg Config, vals []*Validator, outputDir string) error {
return err
}
appState, err := genutil.GenAppStateFromConfig(cdc, tmCfg, initCfg, *genDoc, banktypes.GenesisBalancesIterator{})
appState, err := genutil.GenAppStateFromConfig(cfg.Codec, tmCfg, initCfg, *genDoc, banktypes.GenesisBalancesIterator{})
if err != nil {
return err
}
@ -128,19 +124,19 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance
// set the accounts in the genesis state
var authGenState authtypes.GenesisState
cdc.MustUnmarshalJSON(cfg.GenesisState[authtypes.ModuleName], &authGenState)
cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[authtypes.ModuleName], &authGenState)
authGenState.Accounts = genAccounts
cfg.GenesisState[authtypes.ModuleName] = cdc.MustMarshalJSON(authGenState)
cfg.GenesisState[authtypes.ModuleName] = cfg.Codec.MustMarshalJSON(authGenState)
// set the balances in the genesis state
var bankGenState banktypes.GenesisState
cdc.MustUnmarshalJSON(cfg.GenesisState[banktypes.ModuleName], &bankGenState)
cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[banktypes.ModuleName], &bankGenState)
bankGenState.Balances = genBalances
cfg.GenesisState[banktypes.ModuleName] = cdc.MustMarshalJSON(bankGenState)
cfg.GenesisState[banktypes.ModuleName] = cfg.Codec.MustMarshalJSON(bankGenState)
appGenStateJSON, err := codec.MarshalJSONIndent(cdc, cfg.GenesisState)
appGenStateJSON, err := codec.MarshalJSONIndent(cfg.Codec, cfg.GenesisState)
if err != nil {
return err
}

View File

@ -288,11 +288,6 @@ func PostProcessResponseBare(w http.ResponseWriter, ctx client.Context, body int
default:
resp, err = marshaler.MarshalJSON(body)
if ctx.Indent && err == nil {
resp, err = codec.MarshalIndentFromJSON(resp)
}
if CheckInternalServerError(w, err) {
return
}
@ -332,11 +327,6 @@ func PostProcessResponse(w http.ResponseWriter, ctx client.Context, resp interfa
default:
result, err = marshaler.MarshalJSON(resp)
if ctx.Indent && err == nil {
result, err = codec.MarshalIndentFromJSON(result)
}
if CheckInternalServerError(w, err) {
return
}
@ -345,10 +335,6 @@ func PostProcessResponse(w http.ResponseWriter, ctx client.Context, resp interfa
wrappedResp := NewResponseWithHeight(ctx.Height, result)
output, err := marshaler.MarshalJSON(wrappedResp)
if ctx.Indent && err == nil {
output, err = codec.MarshalIndentFromJSON(output)
}
if CheckInternalServerError(w, err) {
return
}

View File

@ -212,9 +212,6 @@ func TestProcessPostResponse(t *testing.T) {
expectedNoIndent, err := ctx.Codec.MarshalJSON(respNoIndent)
require.Nil(t, err)
expectedWithIndent, err := codec.MarshalIndentFromJSON(expectedNoIndent)
require.Nil(t, err)
// check that negative height writes an error
w := httptest.NewRecorder()
ctx = ctx.WithHeight(-1)
@ -223,10 +220,7 @@ func TestProcessPostResponse(t *testing.T) {
// check that height returns expected response
ctx = ctx.WithHeight(height)
runPostProcessResponse(t, ctx, acc, expectedNoIndent, false)
// check height with indent
runPostProcessResponse(t, ctx, acc, expectedWithIndent, true)
runPostProcessResponse(t, ctx, acc, expectedNoIndent)
}
func TestReadRESTReq(t *testing.T) {
@ -329,7 +323,7 @@ func TestPostProcessResponseBare(t *testing.T) {
require.Equal(t, "text string", string(got))
// write struct and indent response
clientCtx = client.Context{Indent: true}.WithCodec(codec.New())
clientCtx = client.Context{}.WithCodec(codec.New())
w = httptest.NewRecorder()
data := struct {
X int `json:"x"`
@ -345,13 +339,10 @@ func TestPostProcessResponseBare(t *testing.T) {
require.NoError(t, err)
t.Cleanup(func() { res.Body.Close() })
require.Equal(t, `{
"s": "test",
"x": "10"
}`, string(got))
require.Equal(t, "{\"x\":\"10\",\"s\":\"test\"}", string(got))
// write struct, don't indent response
clientCtx = client.Context{Indent: false}.WithCodec(codec.New())
clientCtx = client.Context{}.WithCodec(codec.New())
w = httptest.NewRecorder()
data = struct {
X int `json:"x"`
@ -370,7 +361,7 @@ func TestPostProcessResponseBare(t *testing.T) {
require.Equal(t, `{"x":"10","s":"test"}`, string(got))
// test marshalling failure
clientCtx = client.Context{Indent: false}.WithCodec(codec.New())
clientCtx = client.Context{}.WithCodec(codec.New())
w = httptest.NewRecorder()
data2 := badJSONMarshaller{}
@ -396,11 +387,7 @@ func (badJSONMarshaller) MarshalJSON() ([]byte, error) {
// asserts that ResponseRecorder returns the expected code and body
// runs PostProcessResponse on the objects regular interface and on
// the marshalled struct.
func runPostProcessResponse(t *testing.T, ctx client.Context, obj interface{}, expectedBody []byte, indent bool) {
if indent {
ctx.Indent = indent
}
func runPostProcessResponse(t *testing.T, ctx client.Context, obj interface{}, expectedBody []byte) {
// test using regular struct
w := httptest.NewRecorder()
@ -417,11 +404,6 @@ func runPostProcessResponse(t *testing.T, ctx client.Context, obj interface{}, e
marshalled, err := ctx.Codec.MarshalJSON(obj)
require.NoError(t, err)
if indent {
marshalled, err = codec.MarshalIndentFromJSON(marshalled)
require.NoError(t, err)
}
// test using marshalled struct
w = httptest.NewRecorder()
rest.PostProcessResponse(w, ctx, marshalled)

View File

@ -155,13 +155,7 @@ $ %s query txs --%s 'message.sender=cosmos1...&message.action=withdraw_delegator
return err
}
var output []byte
if clientCtx.Indent {
output, err = cdc.MarshalJSONIndent(txs, "", " ")
} else {
output, err = cdc.MarshalJSON(txs)
}
output, err := cdc.MarshalJSON(txs)
if err != nil {
return err
}

View File

@ -128,18 +128,15 @@ func makeMultiSignCmd(clientCtx client.Context) func(cmd *cobra.Command, args []
newStdSig := types.StdSignature{Signature: sigBz, PubKey: multisigPub.Bytes()} //nolint:staticcheck
newTx := types.NewStdTx(stdTx.GetMsgs(), stdTx.Fee, []types.StdSignature{newStdSig}, stdTx.GetMemo()) //nolint:staticcheck
sigOnly := viper.GetBool(flagSigOnly)
var json []byte
switch {
case sigOnly && clientCtx.Indent:
json, err = cdc.MarshalJSONIndent(newTx.Signatures[0], "", " ")
case sigOnly && !clientCtx.Indent:
sigOnly := viper.GetBool(flagSigOnly)
if sigOnly {
json, err = cdc.MarshalJSON(newTx.Signatures[0])
case !sigOnly && clientCtx.Indent:
json, err = cdc.MarshalJSONIndent(newTx, "", " ")
default:
} else {
json, err = cdc.MarshalJSON(newTx)
}
if err != nil {
return err
}

View File

@ -116,7 +116,7 @@ func makeSignBatchCmd(cdc *codec.Codec) func(cmd *cobra.Command, args []string)
return err
}
json, err := getSignatureJSON(cdc, stdTx, clientCtx.Indent, generateSignatureOnly)
json, err := getSignatureJSON(cdc, stdTx, generateSignatureOnly)
if err != nil {
return err
}
@ -232,7 +232,7 @@ func makeSignCmd(clientCtx client.Context) func(cmd *cobra.Command, args []strin
return err
}
json, err := getSignatureJSON(clientCtx.Codec, newTx, clientCtx.Indent, generateSignatureOnly)
json, err := getSignatureJSON(clientCtx.Codec, newTx, generateSignatureOnly)
if err != nil {
return err
}
@ -256,23 +256,10 @@ func makeSignCmd(clientCtx client.Context) func(cmd *cobra.Command, args []strin
}
}
func getSignatureJSON(cdc *codec.Codec, newTx types.StdTx, indent, generateSignatureOnly bool) ([]byte, error) {
switch generateSignatureOnly {
case true:
switch indent {
case true:
return cdc.MarshalJSONIndent(newTx.Signatures[0], "", " ")
default:
return cdc.MarshalJSON(newTx.Signatures[0])
}
default:
switch indent {
case true:
return cdc.MarshalJSONIndent(newTx, "", " ")
default:
return cdc.MarshalJSON(newTx)
}
func getSignatureJSON(cdc *codec.Codec, newTx types.StdTx, generateSignatureOnly bool) ([]byte, error) {
if generateSignatureOnly {
return cdc.MarshalJSON(newTx.Signatures[0])
}
return cdc.MarshalJSON(newTx)
}

View File

@ -11,10 +11,8 @@ import (
"github.com/gogo/protobuf/jsonpb"
"github.com/pkg/errors"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/input"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -85,12 +83,9 @@ func CompleteAndBroadcastTxCLI(txBldr authtypes.TxBuilder, clientCtx client.Cont
return err
}
json := clientCtx.JSONMarshaler.MustMarshalJSON(stdSignMsg)
if viper.GetBool(flags.FlagIndentResponse) {
json, err = codec.MarshalIndentFromJSON(json)
if err != nil {
panic(err)
}
json, err := clientCtx.JSONMarshaler.MarshalJSON(stdSignMsg)
if err != nil {
return err
}
_, _ = fmt.Fprintf(os.Stderr, "%s\n\n", json)
@ -164,13 +159,6 @@ func PrintUnsignedStdTx(txBldr authtypes.TxBuilder, clientCtx client.Context, ms
return err
}
if viper.GetBool(flags.FlagIndentResponse) {
json, err = codec.MarshalIndentFromJSON(json)
if err != nil {
return err
}
}
_, _ = fmt.Fprintf(clientCtx.Output, "%s\n", json)
return nil
}

View File

@ -1,223 +1,289 @@
// +build cli_test
package cli_test
import (
"bytes"
"fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/cosmos/cosmos-sdk/tests"
"github.com/cosmos/cosmos-sdk/tests/cli"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/bank/client/cli"
)
func TestCLISend(t *testing.T) {
t.Parallel()
f := cli.InitFixtures(t)
type IntegrationTestSuite struct {
suite.Suite
// start simd server
proc := f.SDStart()
t.Cleanup(func() { proc.Stop(false) })
// Save key addresses for later uspackage testse
fooAddr := f.KeyAddress(cli.KeyFoo)
barAddr := f.KeyAddress(cli.KeyBar)
startTokens := sdk.TokensFromConsensusPower(50)
require.Equal(t, startTokens, testutil.QueryBalances(f, fooAddr).AmountOf(cli.Denom))
sendTokens := sdk.TokensFromConsensusPower(10)
// It does not allow to send in offline mode
success, _, stdErr := testutil.TxSend(f, cli.KeyFoo, barAddr, sdk.NewCoin(cli.Denom, sendTokens), "-y", "--offline")
require.Contains(t, stdErr, "no RPC client is defined in offline mode")
require.False(f.T, success)
tests.WaitForNextNBlocksTM(1, f.Port)
// Send some tokens from one account to the other
testutil.TxSend(f, cli.KeyFoo, barAddr, sdk.NewCoin(cli.Denom, sendTokens), "-y")
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure account balances match expected
require.Equal(t, sendTokens.String(), testutil.QueryBalances(f, barAddr).AmountOf(cli.Denom).String())
require.Equal(t, startTokens.Sub(sendTokens).String(), testutil.QueryBalances(f, fooAddr).AmountOf(cli.Denom).String())
// Test --dry-run
success, _, _ = testutil.TxSend(f, cli.KeyFoo, barAddr, sdk.NewCoin(cli.Denom, sendTokens), "--dry-run")
require.True(t, success)
// Test --generate-only
success, stdout, stderr := testutil.TxSend(
f, fooAddr.String(), barAddr, sdk.NewCoin(cli.Denom, sendTokens), "--generate-only=true",
)
require.Empty(t, stderr)
require.True(t, success)
msg := cli.UnmarshalStdTx(f.T, f.Cdc, stdout)
t.Log(msg)
require.NotZero(t, msg.Fee.Gas)
require.Len(t, msg.Msgs, 1)
require.Len(t, msg.GetSignatures(), 0)
// Check state didn't change
require.Equal(t, startTokens.Sub(sendTokens), testutil.QueryBalances(f, fooAddr).AmountOf(cli.Denom))
// test autosequencing
testutil.TxSend(f, cli.KeyFoo, barAddr, sdk.NewCoin(cli.Denom, sendTokens), "-y")
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure account balances match expected
require.Equal(t, sendTokens.MulRaw(2), testutil.QueryBalances(f, barAddr).AmountOf(cli.Denom))
require.Equal(t, startTokens.Sub(sendTokens.MulRaw(2)), testutil.QueryBalances(f, fooAddr).AmountOf(cli.Denom))
// test memo
testutil.TxSend(f, cli.KeyFoo, barAddr, sdk.NewCoin(cli.Denom, sendTokens), "--memo='testmemo'", "-y")
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure account balances match expected
require.Equal(t, sendTokens.MulRaw(3), testutil.QueryBalances(f, barAddr).AmountOf(cli.Denom))
require.Equal(t, startTokens.Sub(sendTokens.MulRaw(3)), testutil.QueryBalances(f, fooAddr).AmountOf(cli.Denom))
f.Cleanup()
cfg testutil.Config
network *testutil.Network
}
func TestCLIMinimumFees(t *testing.T) {
t.Parallel()
f := cli.InitFixtures(t)
func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite")
// start simd server with minimum fees
minGasPrice, _ := sdk.NewDecFromStr("0.000006")
fees := fmt.Sprintf(
"--minimum-gas-prices=%s,%s",
sdk.NewDecCoinFromDec(cli.FeeDenom, minGasPrice),
sdk.NewDecCoinFromDec(cli.Fee2Denom, minGasPrice),
)
proc := f.SDStart(fees)
t.Cleanup(func() { proc.Stop(false) })
cfg := testutil.DefaultConfig()
cfg.NumValidators = 1
barAddr := f.KeyAddress(cli.KeyBar)
s.cfg = cfg
s.network = testutil.NewTestNetwork(s.T(), cfg)
// Send a transaction that will get rejected
success, stdOut, _ := testutil.TxSend(f, cli.KeyFoo, barAddr, sdk.NewInt64Coin(cli.Fee2Denom, 10), "-y")
require.Contains(t, stdOut, "insufficient fees")
require.True(f.T, success)
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure tx w/ correct fees pass
txFees := fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(cli.FeeDenom, 2))
success, _, _ = testutil.TxSend(f, cli.KeyFoo, barAddr, sdk.NewInt64Coin(cli.Fee2Denom, 10), txFees, "-y")
require.True(f.T, success)
tests.WaitForNextNBlocksTM(1, f.Port)
// Ensure tx w/ improper fees fails
txFees = fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(cli.FeeDenom, 1))
success, _, _ = testutil.TxSend(f, cli.KeyFoo, barAddr, sdk.NewInt64Coin(cli.FooDenom, 10), txFees, "-y")
require.Contains(t, stdOut, "insufficient fees")
require.True(f.T, success)
// Cleanup testing directories
f.Cleanup()
_, err := s.network.WaitForHeight(1)
s.Require().NoError(err)
}
func TestCLIGasPrices(t *testing.T) {
t.Parallel()
f := cli.InitFixtures(t)
// start simd server with minimum fees
minGasPrice, _ := sdk.NewDecFromStr("0.000006")
proc := f.SDStart(fmt.Sprintf("--minimum-gas-prices=%s", sdk.NewDecCoinFromDec(cli.FeeDenom, minGasPrice)))
t.Cleanup(func() { proc.Stop(false) })
barAddr := f.KeyAddress(cli.KeyBar)
// insufficient gas prices (tx fails)
badGasPrice, _ := sdk.NewDecFromStr("0.000003")
success, stdOut, _ := testutil.TxSend(
f, cli.KeyFoo, barAddr, sdk.NewInt64Coin(cli.FooDenom, 50),
fmt.Sprintf("--gas-prices=%s", sdk.NewDecCoinFromDec(cli.FeeDenom, badGasPrice)), "-y")
require.Contains(t, stdOut, "insufficient fees")
require.True(t, success)
// wait for a block confirmation
tests.WaitForNextNBlocksTM(1, f.Port)
// sufficient gas prices (tx passes)
success, _, _ = testutil.TxSend(
f, cli.KeyFoo, barAddr, sdk.NewInt64Coin(cli.FooDenom, 50),
fmt.Sprintf("--gas-prices=%s", sdk.NewDecCoinFromDec(cli.FeeDenom, minGasPrice)), "-y")
require.True(t, success)
// wait for a block confirmation
tests.WaitForNextNBlocksTM(1, f.Port)
f.Cleanup()
func (s *IntegrationTestSuite) TearDownSuite() {
s.T().Log("tearing down integration test suite")
s.network.Cleanup()
}
func TestCLIFeesDeduction(t *testing.T) {
t.Parallel()
f := cli.InitFixtures(t)
func (s *IntegrationTestSuite) TestGetBalancesCmd() {
buf := new(bytes.Buffer)
val := s.network.Validators[0]
clientCtx := val.ClientCtx.WithOutput(buf)
// start simd server with minimum fees
minGasPrice, _ := sdk.NewDecFromStr("0.000006")
proc := f.SDStart(fmt.Sprintf("--minimum-gas-prices=%s", sdk.NewDecCoinFromDec(cli.FeeDenom, minGasPrice)))
t.Cleanup(func() { proc.Stop(false) })
testCases := []struct {
name string
args []string
expectErr bool
respType fmt.Stringer
expected fmt.Stringer
}{
{"no address provided", []string{}, true, nil, nil},
{
"total account balance",
[]string{
val.Address.String(),
fmt.Sprintf("--%s=1", flags.FlagHeight),
},
false,
&sdk.Coins{},
sdk.NewCoins(
sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), s.cfg.AccountTokens),
sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Sub(s.cfg.BondedTokens)),
),
},
{
"total account balance of a specific denom",
[]string{
val.Address.String(),
fmt.Sprintf("--%s=%s", cli.FlagDenom, s.cfg.BondDenom),
fmt.Sprintf("--%s=1", flags.FlagHeight),
},
false,
&sdk.Coin{},
sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Sub(s.cfg.BondedTokens)),
},
{
"total account balance of a bogus denom",
[]string{val.Address.String(), fmt.Sprintf("--%s=foobar", cli.FlagDenom)},
false,
&sdk.Coin{},
sdk.NewCoin("foobar", sdk.ZeroInt()),
},
}
// Save key addresses for later use
fooAddr := f.KeyAddress(cli.KeyFoo)
barAddr := f.KeyAddress(cli.KeyBar)
for _, tc := range testCases {
tc := tc
fooAmt := testutil.QueryBalances(f, fooAddr).AmountOf(cli.FooDenom)
s.Run(tc.name, func() {
buf.Reset()
// test simulation
success, _, _ := testutil.TxSend(
f, cli.KeyFoo, barAddr, sdk.NewInt64Coin(cli.FooDenom, 1000),
fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(cli.FeeDenom, 2)), "--dry-run")
require.True(t, success)
cmd := cli.GetBalancesCmd(clientCtx)
cmd.SetErr(buf)
cmd.SetOut(buf)
cmd.SetArgs(tc.args)
// Wait for a block
tests.WaitForNextNBlocksTM(1, f.Port)
// ensure state didn't change
require.Equal(t, fooAmt.Int64(), testutil.QueryBalances(f, fooAddr).AmountOf(cli.FooDenom).Int64())
// insufficient funds (coins + fees) tx fails
largeCoins := sdk.TokensFromConsensusPower(10000000)
success, stdOut, _ := testutil.TxSend(
f, cli.KeyFoo, barAddr, sdk.NewCoin(cli.FooDenom, largeCoins),
fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(cli.FeeDenom, 2)), "-y")
require.Contains(t, stdOut, "insufficient funds")
require.True(t, success)
// Wait for a block
tests.WaitForNextNBlocksTM(1, f.Port)
// ensure state didn't change
require.Equal(t, fooAmt.Int64(), testutil.QueryBalances(f, fooAddr).AmountOf(cli.FooDenom).Int64())
// test success (transfer = coins + fees)
success, _, _ = testutil.TxSend(
f, cli.KeyFoo, barAddr, sdk.NewInt64Coin(cli.FooDenom, 500),
fmt.Sprintf("--fees=%s", sdk.NewInt64Coin(cli.FeeDenom, 2)), "-y")
require.True(t, success)
f.Cleanup()
err := cmd.Execute()
if tc.expectErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(buf.Bytes(), tc.respType))
s.Require().Equal(tc.expected.String(), tc.respType.String())
}
})
}
}
func TestCLIQuerySupply(t *testing.T) {
t.Parallel()
f := cli.InitFixtures(t)
func (s *IntegrationTestSuite) TestGetCmdQueryTotalSupply() {
buf := new(bytes.Buffer)
val := s.network.Validators[0]
clientCtx := val.ClientCtx.WithOutput(buf)
// start simd server
proc := f.SDStart()
t.Cleanup(func() { proc.Stop(false) })
testCases := []struct {
name string
args []string
expectErr bool
respType fmt.Stringer
expected fmt.Stringer
}{
{
"total supply",
[]string{fmt.Sprintf("--%s=1", flags.FlagHeight)},
false,
&sdk.Coins{},
sdk.NewCoins(
sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), s.cfg.AccountTokens),
sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(sdk.NewInt(10))),
),
},
{
"total supply of a specific denomination",
[]string{
fmt.Sprintf("--%s=1", flags.FlagHeight),
fmt.Sprintf("--%s=%s", cli.FlagDenom, s.cfg.BondDenom),
},
false,
&sdk.Coin{},
sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(sdk.NewInt(10))),
},
{
"total supply of a bogus denom",
[]string{
fmt.Sprintf("--%s=1", flags.FlagHeight),
fmt.Sprintf("--%s=foobar", cli.FlagDenom),
},
false,
&sdk.Coin{},
sdk.NewCoin("foobar", sdk.ZeroInt()),
},
}
totalSupply := testutil.QueryTotalSupply(f)
totalSupplyOf := testutil.QueryTotalSupplyOf(f, cli.FooDenom)
for _, tc := range testCases {
tc := tc
require.Equal(t, cli.TotalCoins, totalSupply)
require.True(sdk.IntEq(t, cli.TotalCoins.AmountOf(cli.FooDenom), totalSupplyOf))
s.Run(tc.name, func() {
buf.Reset()
f.Cleanup()
cmd := cli.GetCmdQueryTotalSupply(clientCtx)
cmd.SetErr(buf)
cmd.SetOut(buf)
cmd.SetArgs(tc.args)
err := cmd.Execute()
if tc.expectErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(buf.Bytes(), tc.respType), buf.String())
s.Require().Equal(tc.expected.String(), tc.respType.String())
}
})
}
}
func (s *IntegrationTestSuite) TestNewSendTxCmd() {
buf := new(bytes.Buffer)
val := s.network.Validators[0]
clientCtx := val.ClientCtx.WithOutput(buf)
testCases := []struct {
name string
args []string
expectErr bool
respType fmt.Stringer
expectedCode uint32
}{
{
"valid transaction (gen-only)",
[]string{
val.Address.String(),
val.Address.String(),
sdk.NewCoins(
sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(10)),
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)),
).String(),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
},
false,
&sdk.TxResponse{},
0,
},
{
"valid transaction",
[]string{
val.Address.String(),
val.Address.String(),
sdk.NewCoins(
sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(10)),
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)),
).String(),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
},
false,
&sdk.TxResponse{},
0,
},
{
"not enough fees",
[]string{
val.Address.String(),
val.Address.String(),
sdk.NewCoins(
sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(10)),
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)),
).String(),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(1))).String()),
},
false,
&sdk.TxResponse{},
sdkerrors.ErrInsufficientFee.ABCICode(),
},
{
"not enough gas",
[]string{
val.Address.String(),
val.Address.String(),
sdk.NewCoins(
sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(10)),
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)),
).String(),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
"--gas=10",
},
false,
&sdk.TxResponse{},
sdkerrors.ErrOutOfGas.ABCICode(),
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
buf.Reset()
cmd := cli.NewSendTxCmd(clientCtx)
cmd.SetErr(buf)
cmd.SetOut(buf)
cmd.SetArgs(tc.args)
err := cmd.Execute()
if tc.expectErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(buf.Bytes(), tc.respType), buf.String())
txResp := tc.respType.(*sdk.TxResponse)
s.Require().Equal(tc.expectedCode, txResp.Code)
}
})
}
}
func TestIntegrationTestSuite(t *testing.T) {
suite.Run(t, new(IntegrationTestSuite))
}

View File

@ -6,7 +6,6 @@ import (
"strings"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
@ -17,9 +16,12 @@ import (
)
const (
flagDenom = "denom"
FlagDenom = "denom"
)
// GetQueryCmd returns the parent command for all x/bank CLi query commands. The
// provided clientCtx should have, at a minimum, a verifier, Tendermint RPC client,
// and marshaler set.
func GetQueryCmd(clientCtx client.Context) *cobra.Command {
cmd := &cobra.Command{
Use: types.ModuleName,
@ -41,25 +43,45 @@ func GetBalancesCmd(clientCtx client.Context) *cobra.Command {
cmd := &cobra.Command{
Use: "balances [address]",
Short: "Query for account balances by address",
Args: cobra.ExactArgs(1),
Long: strings.TrimSpace(
fmt.Sprintf(`Query the total balance of an account or of a specific denomination.
Example:
$ %s query %s balances [address]
$ %s query %s balances [address] --denom=[denom]
`,
version.ClientName, types.ModuleName, version.ClientName, types.ModuleName,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
queryClient := types.NewQueryClient(clientCtx.Init())
clientCtx, err := client.ReadQueryCommandFlags(clientCtx, cmd.Flags())
if err != nil {
return err
}
denom, err := cmd.Flags().GetString(FlagDenom)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
addr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
denom := viper.GetString(flagDenom)
pageReq := &query.PageRequest{}
if denom == "" {
params := types.NewQueryAllBalancesRequest(addr, pageReq)
res, err := queryClient.AllBalances(context.Background(), params)
if err != nil {
return err
}
return clientCtx.PrintOutput(res.Balances)
return clientCtx.PrintOutput(res.Balances)
}
params := types.NewQueryBalanceRequest(addr, denom)
@ -67,50 +89,62 @@ func GetBalancesCmd(clientCtx client.Context) *cobra.Command {
if err != nil {
return err
}
return clientCtx.PrintOutput(res.Balance)
},
}
cmd.Flags().String(flagDenom, "", "The specific balance denomination to query for")
cmd.Flags().String(FlagDenom, "", "The specific balance denomination to query for")
return flags.GetCommands(cmd)[0]
}
func GetCmdQueryTotalSupply(clientCtx client.Context) *cobra.Command {
cmd := &cobra.Command{
Use: "total [denom]",
Args: cobra.MaximumNArgs(1),
Use: "total",
Short: "Query the total supply of coins of the chain",
Long: strings.TrimSpace(
fmt.Sprintf(`Query total supply of coins that are held by accounts in the
chain.
fmt.Sprintf(`Query total supply of coins that are held by accounts in the chain.
Example:
$ %s query %s total
$ %s query %s total
To query for the total supply of a specific coin denomination use:
$ %s query %s total stake
$ %s query %s total --denom=[denom]
`,
version.ClientName, types.ModuleName, version.ClientName, types.ModuleName,
),
),
RunE: func(cmd *cobra.Command, args []string) error {
queryClient := types.NewQueryClient(clientCtx.Init())
clientCtx, err := client.ReadQueryCommandFlags(clientCtx, cmd.Flags())
if err != nil {
return err
}
if len(args) == 0 {
denom, err := cmd.Flags().GetString(FlagDenom)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
if denom == "" {
res, err := queryClient.TotalSupply(context.Background(), &types.QueryTotalSupplyRequest{})
if err != nil {
return err
}
return clientCtx.PrintOutput(res.Supply)
}
res, err := queryClient.SupplyOf(context.Background(), &types.QuerySupplyOfRequest{Denom: args[0]})
res, err := queryClient.SupplyOf(context.Background(), &types.QuerySupplyOfRequest{Denom: denom})
if err != nil {
return err
}
return clientCtx.PrintOutput(res.Amount)
},
}
cmd.Flags().String(FlagDenom, "", "The specific balance denomination to query for")
return flags.GetCommands(cmd)[0]
}

View File

@ -32,7 +32,11 @@ func NewSendTxCmd(clientCtx client.Context) *cobra.Command {
Short: "Create and/or sign and broadcast a MsgSend transaction",
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx = clientCtx.InitWithInputAndFrom(cmd.InOrStdin(), args[0])
cmd.Flags().Set(flags.FlagFrom, args[0])
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
if err != nil {
return err
}
toAddr, err := sdk.AccAddressFromBech32(args[1])
if err != nil {
@ -49,7 +53,7 @@ func NewSendTxCmd(clientCtx client.Context) *cobra.Command {
return err
}
return tx.GenerateOrBroadcastTx(clientCtx, msg)
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

View File

@ -96,7 +96,8 @@ func (s *IntegrationTestSuite) TestTotalSupplyHandlerFn() {
{
"total supply",
fmt.Sprintf("%s/bank/total?height=1", baseURL),
&sdk.Coins{}, sdk.NewCoins(
&sdk.Coins{},
sdk.NewCoins(
sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), s.cfg.AccountTokens),
sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(sdk.NewInt(10))),
),

View File

@ -13,10 +13,11 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)
// TODO: REMOVE OR COMPLETELY REFACTOR THIS FILE.
// TxSend is simcli tx send
func TxSend(f *cli.Fixtures, from string, to sdk.AccAddress, amount sdk.Coin, flags ...string) (bool, string, string) {
cmd := fmt.Sprintf("%s tx send --keyring-backend=test %s %s %s %v", f.SimcliBinary, from,
to, amount, f.Flags())
cmd := fmt.Sprintf("%s tx send --keyring-backend=test %s %s %s %v", f.SimcliBinary, from, to, amount, f.Flags())
return cli.ExecuteWriteRetStdStreams(f.T, cli.AddFlags(cmd, flags), clientkeys.DefaultKeyPass)
}

View File

@ -3,11 +3,12 @@ package keeper
import (
"context"
"github.com/cosmos/cosmos-sdk/store/prefix"
"github.com/cosmos/cosmos-sdk/types/query"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/cosmos/cosmos-sdk/store/prefix"
"github.com/cosmos/cosmos-sdk/types/query"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
@ -90,5 +91,5 @@ func (q BaseKeeper) SupplyOf(c context.Context, req *types.QuerySupplyOfRequest)
ctx := sdk.UnwrapSDKContext(c)
supply := q.GetSupply(ctx).GetTotal().AmountOf(req.Denom)
return &types.QuerySupplyOfResponse{Amount: supply}, nil
return &types.QuerySupplyOfResponse{Amount: sdk.NewCoin(req.Denom, supply)}, nil
}

View File

@ -127,5 +127,5 @@ func (suite *IntegrationTestSuite) TestQueryTotalSupplyOf() {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(test1Supply.Amount, res.Amount)
suite.Require().Equal(test1Supply, res.Amount)
}

View File

@ -371,7 +371,7 @@ func (m *QuerySupplyOfRequest) GetDenom() string {
// QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method
type QuerySupplyOfResponse struct {
// amount is the supply of the coin
Amount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,1,opt,name=amount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"amount"`
Amount github_com_cosmos_cosmos_sdk_types.Coin `protobuf:"bytes,1,opt,name=amount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Coin" json:"amount"`
}
func (m *QuerySupplyOfResponse) Reset() { *m = QuerySupplyOfResponse{} }
@ -421,40 +421,40 @@ func init() {
func init() { proto.RegisterFile("cosmos/bank/query.proto", fileDescriptor_1b02ea4db7d9aa9f) }
var fileDescriptor_1b02ea4db7d9aa9f = []byte{
// 527 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x94, 0xc1, 0x6e, 0xd3, 0x30,
0x18, 0xc7, 0x93, 0x4d, 0x6b, 0x87, 0xbb, 0x93, 0x57, 0xb4, 0x2e, 0x12, 0x69, 0xb1, 0x60, 0x2a,
0x62, 0x4b, 0xa0, 0xdc, 0x91, 0xda, 0x49, 0x48, 0x88, 0x03, 0x23, 0x43, 0x1c, 0x26, 0x24, 0x94,
0xa6, 0x26, 0x54, 0x4b, 0xed, 0x34, 0x4e, 0xa4, 0xf5, 0x2d, 0x90, 0x78, 0x05, 0x4e, 0x3c, 0xc9,
0x8e, 0x3b, 0x22, 0x0e, 0x05, 0xb5, 0x37, 0x1e, 0x81, 0x13, 0xb2, 0xfd, 0x65, 0x4a, 0xdb, 0xa8,
0xec, 0xc0, 0x6e, 0x89, 0xfd, 0xff, 0xfe, 0xfe, 0x7d, 0xfe, 0x7f, 0x09, 0xda, 0x0b, 0xb8, 0x18,
0x71, 0xe1, 0xf6, 0x7d, 0x76, 0xee, 0x8e, 0x33, 0x9a, 0x4c, 0x9c, 0x38, 0xe1, 0x29, 0xc7, 0x35,
0xbd, 0xe1, 0xc8, 0x0d, 0xeb, 0x1e, 0xa8, 0x94, 0xc0, 0x8d, 0xfd, 0x70, 0xc8, 0xfc, 0x74, 0xc8,
0x99, 0xd6, 0x5a, 0xf5, 0x90, 0x87, 0x5c, 0x3d, 0xba, 0xf2, 0x09, 0x56, 0x77, 0xa1, 0x08, 0x8c,
0xd4, 0x22, 0xb9, 0x40, 0xbb, 0x6f, 0xa4, 0x49, 0xcf, 0x8f, 0x7c, 0x16, 0x50, 0x8f, 0x8e, 0x33,
0x2a, 0x52, 0xfc, 0x0a, 0x55, 0xfd, 0xc1, 0x20, 0xa1, 0x42, 0x34, 0xcc, 0x96, 0xd9, 0xde, 0xe9,
0x3d, 0xfd, 0x33, 0x6d, 0x1e, 0x85, 0xc3, 0xf4, 0x53, 0xd6, 0x77, 0x02, 0x3e, 0x72, 0x17, 0xbc,
0x8e, 0xc4, 0xe0, 0xdc, 0x4d, 0x27, 0x31, 0x15, 0x4e, 0x37, 0x08, 0xba, 0xba, 0xd0, 0xcb, 0x1d,
0x70, 0x1d, 0x6d, 0x0d, 0x28, 0xe3, 0xa3, 0xc6, 0x46, 0xcb, 0x6c, 0xdf, 0xf1, 0xf4, 0x0b, 0x79,
0x8e, 0xea, 0x8b, 0x27, 0x8b, 0x98, 0x33, 0x41, 0xf1, 0x01, 0xaa, 0xf6, 0xf5, 0x92, 0x3a, 0xba,
0xd6, 0xd9, 0x71, 0x80, 0xf8, 0x98, 0x0f, 0x99, 0x97, 0x6f, 0x92, 0x2f, 0x26, 0xda, 0x53, 0x06,
0xdd, 0x28, 0x02, 0x0f, 0x71, 0x2b, 0xf8, 0x8f, 0xd1, 0x66, 0x42, 0xc7, 0x0a, 0xbe, 0xd6, 0xd9,
0xcf, 0x61, 0x74, 0x36, 0x27, 0x7e, 0x98, 0xdf, 0x99, 0x27, 0x55, 0xe4, 0xab, 0x89, 0x1a, 0xab,
0x54, 0xd0, 0xda, 0x19, 0xda, 0x06, 0x7a, 0xc9, 0xb5, 0xb9, 0xdc, 0x5b, 0xef, 0xc9, 0xe5, 0xb4,
0x69, 0x7c, 0xfb, 0xd9, 0x6c, 0xdf, 0x80, 0x54, 0x16, 0x08, 0xef, 0xda, 0x0f, 0x1f, 0x4a, 0x4a,
0x01, 0x94, 0x56, 0x19, 0xa5, 0x86, 0x90, 0x98, 0x82, 0xec, 0xc3, 0xdd, 0xbd, 0xe5, 0xa9, 0x1f,
0x9d, 0x66, 0x71, 0x1c, 0x4d, 0xa0, 0x0d, 0x92, 0x40, 0x03, 0x0b, 0x5b, 0xd0, 0xc0, 0x3b, 0x54,
0x11, 0x6a, 0xe5, 0x3f, 0xe1, 0x83, 0x1b, 0x39, 0x84, 0x59, 0xd0, 0xc7, 0xbd, 0xfe, 0x98, 0xe7,
0x78, 0x3d, 0x39, 0x66, 0x71, 0x72, 0x3e, 0xa0, 0xbb, 0x4b, 0x6a, 0xc0, 0x7b, 0x81, 0x2a, 0xfe,
0x88, 0x67, 0x2c, 0xd5, 0xfa, 0x9e, 0x23, 0x81, 0x7e, 0x4c, 0x9b, 0x07, 0x37, 0x00, 0x7a, 0xc9,
0x52, 0x0f, 0xaa, 0x3b, 0xbf, 0x37, 0xd0, 0x96, 0x3a, 0x01, 0x9f, 0xa0, 0x2a, 0xa4, 0x88, 0x5b,
0x4e, 0xe1, 0x0b, 0x74, 0x4a, 0x3e, 0x1a, 0xeb, 0xfe, 0x1a, 0x85, 0x26, 0x24, 0x06, 0x7e, 0x8f,
0x6a, 0x85, 0xd1, 0xc0, 0x0f, 0x56, 0x6b, 0x56, 0xe7, 0xd9, 0x7a, 0xf8, 0x0f, 0x55, 0xd1, 0xbd,
0x90, 0x5b, 0x99, 0xfb, 0x6a, 0xe2, 0x65, 0xee, 0x25, 0xe1, 0x13, 0x03, 0x9f, 0xa2, 0xed, 0xfc,
0xce, 0x71, 0x49, 0xb3, 0x4b, 0xe9, 0x59, 0x64, 0x9d, 0x24, 0x37, 0xed, 0x1d, 0x5f, 0xce, 0x6c,
0xf3, 0x6a, 0x66, 0x9b, 0xbf, 0x66, 0xb6, 0xf9, 0x79, 0x6e, 0x1b, 0x57, 0x73, 0xdb, 0xf8, 0x3e,
0xb7, 0x8d, 0xb3, 0x47, 0x6b, 0x63, 0xbb, 0xd0, 0xff, 0x48, 0x95, 0x5e, 0xbf, 0xa2, 0xfe, 0x66,
0xcf, 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0x6e, 0x62, 0xaf, 0x8a, 0x3f, 0x05, 0x00, 0x00,
// 525 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x94, 0xcf, 0x6e, 0xd3, 0x4c,
0x14, 0xc5, 0xed, 0x56, 0x4d, 0xfa, 0x4d, 0xba, 0x9a, 0xe6, 0x53, 0x53, 0x4b, 0x38, 0x61, 0xc4,
0x9f, 0x20, 0x5a, 0x1b, 0xc2, 0x1e, 0x29, 0xee, 0x92, 0x05, 0xc5, 0x05, 0x16, 0x15, 0x1b, 0xc7,
0x19, 0x4c, 0x54, 0x67, 0xc6, 0xf1, 0xd8, 0x52, 0xf3, 0x16, 0x48, 0xbc, 0x02, 0x2b, 0x9e, 0xa4,
0xcb, 0x2e, 0x11, 0x8b, 0x80, 0x92, 0x1d, 0x8f, 0xc0, 0x0a, 0xcd, 0xcc, 0x75, 0xe5, 0x24, 0x56,
0xe8, 0x02, 0x76, 0xf6, 0xcc, 0x9d, 0x73, 0x7f, 0xd7, 0xe7, 0x78, 0xd0, 0x41, 0xc8, 0xc5, 0x98,
0x0b, 0x77, 0x10, 0xb0, 0x0b, 0x77, 0x92, 0xd3, 0x74, 0xea, 0x24, 0x29, 0xcf, 0x38, 0x6e, 0xe8,
0x0d, 0x47, 0x6e, 0x58, 0x77, 0xa0, 0x4a, 0x15, 0xb8, 0x49, 0x10, 0x8d, 0x58, 0x90, 0x8d, 0x38,
0xd3, 0xb5, 0x56, 0x33, 0xe2, 0x11, 0x57, 0x8f, 0xae, 0x7c, 0x82, 0xd5, 0x7d, 0x38, 0x04, 0x42,
0x6a, 0x91, 0x5c, 0xa2, 0xfd, 0x57, 0x52, 0xc4, 0x0b, 0xe2, 0x80, 0x85, 0xd4, 0xa7, 0x93, 0x9c,
0x8a, 0x0c, 0xbf, 0x40, 0xf5, 0x60, 0x38, 0x4c, 0xa9, 0x10, 0x2d, 0xb3, 0x63, 0x76, 0xf7, 0xbc,
0xa7, 0xbf, 0x66, 0xed, 0xe3, 0x68, 0x94, 0x7d, 0xc8, 0x07, 0x4e, 0xc8, 0xc7, 0xee, 0x92, 0xd6,
0xb1, 0x18, 0x5e, 0xb8, 0xd9, 0x34, 0xa1, 0xc2, 0xe9, 0x87, 0x61, 0x5f, 0x1f, 0xf4, 0x0b, 0x05,
0xdc, 0x44, 0x3b, 0x43, 0xca, 0xf8, 0xb8, 0xb5, 0xd5, 0x31, 0xbb, 0xff, 0xf9, 0xfa, 0x85, 0x3c,
0x47, 0xcd, 0xe5, 0xce, 0x22, 0xe1, 0x4c, 0x50, 0xfc, 0x00, 0xd5, 0x07, 0x7a, 0x49, 0xb5, 0x6e,
0xf4, 0xf6, 0x1c, 0x20, 0x3e, 0xe1, 0x23, 0xe6, 0x17, 0x9b, 0xe4, 0x93, 0x89, 0x0e, 0x94, 0x40,
0x3f, 0x8e, 0x41, 0x43, 0xfc, 0x13, 0xfc, 0xc7, 0x68, 0x3b, 0xa5, 0x13, 0x05, 0xdf, 0xe8, 0x1d,
0x16, 0x30, 0xda, 0x9b, 0xd3, 0x20, 0x2a, 0xbe, 0x99, 0x2f, 0xab, 0xc8, 0x67, 0x13, 0xb5, 0xd6,
0xa9, 0x60, 0xb4, 0x73, 0xb4, 0x0b, 0xf4, 0x92, 0x6b, 0x7b, 0x75, 0x36, 0xef, 0xc9, 0xd5, 0xac,
0x6d, 0x7c, 0xf9, 0xde, 0xee, 0xde, 0x82, 0x54, 0x1e, 0x10, 0xfe, 0x8d, 0x1e, 0x3e, 0x92, 0x94,
0x02, 0x28, 0xad, 0x2a, 0x4a, 0x0d, 0x21, 0x31, 0x05, 0x39, 0x84, 0x6f, 0xf7, 0x9a, 0x67, 0x41,
0x7c, 0x96, 0x27, 0x49, 0x3c, 0x85, 0x31, 0x48, 0x0a, 0x03, 0x2c, 0x6d, 0xc1, 0x00, 0x6f, 0x51,
0x4d, 0xa8, 0x95, 0xbf, 0x84, 0x0f, 0x6a, 0xe4, 0x08, 0xb2, 0xa0, 0xdb, 0xbd, 0x7c, 0x5f, 0xf8,
0x78, 0x93, 0x1c, 0xb3, 0x9c, 0x1c, 0x86, 0xfe, 0x5f, 0xa9, 0x06, 0xbc, 0x37, 0xa8, 0x16, 0x8c,
0x79, 0xce, 0xb2, 0xaa, 0xe4, 0x78, 0xae, 0xc4, 0xfb, 0x36, 0x6b, 0x3f, 0xbc, 0x25, 0x9e, 0x0f,
0x62, 0xbd, 0x9f, 0x5b, 0x68, 0x47, 0x35, 0xc4, 0xa7, 0xa8, 0x0e, 0xa6, 0xe2, 0x8e, 0x53, 0xfa,
0x21, 0x9d, 0x8a, 0x7f, 0xc8, 0xba, 0xbb, 0xa1, 0x42, 0x03, 0x13, 0x03, 0xbf, 0x43, 0x8d, 0x52,
0x52, 0xf0, 0xbd, 0xf5, 0x33, 0xeb, 0xf1, 0xb6, 0xee, 0xff, 0xa1, 0xaa, 0xac, 0x5e, 0xb2, 0xb1,
0x4a, 0x7d, 0x3d, 0x00, 0x55, 0xea, 0x15, 0x59, 0x20, 0x06, 0x3e, 0x43, 0xbb, 0x85, 0x05, 0xb8,
0x62, 0xd8, 0x15, 0x33, 0x2d, 0xb2, 0xa9, 0xa4, 0x10, 0xf5, 0x4e, 0xae, 0xe6, 0xb6, 0x79, 0x3d,
0xb7, 0xcd, 0x1f, 0x73, 0xdb, 0xfc, 0xb8, 0xb0, 0x8d, 0xeb, 0x85, 0x6d, 0x7c, 0x5d, 0xd8, 0xc6,
0xf9, 0xa3, 0x8d, 0xbe, 0x5d, 0xea, 0x2b, 0x53, 0xd9, 0x37, 0xa8, 0xa9, 0xcb, 0xed, 0xd9, 0xef,
0x00, 0x00, 0x00, 0xff, 0xff, 0x06, 0xd8, 0xbc, 0xab, 0x4e, 0x05, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -1782,7 +1782,7 @@ func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error {
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
}
var stringLen uint64
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowQuery
@ -1792,16 +1792,15 @@ func (m *QuerySupplyOfResponse) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
if msglen < 0 {
return ErrInvalidLengthQuery
}
postIndex := iNdEx + intStringLen
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthQuery
}

View File

@ -4,7 +4,6 @@ import (
"fmt"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
"github.com/cosmos/cosmos-sdk/x/gov/types"
@ -71,10 +70,6 @@ func QueryDepositsByTxQuery(clientCtx client.Context, params types.QueryProposal
return nil, err
}
if clientCtx.Indent {
return codec.MarshalIndentFromJSON(bz)
}
return bz, nil
}
@ -127,10 +122,6 @@ func QueryVotesByTxQuery(clientCtx client.Context, params types.QueryProposalVot
return nil, err
}
if clientCtx.Indent {
return codec.MarshalIndentFromJSON(bz)
}
return bz, nil
}
@ -165,10 +156,6 @@ func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams)
return nil, err
}
if clientCtx.Indent {
return codec.MarshalIndentFromJSON(bz)
}
return bz, nil
}
}
@ -210,10 +197,6 @@ func QueryDepositByTxQuery(clientCtx client.Context, params types.QueryDepositPa
return nil, err
}
if clientCtx.Indent {
return codec.MarshalIndentFromJSON(bz)
}
return bz, nil
}
}

View File

@ -60,7 +60,7 @@ func NewCreateValidatorCmd(clientCtx client.Context) *cobra.Command {
Short: "create new validator initialized with a self-delegation to it",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := clientCtx.InitWithInput(cmd.InOrStdin())
txf := tx.NewFactoryFromCLI(clientCtx.Input).WithTxGenerator(clientCtx.TxGenerator).WithAccountRetriever(clientCtx.AccountRetriever)
txf := tx.NewFactoryFromDeprecated(clientCtx.Input).WithTxGenerator(clientCtx.TxGenerator).WithAccountRetriever(clientCtx.AccountRetriever)
txf, msg, err := NewBuildCreateValidatorMsg(clientCtx, txf)
if err != nil {