From c78688a9087394680bb697b690c8ce1c8e0ba692 Mon Sep 17 00:00:00 2001 From: David Tumcharoen Date: Tue, 12 Mar 2024 16:28:20 +0700 Subject: [PATCH 1/3] fix(x/gov): grpc query tally for failed proposal (#19725) --- x/gov/keeper/grpc_query.go | 5 + x/gov/keeper/grpc_query_test.go | 350 ++++++++++++++++++++++++++++++++ 2 files changed, 355 insertions(+) diff --git a/x/gov/keeper/grpc_query.go b/x/gov/keeper/grpc_query.go index 80a86cab85..24598dd00e 100644 --- a/x/gov/keeper/grpc_query.go +++ b/x/gov/keeper/grpc_query.go @@ -264,8 +264,13 @@ func (q Keeper) TallyResult(c context.Context, req *types.QueryTallyResultReques case proposal.Status == types.StatusDepositPeriod: tallyResult = types.EmptyTallyResult() +<<<<<<< HEAD case proposal.Status == types.StatusPassed || proposal.Status == types.StatusRejected: tallyResult = proposal.FinalTallyResult +======= + case proposal.Status == v1.StatusPassed || proposal.Status == v1.StatusRejected || proposal.Status == v1.StatusFailed: + tallyResult = *proposal.FinalTallyResult +>>>>>>> d961aef76b (fix(x/gov): grpc query tally for failed proposal (#19725)) default: // proposal is in voting period diff --git a/x/gov/keeper/grpc_query_test.go b/x/gov/keeper/grpc_query_test.go index dae0206801..6865af3584 100644 --- a/x/gov/keeper/grpc_query_test.go +++ b/x/gov/keeper/grpc_query_test.go @@ -798,6 +798,48 @@ func (suite *KeeperTestSuite) TestGRPCQueryTally() { }, true, }, + { + "proposal status failed", + func() { + propTime := time.Now() + proposal := v1.Proposal{ + Id: 1, + Status: v1.StatusFailed, + FinalTallyResult: &v1.TallyResult{ + YesCount: "4", + AbstainCount: "1", + NoCount: "0", + NoWithVetoCount: "0", + OptionOneCount: "4", + OptionTwoCount: "1", + OptionThreeCount: "0", + OptionFourCount: "0", + SpamCount: "0", + }, + SubmitTime: &propTime, + VotingStartTime: &propTime, + VotingEndTime: &propTime, + Metadata: "proposal metadata", + } + err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) + suite.Require().NoError(err) + + req = &v1.QueryTallyResultRequest{ProposalId: proposal.Id} + + expTally = &v1.TallyResult{ + YesCount: "4", + AbstainCount: "1", + NoCount: "0", + NoWithVetoCount: "0", + OptionOneCount: "4", + OptionTwoCount: "1", + OptionThreeCount: "0", + OptionFourCount: "0", + SpamCount: "0", + } + }, + true, + }, } for _, testCase := range testCases { @@ -811,7 +853,315 @@ func (suite *KeeperTestSuite) TestGRPCQueryTally() { suite.Require().Equal(expRes.String(), tally.String()) } else { suite.Require().Error(err) +<<<<<<< HEAD suite.Require().Nil(tally) +======= + suite.Require().Nil(tallyRes) + } + }) + } +} + +func (suite *KeeperTestSuite) TestLegacyGRPCQueryTallyResult() { + suite.reset() + queryClient := suite.legacyQueryClient + + var ( + req *v1beta1.QueryTallyResultRequest + expTally *v1beta1.TallyResult + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + { + "empty request", + func() { + req = &v1beta1.QueryTallyResultRequest{} + }, + false, + }, + { + "non existing proposal request", + func() { + req = &v1beta1.QueryTallyResultRequest{ProposalId: 2} + }, + false, + }, + { + "zero proposal id request", + func() { + req = &v1beta1.QueryTallyResultRequest{ProposalId: 0} + }, + false, + }, + { + "valid request with proposal status passed", + func() { + propTime := time.Now() + proposal := v1.Proposal{ + Id: 1, + Status: v1.StatusPassed, + FinalTallyResult: &v1.TallyResult{ + YesCount: "4", + AbstainCount: "1", + NoCount: "0", + NoWithVetoCount: "0", + SpamCount: "0", + }, + SubmitTime: &propTime, + VotingStartTime: &propTime, + VotingEndTime: &propTime, + Metadata: "proposal metadata", + } + err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) + suite.Require().NoError(err) + + req = &v1beta1.QueryTallyResultRequest{ProposalId: proposal.Id} + + expTally = &v1beta1.TallyResult{ + Yes: math.NewInt(4), + Abstain: math.NewInt(1), + No: math.NewInt(0), + NoWithVeto: math.NewInt(0), + } + }, + true, + }, + { + "proposal status deposit", + func() { + propTime := time.Now() + proposal := v1.Proposal{ + Id: 1, + Status: v1.StatusDepositPeriod, + SubmitTime: &propTime, + VotingStartTime: &propTime, + VotingEndTime: &propTime, + Metadata: "proposal metadata", + } + err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) + suite.Require().NoError(err) + + req = &v1beta1.QueryTallyResultRequest{ProposalId: proposal.Id} + + expTally = &v1beta1.TallyResult{ + Yes: math.NewInt(0), + Abstain: math.NewInt(0), + No: math.NewInt(0), + NoWithVeto: math.NewInt(0), + } + }, + true, + }, + { + "proposal is in voting period", + func() { + propTime := time.Now() + proposal := v1.Proposal{ + Id: 1, + Status: v1.StatusVotingPeriod, + SubmitTime: &propTime, + VotingStartTime: &propTime, + VotingEndTime: &propTime, + Metadata: "proposal metadata", + } + err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) + suite.Require().NoError(err) + req = &v1beta1.QueryTallyResultRequest{ProposalId: proposal.Id} + + expTally = &v1beta1.TallyResult{ + Yes: math.NewInt(0), + Abstain: math.NewInt(0), + No: math.NewInt(0), + NoWithVeto: math.NewInt(0), + } + }, + true, + }, + { + "proposal status failed", + func() { + propTime := time.Now() + proposal := v1.Proposal{ + Id: 1, + Status: v1.StatusFailed, + FinalTallyResult: &v1.TallyResult{ + YesCount: "4", + AbstainCount: "1", + NoCount: "0", + NoWithVetoCount: "0", + SpamCount: "0", + }, + SubmitTime: &propTime, + VotingStartTime: &propTime, + VotingEndTime: &propTime, + Metadata: "proposal metadata", + } + err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) + suite.Require().NoError(err) + + req = &v1beta1.QueryTallyResultRequest{ProposalId: proposal.Id} + + expTally = &v1beta1.TallyResult{ + Yes: math.NewInt(4), + Abstain: math.NewInt(1), + No: math.NewInt(0), + NoWithVeto: math.NewInt(0), + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + if tc.malleate != nil { + tc.malleate() + } + + tallyRes, err := queryClient.TallyResult(gocontext.Background(), req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotEmpty(tallyRes.Tally.String()) + suite.Require().Equal(expTally.String(), tallyRes.Tally.String()) + } else { + suite.Require().Error(err) + suite.Require().Nil(tallyRes) + } + }) + } +} + +func (suite *KeeperTestSuite) TestProposalVoteOptions() { + suite.reset() + + testCases := []struct { + name string + malleate func() + req *v1.QueryProposalVoteOptionsRequest + expResp *v1.QueryProposalVoteOptionsResponse + errStr string + }{ + { + name: "invalid proposal id", + req: &v1.QueryProposalVoteOptionsRequest{}, + errStr: "proposal id can not be 0", + }, + { + name: "proposal not found", + req: &v1.QueryProposalVoteOptionsRequest{ProposalId: 1}, + errStr: "proposal 1 doesn't exist", + }, + { + name: "non multiple choice proposal", + malleate: func() { + propTime := time.Now() + proposal := v1.Proposal{ + Id: 1, + Status: v1.StatusVotingPeriod, + SubmitTime: &propTime, + VotingStartTime: &propTime, + VotingEndTime: &propTime, + Metadata: "proposal metadata", + ProposalType: v1.ProposalType_PROPOSAL_TYPE_STANDARD, + } + err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) + suite.Require().NoError(err) + }, + req: &v1.QueryProposalVoteOptionsRequest{ProposalId: 1}, + expResp: &v1.QueryProposalVoteOptionsResponse{ + VoteOptions: &v1.ProposalVoteOptions{ + OptionOne: "yes", + OptionTwo: "abstain", + OptionThree: "no", + OptionFour: "no_with_veto", + OptionSpam: "spam", + }, + }, + }, + { + name: "invalid multiple choice proposal", + req: &v1.QueryProposalVoteOptionsRequest{ProposalId: 2}, + malleate: func() { + propTime := time.Now() + proposal := v1.Proposal{ + Id: 2, + Status: v1.StatusVotingPeriod, + SubmitTime: &propTime, + VotingStartTime: &propTime, + VotingEndTime: &propTime, + Metadata: "proposal metadata", + ProposalType: v1.ProposalType_PROPOSAL_TYPE_MULTIPLE_CHOICE, + } + err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) + suite.Require().NoError(err) + + // multiple choice proposal, but no vote options set + // because the query does not check the proposal type, + // it falls back to the default vote options + }, + expResp: &v1.QueryProposalVoteOptionsResponse{ + VoteOptions: &v1.ProposalVoteOptions{ + OptionOne: "yes", + OptionTwo: "abstain", + OptionThree: "no", + OptionFour: "no_with_veto", + OptionSpam: "spam", + }, + }, + }, + { + name: "multiple choice proposal", + req: &v1.QueryProposalVoteOptionsRequest{ProposalId: 3}, + malleate: func() { + propTime := time.Now() + proposal := v1.Proposal{ + Id: 3, + Status: v1.StatusVotingPeriod, + SubmitTime: &propTime, + VotingStartTime: &propTime, + VotingEndTime: &propTime, + Metadata: "proposal metadata", + ProposalType: v1.ProposalType_PROPOSAL_TYPE_MULTIPLE_CHOICE, + } + err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) + suite.Require().NoError(err) + err = suite.govKeeper.ProposalVoteOptions.Set(suite.ctx, proposal.Id, v1.ProposalVoteOptions{ + OptionOne: "Vote for @tac0turle", + OptionTwo: "Vote for @facudomedica", + OptionThree: "Vote for @alexanderbez", + }) + suite.Require().NoError(err) + }, + expResp: &v1.QueryProposalVoteOptionsResponse{ + VoteOptions: &v1.ProposalVoteOptions{ + OptionOne: "Vote for @tac0turle", + OptionTwo: "Vote for @facudomedica", + OptionThree: "Vote for @alexanderbez", + OptionSpam: "spam", + }, + }, + }, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + if tc.malleate != nil { + tc.malleate() + } + + resp, err := suite.queryClient.ProposalVoteOptions(suite.ctx, tc.req) + if tc.errStr != "" { + suite.Require().Error(err) + suite.Require().Contains(err.Error(), tc.errStr) + } else { + suite.Require().NoError(err) + suite.Require().Equal(tc.expResp, resp) +>>>>>>> d961aef76b (fix(x/gov): grpc query tally for failed proposal (#19725)) } }) } From f70280c29c782b42e866ae6b3aca6309f89e11a3 Mon Sep 17 00:00:00 2001 From: 170210 Date: Tue, 26 Mar 2024 16:04:44 +0900 Subject: [PATCH 2/3] fix: fix conflict Signed-off-by: 170210 --- x/gov/keeper/grpc_query.go | 7 +- x/gov/keeper/grpc_query_test.go | 356 ++------------------------------ 2 files changed, 18 insertions(+), 345 deletions(-) diff --git a/x/gov/keeper/grpc_query.go b/x/gov/keeper/grpc_query.go index 24598dd00e..226f4221e6 100644 --- a/x/gov/keeper/grpc_query.go +++ b/x/gov/keeper/grpc_query.go @@ -264,13 +264,8 @@ func (q Keeper) TallyResult(c context.Context, req *types.QueryTallyResultReques case proposal.Status == types.StatusDepositPeriod: tallyResult = types.EmptyTallyResult() -<<<<<<< HEAD - case proposal.Status == types.StatusPassed || proposal.Status == types.StatusRejected: + case proposal.Status == types.StatusPassed || proposal.Status == types.StatusRejected || proposal.Status == types.StatusFailed: tallyResult = proposal.FinalTallyResult -======= - case proposal.Status == v1.StatusPassed || proposal.Status == v1.StatusRejected || proposal.Status == v1.StatusFailed: - tallyResult = *proposal.FinalTallyResult ->>>>>>> d961aef76b (fix(x/gov): grpc query tally for failed proposal (#19725)) default: // proposal is in voting period diff --git a/x/gov/keeper/grpc_query_test.go b/x/gov/keeper/grpc_query_test.go index 6865af3584..73aa23e555 100644 --- a/x/gov/keeper/grpc_query_test.go +++ b/x/gov/keeper/grpc_query_test.go @@ -4,6 +4,7 @@ import ( gocontext "context" "fmt" "strconv" + "time" "github.com/Finschia/finschia-sdk/simapp" sdk "github.com/Finschia/finschia-sdk/types" @@ -802,40 +803,25 @@ func (suite *KeeperTestSuite) TestGRPCQueryTally() { "proposal status failed", func() { propTime := time.Now() - proposal := v1.Proposal{ - Id: 1, - Status: v1.StatusFailed, - FinalTallyResult: &v1.TallyResult{ - YesCount: "4", - AbstainCount: "1", - NoCount: "0", - NoWithVetoCount: "0", - OptionOneCount: "4", - OptionTwoCount: "1", - OptionThreeCount: "0", - OptionFourCount: "0", - SpamCount: "0", + proposal := types.Proposal{ + ProposalId: 1, + Status: types.StatusFailed, + FinalTallyResult: types.TallyResult{ + Yes: sdk.NewInt(4), + Abstain: sdk.NewInt(1), + No: sdk.NewInt(0), + NoWithVeto: sdk.NewInt(0), }, - SubmitTime: &propTime, - VotingStartTime: &propTime, - VotingEndTime: &propTime, - Metadata: "proposal metadata", + SubmitTime: propTime, + VotingStartTime: propTime, + VotingEndTime: propTime, } - err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) - suite.Require().NoError(err) + app.GovKeeper.SetProposal(ctx, proposal) + + req = &types.QueryTallyResultRequest{ProposalId: proposal.ProposalId} - req = &v1.QueryTallyResultRequest{ProposalId: proposal.Id} - - expTally = &v1.TallyResult{ - YesCount: "4", - AbstainCount: "1", - NoCount: "0", - NoWithVetoCount: "0", - OptionOneCount: "4", - OptionTwoCount: "1", - OptionThreeCount: "0", - OptionFourCount: "0", - SpamCount: "0", + expRes = &types.QueryTallyResultResponse{ + Tally: proposal.FinalTallyResult, } }, true, @@ -853,315 +839,7 @@ func (suite *KeeperTestSuite) TestGRPCQueryTally() { suite.Require().Equal(expRes.String(), tally.String()) } else { suite.Require().Error(err) -<<<<<<< HEAD suite.Require().Nil(tally) -======= - suite.Require().Nil(tallyRes) - } - }) - } -} - -func (suite *KeeperTestSuite) TestLegacyGRPCQueryTallyResult() { - suite.reset() - queryClient := suite.legacyQueryClient - - var ( - req *v1beta1.QueryTallyResultRequest - expTally *v1beta1.TallyResult - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = &v1beta1.QueryTallyResultRequest{} - }, - false, - }, - { - "non existing proposal request", - func() { - req = &v1beta1.QueryTallyResultRequest{ProposalId: 2} - }, - false, - }, - { - "zero proposal id request", - func() { - req = &v1beta1.QueryTallyResultRequest{ProposalId: 0} - }, - false, - }, - { - "valid request with proposal status passed", - func() { - propTime := time.Now() - proposal := v1.Proposal{ - Id: 1, - Status: v1.StatusPassed, - FinalTallyResult: &v1.TallyResult{ - YesCount: "4", - AbstainCount: "1", - NoCount: "0", - NoWithVetoCount: "0", - SpamCount: "0", - }, - SubmitTime: &propTime, - VotingStartTime: &propTime, - VotingEndTime: &propTime, - Metadata: "proposal metadata", - } - err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) - suite.Require().NoError(err) - - req = &v1beta1.QueryTallyResultRequest{ProposalId: proposal.Id} - - expTally = &v1beta1.TallyResult{ - Yes: math.NewInt(4), - Abstain: math.NewInt(1), - No: math.NewInt(0), - NoWithVeto: math.NewInt(0), - } - }, - true, - }, - { - "proposal status deposit", - func() { - propTime := time.Now() - proposal := v1.Proposal{ - Id: 1, - Status: v1.StatusDepositPeriod, - SubmitTime: &propTime, - VotingStartTime: &propTime, - VotingEndTime: &propTime, - Metadata: "proposal metadata", - } - err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) - suite.Require().NoError(err) - - req = &v1beta1.QueryTallyResultRequest{ProposalId: proposal.Id} - - expTally = &v1beta1.TallyResult{ - Yes: math.NewInt(0), - Abstain: math.NewInt(0), - No: math.NewInt(0), - NoWithVeto: math.NewInt(0), - } - }, - true, - }, - { - "proposal is in voting period", - func() { - propTime := time.Now() - proposal := v1.Proposal{ - Id: 1, - Status: v1.StatusVotingPeriod, - SubmitTime: &propTime, - VotingStartTime: &propTime, - VotingEndTime: &propTime, - Metadata: "proposal metadata", - } - err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) - suite.Require().NoError(err) - req = &v1beta1.QueryTallyResultRequest{ProposalId: proposal.Id} - - expTally = &v1beta1.TallyResult{ - Yes: math.NewInt(0), - Abstain: math.NewInt(0), - No: math.NewInt(0), - NoWithVeto: math.NewInt(0), - } - }, - true, - }, - { - "proposal status failed", - func() { - propTime := time.Now() - proposal := v1.Proposal{ - Id: 1, - Status: v1.StatusFailed, - FinalTallyResult: &v1.TallyResult{ - YesCount: "4", - AbstainCount: "1", - NoCount: "0", - NoWithVetoCount: "0", - SpamCount: "0", - }, - SubmitTime: &propTime, - VotingStartTime: &propTime, - VotingEndTime: &propTime, - Metadata: "proposal metadata", - } - err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) - suite.Require().NoError(err) - - req = &v1beta1.QueryTallyResultRequest{ProposalId: proposal.Id} - - expTally = &v1beta1.TallyResult{ - Yes: math.NewInt(4), - Abstain: math.NewInt(1), - No: math.NewInt(0), - NoWithVeto: math.NewInt(0), - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - if tc.malleate != nil { - tc.malleate() - } - - tallyRes, err := queryClient.TallyResult(gocontext.Background(), req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotEmpty(tallyRes.Tally.String()) - suite.Require().Equal(expTally.String(), tallyRes.Tally.String()) - } else { - suite.Require().Error(err) - suite.Require().Nil(tallyRes) - } - }) - } -} - -func (suite *KeeperTestSuite) TestProposalVoteOptions() { - suite.reset() - - testCases := []struct { - name string - malleate func() - req *v1.QueryProposalVoteOptionsRequest - expResp *v1.QueryProposalVoteOptionsResponse - errStr string - }{ - { - name: "invalid proposal id", - req: &v1.QueryProposalVoteOptionsRequest{}, - errStr: "proposal id can not be 0", - }, - { - name: "proposal not found", - req: &v1.QueryProposalVoteOptionsRequest{ProposalId: 1}, - errStr: "proposal 1 doesn't exist", - }, - { - name: "non multiple choice proposal", - malleate: func() { - propTime := time.Now() - proposal := v1.Proposal{ - Id: 1, - Status: v1.StatusVotingPeriod, - SubmitTime: &propTime, - VotingStartTime: &propTime, - VotingEndTime: &propTime, - Metadata: "proposal metadata", - ProposalType: v1.ProposalType_PROPOSAL_TYPE_STANDARD, - } - err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) - suite.Require().NoError(err) - }, - req: &v1.QueryProposalVoteOptionsRequest{ProposalId: 1}, - expResp: &v1.QueryProposalVoteOptionsResponse{ - VoteOptions: &v1.ProposalVoteOptions{ - OptionOne: "yes", - OptionTwo: "abstain", - OptionThree: "no", - OptionFour: "no_with_veto", - OptionSpam: "spam", - }, - }, - }, - { - name: "invalid multiple choice proposal", - req: &v1.QueryProposalVoteOptionsRequest{ProposalId: 2}, - malleate: func() { - propTime := time.Now() - proposal := v1.Proposal{ - Id: 2, - Status: v1.StatusVotingPeriod, - SubmitTime: &propTime, - VotingStartTime: &propTime, - VotingEndTime: &propTime, - Metadata: "proposal metadata", - ProposalType: v1.ProposalType_PROPOSAL_TYPE_MULTIPLE_CHOICE, - } - err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) - suite.Require().NoError(err) - - // multiple choice proposal, but no vote options set - // because the query does not check the proposal type, - // it falls back to the default vote options - }, - expResp: &v1.QueryProposalVoteOptionsResponse{ - VoteOptions: &v1.ProposalVoteOptions{ - OptionOne: "yes", - OptionTwo: "abstain", - OptionThree: "no", - OptionFour: "no_with_veto", - OptionSpam: "spam", - }, - }, - }, - { - name: "multiple choice proposal", - req: &v1.QueryProposalVoteOptionsRequest{ProposalId: 3}, - malleate: func() { - propTime := time.Now() - proposal := v1.Proposal{ - Id: 3, - Status: v1.StatusVotingPeriod, - SubmitTime: &propTime, - VotingStartTime: &propTime, - VotingEndTime: &propTime, - Metadata: "proposal metadata", - ProposalType: v1.ProposalType_PROPOSAL_TYPE_MULTIPLE_CHOICE, - } - err := suite.govKeeper.Proposals.Set(suite.ctx, proposal.Id, proposal) - suite.Require().NoError(err) - err = suite.govKeeper.ProposalVoteOptions.Set(suite.ctx, proposal.Id, v1.ProposalVoteOptions{ - OptionOne: "Vote for @tac0turle", - OptionTwo: "Vote for @facudomedica", - OptionThree: "Vote for @alexanderbez", - }) - suite.Require().NoError(err) - }, - expResp: &v1.QueryProposalVoteOptionsResponse{ - VoteOptions: &v1.ProposalVoteOptions{ - OptionOne: "Vote for @tac0turle", - OptionTwo: "Vote for @facudomedica", - OptionThree: "Vote for @alexanderbez", - OptionSpam: "spam", - }, - }, - }, - } - - for _, tc := range testCases { - suite.Run(tc.name, func() { - if tc.malleate != nil { - tc.malleate() - } - - resp, err := suite.queryClient.ProposalVoteOptions(suite.ctx, tc.req) - if tc.errStr != "" { - suite.Require().Error(err) - suite.Require().Contains(err.Error(), tc.errStr) - } else { - suite.Require().NoError(err) - suite.Require().Equal(tc.expResp, resp) ->>>>>>> d961aef76b (fix(x/gov): grpc query tally for failed proposal (#19725)) } }) } From 3a5cc59764b1ca15bdaa2b415df5371553a3ac5a Mon Sep 17 00:00:00 2001 From: 170210 Date: Tue, 26 Mar 2024 16:12:24 +0900 Subject: [PATCH 3/3] chore: update CHANGELOG.md Signed-off-by: 170210 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f53c61cd4..6d9830a7c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/collection, x/token) [\#1288](https://github.com/Finschia/finschia-sdk/pull/1288) use accAddress to compare in validatebasic function in collection & token modules * (x/collection) [\#1268](https://github.com/Finschia/finschia-sdk/pull/1268) export x/collection params into genesis * (x/collection) [\#1294](https://github.com/Finschia/finschia-sdk/pull/1294) reject NFT coins on FT APIs +* (x/gov) [\#1304](https://github.com/Finschia/finschia-sdk/pull/1304) fetch a failed proposal tally from proposal.FinalTallyResult in the gprc query ### Removed