diff --git a/packages/tendermint-rpc/src/adaptors/v0-33/requests.ts b/packages/tendermint-rpc/src/adaptors/v0-33/requests.ts index c5d8a7ac..0ec03de3 100644 --- a/packages/tendermint-rpc/src/adaptors/v0-33/requests.ts +++ b/packages/tendermint-rpc/src/adaptors/v0-33/requests.ts @@ -84,6 +84,19 @@ function encodeTxSearchParams(params: requests.TxSearchParams): RpcTxSearchParam }; } +interface RpcValidatorsParams { + readonly height?: string; + readonly page?: string; + readonly per_page?: string; +} +function encodeValidatorsParams(params: requests.ValidatorsParams): RpcValidatorsParams { + return { + height: may(Integer.encode, params.height), + page: may(Integer.encode, params.page), + per_page: may(Integer.encode, params.per_page), + }; +} + export class Params { public static encodeAbciInfo(req: requests.AbciInfoRequest): JsonRpcRequest { return createJsonRpcRequest(req.method); @@ -141,6 +154,6 @@ export class Params { } public static encodeValidators(req: requests.ValidatorsRequest): JsonRpcRequest { - return createJsonRpcRequest(req.method, encodeHeightParam(req.params)); + return createJsonRpcRequest(req.method, encodeValidatorsParams(req.params)); } } diff --git a/packages/tendermint-rpc/src/client.spec.ts b/packages/tendermint-rpc/src/client.spec.ts index 0cc81bff..c9b523ea 100644 --- a/packages/tendermint-rpc/src/client.spec.ts +++ b/packages/tendermint-rpc/src/client.spec.ts @@ -133,7 +133,25 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte it("can get validators", async () => { pendingWithoutTendermint(); const client = await Client.create(rpcFactory(), adaptor); - const response = await client.validators(); + const response = await client.validators({}); + + expect(response).toBeTruthy(); + expect(response.blockHeight).toBeGreaterThanOrEqual(1); + expect(response.count).toBeGreaterThanOrEqual(1); + expect(response.total).toBeGreaterThanOrEqual(1); + expect(response.validators.length).toBeGreaterThanOrEqual(1); + expect(response.validators[0].address.length).toEqual(20); + expect(response.validators[0].pubkey).toBeDefined(); + expect(response.validators[0].votingPower).toBeGreaterThanOrEqual(0); + expect(response.validators[0].proposerPriority).toBeGreaterThanOrEqual(0); + + client.disconnect(); + }); + + it("can get all validators", async () => { + pendingWithoutTendermint(); + const client = await Client.create(rpcFactory(), adaptor); + const response = await client.validatorsAll(); expect(response).toBeTruthy(); expect(response.blockHeight).toBeGreaterThanOrEqual(1); diff --git a/packages/tendermint-rpc/src/client.ts b/packages/tendermint-rpc/src/client.ts index 9df10731..945db730 100644 --- a/packages/tendermint-rpc/src/client.ts +++ b/packages/tendermint-rpc/src/client.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { Stream } from "xstream"; import { Adaptor, Decoder, Encoder, Params, Responses } from "./adaptor"; @@ -248,14 +249,44 @@ export class Client { }; } - public async validators(height?: number): Promise { + public async validators(params: requests.ValidatorsParams): Promise { const query: requests.ValidatorsRequest = { method: requests.Method.Validators, - params: { height: height }, + params: params, }; return this.doCall(query, this.p.encodeValidators, this.r.decodeValidators); } + public async validatorsAll(height?: number): Promise { + const validators: responses.Validator[] = []; + let page = 1; + let done = false; + let blockHeight = height; + + while (!done) { + const response = await this.validators({ + per_page: 50, + height: blockHeight, + page: page, + }); + validators.push(...response.validators); + blockHeight = blockHeight || response.blockHeight; + if (validators.length < response.total) { + page++; + } else { + done = true; + } + } + + return { + // NOTE: Default value is for type safety but this should always be set + blockHeight: blockHeight ?? 0, + count: validators.length, + total: validators.length, + validators: validators, + }; + } + // doCall is a helper to handle the encode/call/decode logic private async doCall( request: T, diff --git a/packages/tendermint-rpc/src/index.ts b/packages/tendermint-rpc/src/index.ts index 1d762ea2..6b87b4e2 100644 --- a/packages/tendermint-rpc/src/index.ts +++ b/packages/tendermint-rpc/src/index.ts @@ -31,6 +31,7 @@ export { TxSearchParams, TxSearchRequest, ValidatorsRequest, + ValidatorsParams, } from "./requests"; export { AbciInfoResponse, diff --git a/packages/tendermint-rpc/src/requests.ts b/packages/tendermint-rpc/src/requests.ts index b4c7e8f4..d985b8e6 100644 --- a/packages/tendermint-rpc/src/requests.ts +++ b/packages/tendermint-rpc/src/requests.ts @@ -161,9 +161,13 @@ export interface TxSearchParams { export interface ValidatorsRequest { readonly method: Method.Validators; - readonly params: { - readonly height?: number; - }; + readonly params: ValidatorsParams; +} + +export interface ValidatorsParams { + readonly height?: number; + readonly page?: number; + readonly per_page?: number; } export interface BuildQueryComponents {