Fix and improve gov testing

This commit is contained in:
Simon Warta 2021-07-28 18:40:22 +02:00
parent 869ba7e23c
commit 9ddfe6e679
2 changed files with 125 additions and 31 deletions

View File

@ -1,4 +1,4 @@
import { coins } from "@cosmjs/amino";
import { coin, coins, makeCosmoshubPath } from "@cosmjs/amino";
import { toAscii } from "@cosmjs/encoding";
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { Tendermint34Client } from "@cosmjs/tendermint-rpc";
@ -7,7 +7,11 @@ import { ProposalStatus, TextProposal, VoteOption } from "cosmjs-types/cosmos/go
import { Any } from "cosmjs-types/google/protobuf/any";
import Long from "long";
import { MsgSubmitProposalEncodeObject, MsgVoteEncodeObject } from "../encodeobjects";
import {
MsgDelegateEncodeObject,
MsgSubmitProposalEncodeObject,
MsgVoteEncodeObject,
} from "../encodeobjects";
import { SigningStargateClient } from "../signingstargateclient";
import { assertIsBroadcastTxSuccess } from "../stargateclient";
import {
@ -17,6 +21,7 @@ import {
pendingWithoutSimapp,
simapp,
simappEnabled,
validator,
} from "../testutils.spec";
import { GovExtension, setupGovExtension } from "./gov";
import { QueryClient } from "./queryclient";
@ -37,12 +42,19 @@ describe("GovExtension", () => {
description: "This proposal proposes to test whether this proposal passes",
});
const initialDeposit = coins(12300000, "ustake");
const delegationVoter1 = coin(424242, "ustake");
const delegationVoter2 = coin(777, "ustake");
const voter1Address = faucet.address1;
const voter2Address = faucet.address2;
let proposalId: string;
beforeAll(async () => {
if (simappEnabled()) {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic);
const [firstAccount] = await wallet.getAccounts();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic, {
// Use address 1 and 2 instead of 0 to avoid conflicts with other delegation tests
// This must match `voterAddress` above.
hdPaths: [makeCosmoshubPath(1), makeCosmoshubPath(2)],
});
const client = await SigningStargateClient.connectWithSigner(
simapp.tendermintUrl,
wallet,
@ -56,12 +68,12 @@ describe("GovExtension", () => {
typeUrl: "/cosmos.gov.v1beta1.TextProposal",
value: Uint8Array.from(TextProposal.encode(textProposal).finish()),
}),
proposer: faucet.address0,
proposer: voter1Address,
initialDeposit: initialDeposit,
},
};
const proposalResult = await client.signAndBroadcast(
firstAccount.address,
voter1Address,
[proposalMsg],
defaultFee,
"Test proposal for simd",
@ -73,18 +85,65 @@ describe("GovExtension", () => {
.attributes.find(({ key }: any) => key === "proposal_id").value;
assert(proposalId.match(nonNegativeIntegerMatcher));
const voteMsg: MsgVoteEncodeObject = {
typeUrl: "/cosmos.gov.v1beta1.MsgVote",
value: {
proposalId: longify(proposalId),
voter: faucet.address0,
option: VoteOption.VOTE_OPTION_YES,
},
};
const voteMemo = "Test vote for simd";
await client.signAndBroadcast(firstAccount.address, [voteMsg], defaultFee, voteMemo);
// Voter 1
{
// My vote only counts when I delegate
if (!(await client.getDelegation(voter1Address, validator.validatorAddress))) {
const msgDelegate: MsgDelegateEncodeObject = {
typeUrl: "/cosmos.staking.v1beta1.MsgDelegate",
value: {
delegatorAddress: voter1Address,
validatorAddress: validator.validatorAddress,
amount: delegationVoter1,
},
};
const result = await client.signAndBroadcast(voter1Address, [msgDelegate], defaultFee);
assertIsBroadcastTxSuccess(result);
}
const voteMsg: MsgVoteEncodeObject = {
typeUrl: "/cosmos.gov.v1beta1.MsgVote",
value: {
proposalId: longify(proposalId),
voter: voter1Address,
option: VoteOption.VOTE_OPTION_YES,
},
};
const voteResult = await client.signAndBroadcast(voter1Address, [voteMsg], defaultFee);
assertIsBroadcastTxSuccess(voteResult);
}
// Voter 2
{
// My vote only counts when I delegate
if (!(await client.getDelegation(voter2Address, validator.validatorAddress))) {
const msgDelegate: MsgDelegateEncodeObject = {
typeUrl: "/cosmos.staking.v1beta1.MsgDelegate",
value: {
delegatorAddress: voter2Address,
validatorAddress: validator.validatorAddress,
amount: delegationVoter2,
},
};
const result = await client.signAndBroadcast(voter2Address, [msgDelegate], defaultFee);
assertIsBroadcastTxSuccess(result);
}
const voteMsg: MsgVoteEncodeObject = {
typeUrl: "/cosmos.gov.v1beta1.MsgVote",
value: {
proposalId: longify(proposalId),
voter: voter2Address,
option: VoteOption.VOTE_OPTION_NO_WITH_VETO,
},
};
const voteResult = await client.signAndBroadcast(voter2Address, [voteMsg], defaultFee);
assertIsBroadcastTxSuccess(voteResult);
}
await sleep(75); // wait until transactions are indexed
client.disconnect();
}
});
@ -155,8 +214,8 @@ describe("GovExtension", () => {
const response = await client.gov.proposals(
ProposalStatus.PROPOSAL_STATUS_VOTING_PERIOD,
faucet.address0,
faucet.address0,
voter1Address,
voter1Address,
);
expect(response.proposals.length).toBeGreaterThanOrEqual(1);
expect(response.proposals[response.proposals.length - 1]).toEqual({
@ -212,7 +271,7 @@ describe("GovExtension", () => {
expect(response.deposits).toEqual([
{
proposalId: longify(proposalId),
depositor: faucet.address0,
depositor: voter1Address,
amount: initialDeposit,
},
]);
@ -226,10 +285,10 @@ describe("GovExtension", () => {
pendingWithoutSimapp();
const [client, tmClient] = await makeClientWithGov(simapp.tendermintUrl);
const response = await client.gov.deposit(proposalId, faucet.address0);
const response = await client.gov.deposit(proposalId, voter1Address);
expect(response.deposit).toEqual({
proposalId: longify(proposalId),
depositor: faucet.address0,
depositor: voter1Address,
amount: initialDeposit,
});
@ -244,10 +303,10 @@ describe("GovExtension", () => {
const response = await client.gov.tally(proposalId);
expect(response.tally).toEqual({
yes: "0",
yes: delegationVoter1.amount,
abstain: "0",
no: "0",
noWithVeto: "0",
noWithVeto: delegationVoter2.amount,
});
tmClient.disconnect();
@ -261,9 +320,15 @@ describe("GovExtension", () => {
const response = await client.gov.votes(proposalId);
expect(response.votes).toEqual([
// why is vote 2 first?
{
proposalId: longify(proposalId),
voter: faucet.address0,
voter: voter2Address,
option: VoteOption.VOTE_OPTION_NO_WITH_VETO,
},
{
proposalId: longify(proposalId),
voter: voter1Address,
option: VoteOption.VOTE_OPTION_YES,
},
]);
@ -277,9 +342,9 @@ describe("GovExtension", () => {
pendingWithoutSimapp();
const [client, tmClient] = await makeClientWithGov(simapp.tendermintUrl);
const response = await client.gov.vote(proposalId, faucet.address0);
const response = await client.gov.vote(proposalId, voter1Address);
expect(response.vote).toEqual({
voter: faucet.address0,
voter: voter1Address,
proposalId: longify(proposalId),
option: VoteOption.VOTE_OPTION_YES,
});

View File

@ -7,7 +7,15 @@ import { MsgData } from "cosmjs-types/cosmos/base/abci/v1beta1/abci";
import { Coin } from "cosmjs-types/cosmos/base/v1beta1/coin";
import { Account, accountFromAny } from "./accounts";
import { AuthExtension, BankExtension, QueryClient, setupAuthExtension, setupBankExtension } from "./queries";
import {
AuthExtension,
BankExtension,
QueryClient,
setupAuthExtension,
setupBankExtension,
setupStakingExtension,
StakingExtension,
} from "./queries";
import {
isSearchByHeightQuery,
isSearchBySentFromOrToQuery,
@ -138,7 +146,7 @@ export interface PrivateStargateClient {
export class StargateClient {
private readonly tmClient: Tendermint34Client | undefined;
private readonly queryClient: (QueryClient & AuthExtension & BankExtension) | undefined;
private readonly queryClient: (QueryClient & AuthExtension & BankExtension & StakingExtension) | undefined;
private chainId: string | undefined;
public static async connect(endpoint: string): Promise<StargateClient> {
@ -149,7 +157,12 @@ export class StargateClient {
protected constructor(tmClient: Tendermint34Client | undefined) {
if (tmClient) {
this.tmClient = tmClient;
this.queryClient = QueryClient.withExtensions(tmClient, setupAuthExtension, setupBankExtension);
this.queryClient = QueryClient.withExtensions(
tmClient,
setupAuthExtension,
setupBankExtension,
setupStakingExtension,
);
}
}
@ -166,11 +179,11 @@ export class StargateClient {
return this.tmClient;
}
protected getQueryClient(): (QueryClient & AuthExtension & BankExtension) | undefined {
protected getQueryClient(): (QueryClient & AuthExtension & BankExtension & StakingExtension) | undefined {
return this.queryClient;
}
protected forceGetQueryClient(): QueryClient & AuthExtension & BankExtension {
protected forceGetQueryClient(): QueryClient & AuthExtension & BankExtension & StakingExtension {
if (!this.queryClient) {
throw new Error("Query client not available. You cannot use online functionality in offline mode.");
}
@ -254,6 +267,22 @@ export class StargateClient {
return this.forceGetQueryClient().bank.allBalances(address);
}
public async getDelegation(delegatorAddress: string, validatorAddress: string): Promise<Coin | null> {
let delegatedAmount: Coin | undefined;
try {
delegatedAmount = (
await this.forceGetQueryClient().staking.delegation(delegatorAddress, validatorAddress)
).delegationResponse?.balance;
} catch (e) {
if (e.toString().includes("key not found")) {
// ignore, `delegatedAmount` remains undefined
} else {
throw e;
}
}
return delegatedAmount || null;
}
public async getTx(id: string): Promise<IndexedTx | null> {
const results = await this.txsQuery(`tx.hash='${id}'`);
return results[0] ?? null;