diff --git a/packages/sdk38/src/lcdapi/staking.spec.ts b/packages/sdk38/src/lcdapi/staking.spec.ts index 93eb4fd9..89983182 100644 --- a/packages/sdk38/src/lcdapi/staking.spec.ts +++ b/packages/sdk38/src/lcdapi/staking.spec.ts @@ -1,5 +1,21 @@ +import { assert, sleep } from "@cosmjs/utils"; + +import { coin, coins } from "../coins"; +import { isPostTxFailure } from "../cosmosclient"; +import { makeSignBytes } from "../encoding"; +import { MsgDelegate } from "../msgs"; +import { SigningCosmosClient } from "../signingcosmosclient"; /* eslint-disable @typescript-eslint/naming-convention */ -import { nonNegativeIntegerMatcher, pendingWithoutWasmd, wasmd } from "../testutils.spec"; +import { + bigDecimalMatcher, + faucet, + nonNegativeIntegerMatcher, + pendingWithoutWasmd, + validatorAddress, + wasmd, + wasmdEnabled, +} from "../testutils.spec"; +import { Secp256k1Wallet } from "../wallet"; import { LcdClient } from "./lcdclient"; import { setupStakingExtension, StakingExtension } from "./staking"; @@ -8,6 +24,209 @@ function makeStakingClient(apiUrl: string): LcdClient & StakingExtension { } describe("StakingExtension", () => { + const defaultFee = { + amount: coins(25000, "ucosm"), + gas: "1500000", // 1.5 million + }; + + beforeAll(async () => { + if (wasmdEnabled()) { + const wallet = await Secp256k1Wallet.fromMnemonic(faucet.mnemonic); + const client = new SigningCosmosClient(wasmd.endpoint, faucet.address, wallet, {}); + + const chainId = await client.getChainId(); + const msg: MsgDelegate = { + type: "cosmos-sdk/MsgDelegate", + value: { + delegator_address: faucet.address, + validator_address: validatorAddress, + amount: coin(25000, "ustake"), + }, + }; + const memo = "Test delegation for wasmd"; + const { accountNumber, sequence } = await client.getNonce(); + const signBytes = makeSignBytes([msg], defaultFee, chainId, memo, accountNumber, sequence); + const signature = await wallet.sign(faucet.address, signBytes); + const tx = { + msg: [msg], + fee: defaultFee, + memo: memo, + signatures: [signature], + }; + + const receipt = await client.postTx(tx); + assert(!isPostTxFailure(receipt)); + + await sleep(75); // wait until transactions are indexed + } + }); + + describe("delegatorDelegations", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = makeStakingClient(wasmd.endpoint); + const response = await client.staking.delegatorDelegations(faucet.address); + expect(response).toEqual({ + height: jasmine.stringMatching(nonNegativeIntegerMatcher), + result: [ + { + delegator_address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + validator_address: "cosmosvaloper1gjvanqxc774u6ed9thj4gpn9gj5zus5u32enqn", + shares: jasmine.stringMatching(bigDecimalMatcher), + balance: { denom: "ustake", amount: jasmine.stringMatching(nonNegativeIntegerMatcher) }, + }, + ], + }); + }); + }); + + describe("delegatorUnbondingDelegations", () => { + it("works", async () => { + // TODO: Set up a result for this test + pendingWithoutWasmd(); + const client = makeStakingClient(wasmd.endpoint); + const response = await client.staking.delegatorUnbondingDelegations(faucet.address); + expect(response).toEqual({ + height: jasmine.stringMatching(nonNegativeIntegerMatcher), + result: [], + }); + }); + }); + + describe("delegatorTransactions", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = makeStakingClient(wasmd.endpoint); + const response = await client.staking.delegatorTransactions(faucet.address); + expect(response.length).toEqual(3); + }); + }); + + describe("delegatorValidators", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = makeStakingClient(wasmd.endpoint); + const response = await client.staking.delegatorValidators(faucet.address); + expect(response).toEqual({ + height: jasmine.stringMatching(nonNegativeIntegerMatcher), + result: [ + { + operator_address: "cosmosvaloper1gjvanqxc774u6ed9thj4gpn9gj5zus5u32enqn", + consensus_pubkey: + "cosmosvalconspub1zcjduepqau36ht2r742jh230pxlu4wjmwcmkwpeqava80acphsu87vt5xlpqx6g7qh", + jailed: false, + status: 2, + tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), + delegator_shares: jasmine.stringMatching(bigDecimalMatcher), + description: { + moniker: "testing", + identity: "", + website: "", + security_contact: "", + details: "", + }, + unbonding_height: "0", + unbonding_time: "1970-01-01T00:00:00Z", + commission: { + commission_rates: { + rate: "0.100000000000000000", + max_rate: "0.200000000000000000", + max_change_rate: "0.010000000000000000", + }, + update_time: "2020-06-03T06:01:17.4747987Z", + }, + min_self_delegation: "1", + }, + ], + }); + }); + }); + + describe("delegatorValidator", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = makeStakingClient(wasmd.endpoint); + const response = await client.staking.delegatorValidator(faucet.address, validatorAddress); + expect(response).toEqual({ + height: jasmine.stringMatching(nonNegativeIntegerMatcher), + result: { + operator_address: "cosmosvaloper1gjvanqxc774u6ed9thj4gpn9gj5zus5u32enqn", + consensus_pubkey: + "cosmosvalconspub1zcjduepqau36ht2r742jh230pxlu4wjmwcmkwpeqava80acphsu87vt5xlpqx6g7qh", + jailed: false, + status: 2, + tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), + delegator_shares: jasmine.stringMatching(bigDecimalMatcher), + description: { + moniker: "testing", + identity: "", + website: "", + security_contact: "", + details: "", + }, + unbonding_height: "0", + unbonding_time: "1970-01-01T00:00:00Z", + commission: { + commission_rates: { + rate: "0.100000000000000000", + max_rate: "0.200000000000000000", + max_change_rate: "0.010000000000000000", + }, + update_time: "2020-06-03T06:01:17.4747987Z", + }, + min_self_delegation: "1", + }, + }); + }); + }); + + describe("delegation", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = makeStakingClient(wasmd.endpoint); + const response = await client.staking.delegation(faucet.address, validatorAddress); + expect(response).toEqual({ + height: jasmine.stringMatching(nonNegativeIntegerMatcher), + result: { + delegator_address: faucet.address, + validator_address: validatorAddress, + shares: jasmine.stringMatching(bigDecimalMatcher), + balance: { denom: "ustake", amount: jasmine.stringMatching(nonNegativeIntegerMatcher) }, + }, + }); + }); + }); + + xdescribe("unbondingDelegation", () => { + it("works", async () => { + // TODO: Set up a result for this test + pendingWithoutWasmd(); + const client = makeStakingClient(wasmd.endpoint); + const response = await client.staking.unbondingDelegation(faucet.address, validatorAddress); + expect(response).toEqual({ + height: jasmine.stringMatching(nonNegativeIntegerMatcher), + result: { + delegator_address: faucet.address, + validator_address: validatorAddress, + entries: [], + }, + }); + }); + }); + + describe("redelegations", () => { + it("works", async () => { + // TODO: Set up a result for this test + pendingWithoutWasmd(); + const client = makeStakingClient(wasmd.endpoint); + const response = await client.staking.redelegations(); + expect(response).toEqual({ + height: jasmine.stringMatching(nonNegativeIntegerMatcher), + result: [], + }); + }); + }); + describe("validators", () => { it("works", async () => { pendingWithoutWasmd(); @@ -22,8 +241,8 @@ describe("StakingExtension", () => { "cosmosvalconspub1zcjduepqau36ht2r742jh230pxlu4wjmwcmkwpeqava80acphsu87vt5xlpqx6g7qh", jailed: false, status: 2, - tokens: "250000000", - delegator_shares: "250000000.000000000000000000", + tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), + delegator_shares: jasmine.stringMatching(bigDecimalMatcher), description: { moniker: "testing", identity: "", @@ -70,8 +289,8 @@ describe("StakingExtension", () => { "cosmosvalconspub1zcjduepqau36ht2r742jh230pxlu4wjmwcmkwpeqava80acphsu87vt5xlpqx6g7qh", jailed: false, status: 2, - tokens: "250000000", - delegator_shares: "250000000.000000000000000000", + tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), + delegator_shares: jasmine.stringMatching(bigDecimalMatcher), description: { moniker: "testing", identity: "", @@ -96,6 +315,105 @@ describe("StakingExtension", () => { }); }); + describe("validator", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = makeStakingClient(wasmd.endpoint); + const response = await client.staking.validator(validatorAddress); + expect(response).toEqual({ + height: jasmine.stringMatching(nonNegativeIntegerMatcher), + result: { + operator_address: "cosmosvaloper1gjvanqxc774u6ed9thj4gpn9gj5zus5u32enqn", + consensus_pubkey: + "cosmosvalconspub1zcjduepqau36ht2r742jh230pxlu4wjmwcmkwpeqava80acphsu87vt5xlpqx6g7qh", + jailed: false, + status: 2, + tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), + delegator_shares: jasmine.stringMatching(bigDecimalMatcher), + description: { + moniker: "testing", + identity: "", + website: "", + security_contact: "", + details: "", + }, + unbonding_height: "0", + unbonding_time: "1970-01-01T00:00:00Z", + commission: { + commission_rates: { + rate: "0.100000000000000000", + max_rate: "0.200000000000000000", + max_change_rate: "0.010000000000000000", + }, + update_time: "2020-06-03T06:01:17.4747987Z", + }, + min_self_delegation: "1", + }, + }); + }); + }); + + describe("validatorDelegations", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = makeStakingClient(wasmd.endpoint); + const response = await client.staking.validatorDelegations(validatorAddress); + expect(response).toEqual({ + height: jasmine.stringMatching(nonNegativeIntegerMatcher), + result: [ + { + delegator_address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6", + validator_address: "cosmosvaloper1gjvanqxc774u6ed9thj4gpn9gj5zus5u32enqn", + shares: jasmine.stringMatching(bigDecimalMatcher), + balance: { denom: "ustake", amount: jasmine.stringMatching(nonNegativeIntegerMatcher) }, + }, + { + delegator_address: "cosmos1gjvanqxc774u6ed9thj4gpn9gj5zus5u57dxvq", + validator_address: "cosmosvaloper1gjvanqxc774u6ed9thj4gpn9gj5zus5u32enqn", + shares: "250000000.000000000000000000", + balance: { denom: "ustake", amount: "250000000" }, + }, + ], + }); + }); + }); + + describe("validatorUnbondingDelegations", () => { + it("works", async () => { + pendingWithoutWasmd(); + const client = makeStakingClient(wasmd.endpoint); + const response = await client.staking.validatorUnbondingDelegations(validatorAddress); + expect(response).toEqual({ + height: jasmine.stringMatching(nonNegativeIntegerMatcher), + result: [], + }); + }); + }); + + xdescribe("historicalInfo", () => { + it("works", async () => { + // TODO: Find a result for this test + pendingWithoutWasmd(); + const client = makeStakingClient(wasmd.endpoint); + const response = await client.staking.historicalInfo("100"); + expect(response).toEqual({ + height: jasmine.stringMatching(nonNegativeIntegerMatcher), + result: { + header: { + version: { + block: "", + app: "", + }, + height: 10, + chainId: "", + time: "", + }, + validators: [], + }, + }); + }); + }); + describe("pool", () => { it("works", async () => { pendingWithoutWasmd(); @@ -105,7 +423,7 @@ describe("StakingExtension", () => { height: jasmine.stringMatching(nonNegativeIntegerMatcher), result: { not_bonded_tokens: "0", - bonded_tokens: "250000000", + bonded_tokens: jasmine.stringMatching(nonNegativeIntegerMatcher), }, }); }); diff --git a/packages/sdk38/src/lcdapi/staking.ts b/packages/sdk38/src/lcdapi/staking.ts index 6b370902..efc238f5 100644 --- a/packages/sdk38/src/lcdapi/staking.ts +++ b/packages/sdk38/src/lcdapi/staking.ts @@ -1,4 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ +import { Coin } from "../coins"; +import { BlockHeader } from "../cosmosclient"; +import { SearchTxsResponse } from "./base"; import { LcdClient } from "./lcdclient"; export interface StakingValidatorsParams { @@ -40,11 +43,107 @@ interface Validator { readonly min_self_delegation: string; } +interface Delegation { + readonly delegator_address: string; + readonly validator_address: string; + readonly shares: string; + readonly balance: Coin; +} + +export interface StakingDelegatorDelegationsResponse { + readonly height: string; + readonly result: readonly Delegation[]; +} + +interface UnbondingDelegationEntry { + readonly creation_height: string; + readonly completion_time: string; + readonly initial_balance: Coin; + readonly balance: Coin; +} + +interface UnbondingDelegation { + readonly delegator_address: string; + readonly validator_address: string; + readonly entries: readonly UnbondingDelegationEntry[]; +} + +export interface StakingDelegatorUnbondingDelegationsResponse { + readonly height: string; + readonly result: readonly UnbondingDelegation[]; +} + +export type StakingDelegatorTransactionsResponse = readonly SearchTxsResponse[]; + +export interface StakingDelegatorValidatorsResponse { + readonly height: string; + readonly result: readonly Validator[]; +} + +export interface StakingDelegatorValidatorResponse { + readonly height: string; + readonly result: Validator; +} + +export interface StakingDelegationResponse { + readonly height: string; + readonly result: Delegation; +} + +export interface StakingUnbondingDelegationResponse { + readonly height: string; + readonly result: UnbondingDelegation | null; +} + +interface RedelegationEntry { + readonly creation_height: string; + readonly completion_time: string; + readonly initial_balance: Coin; + readonly shares_dst: string; +} + +interface Redelegation { + readonly delegator_address: string; + readonly validator_src_address: string; + readonly validator_dst_address: string; + readonly entries: readonly RedelegationEntry[]; +} + +export interface StakingRedelegationsResponse { + readonly height: string; + readonly result: readonly Redelegation[]; +} + export interface StakingValidatorsResponse { readonly height: string; readonly result: readonly Validator[]; } +export interface StakingValidatorResponse { + readonly height: string; + readonly result: Validator; +} + +export interface StakingValidatorDelegationsResponse { + readonly height: string; + readonly result: readonly Delegation[]; +} + +export interface StakingValidatorUnbondingDelegationsResponse { + readonly height: string; + readonly result: readonly UnbondingDelegation[]; +} + +interface HistoricalInfo { + readonly header: BlockHeader; + readonly validators: readonly Validator[]; +} + +export interface StakingHistoricalInfoResponse { + readonly height: string; + readonly result: HistoricalInfo; +} + export interface StakingPoolResponse { readonly height: string; readonly result: { @@ -66,45 +165,47 @@ export interface StakingParametersResponse { export interface StakingExtension { readonly staking: { - // Get all delegations from a delegator - // /staking/delegators/{delegatorAddr}/delegations - - // Get all unbonding delegations from a delegator - // /staking/delegators/{delegatorAddr}/unbonding_delegations - - // Get all staking txs (i.e msgs) from a delegator - // /staking/delegators/{delegatorAddr}/txs - - // Query all validators that a delegator is bonded to - // /staking/delegators/{delegatorAddr}/validators - - // Query a validator that a delegator is bonded to - // /staking/delegators/{delegatorAddr}/validators/{validatorAddr} - - // Query a delegation between a delegator and a validator - // /staking/delegators/{delegatorAddr}/delegations/{validatorAddr} - - // Query all unbonding delegations between a delegator and a validator - // /staking/delegators/{delegatorAddr}/unbonding_delegations/{validatorAddr} - - // Query redelegations (filters in query params) - // /staking/redelegations - + /** Get all delegations from a delegator */ + readonly delegatorDelegations: (delegatorAddress: string) => Promise; + /** Get all unbonding delegations from a delegator */ + readonly delegatorUnbondingDelegations: ( + delegatorAddress: string, + ) => Promise; + /** Get all staking txs (i.e msgs) from a delegator */ + readonly delegatorTransactions: ( + delegatorAddress: string, + ) => Promise; + /** Query all validators that a delegator is bonded to */ + readonly delegatorValidators: (delegatorAddress: string) => Promise; + /** Query a validator that a delegator is bonded to */ + readonly delegatorValidator: ( + delegatorAddress: string, + validatorAddress: string, + ) => Promise; + /** Query a delegation between a delegator and a validator */ + readonly delegation: ( + delegatorAddress: string, + validatorAddress: string, + ) => Promise; + /** Query all unbonding delegations between a delegator and a validator */ + readonly unbondingDelegation: ( + delegatorAddress: string, + validatorAddress: string, + ) => Promise; + /** Query redelegations (filters in query params) */ + readonly redelegations: () => Promise; /** Get all validators */ readonly validators: (options?: StakingValidatorsParams) => Promise; - - // Get a single validator info - // /staking/validators/{validatorAddr} - + /** Get a single validator info */ + readonly validator: (validatorAddress: string) => Promise; // Get all delegations to a validator - // "/staking/validators/{validatorAddr}/delegations - - // Get all unbonding delegations from a validator - // /staking/validators/{validatorAddr}/unbonding_delegations - - // Get HistoricalInfo at a given height - // /staking/historical_info/{height} - + readonly validatorDelegations: (validatorAddress: string) => Promise; + /** Get all unbonding delegations from a validator */ + readonly validatorUnbondingDelegations: ( + validatorAddress: string, + ) => Promise; + /** Get HistoricalInfo at a given height */ + readonly historicalInfo: (height: string) => Promise; /** Get the current state of the staking pool */ readonly pool: () => Promise; /** Get the current staking parameter values */ @@ -115,7 +216,29 @@ export interface StakingExtension { export function setupStakingExtension(base: LcdClient): StakingExtension { return { staking: { + delegatorDelegations: async (delegatorAddress: string) => + base.get(`/staking/delegators/${delegatorAddress}/delegations`), + delegatorUnbondingDelegations: async (delegatorAddress: string) => + base.get(`/staking/delegators/${delegatorAddress}/unbonding_delegations`), + delegatorTransactions: async (delegatorAddress: string) => + base.get(`/staking/delegators/${delegatorAddress}/txs`), + delegatorValidators: async (delegatorAddress: string) => + base.get(`/staking/delegators/${delegatorAddress}/validators`), + delegatorValidator: async (delegatorAddress: string, validatorAddress: string) => + base.get(`/staking/delegators/${delegatorAddress}/validators/${validatorAddress}`), + delegation: async (delegatorAddress: string, validatorAddress: string) => + base.get(`/staking/delegators/${delegatorAddress}/delegations/${validatorAddress}`), + unbondingDelegation: async (delegatorAddress: string, validatorAddress: string) => + base.get(`/staking/delegators/${delegatorAddress}/unbonding_delegations/${validatorAddress}`), + redelegations: async () => base.get(`/staking/redelegations`), validators: async (params?: StakingValidatorsParams) => base.get(`/staking/validators`, params), + validator: async (validatorAddress: string) => base.get(`/staking/validators/${validatorAddress}`), + validatorDelegations: async (validatorAddress: string) => + base.get(`/staking/validators/${validatorAddress}/delegations + `), + validatorUnbondingDelegations: async (validatorAddress: string) => + base.get(`/staking/validators/${validatorAddress}/unbonding_delegations`), + historicalInfo: async (height: string) => base.get(`/staking/historical_info/${height}`), pool: async () => base.get(`/staking/pool`), parameters: async () => base.get(`/staking/parameters`), }, diff --git a/packages/sdk38/types/lcdapi/staking.d.ts b/packages/sdk38/types/lcdapi/staking.d.ts index bc0ca5b4..fc50631f 100644 --- a/packages/sdk38/types/lcdapi/staking.d.ts +++ b/packages/sdk38/types/lcdapi/staking.d.ts @@ -1,3 +1,6 @@ +import { Coin } from "../coins"; +import { BlockHeader } from "../cosmosclient"; +import { SearchTxsResponse } from "./base"; import { LcdClient } from "./lcdclient"; export interface StakingValidatorsParams { /** @see https://github.com/cosmos/cosmos-sdk/blob/v0.38.5/types/staking.go#L43-L49 */ @@ -36,10 +39,88 @@ interface Validator { }; readonly min_self_delegation: string; } +interface Delegation { + readonly delegator_address: string; + readonly validator_address: string; + readonly shares: string; + readonly balance: Coin; +} +export interface StakingDelegatorDelegationsResponse { + readonly height: string; + readonly result: readonly Delegation[]; +} +interface UnbondingDelegationEntry { + readonly creation_height: string; + readonly completion_time: string; + readonly initial_balance: Coin; + readonly balance: Coin; +} +interface UnbondingDelegation { + readonly delegator_address: string; + readonly validator_address: string; + readonly entries: readonly UnbondingDelegationEntry[]; +} +export interface StakingDelegatorUnbondingDelegationsResponse { + readonly height: string; + readonly result: readonly UnbondingDelegation[]; +} +export declare type StakingDelegatorTransactionsResponse = readonly SearchTxsResponse[]; +export interface StakingDelegatorValidatorsResponse { + readonly height: string; + readonly result: readonly Validator[]; +} +export interface StakingDelegatorValidatorResponse { + readonly height: string; + readonly result: Validator; +} +export interface StakingDelegationResponse { + readonly height: string; + readonly result: Delegation; +} +export interface StakingUnbondingDelegationResponse { + readonly height: string; + readonly result: UnbondingDelegation | null; +} +interface RedelegationEntry { + readonly creation_height: string; + readonly completion_time: string; + readonly initial_balance: Coin; + readonly shares_dst: string; +} +interface Redelegation { + readonly delegator_address: string; + readonly validator_src_address: string; + readonly validator_dst_address: string; + readonly entries: readonly RedelegationEntry[]; +} +export interface StakingRedelegationsResponse { + readonly height: string; + readonly result: readonly Redelegation[]; +} export interface StakingValidatorsResponse { readonly height: string; readonly result: readonly Validator[]; } +export interface StakingValidatorResponse { + readonly height: string; + readonly result: Validator; +} +export interface StakingValidatorDelegationsResponse { + readonly height: string; + readonly result: readonly Delegation[]; +} +export interface StakingValidatorUnbondingDelegationsResponse { + readonly height: string; + readonly result: readonly UnbondingDelegation[]; +} +interface HistoricalInfo { + readonly header: BlockHeader; + readonly validators: readonly Validator[]; +} +export interface StakingHistoricalInfoResponse { + readonly height: string; + readonly result: HistoricalInfo; +} export interface StakingPoolResponse { readonly height: string; readonly result: { @@ -59,8 +140,46 @@ export interface StakingParametersResponse { } export interface StakingExtension { readonly staking: { + /** Get all delegations from a delegator */ + readonly delegatorDelegations: (delegatorAddress: string) => Promise; + /** Get all unbonding delegations from a delegator */ + readonly delegatorUnbondingDelegations: ( + delegatorAddress: string, + ) => Promise; + /** Get all staking txs (i.e msgs) from a delegator */ + readonly delegatorTransactions: ( + delegatorAddress: string, + ) => Promise; + /** Query all validators that a delegator is bonded to */ + readonly delegatorValidators: (delegatorAddress: string) => Promise; + /** Query a validator that a delegator is bonded to */ + readonly delegatorValidator: ( + delegatorAddress: string, + validatorAddress: string, + ) => Promise; + /** Query a delegation between a delegator and a validator */ + readonly delegation: ( + delegatorAddress: string, + validatorAddress: string, + ) => Promise; + /** Query all unbonding delegations between a delegator and a validator */ + readonly unbondingDelegation: ( + delegatorAddress: string, + validatorAddress: string, + ) => Promise; + /** Query redelegations (filters in query params) */ + readonly redelegations: () => Promise; /** Get all validators */ readonly validators: (options?: StakingValidatorsParams) => Promise; + /** Get a single validator info */ + readonly validator: (validatorAddress: string) => Promise; + readonly validatorDelegations: (validatorAddress: string) => Promise; + /** Get all unbonding delegations from a validator */ + readonly validatorUnbondingDelegations: ( + validatorAddress: string, + ) => Promise; + /** Get HistoricalInfo at a given height */ + readonly historicalInfo: (height: string) => Promise; /** Get the current state of the staking pool */ readonly pool: () => Promise; /** Get the current staking parameter values */