diff --git a/docs/cli/zetacored/cli.md b/docs/cli/zetacored/cli.md index 56e293efe4..c5c6401918 100644 --- a/docs/cli/zetacored/cli.md +++ b/docs/cli/zetacored/cli.md @@ -5376,6 +5376,7 @@ zetacored query observer [flags] * [zetacored query](#zetacored-query) - Querying subcommands * [zetacored query observer get-historical-tss-address](#zetacored-query-observer-get-historical-tss-address) - Query tss address by finalized zeta height (for historical tss addresses) * [zetacored query observer get-tss-address](#zetacored-query-observer-get-tss-address) - Query current tss address +* [zetacored query observer list-ballots](#zetacored-query-observer-list-ballots) - Query all ballots * [zetacored query observer list-blame](#zetacored-query-observer-list-blame) - Query AllBlameRecords * [zetacored query observer list-blame-by-msg](#zetacored-query-observer-list-blame-by-msg) - Query AllBlameRecords * [zetacored query observer list-chain-nonces](#zetacored-query-observer-list-chain-nonces) - list all chainNonces @@ -5466,6 +5467,40 @@ zetacored query observer get-tss-address [bitcoinChainId]] [flags] * [zetacored query observer](#zetacored-query-observer) - Querying commands for the observer module +## zetacored query observer list-ballots + +Query all ballots + +``` +zetacored query observer list-ballots [flags] +``` + +### Options + +``` + --grpc-addr string the gRPC endpoint to use for this chain + --grpc-insecure allow gRPC over insecure channels, if not TLS the server must use TLS + --height int Use a specific height to query state at (this can error if the node is pruning state) + -h, --help help for list-ballots + --node string [host]:[port] to Tendermint RPC interface for this chain + -o, --output string Output format (text|json) +``` + +### Options inherited from parent commands + +``` + --chain-id string The network chain ID + --home string directory for config and data + --log_format string The logging format (json|plain) + --log_level string The logging level (trace|debug|info|warn|error|fatal|panic) + --log_no_color Disable colored logs + --trace print out full stack trace on errors +``` + +### SEE ALSO + +* [zetacored query observer](#zetacored-query-observer) - Querying commands for the observer module + ## zetacored query observer list-blame Query AllBlameRecords diff --git a/docs/openapi/openapi.swagger.yaml b/docs/openapi/openapi.swagger.yaml index 65f305da0f..63b56b395e 100644 --- a/docs/openapi/openapi.swagger.yaml +++ b/docs/openapi/openapi.swagger.yaml @@ -29981,6 +29981,65 @@ paths: type: string tags: - Query + /zeta-chain/observer/ballots: + get: + summary: Query all ballots + operationId: Query_Ballots + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/observerQueryBallotsResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: pagination.key + description: |- + key is a value returned in PageResponse.next_key to begin + querying the next page most efficiently. Only one of offset or key + should be set. + in: query + required: false + type: string + format: byte + - name: pagination.offset + description: |- + offset is a numeric offset that can be used when key is unavailable. + It is less efficient than using key. Only one of offset or key should + be set. + in: query + required: false + type: string + format: uint64 + - name: pagination.limit + description: |- + limit is the total number of results to be returned in the result page. + If left empty it will default to a value to be set by each app. + in: query + required: false + type: string + format: uint64 + - name: pagination.count_total + description: |- + count_total is set to true to indicate that the result set should include + a count of the total number of items available for pagination in UIs. + count_total is only respected when offset is used. It is ignored when key + is set. + in: query + required: false + type: boolean + - name: pagination.reverse + description: |- + reverse is set to true if results are to be returned in the descending order. + + Since: cosmos-sdk 0.43 + in: query + required: false + type: boolean + tags: + - Query /zeta-chain/observer/blame_by_chain_and_nonce/{chain_id}/{nonce}: get: summary: Queries a list of VoterByIdentifier items. @@ -57864,6 +57923,31 @@ definitions: properties: valid: type: boolean + observerBallot: + type: object + properties: + index: + type: string + ballot_identifier: + type: string + voter_list: + type: array + items: + type: string + votes: + type: array + items: + $ref: '#/definitions/observerVoteType' + observation_type: + $ref: '#/definitions/observerObservationType' + ballot_threshold: + type: string + ballot_status: + $ref: '#/definitions/observerBallotStatus' + ballot_creation_height: + type: string + format: int64 + title: https://github.com/zeta-chain/node/issues/939 observerBallotStatus: type: string enum: @@ -58180,6 +58264,16 @@ definitions: $ref: '#/definitions/observerObservationType' ballot_status: $ref: '#/definitions/observerBallotStatus' + observerQueryBallotsResponse: + type: object + properties: + ballots: + type: array + items: + type: object + $ref: '#/definitions/observerBallot' + pagination: + $ref: '#/definitions/v1beta1PageResponse' observerQueryBlameByChainAndNonceResponse: type: object properties: diff --git a/typescript/zetachain/zetacore/observer/query_pb.d.ts b/typescript/zetachain/zetacore/observer/query_pb.d.ts index b8916f452d..a3c4a5b240 100644 --- a/typescript/zetachain/zetacore/observer/query_pb.d.ts +++ b/typescript/zetachain/zetacore/observer/query_pb.d.ts @@ -5,13 +5,13 @@ import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; import { Message, proto3 } from "@bufbuild/protobuf"; +import type { PageRequest, PageResponse } from "../../../cosmos/base/query/v1beta1/pagination_pb.js"; +import type { Ballot, BallotStatus, VoterList } from "./ballot_pb.js"; import type { OperationalFlags } from "./operational_pb.js"; import type { TssFundMigratorInfo } from "./tss_funds_migrator_pb.js"; import type { ChainNonces } from "./chain_nonces_pb.js"; -import type { PageRequest, PageResponse } from "../../../cosmos/base/query/v1beta1/pagination_pb.js"; import type { PendingNonces } from "./pending_nonces_pb.js"; import type { TSS } from "./tss_pb.js"; -import type { BallotStatus, VoterList } from "./ballot_pb.js"; import type { LastObserverCount, ObservationType } from "./observer_pb.js"; import type { Chain } from "../pkg/chains/chains_pb.js"; import type { ChainParams, ChainParamsList } from "./params_pb.js"; @@ -20,6 +20,59 @@ import type { CrosschainFlags } from "./crosschain_flags_pb.js"; import type { Keygen } from "./keygen_pb.js"; import type { Blame } from "./blame_pb.js"; +/** + * @generated from message zetachain.zetacore.observer.QueryBallotsRequest + */ +export declare class QueryBallotsRequest extends Message { + /** + * @generated from field: cosmos.base.query.v1beta1.PageRequest pagination = 1; + */ + pagination?: PageRequest; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "zetachain.zetacore.observer.QueryBallotsRequest"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): QueryBallotsRequest; + + static fromJson(jsonValue: JsonValue, options?: Partial): QueryBallotsRequest; + + static fromJsonString(jsonString: string, options?: Partial): QueryBallotsRequest; + + static equals(a: QueryBallotsRequest | PlainMessage | undefined, b: QueryBallotsRequest | PlainMessage | undefined): boolean; +} + +/** + * @generated from message zetachain.zetacore.observer.QueryBallotsResponse + */ +export declare class QueryBallotsResponse extends Message { + /** + * @generated from field: repeated zetachain.zetacore.observer.Ballot ballots = 1; + */ + ballots: Ballot[]; + + /** + * @generated from field: cosmos.base.query.v1beta1.PageResponse pagination = 2; + */ + pagination?: PageResponse; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "zetachain.zetacore.observer.QueryBallotsResponse"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): QueryBallotsResponse; + + static fromJson(jsonValue: JsonValue, options?: Partial): QueryBallotsResponse; + + static fromJsonString(jsonString: string, options?: Partial): QueryBallotsResponse; + + static equals(a: QueryBallotsResponse | PlainMessage | undefined, b: QueryBallotsResponse | PlainMessage | undefined): boolean; +} + /** * @generated from message zetachain.zetacore.observer.QueryOperationalFlagsRequest */ diff --git a/x/observer/client/cli/query_ballot.go b/x/observer/client/cli/query_ballot.go index 60b39e2afc..4e4ce65f6b 100644 --- a/x/observer/client/cli/query_ballot.go +++ b/x/observer/client/cli/query_ballot.go @@ -8,6 +8,7 @@ import ( "github.com/zeta-chain/node/x/observer/types" ) +// CmdBallotByIdentifier returns a command which queries a ballot by its identifier func CmdBallotByIdentifier() *cobra.Command { cmd := &cobra.Command{ Use: "show-ballot [ballot-identifier]", @@ -40,19 +41,27 @@ func CmdBallotByIdentifier() *cobra.Command { return cmd } +// CmdAllBallots returns a command which queries all ballots func CmdAllBallots() *cobra.Command { cmd := &cobra.Command{ Use: "list-ballots", Short: "Query all ballots", Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) (err error) { + RunE: func(cmd *cobra.Command, _ []string) (err error) { clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } queryClient := types.NewQueryClient(clientCtx) - params := &types.QueryBallotsRequest{} + params := &types.QueryBallotsRequest{ + Pagination: pageReq, + } res, err := queryClient.Ballots(cmd.Context(), params) if err != nil { diff --git a/x/observer/keeper/grpc_query_ballot.go b/x/observer/keeper/grpc_query_ballot.go index 20eed7acda..86ebd3aeec 100644 --- a/x/observer/keeper/grpc_query_ballot.go +++ b/x/observer/keeper/grpc_query_ballot.go @@ -3,7 +3,9 @@ package keeper import ( "context" + "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -53,15 +55,34 @@ func (k Keeper) BallotByIdentifier( }, nil } +// Ballots queries all the ballots. It is a paginated query func (k Keeper) Ballots(goCtx context.Context, req *types.QueryBallotsRequest) (*types.QueryBallotsResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") } + ballots := make([]types.Ballot, 0) ctx := sdk.UnwrapSDKContext(goCtx) - ballotList := k.GetAllBallots(ctx) - ballots := make([]types.Ballot, len(ballotList)) - for i, ballot := range ballotList { - ballots[i] = *ballot + + ballotStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.VoterKey)) + + if req.Pagination == nil { + req.Pagination = &query.PageRequest{} + } + if req.Pagination.Limit == 0 || req.Pagination.Limit > 100 { + req.Pagination.Limit = 100 + } + + pageRes, err := query.Paginate(ballotStore, req.Pagination, func(_ []byte, value []byte) error { + var ballot types.Ballot + if err := k.cdc.Unmarshal(value, &ballot); err != nil { + return err + } + ballots = append(ballots, ballot) + return nil + }) + + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) } - return &types.QueryBallotsResponse{Ballots: ballots}, nil + return &types.QueryBallotsResponse{Ballots: ballots, Pagination: pageRes}, nil }