mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 23:35:19 +00:00
add querier
This commit is contained in:
parent
f773f7f278
commit
a0e4ee7736
@ -66,6 +66,22 @@ func (k Keeper) DeleteCommittee(ctx sdk.Context, committeeID uint64) {
|
|||||||
store.Delete(types.GetKeyFromID(committeeID))
|
store.Delete(types.GetKeyFromID(committeeID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IterateCommittees provides an iterator over all stored committees.
|
||||||
|
// For each committee, cb will be called. If cb returns true, the iterator will close and stop.
|
||||||
|
func (k Keeper) IterateCommittees(ctx sdk.Context, cb func(committee types.Committee) (stop bool)) {
|
||||||
|
iterator := sdk.KVStorePrefixIterator(ctx.KVStore(k.storeKey), types.CommitteeKeyPrefix)
|
||||||
|
|
||||||
|
defer iterator.Close()
|
||||||
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
|
var committee types.Committee
|
||||||
|
k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &committee)
|
||||||
|
|
||||||
|
if cb(committee) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------- Proposals ----------
|
// ---------- Proposals ----------
|
||||||
|
|
||||||
// SetNextProposalID stores an ID to be used for the next created proposal
|
// SetNextProposalID stores an ID to be used for the next created proposal
|
||||||
|
220
x/committee/keeper/querier.go
Normal file
220
x/committee/keeper/querier.go
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
package keeper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
|
"github.com/kava-labs/kava/x/committee/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewQuerier creates a new gov Querier instance
|
||||||
|
func NewQuerier(keeper Keeper) sdk.Querier {
|
||||||
|
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) {
|
||||||
|
switch path[0] {
|
||||||
|
|
||||||
|
case types.QueryCommittees:
|
||||||
|
return queryCommittees(ctx, path[1:], req, keeper)
|
||||||
|
case types.QueryCommittee:
|
||||||
|
return queryCommittee(ctx, path[1:], req, keeper)
|
||||||
|
case types.QueryProposals:
|
||||||
|
return queryProposals(ctx, path[1:], req, keeper)
|
||||||
|
case types.QueryProposal:
|
||||||
|
return queryProposal(ctx, path[1:], req, keeper)
|
||||||
|
case types.QueryVotes:
|
||||||
|
return queryVotes(ctx, path[1:], req, keeper)
|
||||||
|
case types.QueryVote:
|
||||||
|
return queryVote(ctx, path[1:], req, keeper)
|
||||||
|
case types.QueryTally:
|
||||||
|
return queryTally(ctx, path[1:], req, keeper)
|
||||||
|
// case types.QueryParams:
|
||||||
|
// return queryParams(ctx, path[1:], req, keeper)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, sdk.ErrUnknownRequest(fmt.Sprintf("unknown %s query endpoint", types.ModuleName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Committees ----------
|
||||||
|
|
||||||
|
func queryCommittees(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
|
||||||
|
|
||||||
|
committees := []types.Committee{}
|
||||||
|
keeper.IterateCommittees(ctx, func(com types.Committee) bool {
|
||||||
|
committees = append(committees, com)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
bz, err := codec.MarshalJSONIndent(keeper.cdc, committees)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
|
}
|
||||||
|
return bz, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryCommittee(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
|
||||||
|
var params types.QueryCommitteeParams
|
||||||
|
err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
committee, found := keeper.GetCommittee(ctx, params.CommitteeID)
|
||||||
|
if !found {
|
||||||
|
return nil, sdk.ErrInternal("not found") ///types.ErrUnknownProposal(types.DefaultCodespace, params.ProposalID)
|
||||||
|
}
|
||||||
|
|
||||||
|
bz, err := codec.MarshalJSONIndent(keeper.cdc, committee)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
|
}
|
||||||
|
return bz, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Proposals ----------
|
||||||
|
|
||||||
|
func queryProposals(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
|
||||||
|
var params types.QueryCommitteeParams
|
||||||
|
err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
proposals := []types.Proposal{}
|
||||||
|
keeper.IterateProposals(ctx, func(p types.Proposal) bool {
|
||||||
|
if p.CommitteeID == params.CommitteeID {
|
||||||
|
proposals = append(proposals, p)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
bz, err := codec.MarshalJSONIndent(keeper.cdc, proposals)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
|
}
|
||||||
|
return bz, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
|
||||||
|
var params types.QueryProposalParams
|
||||||
|
err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
proposal, found := keeper.GetProposal(ctx, params.ProposalID)
|
||||||
|
if !found {
|
||||||
|
return nil, sdk.ErrInternal("not found") // TODO types.ErrUnknownProposal(types.DefaultCodespace, params.ProposalID)
|
||||||
|
}
|
||||||
|
|
||||||
|
bz, err := codec.MarshalJSONIndent(keeper.cdc, proposal)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
|
}
|
||||||
|
return bz, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Votes ----------
|
||||||
|
|
||||||
|
func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
|
||||||
|
var params types.QueryProposalParams
|
||||||
|
err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
votes := []types.Vote{}
|
||||||
|
keeper.IterateVotes(ctx, params.ProposalID, func(v types.Vote) bool {
|
||||||
|
votes = append(votes, v)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
bz, err := codec.MarshalJSONIndent(keeper.cdc, votes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
|
}
|
||||||
|
return bz, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
|
||||||
|
var params types.QueryVoteParams
|
||||||
|
err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
vote, found := keeper.GetVote(ctx, params.ProposalID, params.Voter)
|
||||||
|
if !found {
|
||||||
|
return nil, sdk.ErrInternal("not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
bz, err := codec.MarshalJSONIndent(keeper.cdc, vote)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
|
}
|
||||||
|
return bz, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Tally ----------
|
||||||
|
|
||||||
|
func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
|
||||||
|
var params types.QueryProposalParams
|
||||||
|
err := keeper.cdc.UnmarshalJSON(req.Data, ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO split tally and process result logic so tally logic can be used here
|
||||||
|
pr, found := keeper.GetProposal(ctx, params.ProposalID)
|
||||||
|
if !found {
|
||||||
|
return nil, sdk.ErrInternal("proposal not found")
|
||||||
|
}
|
||||||
|
com, found := keeper.GetCommittee(ctx, pr.CommitteeID)
|
||||||
|
if !found {
|
||||||
|
return nil, sdk.ErrInternal("committee disbanded")
|
||||||
|
}
|
||||||
|
votes := []types.Vote{}
|
||||||
|
keeper.IterateVotes(ctx, params.ProposalID, func(vote types.Vote) bool {
|
||||||
|
votes = append(votes, vote)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
proposalPasses := sdk.NewDec(int64(len(votes))).GTE(types.VoteThreshold.MulInt64(int64(len(com.Members))))
|
||||||
|
// TODO return some kind of tally object, rather than just a bool
|
||||||
|
|
||||||
|
bz, err := codec.MarshalJSONIndent(keeper.cdc, proposalPasses)
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
|
}
|
||||||
|
return bz, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Params ----------
|
||||||
|
|
||||||
|
// func queryParams(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
|
||||||
|
// switch path[0] {
|
||||||
|
// case types.ParamDeposit:
|
||||||
|
// bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetDepositParams(ctx))
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
|
// }
|
||||||
|
// return bz, nil
|
||||||
|
// case types.ParamVoting:
|
||||||
|
// bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetVotingParams(ctx))
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
|
// }
|
||||||
|
// return bz, nil
|
||||||
|
// case types.ParamTallying:
|
||||||
|
// bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetTallyParams(ctx))
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
|
// }
|
||||||
|
// return bz, nil
|
||||||
|
// default:
|
||||||
|
// return nil, sdk.ErrUnknownRequest(fmt.Sprintf("%s is not a valid query request path", req.Path))
|
||||||
|
// }
|
||||||
|
// }
|
252
x/committee/keeper/querier_test.go
Normal file
252
x/committee/keeper/querier_test.go
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
package keeper_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
|
||||||
|
"github.com/kava-labs/kava/app"
|
||||||
|
"github.com/kava-labs/kava/x/committee/keeper"
|
||||||
|
"github.com/kava-labs/kava/x/committee/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
custom = "custom"
|
||||||
|
)
|
||||||
|
|
||||||
|
type QuerierTestSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
|
||||||
|
keeper keeper.Keeper
|
||||||
|
app app.TestApp
|
||||||
|
ctx sdk.Context
|
||||||
|
cdc *codec.Codec
|
||||||
|
|
||||||
|
querier sdk.Querier
|
||||||
|
|
||||||
|
addresses []sdk.AccAddress
|
||||||
|
committees []types.Committee
|
||||||
|
proposals []types.Proposal
|
||||||
|
votes map[uint64]([]types.Vote)
|
||||||
|
expectedTallyForTheFirstProposal bool // TODO replace once tallying has been refactored
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *QuerierTestSuite) SetupTest() {
|
||||||
|
// SetupTest function runs before every test, but a new suite is not created every time.
|
||||||
|
// So be careful about modifying data on suite as data from previous tests will still be there.
|
||||||
|
// For example, don't append proposal to suite.proposals, initialize a new slice value.
|
||||||
|
suite.app = app.NewTestApp()
|
||||||
|
suite.keeper = suite.app.GetCommitteeKeeper()
|
||||||
|
suite.ctx = suite.app.NewContext(true, abci.Header{})
|
||||||
|
suite.cdc = suite.app.Codec()
|
||||||
|
suite.querier = keeper.NewQuerier(suite.keeper)
|
||||||
|
|
||||||
|
_, suite.addresses = app.GeneratePrivKeyAddressPairs(5)
|
||||||
|
suite.app.InitializeFromGenesisStates()
|
||||||
|
// TODO replace below with genesis state
|
||||||
|
normalCom := types.Committee{
|
||||||
|
ID: 12,
|
||||||
|
Members: suite.addresses[:2],
|
||||||
|
Permissions: []types.Permission{types.GodPermission{}},
|
||||||
|
}
|
||||||
|
suite.keeper.SetCommittee(suite.ctx, normalCom)
|
||||||
|
|
||||||
|
pprop1 := gov.NewTextProposal("1A Title", "A description of this proposal.")
|
||||||
|
id1, err := suite.keeper.SubmitProposal(suite.ctx, normalCom.Members[0], normalCom.ID, pprop1)
|
||||||
|
suite.NoError(err)
|
||||||
|
|
||||||
|
pprop2 := gov.NewTextProposal("2A Title", "A description of this proposal.")
|
||||||
|
id2, err := suite.keeper.SubmitProposal(suite.ctx, normalCom.Members[0], normalCom.ID, pprop2)
|
||||||
|
suite.NoError(err)
|
||||||
|
|
||||||
|
err = suite.keeper.AddVote(suite.ctx, id1, normalCom.Members[0])
|
||||||
|
suite.NoError(err)
|
||||||
|
err = suite.keeper.AddVote(suite.ctx, id1, normalCom.Members[1])
|
||||||
|
suite.NoError(err)
|
||||||
|
err = suite.keeper.AddVote(suite.ctx, id2, normalCom.Members[1])
|
||||||
|
suite.NoError(err)
|
||||||
|
|
||||||
|
suite.committees = []types.Committee{}
|
||||||
|
suite.committees = []types.Committee{normalCom} // TODO
|
||||||
|
suite.proposals = []types.Proposal{}
|
||||||
|
suite.keeper.IterateProposals(suite.ctx, func(p types.Proposal) bool {
|
||||||
|
suite.proposals = append(suite.proposals, p)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
suite.votes = map[uint64]([]types.Vote){}
|
||||||
|
suite.keeper.IterateProposals(suite.ctx, func(p types.Proposal) bool {
|
||||||
|
suite.keeper.IterateVotes(suite.ctx, p.ID, func(v types.Vote) bool {
|
||||||
|
suite.votes[p.ID] = append(suite.votes[p.ID], v)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
suite.expectedTallyForTheFirstProposal = true // TODO replace once tallying has been refactored
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *QuerierTestSuite) TestQueryCommittees() {
|
||||||
|
ctx := suite.ctx.WithIsCheckTx(false)
|
||||||
|
// Set up request query
|
||||||
|
query := abci.RequestQuery{
|
||||||
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryCommittees}, "/"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute query and check the []byte result
|
||||||
|
bz, err := suite.querier(ctx, []string{types.QueryCommittees}, query)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.NotNil(bz)
|
||||||
|
|
||||||
|
// Unmarshal the bytes
|
||||||
|
var committees []types.Committee
|
||||||
|
suite.NoError(suite.cdc.UnmarshalJSON(bz, &committees))
|
||||||
|
|
||||||
|
// Check
|
||||||
|
suite.Equal(suite.committees, committees)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *QuerierTestSuite) TestQueryCommittee() {
|
||||||
|
ctx := suite.ctx.WithIsCheckTx(false) // ?
|
||||||
|
// Set up request query
|
||||||
|
query := abci.RequestQuery{
|
||||||
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryCommittee}, "/"),
|
||||||
|
Data: suite.cdc.MustMarshalJSON(types.NewQueryCommitteeParams(suite.committees[0].ID)),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute query and check the []byte result
|
||||||
|
bz, err := suite.querier(ctx, []string{types.QueryCommittee}, query)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.NotNil(bz)
|
||||||
|
|
||||||
|
// Unmarshal the bytes
|
||||||
|
var committee types.Committee
|
||||||
|
suite.NoError(suite.cdc.UnmarshalJSON(bz, &committee))
|
||||||
|
|
||||||
|
// Check
|
||||||
|
suite.Equal(suite.committees[0], committee)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *QuerierTestSuite) TestQueryProposals() {
|
||||||
|
ctx := suite.ctx.WithIsCheckTx(false)
|
||||||
|
// Set up request query
|
||||||
|
comID := suite.proposals[0].CommitteeID
|
||||||
|
query := abci.RequestQuery{
|
||||||
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryProposals}, "/"),
|
||||||
|
Data: suite.cdc.MustMarshalJSON(types.NewQueryCommitteeParams(comID)),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute query and check the []byte result
|
||||||
|
bz, err := suite.querier(ctx, []string{types.QueryProposals}, query)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.NotNil(bz)
|
||||||
|
|
||||||
|
// Unmarshal the bytes
|
||||||
|
var proposals []types.Proposal
|
||||||
|
suite.NoError(suite.cdc.UnmarshalJSON(bz, &proposals))
|
||||||
|
|
||||||
|
// Check
|
||||||
|
expectedProposals := []types.Proposal{}
|
||||||
|
for _, p := range suite.proposals {
|
||||||
|
if p.CommitteeID == comID {
|
||||||
|
expectedProposals = append(expectedProposals, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
suite.Equal(expectedProposals, proposals)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *QuerierTestSuite) TestQueryProposal() {
|
||||||
|
ctx := suite.ctx.WithIsCheckTx(false) // ?
|
||||||
|
// Set up request query
|
||||||
|
query := abci.RequestQuery{
|
||||||
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryProposal}, "/"),
|
||||||
|
Data: suite.cdc.MustMarshalJSON(types.NewQueryProposalParams(suite.proposals[0].ID)),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute query and check the []byte result
|
||||||
|
bz, err := suite.querier(ctx, []string{types.QueryProposal}, query)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.NotNil(bz)
|
||||||
|
|
||||||
|
// Unmarshal the bytes
|
||||||
|
var proposal types.Proposal
|
||||||
|
suite.NoError(suite.cdc.UnmarshalJSON(bz, &proposal))
|
||||||
|
|
||||||
|
// Check
|
||||||
|
suite.Equal(suite.proposals[0], proposal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *QuerierTestSuite) TestQueryVotes() {
|
||||||
|
ctx := suite.ctx.WithIsCheckTx(false)
|
||||||
|
// Set up request query
|
||||||
|
propID := suite.proposals[0].ID
|
||||||
|
query := abci.RequestQuery{
|
||||||
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryVotes}, "/"),
|
||||||
|
Data: suite.cdc.MustMarshalJSON(types.NewQueryProposalParams(propID)),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute query and check the []byte result
|
||||||
|
bz, err := suite.querier(ctx, []string{types.QueryVotes}, query)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.NotNil(bz)
|
||||||
|
|
||||||
|
// Unmarshal the bytes
|
||||||
|
var votes []types.Vote
|
||||||
|
suite.NoError(suite.cdc.UnmarshalJSON(bz, &votes))
|
||||||
|
|
||||||
|
// Check
|
||||||
|
suite.Equal(suite.votes[propID], votes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *QuerierTestSuite) TestQueryVote() {
|
||||||
|
ctx := suite.ctx.WithIsCheckTx(false) // ?
|
||||||
|
// Set up request query
|
||||||
|
propID := suite.proposals[0].ID
|
||||||
|
query := abci.RequestQuery{
|
||||||
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryVote}, "/"),
|
||||||
|
Data: suite.cdc.MustMarshalJSON(types.NewQueryVoteParams(propID, suite.votes[propID][0].Voter)),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute query and check the []byte result
|
||||||
|
bz, err := suite.querier(ctx, []string{types.QueryVote}, query)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.NotNil(bz)
|
||||||
|
|
||||||
|
// Unmarshal the bytes
|
||||||
|
var vote types.Vote
|
||||||
|
suite.NoError(suite.cdc.UnmarshalJSON(bz, &vote))
|
||||||
|
|
||||||
|
// Check
|
||||||
|
suite.Equal(suite.votes[propID][0], vote)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *QuerierTestSuite) TestQueryTally() {
|
||||||
|
ctx := suite.ctx.WithIsCheckTx(false) // ?
|
||||||
|
// Set up request query
|
||||||
|
propID := suite.proposals[0].ID
|
||||||
|
query := abci.RequestQuery{
|
||||||
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryTally}, "/"),
|
||||||
|
Data: suite.cdc.MustMarshalJSON(types.NewQueryProposalParams(propID)),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute query and check the []byte result
|
||||||
|
bz, err := suite.querier(ctx, []string{types.QueryTally}, query)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.NotNil(bz)
|
||||||
|
|
||||||
|
// Unmarshal the bytes
|
||||||
|
var tally bool
|
||||||
|
suite.NoError(suite.cdc.UnmarshalJSON(bz, &tally))
|
||||||
|
|
||||||
|
// Check
|
||||||
|
expectedTally := suite.expectedTallyForTheFirstProposal
|
||||||
|
suite.Equal(expectedTally, tally)
|
||||||
|
}
|
||||||
|
func TestQuerierTestSuite(t *testing.T) {
|
||||||
|
suite.Run(t, new(QuerierTestSuite))
|
||||||
|
}
|
49
x/committee/types/querier.go
Normal file
49
x/committee/types/querier.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Query endpoints supported by the Querier
|
||||||
|
const (
|
||||||
|
//QueryParams = "params"
|
||||||
|
QueryCommittees = "committees"
|
||||||
|
QueryCommittee = "committee"
|
||||||
|
QueryProposals = "proposals"
|
||||||
|
QueryProposal = "proposal"
|
||||||
|
QueryVotes = "votes"
|
||||||
|
QueryVote = "vote"
|
||||||
|
QueryTally = "tally"
|
||||||
|
)
|
||||||
|
|
||||||
|
type QueryCommitteeParams struct {
|
||||||
|
CommitteeID uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQueryCommitteeParams(committeeID uint64) QueryCommitteeParams {
|
||||||
|
return QueryCommitteeParams{
|
||||||
|
CommitteeID: committeeID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryProposalParams struct {
|
||||||
|
ProposalID uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQueryProposalParams(proposalID uint64) QueryProposalParams {
|
||||||
|
return QueryProposalParams{
|
||||||
|
ProposalID: proposalID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryVoteParams struct {
|
||||||
|
ProposalID uint64
|
||||||
|
Voter sdk.AccAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQueryVoteParams(proposalID uint64, voter sdk.AccAddress) QueryVoteParams {
|
||||||
|
return QueryVoteParams{
|
||||||
|
ProposalID: proposalID,
|
||||||
|
Voter: voter,
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
@ -65,6 +67,21 @@ func (p Proposal) HasExpiredBy(time time.Time) bool {
|
|||||||
return !time.Before(p.Deadline)
|
return !time.Before(p.Deadline)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String implements the fmt.Stringer interface, and importantly overrides the String methods inherited from the embedded PubProposal type.
|
||||||
|
func (p Proposal) String() string {
|
||||||
|
return strings.TrimSpace(fmt.Sprintf(`Proposal:
|
||||||
|
PubProposal:
|
||||||
|
%s
|
||||||
|
ID: %d
|
||||||
|
Committee ID: %d
|
||||||
|
Deadline: %s`,
|
||||||
|
p.PubProposal,
|
||||||
|
p.ID,
|
||||||
|
p.CommitteeID,
|
||||||
|
p.Deadline,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
type Vote struct {
|
type Vote struct {
|
||||||
ProposalID uint64
|
ProposalID uint64
|
||||||
Voter sdk.AccAddress
|
Voter sdk.AccAddress
|
||||||
|
Loading…
Reference in New Issue
Block a user