Synopsis
This document describes the lifecycle of a query in a Cosmos SDK application, from the user interface to application stores and back. The query is referred to asMyQuery
.
Pre-requisite Readings
Query Creation
A query is a request for information made by end-users of applications through an interface and processed by a full-node. Users can query information about the network, the application itself, and application state directly from the application’s stores or modules. Note that queries are different from transactions (view the lifecycle here), particularly in that they do not require consensus to be processed (as they do not trigger state-transitions); they can be fully handled by one full-node. For the purpose of explaining the query lifecycle, let’s say the query,MyQuery
, is requesting a list of delegations made by a certain delegator address in the application called simapp
. As is to be expected, the staking
module handles this query. But first, there are a few ways MyQuery
can be created by users.
CLI
The main interface for an application is the command-line interface. Users connect to a full-node and run the CLI directly from their machines - the CLI interacts directly with the full-node. To createMyQuery
from their terminal, users type the following command:
Copy
Ask AI
simd query staking delegations <delegatorAddress>
staking
module developer and added to the list of subcommands by the application developer when creating the CLI.
Note that the general format is as follows:
Copy
Ask AI
simd query [moduleName] [command] <arguments> --flag <flagArg>
--node
(the full-node the CLI connects to), the user can use the app.toml
config file to set them or provide them as flags.
The CLI understands a specific set of commands, defined in a hierarchical structure by the application developer: from the root command (simd
), the type of command (Myquery
), the module that contains the command (staking
), and command itself (delegations
). Thus, the CLI knows exactly which module handles this command and directly passes the call there.
gRPC
Another interface through which users can make queries is gRPC requests to a gRPC server. The endpoints are defined as Protocol Buffers service methods inside.proto
files, written in Protobuf’s own language-agnostic interface definition language (IDL). The Protobuf ecosystem developed tools for code-generation from *.proto
files into various languages. These tools allow to build gRPC clients easily.
One such tool is grpcurl, and a gRPC request for MyQuery
using this client looks like:
Copy
Ask AI
grpcurl \
-plaintext # We want results in plain test
-import-path ./proto \ # Import these .proto files
-proto ./proto/cosmos/staking/v1beta1/query.proto \ # Look into this .proto file for the Query protobuf service
-d '{"address":"$MY_DELEGATOR"}' \ # Query arguments
localhost:9090 \ # gRPC server endpoint
cosmos.staking.v1beta1.Query/Delegations # Fully-qualified service method name
REST
Another interface through which users can make queries is through HTTP Requests to a REST server. The REST server is fully auto-generated from Protobuf services, using gRPC-gateway. An example HTTP request forMyQuery
looks like:
Copy
Ask AI
GET http://localhost:1317/cosmos/staking/v1beta1/delegators/{delegatorAddr}/delegations
How Queries are Handled by the CLI
The preceding examples show how an external user can interact with a node by querying its state. To understand in more detail the exact lifecycle of a query, let’s dig into how the CLI prepares the query, and how the node handles it. The interactions from the users’ perspective are a bit different, but the underlying functions are almost identical because they are implementations of the same command defined by the module developer. This step of processing happens within the CLI, gRPC, or REST server, and heavily involves aclient.Context
.
Context
The first thing that is created in the execution of a CLI command is aclient.Context
. A client.Context
is an object that stores all the data needed to process a request on the user side. In particular, a client.Context
stores the following:
- Codec: The encoder/decoder used by the application, used to marshal the parameters and query before making the CometBFT RPC request and unmarshal the returned response into a JSON object. The default codec used by the CLI is Protobuf.
- Account Decoder: The account decoder from the
auth
module, which translates[]byte
s into accounts. - RPC Client: The CometBFT RPC Client, or node, to which requests are relayed.
- Keyring: A Key Manager used to sign transactions and handle other operations with keys.
- Output Writer: A Writer used to output the response.
- Configurations: The flags configured by the user for this command, including
--height
, specifying the height of the blockchain to query, and--indent
, which indicates to add an indent to the JSON response.
client.Context
also contains various functions such as Query()
, which retrieves the RPC Client and makes an ABCI call to relay a query to a full-node.
Copy
Ask AI
package client
import (
"bufio"
"encoding/json"
"fmt"
"io"
"os"
"github.com/cosmos/gogoproto/proto"
"github.com/spf13/viper"
"google.golang.org/grpc"
"sigs.k8s.io/yaml"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
)
/ PreprocessTxFn defines a hook by which chains can preprocess transactions before broadcasting
type PreprocessTxFn func(chainID string, key keyring.KeyType, tx TxBuilder)
error
/ Context implements a typical context created in SDK modules for transaction
/ handling and queries.
type Context struct {
FromAddress sdk.AccAddress
Client TendermintRPC
GRPCClient *grpc.ClientConn
ChainID string
Codec codec.Codec
InterfaceRegistry codectypes.InterfaceRegistry
Input io.Reader
Keyring keyring.Keyring
KeyringOptions []keyring.Option
Output io.Writer
OutputFormat string
Height int64
HomeDir string
KeyringDir string
From string
BroadcastMode string
FromName string
SignModeStr string
UseLedger bool
Simulate bool
GenerateOnly bool
Offline bool
SkipConfirm bool
TxConfig TxConfig
AccountRetriever AccountRetriever
NodeURI string
FeePayer sdk.AccAddress
FeeGranter sdk.AccAddress
Viper *viper.Viper
LedgerHasProtobuf bool
PreprocessTxHook PreprocessTxFn
/ IsAux is true when the signer is an auxiliary signer (e.g. the tipper).
IsAux bool
/ TODO: Deprecated (remove).
LegacyAmino *codec.LegacyAmino
}
/ WithKeyring returns a copy of the context with an updated keyring.
func (ctx Context)
WithKeyring(k keyring.Keyring)
Context {
ctx.Keyring = k
return ctx
}
/ WithKeyringOptions returns a copy of the context with an updated keyring.
func (ctx Context)
WithKeyringOptions(opts ...keyring.Option)
Context {
ctx.KeyringOptions = opts
return ctx
}
/ WithInput returns a copy of the context with an updated input.
func (ctx Context)
WithInput(r io.Reader)
Context {
/ convert to a bufio.Reader to have a shared buffer between the keyring and the
/ the Commands, ensuring a read from one advance the read pointer for the other.
/ see https://github.com/cosmos/cosmos-sdk/issues/9566.
ctx.Input = bufio.NewReader(r)
return ctx
}
/ WithCodec returns a copy of the Context with an updated Codec.
func (ctx Context)
WithCodec(m codec.Codec)
Context {
ctx.Codec = m
return ctx
}
/ WithLegacyAmino returns a copy of the context with an updated LegacyAmino codec.
/ TODO: Deprecated (remove).
func (ctx Context)
WithLegacyAmino(cdc *codec.LegacyAmino)
Context {
ctx.LegacyAmino = cdc
return ctx
}
/ WithOutput returns a copy of the context with an updated output writer (e.g. stdout).
func (ctx Context)
WithOutput(w io.Writer)
Context {
ctx.Output = w
return ctx
}
/ WithFrom returns a copy of the context with an updated from address or name.
func (ctx Context)
WithFrom(from string)
Context {
ctx.From = from
return ctx
}
/ WithOutputFormat returns a copy of the context with an updated OutputFormat field.
func (ctx Context)
WithOutputFormat(format string)
Context {
ctx.OutputFormat = format
return ctx
}
/ WithNodeURI returns a copy of the context with an updated node URI.
func (ctx Context)
WithNodeURI(nodeURI string)
Context {
ctx.NodeURI = nodeURI
return ctx
}
/ WithHeight returns a copy of the context with an updated height.
func (ctx Context)
WithHeight(height int64)
Context {
ctx.Height = height
return ctx
}
/ WithClient returns a copy of the context with an updated RPC client
/ instance.
func (ctx Context)
WithClient(client TendermintRPC)
Context {
ctx.Client = client
return ctx
}
/ WithGRPCClient returns a copy of the context with an updated GRPC client
/ instance.
func (ctx Context)
WithGRPCClient(grpcClient *grpc.ClientConn)
Context {
ctx.GRPCClient = grpcClient
return ctx
}
/ WithUseLedger returns a copy of the context with an updated UseLedger flag.
func (ctx Context)
WithUseLedger(useLedger bool)
Context {
ctx.UseLedger = useLedger
return ctx
}
/ WithChainID returns a copy of the context with an updated chain ID.
func (ctx Context)
WithChainID(chainID string)
Context {
ctx.ChainID = chainID
return ctx
}
/ WithHomeDir returns a copy of the Context with HomeDir set.
func (ctx Context)
WithHomeDir(dir string)
Context {
if dir != "" {
ctx.HomeDir = dir
}
return ctx
}
/ WithKeyringDir returns a copy of the Context with KeyringDir set.
func (ctx Context)
WithKeyringDir(dir string)
Context {
ctx.KeyringDir = dir
return ctx
}
/ WithGenerateOnly returns a copy of the context with updated GenerateOnly value
func (ctx Context)
WithGenerateOnly(generateOnly bool)
Context {
ctx.GenerateOnly = generateOnly
return ctx
}
/ WithSimulation returns a copy of the context with updated Simulate value
func (ctx Context)
WithSimulation(simulate bool)
Context {
ctx.Simulate = simulate
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
return ctx
}
/ WithFromAddress returns a copy of the context with an updated from account
/ address.
func (ctx Context)
WithFromAddress(addr sdk.AccAddress)
Context {
ctx.FromAddress = addr
return ctx
}
/ WithFeePayerAddress returns a copy of the context with an updated fee payer account
/ address.
func (ctx Context)
WithFeePayerAddress(addr sdk.AccAddress)
Context {
ctx.FeePayer = addr
return ctx
}
/ WithFeeGranterAddress returns a copy of the context with an updated fee granter account
/ address.
func (ctx Context)
WithFeeGranterAddress(addr sdk.AccAddress)
Context {
ctx.FeeGranter = addr
return ctx
}
/ WithBroadcastMode returns a copy of the context with an updated broadcast
/ mode.
func (ctx Context)
WithBroadcastMode(mode string)
Context {
ctx.BroadcastMode = mode
return ctx
}
/ WithSignModeStr returns a copy of the context with an updated SignMode
/ value.
func (ctx Context)
WithSignModeStr(signModeStr string)
Context {
ctx.SignModeStr = signModeStr
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
}
/ WithTxConfig returns the context with an updated TxConfig
func (ctx Context)
WithTxConfig(generator TxConfig)
Context {
ctx.TxConfig = generator
return ctx
}
/ WithAccountRetriever returns the context with an updated AccountRetriever
func (ctx Context)
WithAccountRetriever(retriever AccountRetriever)
Context {
ctx.AccountRetriever = retriever
return ctx
}
/ WithInterfaceRegistry returns the context with an updated InterfaceRegistry
func (ctx Context)
WithInterfaceRegistry(interfaceRegistry codectypes.InterfaceRegistry)
Context {
ctx.InterfaceRegistry = interfaceRegistry
return ctx
}
/ WithViper returns the context with Viper field. This Viper instance is used to read
/ client-side config from the config file.
func (ctx Context)
WithViper(prefix string)
Context {
v := viper.New()
v.SetEnvPrefix(prefix)
v.AutomaticEnv()
ctx.Viper = v
return ctx
}
/ WithAux returns a copy of the context with an updated IsAux value.
func (ctx Context)
WithAux(isAux bool)
Context {
ctx.IsAux = isAux
return ctx
}
/ WithLedgerHasProto returns the context with the provided boolean value, indicating
/ whether the target Ledger application can support Protobuf payloads.
func (ctx Context)
WithLedgerHasProtobuf(val bool)
Context {
ctx.LedgerHasProtobuf = val
return ctx
}
/ WithPreprocessTxHook returns the context with the provided preprocessing hook, which
/ enables chains to preprocess the transaction using the builder.
func (ctx Context)
WithPreprocessTxHook(preprocessFn PreprocessTxFn)
Context {
ctx.PreprocessTxHook = preprocessFn
return ctx
}
/ PrintString prints the raw string to ctx.Output if it's defined, otherwise to os.Stdout
func (ctx Context)
PrintString(str string)
error {
return ctx.PrintBytes([]byte(str))
}
/ PrintBytes prints the raw bytes to ctx.Output if it's defined, otherwise to os.Stdout.
/ NOTE: for printing a complex state object, you should use ctx.PrintOutput
func (ctx Context)
PrintBytes(o []byte)
error {
writer := ctx.Output
if writer == nil {
writer = os.Stdout
}
_, err := writer.Write(o)
return err
}
/ PrintProto outputs toPrint to the ctx.Output based on ctx.OutputFormat which is
/ either text or json. If text, toPrint will be YAML encoded. Otherwise, toPrint
/ will be JSON encoded using ctx.Codec. An error is returned upon failure.
func (ctx Context)
PrintProto(toPrint proto.Message)
error {
/ always serialize JSON initially because proto json can't be directly YAML encoded
out, err := ctx.Codec.MarshalJSON(toPrint)
if err != nil {
return err
}
return ctx.printOutput(out)
}
/ PrintObjectLegacy is a variant of PrintProto that doesn't require a proto.Message type
/ and uses amino JSON encoding.
/ Deprecated: It will be removed in the near future!
func (ctx Context)
PrintObjectLegacy(toPrint interface{
})
error {
out, err := ctx.LegacyAmino.MarshalJSON(toPrint)
if err != nil {
return err
}
return ctx.printOutput(out)
}
/ PrintRaw is a variant of PrintProto that doesn't require a proto.Message type
/ and uses a raw JSON message. No marshaling is performed.
func (ctx Context)
PrintRaw(toPrint json.RawMessage)
error {
return ctx.printOutput(toPrint)
}
func (ctx Context)
printOutput(out []byte)
error {
var err error
if ctx.OutputFormat == "text" {
out, err = yaml.JSONToYAML(out)
if err != nil {
return err
}
}
writer := ctx.Output
if writer == nil {
writer = os.Stdout
}
_, err = writer.Write(out)
if err != nil {
return err
}
if ctx.OutputFormat != "text" {
/ append new-line for formats besides YAML
_, err = writer.Write([]byte("\n"))
if err != nil {
return err
}
}
return nil
}
/ GetFromFields returns a from account address, account name and keyring type, given either an address or key name.
/ If clientCtx.Simulate is true the keystore is not accessed and a valid address must be provided
/ If clientCtx.GenerateOnly is true the keystore is only accessed if a key name is provided
func GetFromFields(clientCtx Context, kr keyring.Keyring, from string) (sdk.AccAddress, string, keyring.KeyType, error) {
if from == "" {
return nil, "", 0, nil
}
addr, err := sdk.AccAddressFromBech32(from)
switch {
case clientCtx.Simulate:
if err != nil {
return nil, "", 0, fmt.Errorf("a valid bech32 address must be provided in simulation mode: %w", err)
}
return addr, "", 0, nil
case clientCtx.GenerateOnly:
if err == nil {
return addr, "", 0, nil
}
}
var k *keyring.Record
if err == nil {
k, err = kr.KeyByAddress(addr)
if err != nil {
return nil, "", 0, err
}
}
else {
k, err = kr.Key(from)
if err != nil {
return nil, "", 0, err
}
}
addr, err = k.GetAddress()
if err != nil {
return nil, "", 0, err
}
return addr, k.Name, k.GetType(), nil
}
/ NewKeyringFromBackend gets a Keyring object from a backend
func NewKeyringFromBackend(ctx Context, backend string) (keyring.Keyring, error) {
if ctx.Simulate {
backend = keyring.BackendMemory
}
return keyring.New(sdk.KeyringServiceName(), backend, ctx.KeyringDir, ctx.Input, ctx.Codec, ctx.KeyringOptions...)
}
client.Context
’s primary role is to store data used during interactions with the end-user and provide methods to interact with this data - it is used before and after the query is processed by the full-node. Specifically, in handling MyQuery
, the client.Context
is utilized to encode the query parameters, retrieve the full-node, and write the output. Prior to being relayed to a full-node, the query needs to be encoded into a []byte
form, as full-nodes are application-agnostic and do not understand specific types. The full-node (RPC Client) itself is retrieved using the client.Context
, which knows which node the user CLI is connected to. The query is relayed to this full-node to be processed. Finally, the client.Context
contains a Writer
to write output when the response is returned. These steps are further described in later sections.
Arguments and Route Creation
At this point in the lifecycle, the user has created a CLI command with all of the data they wish to include in their query. Aclient.Context
exists to assist in the rest of the MyQuery
’s journey. Now, the next step is to parse the command or request, extract the arguments, and encode everything. These steps all happen on the user side within the interface they are interacting with.
Encoding
In our case (querying an address’s delegations),MyQuery
contains an address delegatorAddress
as its only argument. However, the request can only contain []byte
s, as it is ultimately relayed to a consensus engine (e.g. CometBFT) of a full-node that has no inherent knowledge of the application types. Thus, the codec
of client.Context
is used to marshal the address.
Here is what the code looks like for the CLI command:
Copy
Ask AI
package cli
import (
"fmt"
"strconv"
"strings"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
/ GetQueryCmd returns the cli query commands for this module
func GetQueryCmd() *cobra.Command {
stakingQueryCmd := &cobra.Command{
Use: types.ModuleName,
Short: "Querying commands for the staking module",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
stakingQueryCmd.AddCommand(
GetCmdQueryDelegation(),
GetCmdQueryDelegations(),
GetCmdQueryUnbondingDelegation(),
GetCmdQueryUnbondingDelegations(),
GetCmdQueryRedelegation(),
GetCmdQueryRedelegations(),
GetCmdQueryValidator(),
GetCmdQueryValidators(),
GetCmdQueryValidatorDelegations(),
GetCmdQueryValidatorUnbondingDelegations(),
GetCmdQueryValidatorRedelegations(),
GetCmdQueryHistoricalInfo(),
GetCmdQueryParams(),
GetCmdQueryPool(),
)
return stakingQueryCmd
}
/ GetCmdQueryValidator implements the validator query command.
func GetCmdQueryValidator() *cobra.Command {
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "validator [validator-addr]",
Short: "Query a validator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query details about an individual validator.
Example:
$ %s query staking validator %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
addr, err := sdk.ValAddressFromBech32(args[0])
if err != nil {
return err
}
params := &types.QueryValidatorRequest{
ValidatorAddr: addr.String()
}
res, err := queryClient.Validator(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(&res.Validator)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
/ GetCmdQueryValidators implements the query all validators command.
func GetCmdQueryValidators() *cobra.Command {
cmd := &cobra.Command{
Use: "validators",
Short: "Query for all validators",
Args: cobra.NoArgs,
Long: strings.TrimSpace(
fmt.Sprintf(`Query details about all validators on a network.
Example:
$ %s query staking validators
`,
version.AppName,
),
),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
result, err := queryClient.Validators(cmd.Context(), &types.QueryValidatorsRequest{
/ Leaving status empty on purpose to query all validators.
Pagination: pageReq,
})
if err != nil {
return err
}
return clientCtx.PrintProto(result)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "validators")
return cmd
}
/ GetCmdQueryValidatorUnbondingDelegations implements the query all unbonding delegatations from a validator command.
func GetCmdQueryValidatorUnbondingDelegations() *cobra.Command {
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "unbonding-delegations-from [validator-addr]",
Short: "Query all unbonding delegatations from a validator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query delegations that are unbonding _from_ a validator.
Example:
$ %s query staking unbonding-delegations-from %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
valAddr, err := sdk.ValAddressFromBech32(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
params := &types.QueryValidatorUnbondingDelegationsRequest{
ValidatorAddr: valAddr.String(),
Pagination: pageReq,
}
res, err := queryClient.ValidatorUnbondingDelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "unbonding delegations")
return cmd
}
/ GetCmdQueryValidatorRedelegations implements the query all redelegatations
/ from a validator command.
func GetCmdQueryValidatorRedelegations() *cobra.Command {
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "redelegations-from [validator-addr]",
Short: "Query all outgoing redelegatations from a validator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query delegations that are redelegating _from_ a validator.
Example:
$ %s query staking redelegations-from %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
valSrcAddr, err := sdk.ValAddressFromBech32(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
params := &types.QueryRedelegationsRequest{
SrcValidatorAddr: valSrcAddr.String(),
Pagination: pageReq,
}
res, err := queryClient.Redelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "validator redelegations")
return cmd
}
/ GetCmdQueryDelegation the query delegation command.
func GetCmdQueryDelegation() *cobra.Command {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "delegation [delegator-addr] [validator-addr]",
Short: "Query a delegation based on address and validator address",
Long: strings.TrimSpace(
fmt.Sprintf(`Query delegations for an individual delegator on an individual validator.
Example:
$ %s query staking delegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixAccAddr, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
delAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
valAddr, err := sdk.ValAddressFromBech32(args[1])
if err != nil {
return err
}
params := &types.QueryDelegationRequest{
DelegatorAddr: delAddr.String(),
ValidatorAddr: valAddr.String(),
}
res, err := queryClient.Delegation(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res.DelegationResponse)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
/ GetCmdQueryDelegations implements the command to query all the delegations
/ made from one delegator.
func GetCmdQueryDelegations() *cobra.Command {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
cmd := &cobra.Command{
Use: "delegations [delegator-addr]",
Short: "Query all delegations made by one delegator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query delegations for an individual delegator on all validators.
Example:
$ %s query staking delegations %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p
`,
version.AppName, bech32PrefixAccAddr,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
delAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
params := &types.QueryDelegatorDelegationsRequest{
DelegatorAddr: delAddr.String(),
Pagination: pageReq,
}
res, err := queryClient.DelegatorDelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "delegations")
return cmd
}
/ GetCmdQueryValidatorDelegations implements the command to query all the
/ delegations to a specific validator.
func GetCmdQueryValidatorDelegations() *cobra.Command {
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "delegations-to [validator-addr]",
Short: "Query all delegations made to one validator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query delegations on an individual validator.
Example:
$ %s query staking delegations-to %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
valAddr, err := sdk.ValAddressFromBech32(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
params := &types.QueryValidatorDelegationsRequest{
ValidatorAddr: valAddr.String(),
Pagination: pageReq,
}
res, err := queryClient.ValidatorDelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "validator delegations")
return cmd
}
/ GetCmdQueryUnbondingDelegation implements the command to query a single
/ unbonding-delegation record.
func GetCmdQueryUnbondingDelegation() *cobra.Command {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "unbonding-delegation [delegator-addr] [validator-addr]",
Short: "Query an unbonding-delegation record based on delegator and validator address",
Long: strings.TrimSpace(
fmt.Sprintf(`Query unbonding delegations for an individual delegator on an individual validator.
Example:
$ %s query staking unbonding-delegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixAccAddr, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
valAddr, err := sdk.ValAddressFromBech32(args[1])
if err != nil {
return err
}
delAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
params := &types.QueryUnbondingDelegationRequest{
DelegatorAddr: delAddr.String(),
ValidatorAddr: valAddr.String(),
}
res, err := queryClient.UnbondingDelegation(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(&res.Unbond)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
/ GetCmdQueryUnbondingDelegations implements the command to query all the
/ unbonding-delegation records for a delegator.
func GetCmdQueryUnbondingDelegations() *cobra.Command {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
cmd := &cobra.Command{
Use: "unbonding-delegations [delegator-addr]",
Short: "Query all unbonding-delegations records for one delegator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query unbonding delegations for an individual delegator.
Example:
$ %s query staking unbonding-delegations %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p
`,
version.AppName, bech32PrefixAccAddr,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
delegatorAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
params := &types.QueryDelegatorUnbondingDelegationsRequest{
DelegatorAddr: delegatorAddr.String(),
Pagination: pageReq,
}
res, err := queryClient.DelegatorUnbondingDelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "unbonding delegations")
return cmd
}
/ GetCmdQueryRedelegation implements the command to query a single
/ redelegation record.
func GetCmdQueryRedelegation() *cobra.Command {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "redelegation [delegator-addr] [src-validator-addr] [dst-validator-addr]",
Short: "Query a redelegation record based on delegator and a source and destination validator address",
Long: strings.TrimSpace(
fmt.Sprintf(`Query a redelegation record for an individual delegator between a source and destination validator.
Example:
$ %s query staking redelegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixAccAddr, bech32PrefixValAddr, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
delAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
valSrcAddr, err := sdk.ValAddressFromBech32(args[1])
if err != nil {
return err
}
valDstAddr, err := sdk.ValAddressFromBech32(args[2])
if err != nil {
return err
}
params := &types.QueryRedelegationsRequest{
DelegatorAddr: delAddr.String(),
DstValidatorAddr: valDstAddr.String(),
SrcValidatorAddr: valSrcAddr.String(),
}
res, err := queryClient.Redelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
/ GetCmdQueryRedelegations implements the command to query all the
/ redelegation records for a delegator.
func GetCmdQueryRedelegations() *cobra.Command {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
cmd := &cobra.Command{
Use: "redelegations [delegator-addr]",
Args: cobra.ExactArgs(1),
Short: "Query all redelegations records for one delegator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query all redelegation records for an individual delegator.
Example:
$ %s query staking redelegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p
`,
version.AppName, bech32PrefixAccAddr,
),
),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
delAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
params := &types.QueryRedelegationsRequest{
DelegatorAddr: delAddr.String(),
Pagination: pageReq,
}
res, err := queryClient.Redelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "delegator redelegations")
return cmd
}
/ GetCmdQueryHistoricalInfo implements the historical info query command
func GetCmdQueryHistoricalInfo() *cobra.Command {
cmd := &cobra.Command{
Use: "historical-info [height]",
Args: cobra.ExactArgs(1),
Short: "Query historical info at given height",
Long: strings.TrimSpace(
fmt.Sprintf(`Query historical info at given height.
Example:
$ %s query staking historical-info 5
`,
version.AppName,
),
),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
height, err := strconv.ParseInt(args[0], 10, 64)
if err != nil || height < 0 {
return fmt.Errorf("height argument provided must be a non-negative-integer: %v", err)
}
params := &types.QueryHistoricalInfoRequest{
Height: height
}
res, err := queryClient.HistoricalInfo(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res.Hist)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
/ GetCmdQueryPool implements the pool query command.
func GetCmdQueryPool() *cobra.Command {
cmd := &cobra.Command{
Use: "pool",
Args: cobra.NoArgs,
Short: "Query the current staking pool values",
Long: strings.TrimSpace(
fmt.Sprintf(`Query values for amounts stored in the staking pool.
Example:
$ %s query staking pool
`,
version.AppName,
),
),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Pool(cmd.Context(), &types.QueryPoolRequest{
})
if err != nil {
return err
}
return clientCtx.PrintProto(&res.Pool)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
/ GetCmdQueryParams implements the params query command.
func GetCmdQueryParams() *cobra.Command {
cmd := &cobra.Command{
Use: "params",
Args: cobra.NoArgs,
Short: "Query the current staking parameters information",
Long: strings.TrimSpace(
fmt.Sprintf(`Query values set as staking parameters.
Example:
$ %s query staking params
`,
version.AppName,
),
),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{
})
if err != nil {
return err
}
return clientCtx.PrintProto(&res.Params)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
gRPC Query Client Creation
The Cosmos SDK leverages code generated from Protobuf services to make queries. Thestaking
module’s MyQuery
service generates a queryClient
, which the CLI uses to make queries. Here is the relevant code:
Copy
Ask AI
package cli
import (
"fmt"
"strconv"
"strings"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
/ GetQueryCmd returns the cli query commands for this module
func GetQueryCmd() *cobra.Command {
stakingQueryCmd := &cobra.Command{
Use: types.ModuleName,
Short: "Querying commands for the staking module",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
stakingQueryCmd.AddCommand(
GetCmdQueryDelegation(),
GetCmdQueryDelegations(),
GetCmdQueryUnbondingDelegation(),
GetCmdQueryUnbondingDelegations(),
GetCmdQueryRedelegation(),
GetCmdQueryRedelegations(),
GetCmdQueryValidator(),
GetCmdQueryValidators(),
GetCmdQueryValidatorDelegations(),
GetCmdQueryValidatorUnbondingDelegations(),
GetCmdQueryValidatorRedelegations(),
GetCmdQueryHistoricalInfo(),
GetCmdQueryParams(),
GetCmdQueryPool(),
)
return stakingQueryCmd
}
/ GetCmdQueryValidator implements the validator query command.
func GetCmdQueryValidator() *cobra.Command {
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "validator [validator-addr]",
Short: "Query a validator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query details about an individual validator.
Example:
$ %s query staking validator %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
addr, err := sdk.ValAddressFromBech32(args[0])
if err != nil {
return err
}
params := &types.QueryValidatorRequest{
ValidatorAddr: addr.String()
}
res, err := queryClient.Validator(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(&res.Validator)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
/ GetCmdQueryValidators implements the query all validators command.
func GetCmdQueryValidators() *cobra.Command {
cmd := &cobra.Command{
Use: "validators",
Short: "Query for all validators",
Args: cobra.NoArgs,
Long: strings.TrimSpace(
fmt.Sprintf(`Query details about all validators on a network.
Example:
$ %s query staking validators
`,
version.AppName,
),
),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
result, err := queryClient.Validators(cmd.Context(), &types.QueryValidatorsRequest{
/ Leaving status empty on purpose to query all validators.
Pagination: pageReq,
})
if err != nil {
return err
}
return clientCtx.PrintProto(result)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "validators")
return cmd
}
/ GetCmdQueryValidatorUnbondingDelegations implements the query all unbonding delegatations from a validator command.
func GetCmdQueryValidatorUnbondingDelegations() *cobra.Command {
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "unbonding-delegations-from [validator-addr]",
Short: "Query all unbonding delegatations from a validator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query delegations that are unbonding _from_ a validator.
Example:
$ %s query staking unbonding-delegations-from %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
valAddr, err := sdk.ValAddressFromBech32(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
params := &types.QueryValidatorUnbondingDelegationsRequest{
ValidatorAddr: valAddr.String(),
Pagination: pageReq,
}
res, err := queryClient.ValidatorUnbondingDelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "unbonding delegations")
return cmd
}
/ GetCmdQueryValidatorRedelegations implements the query all redelegatations
/ from a validator command.
func GetCmdQueryValidatorRedelegations() *cobra.Command {
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "redelegations-from [validator-addr]",
Short: "Query all outgoing redelegatations from a validator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query delegations that are redelegating _from_ a validator.
Example:
$ %s query staking redelegations-from %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
valSrcAddr, err := sdk.ValAddressFromBech32(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
params := &types.QueryRedelegationsRequest{
SrcValidatorAddr: valSrcAddr.String(),
Pagination: pageReq,
}
res, err := queryClient.Redelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "validator redelegations")
return cmd
}
/ GetCmdQueryDelegation the query delegation command.
func GetCmdQueryDelegation() *cobra.Command {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "delegation [delegator-addr] [validator-addr]",
Short: "Query a delegation based on address and validator address",
Long: strings.TrimSpace(
fmt.Sprintf(`Query delegations for an individual delegator on an individual validator.
Example:
$ %s query staking delegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixAccAddr, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
delAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
valAddr, err := sdk.ValAddressFromBech32(args[1])
if err != nil {
return err
}
params := &types.QueryDelegationRequest{
DelegatorAddr: delAddr.String(),
ValidatorAddr: valAddr.String(),
}
res, err := queryClient.Delegation(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res.DelegationResponse)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
/ GetCmdQueryDelegations implements the command to query all the delegations
/ made from one delegator.
func GetCmdQueryDelegations() *cobra.Command {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
cmd := &cobra.Command{
Use: "delegations [delegator-addr]",
Short: "Query all delegations made by one delegator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query delegations for an individual delegator on all validators.
Example:
$ %s query staking delegations %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p
`,
version.AppName, bech32PrefixAccAddr,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
delAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
params := &types.QueryDelegatorDelegationsRequest{
DelegatorAddr: delAddr.String(),
Pagination: pageReq,
}
res, err := queryClient.DelegatorDelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "delegations")
return cmd
}
/ GetCmdQueryValidatorDelegations implements the command to query all the
/ delegations to a specific validator.
func GetCmdQueryValidatorDelegations() *cobra.Command {
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "delegations-to [validator-addr]",
Short: "Query all delegations made to one validator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query delegations on an individual validator.
Example:
$ %s query staking delegations-to %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
valAddr, err := sdk.ValAddressFromBech32(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
params := &types.QueryValidatorDelegationsRequest{
ValidatorAddr: valAddr.String(),
Pagination: pageReq,
}
res, err := queryClient.ValidatorDelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "validator delegations")
return cmd
}
/ GetCmdQueryUnbondingDelegation implements the command to query a single
/ unbonding-delegation record.
func GetCmdQueryUnbondingDelegation() *cobra.Command {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "unbonding-delegation [delegator-addr] [validator-addr]",
Short: "Query an unbonding-delegation record based on delegator and validator address",
Long: strings.TrimSpace(
fmt.Sprintf(`Query unbonding delegations for an individual delegator on an individual validator.
Example:
$ %s query staking unbonding-delegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixAccAddr, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
valAddr, err := sdk.ValAddressFromBech32(args[1])
if err != nil {
return err
}
delAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
params := &types.QueryUnbondingDelegationRequest{
DelegatorAddr: delAddr.String(),
ValidatorAddr: valAddr.String(),
}
res, err := queryClient.UnbondingDelegation(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(&res.Unbond)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
/ GetCmdQueryUnbondingDelegations implements the command to query all the
/ unbonding-delegation records for a delegator.
func GetCmdQueryUnbondingDelegations() *cobra.Command {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
cmd := &cobra.Command{
Use: "unbonding-delegations [delegator-addr]",
Short: "Query all unbonding-delegations records for one delegator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query unbonding delegations for an individual delegator.
Example:
$ %s query staking unbonding-delegations %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p
`,
version.AppName, bech32PrefixAccAddr,
),
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
delegatorAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
params := &types.QueryDelegatorUnbondingDelegationsRequest{
DelegatorAddr: delegatorAddr.String(),
Pagination: pageReq,
}
res, err := queryClient.DelegatorUnbondingDelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "unbonding delegations")
return cmd
}
/ GetCmdQueryRedelegation implements the command to query a single
/ redelegation record.
func GetCmdQueryRedelegation() *cobra.Command {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
cmd := &cobra.Command{
Use: "redelegation [delegator-addr] [src-validator-addr] [dst-validator-addr]",
Short: "Query a redelegation record based on delegator and a source and destination validator address",
Long: strings.TrimSpace(
fmt.Sprintf(`Query a redelegation record for an individual delegator between a source and destination validator.
Example:
$ %s query staking redelegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj
`,
version.AppName, bech32PrefixAccAddr, bech32PrefixValAddr, bech32PrefixValAddr,
),
),
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
delAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
valSrcAddr, err := sdk.ValAddressFromBech32(args[1])
if err != nil {
return err
}
valDstAddr, err := sdk.ValAddressFromBech32(args[2])
if err != nil {
return err
}
params := &types.QueryRedelegationsRequest{
DelegatorAddr: delAddr.String(),
DstValidatorAddr: valDstAddr.String(),
SrcValidatorAddr: valSrcAddr.String(),
}
res, err := queryClient.Redelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
/ GetCmdQueryRedelegations implements the command to query all the
/ redelegation records for a delegator.
func GetCmdQueryRedelegations() *cobra.Command {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
cmd := &cobra.Command{
Use: "redelegations [delegator-addr]",
Args: cobra.ExactArgs(1),
Short: "Query all redelegations records for one delegator",
Long: strings.TrimSpace(
fmt.Sprintf(`Query all redelegation records for an individual delegator.
Example:
$ %s query staking redelegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p
`,
version.AppName, bech32PrefixAccAddr,
),
),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
delAddr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
params := &types.QueryRedelegationsRequest{
DelegatorAddr: delAddr.String(),
Pagination: pageReq,
}
res, err := queryClient.Redelegations(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "delegator redelegations")
return cmd
}
/ GetCmdQueryHistoricalInfo implements the historical info query command
func GetCmdQueryHistoricalInfo() *cobra.Command {
cmd := &cobra.Command{
Use: "historical-info [height]",
Args: cobra.ExactArgs(1),
Short: "Query historical info at given height",
Long: strings.TrimSpace(
fmt.Sprintf(`Query historical info at given height.
Example:
$ %s query staking historical-info 5
`,
version.AppName,
),
),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
height, err := strconv.ParseInt(args[0], 10, 64)
if err != nil || height < 0 {
return fmt.Errorf("height argument provided must be a non-negative-integer: %v", err)
}
params := &types.QueryHistoricalInfoRequest{
Height: height
}
res, err := queryClient.HistoricalInfo(cmd.Context(), params)
if err != nil {
return err
}
return clientCtx.PrintProto(res.Hist)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
/ GetCmdQueryPool implements the pool query command.
func GetCmdQueryPool() *cobra.Command {
cmd := &cobra.Command{
Use: "pool",
Args: cobra.NoArgs,
Short: "Query the current staking pool values",
Long: strings.TrimSpace(
fmt.Sprintf(`Query values for amounts stored in the staking pool.
Example:
$ %s query staking pool
`,
version.AppName,
),
),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Pool(cmd.Context(), &types.QueryPoolRequest{
})
if err != nil {
return err
}
return clientCtx.PrintProto(&res.Pool)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
/ GetCmdQueryParams implements the params query command.
func GetCmdQueryParams() *cobra.Command {
cmd := &cobra.Command{
Use: "params",
Args: cobra.NoArgs,
Short: "Query the current staking parameters information",
Long: strings.TrimSpace(
fmt.Sprintf(`Query values set as staking parameters.
Example:
$ %s query staking params
`,
version.AppName,
),
),
RunE: func(cmd *cobra.Command, args []string)
error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{
})
if err != nil {
return err
}
return clientCtx.PrintProto(&res.Params)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
client.Context
has a Query()
function used to retrieve the pre-configured node and relay a query to it; the function takes the query fully-qualified service method name as path (in our case: /cosmos.staking.v1beta1.Query/Delegations
), and arguments as parameters. It first retrieves the RPC Client (called the node) configured by the user to relay this query to, and creates the ABCIQueryOptions
(parameters formatted for the ABCI call). The node is then used to make the ABCI call, ABCIQueryWithOptions()
.
Here is what the code looks like:
Copy
Ask AI
package client
import (
"context"
"fmt"
"strings"
"github.com/pkg/errors"
abci "github.com/tendermint/tendermint/abci/types"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
rpcclient "github.com/tendermint/tendermint/rpc/client"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/cosmos/cosmos-sdk/store/rootmulti"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
/ GetNode returns an RPC client. If the context's client is not defined, an
/ error is returned.
func (ctx Context)
GetNode() (TendermintRPC, error) {
if ctx.Client == nil {
return nil, errors.New("no RPC client is defined in offline mode")
}
return ctx.Client, nil
}
/ Query performs a query to a Tendermint node with the provided path.
/ It returns the result and height of the query upon success or an error if
/ the query fails.
func (ctx Context)
Query(path string) ([]byte, int64, error) {
return ctx.query(path, nil)
}
/ QueryWithData performs a query to a Tendermint node with the provided path
/ and a data payload. It returns the result and height of the query upon success
/ or an error if the query fails.
func (ctx Context)
QueryWithData(path string, data []byte) ([]byte, int64, error) {
return ctx.query(path, data)
}
/ QueryStore performs a query to a Tendermint node with the provided key and
/ store name. It returns the result and height of the query upon success
/ or an error if the query fails.
func (ctx Context)
QueryStore(key tmbytes.HexBytes, storeName string) ([]byte, int64, error) {
return ctx.queryStore(key, storeName, "key")
}
/ QueryABCI performs a query to a Tendermint node with the provide RequestQuery.
/ It returns the ResultQuery obtained from the query. The height used to perform
/ the query is the RequestQuery Height if it is non-zero, otherwise the context
/ height is used.
func (ctx Context)
QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) {
return ctx.queryABCI(req)
}
/ GetFromAddress returns the from address from the context's name.
func (ctx Context)
GetFromAddress()
sdk.AccAddress {
return ctx.FromAddress
}
/ GetFeePayerAddress returns the fee granter address from the context
func (ctx Context)
GetFeePayerAddress()
sdk.AccAddress {
return ctx.FeePayer
}
/ GetFeeGranterAddress returns the fee granter address from the context
func (ctx Context)
GetFeeGranterAddress()
sdk.AccAddress {
return ctx.FeeGranter
}
/ GetFromName returns the key name for the current context.
func (ctx Context)
GetFromName()
string {
return ctx.FromName
}
func (ctx Context)
queryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) {
node, err := ctx.GetNode()
if err != nil {
return abci.ResponseQuery{
}, err
}
var queryHeight int64
if req.Height != 0 {
queryHeight = req.Height
}
else {
/ fallback on the context height
queryHeight = ctx.Height
}
opts := rpcclient.ABCIQueryOptions{
Height: queryHeight,
Prove: req.Prove,
}
result, err := node.ABCIQueryWithOptions(context.Background(), req.Path, req.Data, opts)
if err != nil {
return abci.ResponseQuery{
}, err
}
if !result.Response.IsOK() {
return abci.ResponseQuery{
}, sdkErrorToGRPCError(result.Response)
}
/ data from trusted node or subspace query doesn't need verification
if !opts.Prove || !isQueryStoreWithProof(req.Path) {
return result.Response, nil
}
return result.Response, nil
}
func sdkErrorToGRPCError(resp abci.ResponseQuery)
error {
switch resp.Code {
case sdkerrors.ErrInvalidRequest.ABCICode():
return status.Error(codes.InvalidArgument, resp.Log)
case sdkerrors.ErrUnauthorized.ABCICode():
return status.Error(codes.Unauthenticated, resp.Log)
case sdkerrors.ErrKeyNotFound.ABCICode():
return status.Error(codes.NotFound, resp.Log)
default:
return status.Error(codes.Unknown, resp.Log)
}
}
/ query performs a query to a Tendermint node with the provided store name
/ and path. It returns the result and height of the query upon success
/ or an error if the query fails.
func (ctx Context)
query(path string, key tmbytes.HexBytes) ([]byte, int64, error) {
resp, err := ctx.queryABCI(abci.RequestQuery{
Path: path,
Data: key,
Height: ctx.Height,
})
if err != nil {
return nil, 0, err
}
return resp.Value, resp.Height, nil
}
/ queryStore performs a query to a Tendermint node with the provided a store
/ name and path. It returns the result and height of the query upon success
/ or an error if the query fails.
func (ctx Context)
queryStore(key tmbytes.HexBytes, storeName, endPath string) ([]byte, int64, error) {
path := fmt.Sprintf("/store/%s/%s", storeName, endPath)
return ctx.query(path, key)
}
/ isQueryStoreWithProof expects a format like /<queryType>/<storeName>/<subpath>
/ queryType must be "store" and subpath must be "key" to require a proof.
func isQueryStoreWithProof(path string)
bool {
if !strings.HasPrefix(path, "/") {
return false
}
paths := strings.SplitN(path[1:], "/", 3)
switch {
case len(paths) != 3:
return false
case paths[0] != "store":
return false
case rootmulti.RequireProof("/" + paths[2]):
return true
}
return false
}
RPC
With a call toABCIQueryWithOptions()
, MyQuery
is received by a full-node which then processes the request. Note that, while the RPC is made to the consensus engine (e.g. CometBFT) of a full-node, queries are not part of consensus and so are not broadcasted to the rest of the network, as they do not require anything the network needs to agree upon.
Read more about ABCI Clients and CometBFT RPC in the CometBFT documentation.
Application Query Handling
When a query is received by the full-node after it has been relayed from the underlying consensus engine, it is at that point being handled within an environment that understands application-specific types and has a copy of the state.baseapp
implements the ABCI Query()
function and handles gRPC queries. The query route is parsed, and it matches the fully-qualified service method name of an existing service method (most likely in one of the modules), then baseapp
relays the request to the relevant module.
Since MyQuery
has a Protobuf fully-qualified service method name from the staking
module (recall /cosmos.staking.v1beta1.Query/Delegations
), baseapp
first parses the path, then uses its own internal GRPCQueryRouter
to retrieve the corresponding gRPC handler, and routes the query to the module. The gRPC handler is responsible for recognizing this query, retrieving the appropriate values from the application’s stores, and returning a response. Read more about query services here.
Once a result is received from the querier, baseapp
begins the process of returning a response to the user.
Response
SinceQuery()
is an ABCI function, baseapp
returns the response as an abci.ResponseQuery
type. The client.Context
Query()
routine receives the response and.
CLI Response
The applicationcodec
is used to unmarshal the response to a JSON and the client.Context
prints the output to the command line, applying any configurations such as the output type (text, JSON or YAML).
Copy
Ask AI
package client
import (
"bufio"
"encoding/json"
"fmt"
"io"
"os"
"github.com/cosmos/gogoproto/proto"
"github.com/spf13/viper"
"google.golang.org/grpc"
"sigs.k8s.io/yaml"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
)
/ PreprocessTxFn defines a hook by which chains can preprocess transactions before broadcasting
type PreprocessTxFn func(chainID string, key keyring.KeyType, tx TxBuilder)
error
/ Context implements a typical context created in SDK modules for transaction
/ handling and queries.
type Context struct {
FromAddress sdk.AccAddress
Client TendermintRPC
GRPCClient *grpc.ClientConn
ChainID string
Codec codec.Codec
InterfaceRegistry codectypes.InterfaceRegistry
Input io.Reader
Keyring keyring.Keyring
KeyringOptions []keyring.Option
Output io.Writer
OutputFormat string
Height int64
HomeDir string
KeyringDir string
From string
BroadcastMode string
FromName string
SignModeStr string
UseLedger bool
Simulate bool
GenerateOnly bool
Offline bool
SkipConfirm bool
TxConfig TxConfig
AccountRetriever AccountRetriever
NodeURI string
FeePayer sdk.AccAddress
FeeGranter sdk.AccAddress
Viper *viper.Viper
LedgerHasProtobuf bool
PreprocessTxHook PreprocessTxFn
/ IsAux is true when the signer is an auxiliary signer (e.g. the tipper).
IsAux bool
/ TODO: Deprecated (remove).
LegacyAmino *codec.LegacyAmino
}
/ WithKeyring returns a copy of the context with an updated keyring.
func (ctx Context)
WithKeyring(k keyring.Keyring)
Context {
ctx.Keyring = k
return ctx
}
/ WithKeyringOptions returns a copy of the context with an updated keyring.
func (ctx Context)
WithKeyringOptions(opts ...keyring.Option)
Context {
ctx.KeyringOptions = opts
return ctx
}
/ WithInput returns a copy of the context with an updated input.
func (ctx Context)
WithInput(r io.Reader)
Context {
/ convert to a bufio.Reader to have a shared buffer between the keyring and the
/ the Commands, ensuring a read from one advance the read pointer for the other.
/ see https://github.com/cosmos/cosmos-sdk/issues/9566.
ctx.Input = bufio.NewReader(r)
return ctx
}
/ WithCodec returns a copy of the Context with an updated Codec.
func (ctx Context)
WithCodec(m codec.Codec)
Context {
ctx.Codec = m
return ctx
}
/ WithLegacyAmino returns a copy of the context with an updated LegacyAmino codec.
/ TODO: Deprecated (remove).
func (ctx Context)
WithLegacyAmino(cdc *codec.LegacyAmino)
Context {
ctx.LegacyAmino = cdc
return ctx
}
/ WithOutput returns a copy of the context with an updated output writer (e.g. stdout).
func (ctx Context)
WithOutput(w io.Writer)
Context {
ctx.Output = w
return ctx
}
/ WithFrom returns a copy of the context with an updated from address or name.
func (ctx Context)
WithFrom(from string)
Context {
ctx.From = from
return ctx
}
/ WithOutputFormat returns a copy of the context with an updated OutputFormat field.
func (ctx Context)
WithOutputFormat(format string)
Context {
ctx.OutputFormat = format
return ctx
}
/ WithNodeURI returns a copy of the context with an updated node URI.
func (ctx Context)
WithNodeURI(nodeURI string)
Context {
ctx.NodeURI = nodeURI
return ctx
}
/ WithHeight returns a copy of the context with an updated height.
func (ctx Context)
WithHeight(height int64)
Context {
ctx.Height = height
return ctx
}
/ WithClient returns a copy of the context with an updated RPC client
/ instance.
func (ctx Context)
WithClient(client TendermintRPC)
Context {
ctx.Client = client
return ctx
}
/ WithGRPCClient returns a copy of the context with an updated GRPC client
/ instance.
func (ctx Context)
WithGRPCClient(grpcClient *grpc.ClientConn)
Context {
ctx.GRPCClient = grpcClient
return ctx
}
/ WithUseLedger returns a copy of the context with an updated UseLedger flag.
func (ctx Context)
WithUseLedger(useLedger bool)
Context {
ctx.UseLedger = useLedger
return ctx
}
/ WithChainID returns a copy of the context with an updated chain ID.
func (ctx Context)
WithChainID(chainID string)
Context {
ctx.ChainID = chainID
return ctx
}
/ WithHomeDir returns a copy of the Context with HomeDir set.
func (ctx Context)
WithHomeDir(dir string)
Context {
if dir != "" {
ctx.HomeDir = dir
}
return ctx
}
/ WithKeyringDir returns a copy of the Context with KeyringDir set.
func (ctx Context)
WithKeyringDir(dir string)
Context {
ctx.KeyringDir = dir
return ctx
}
/ WithGenerateOnly returns a copy of the context with updated GenerateOnly value
func (ctx Context)
WithGenerateOnly(generateOnly bool)
Context {
ctx.GenerateOnly = generateOnly
return ctx
}
/ WithSimulation returns a copy of the context with updated Simulate value
func (ctx Context)
WithSimulation(simulate bool)
Context {
ctx.Simulate = simulate
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
return ctx
}
/ WithFromAddress returns a copy of the context with an updated from account
/ address.
func (ctx Context)
WithFromAddress(addr sdk.AccAddress)
Context {
ctx.FromAddress = addr
return ctx
}
/ WithFeePayerAddress returns a copy of the context with an updated fee payer account
/ address.
func (ctx Context)
WithFeePayerAddress(addr sdk.AccAddress)
Context {
ctx.FeePayer = addr
return ctx
}
/ WithFeeGranterAddress returns a copy of the context with an updated fee granter account
/ address.
func (ctx Context)
WithFeeGranterAddress(addr sdk.AccAddress)
Context {
ctx.FeeGranter = addr
return ctx
}
/ WithBroadcastMode returns a copy of the context with an updated broadcast
/ mode.
func (ctx Context)
WithBroadcastMode(mode string)
Context {
ctx.BroadcastMode = mode
return ctx
}
/ WithSignModeStr returns a copy of the context with an updated SignMode
/ value.
func (ctx Context)
WithSignModeStr(signModeStr string)
Context {
ctx.SignModeStr = signModeStr
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
}
/ WithTxConfig returns the context with an updated TxConfig
func (ctx Context)
WithTxConfig(generator TxConfig)
Context {
ctx.TxConfig = generator
return ctx
}
/ WithAccountRetriever returns the context with an updated AccountRetriever
func (ctx Context)
WithAccountRetriever(retriever AccountRetriever)
Context {
ctx.AccountRetriever = retriever
return ctx
}
/ WithInterfaceRegistry returns the context with an updated InterfaceRegistry
func (ctx Context)
WithInterfaceRegistry(interfaceRegistry codectypes.InterfaceRegistry)
Context {
ctx.InterfaceRegistry = interfaceRegistry
return ctx
}
/ WithViper returns the context with Viper field. This Viper instance is used to read
/ client-side config from the config file.
func (ctx Context)
WithViper(prefix string)
Context {
v := viper.New()
v.SetEnvPrefix(prefix)
v.AutomaticEnv()
ctx.Viper = v
return ctx
}
/ WithAux returns a copy of the context with an updated IsAux value.
func (ctx Context)
WithAux(isAux bool)
Context {
ctx.IsAux = isAux
return ctx
}
/ WithLedgerHasProto returns the context with the provided boolean value, indicating
/ whether the target Ledger application can support Protobuf payloads.
func (ctx Context)
WithLedgerHasProtobuf(val bool)
Context {
ctx.LedgerHasProtobuf = val
return ctx
}
/ WithPreprocessTxHook returns the context with the provided preprocessing hook, which
/ enables chains to preprocess the transaction using the builder.
func (ctx Context)
WithPreprocessTxHook(preprocessFn PreprocessTxFn)
Context {
ctx.PreprocessTxHook = preprocessFn
return ctx
}
/ PrintString prints the raw string to ctx.Output if it's defined, otherwise to os.Stdout
func (ctx Context)
PrintString(str string)
error {
return ctx.PrintBytes([]byte(str))
}
/ PrintBytes prints the raw bytes to ctx.Output if it's defined, otherwise to os.Stdout.
/ NOTE: for printing a complex state object, you should use ctx.PrintOutput
func (ctx Context)
PrintBytes(o []byte)
error {
writer := ctx.Output
if writer == nil {
writer = os.Stdout
}
_, err := writer.Write(o)
return err
}
/ PrintProto outputs toPrint to the ctx.Output based on ctx.OutputFormat which is
/ either text or json. If text, toPrint will be YAML encoded. Otherwise, toPrint
/ will be JSON encoded using ctx.Codec. An error is returned upon failure.
func (ctx Context)
PrintProto(toPrint proto.Message)
error {
/ always serialize JSON initially because proto json can't be directly YAML encoded
out, err := ctx.Codec.MarshalJSON(toPrint)
if err != nil {
return err
}
return ctx.printOutput(out)
}
/ PrintObjectLegacy is a variant of PrintProto that doesn't require a proto.Message type
/ and uses amino JSON encoding.
/ Deprecated: It will be removed in the near future!
func (ctx Context)
PrintObjectLegacy(toPrint interface{
})
error {
out, err := ctx.LegacyAmino.MarshalJSON(toPrint)
if err != nil {
return err
}
return ctx.printOutput(out)
}
/ PrintRaw is a variant of PrintProto that doesn't require a proto.Message type
/ and uses a raw JSON message. No marshaling is performed.
func (ctx Context)
PrintRaw(toPrint json.RawMessage)
error {
return ctx.printOutput(toPrint)
}
func (ctx Context)
printOutput(out []byte)
error {
var err error
if ctx.OutputFormat == "text" {
out, err = yaml.JSONToYAML(out)
if err != nil {
return err
}
}
writer := ctx.Output
if writer == nil {
writer = os.Stdout
}
_, err = writer.Write(out)
if err != nil {
return err
}
if ctx.OutputFormat != "text" {
/ append new-line for formats besides YAML
_, err = writer.Write([]byte("\n"))
if err != nil {
return err
}
}
return nil
}
/ GetFromFields returns a from account address, account name and keyring type, given either an address or key name.
/ If clientCtx.Simulate is true the keystore is not accessed and a valid address must be provided
/ If clientCtx.GenerateOnly is true the keystore is only accessed if a key name is provided
func GetFromFields(clientCtx Context, kr keyring.Keyring, from string) (sdk.AccAddress, string, keyring.KeyType, error) {
if from == "" {
return nil, "", 0, nil
}
addr, err := sdk.AccAddressFromBech32(from)
switch {
case clientCtx.Simulate:
if err != nil {
return nil, "", 0, fmt.Errorf("a valid bech32 address must be provided in simulation mode: %w", err)
}
return addr, "", 0, nil
case clientCtx.GenerateOnly:
if err == nil {
return addr, "", 0, nil
}
}
var k *keyring.Record
if err == nil {
k, err = kr.KeyByAddress(addr)
if err != nil {
return nil, "", 0, err
}
}
else {
k, err = kr.Key(from)
if err != nil {
return nil, "", 0, err
}
}
addr, err = k.GetAddress()
if err != nil {
return nil, "", 0, err
}
return addr, k.Name, k.GetType(), nil
}
/ NewKeyringFromBackend gets a Keyring object from a backend
func NewKeyringFromBackend(ctx Context, backend string) (keyring.Keyring, error) {
if ctx.Simulate {
backend = keyring.BackendMemory
}
return keyring.New(sdk.KeyringServiceName(), backend, ctx.KeyringDir, ctx.Input, ctx.Codec, ctx.KeyringOptions...)
}