github.com/Finschia/finschia-sdk@v0.48.1/x/gov/keeper/grpc_query.go (about)

     1  package keeper
     2  
     3  import (
     4  	"context"
     5  
     6  	"google.golang.org/grpc/codes"
     7  	"google.golang.org/grpc/status"
     8  
     9  	"github.com/Finschia/finschia-sdk/store/prefix"
    10  	sdk "github.com/Finschia/finschia-sdk/types"
    11  	"github.com/Finschia/finschia-sdk/types/query"
    12  	"github.com/Finschia/finschia-sdk/x/gov/types"
    13  )
    14  
    15  var _ types.QueryServer = Keeper{}
    16  
    17  // Proposal returns proposal details based on ProposalID
    18  func (q Keeper) Proposal(c context.Context, req *types.QueryProposalRequest) (*types.QueryProposalResponse, error) {
    19  	if req == nil {
    20  		return nil, status.Error(codes.InvalidArgument, "invalid request")
    21  	}
    22  
    23  	if req.ProposalId == 0 {
    24  		return nil, status.Error(codes.InvalidArgument, "proposal id can not be 0")
    25  	}
    26  
    27  	ctx := sdk.UnwrapSDKContext(c)
    28  
    29  	proposal, found := q.GetProposal(ctx, req.ProposalId)
    30  	if !found {
    31  		return nil, status.Errorf(codes.NotFound, "proposal %d doesn't exist", req.ProposalId)
    32  	}
    33  
    34  	return &types.QueryProposalResponse{Proposal: proposal}, nil
    35  }
    36  
    37  // Proposals implements the Query/Proposals gRPC method
    38  func (q Keeper) Proposals(c context.Context, req *types.QueryProposalsRequest) (*types.QueryProposalsResponse, error) {
    39  	var filteredProposals types.Proposals
    40  	ctx := sdk.UnwrapSDKContext(c)
    41  
    42  	store := ctx.KVStore(q.storeKey)
    43  	proposalStore := prefix.NewStore(store, types.ProposalsKeyPrefix)
    44  
    45  	pageRes, err := query.FilteredPaginate(proposalStore, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) {
    46  		var p types.Proposal
    47  		if err := q.cdc.Unmarshal(value, &p); err != nil {
    48  			return false, status.Error(codes.Internal, err.Error())
    49  		}
    50  
    51  		matchVoter, matchDepositor, matchStatus := true, true, true
    52  
    53  		// match status (if supplied/valid)
    54  		if types.ValidProposalStatus(req.ProposalStatus) {
    55  			matchStatus = p.Status == req.ProposalStatus
    56  		}
    57  
    58  		// match voter address (if supplied)
    59  		if len(req.Voter) > 0 {
    60  			voter, err := sdk.AccAddressFromBech32(req.Voter)
    61  			if err != nil {
    62  				return false, err
    63  			}
    64  
    65  			_, matchVoter = q.GetVote(ctx, p.ProposalId, voter)
    66  		}
    67  
    68  		// match depositor (if supplied)
    69  		if len(req.Depositor) > 0 {
    70  			depositor, err := sdk.AccAddressFromBech32(req.Depositor)
    71  			if err != nil {
    72  				return false, err
    73  			}
    74  			_, matchDepositor = q.GetDeposit(ctx, p.ProposalId, depositor)
    75  		}
    76  
    77  		if matchVoter && matchDepositor && matchStatus {
    78  			if accumulate {
    79  				filteredProposals = append(filteredProposals, p)
    80  			}
    81  
    82  			return true, nil
    83  		}
    84  
    85  		return false, nil
    86  	})
    87  	if err != nil {
    88  		return nil, status.Error(codes.Internal, err.Error())
    89  	}
    90  
    91  	return &types.QueryProposalsResponse{Proposals: filteredProposals, Pagination: pageRes}, nil
    92  }
    93  
    94  // Vote returns Voted information based on proposalID, voterAddr
    95  func (q Keeper) Vote(c context.Context, req *types.QueryVoteRequest) (*types.QueryVoteResponse, error) {
    96  	if req == nil {
    97  		return nil, status.Error(codes.InvalidArgument, "invalid request")
    98  	}
    99  
   100  	if req.ProposalId == 0 {
   101  		return nil, status.Error(codes.InvalidArgument, "proposal id can not be 0")
   102  	}
   103  
   104  	if req.Voter == "" {
   105  		return nil, status.Error(codes.InvalidArgument, "empty voter address")
   106  	}
   107  
   108  	ctx := sdk.UnwrapSDKContext(c)
   109  
   110  	voter, err := sdk.AccAddressFromBech32(req.Voter)
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  	vote, found := q.GetVote(ctx, req.ProposalId, voter)
   115  	if !found {
   116  		return nil, status.Errorf(codes.InvalidArgument,
   117  			"voter: %v not found for proposal: %v", req.Voter, req.ProposalId)
   118  	}
   119  
   120  	return &types.QueryVoteResponse{Vote: vote}, nil
   121  }
   122  
   123  // Votes returns single proposal's votes
   124  func (q Keeper) Votes(c context.Context, req *types.QueryVotesRequest) (*types.QueryVotesResponse, error) {
   125  	if req == nil {
   126  		return nil, status.Error(codes.InvalidArgument, "invalid request")
   127  	}
   128  
   129  	if req.ProposalId == 0 {
   130  		return nil, status.Error(codes.InvalidArgument, "proposal id can not be 0")
   131  	}
   132  
   133  	var votes types.Votes
   134  	ctx := sdk.UnwrapSDKContext(c)
   135  
   136  	store := ctx.KVStore(q.storeKey)
   137  	votesStore := prefix.NewStore(store, types.VotesKey(req.ProposalId))
   138  
   139  	pageRes, err := query.Paginate(votesStore, req.Pagination, func(key []byte, value []byte) error {
   140  		var vote types.Vote
   141  		if err := q.cdc.Unmarshal(value, &vote); err != nil {
   142  			return err
   143  		}
   144  		populateLegacyOption(&vote)
   145  
   146  		votes = append(votes, vote)
   147  		return nil
   148  	})
   149  	if err != nil {
   150  		return nil, status.Error(codes.Internal, err.Error())
   151  	}
   152  
   153  	return &types.QueryVotesResponse{Votes: votes, Pagination: pageRes}, nil
   154  }
   155  
   156  // Params queries all params
   157  func (q Keeper) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
   158  	if req == nil {
   159  		return nil, status.Error(codes.InvalidArgument, "invalid request")
   160  	}
   161  
   162  	ctx := sdk.UnwrapSDKContext(c)
   163  
   164  	switch req.ParamsType {
   165  	case types.ParamDeposit:
   166  		depositParmas := q.GetDepositParams(ctx)
   167  		return &types.QueryParamsResponse{DepositParams: depositParmas}, nil
   168  
   169  	case types.ParamVoting:
   170  		votingParmas := q.GetVotingParams(ctx)
   171  		return &types.QueryParamsResponse{VotingParams: votingParmas}, nil
   172  
   173  	case types.ParamTallying:
   174  		tallyParams := q.GetTallyParams(ctx)
   175  		return &types.QueryParamsResponse{TallyParams: tallyParams}, nil
   176  
   177  	default:
   178  		return nil, status.Errorf(codes.InvalidArgument,
   179  			"%s is not a valid parameter type", req.ParamsType)
   180  	}
   181  }
   182  
   183  // Deposit queries single deposit information based proposalID, depositAddr
   184  func (q Keeper) Deposit(c context.Context, req *types.QueryDepositRequest) (*types.QueryDepositResponse, error) {
   185  	if req == nil {
   186  		return nil, status.Error(codes.InvalidArgument, "invalid request")
   187  	}
   188  
   189  	if req.ProposalId == 0 {
   190  		return nil, status.Error(codes.InvalidArgument, "proposal id can not be 0")
   191  	}
   192  
   193  	if req.Depositor == "" {
   194  		return nil, status.Error(codes.InvalidArgument, "empty depositor address")
   195  	}
   196  
   197  	ctx := sdk.UnwrapSDKContext(c)
   198  
   199  	depositor, err := sdk.AccAddressFromBech32(req.Depositor)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  	deposit, found := q.GetDeposit(ctx, req.ProposalId, depositor)
   204  	if !found {
   205  		return nil, status.Errorf(codes.InvalidArgument,
   206  			"depositer: %v not found for proposal: %v", req.Depositor, req.ProposalId)
   207  	}
   208  
   209  	return &types.QueryDepositResponse{Deposit: deposit}, nil
   210  }
   211  
   212  // Deposits returns single proposal's all deposits
   213  func (q Keeper) Deposits(c context.Context, req *types.QueryDepositsRequest) (*types.QueryDepositsResponse, error) {
   214  	if req == nil {
   215  		return nil, status.Error(codes.InvalidArgument, "invalid request")
   216  	}
   217  
   218  	if req.ProposalId == 0 {
   219  		return nil, status.Error(codes.InvalidArgument, "proposal id can not be 0")
   220  	}
   221  
   222  	var deposits types.Deposits
   223  	ctx := sdk.UnwrapSDKContext(c)
   224  
   225  	store := ctx.KVStore(q.storeKey)
   226  	depositStore := prefix.NewStore(store, types.DepositsKey(req.ProposalId))
   227  
   228  	pageRes, err := query.Paginate(depositStore, req.Pagination, func(key []byte, value []byte) error {
   229  		var deposit types.Deposit
   230  		if err := q.cdc.Unmarshal(value, &deposit); err != nil {
   231  			return err
   232  		}
   233  
   234  		deposits = append(deposits, deposit)
   235  		return nil
   236  	})
   237  	if err != nil {
   238  		return nil, status.Error(codes.Internal, err.Error())
   239  	}
   240  
   241  	return &types.QueryDepositsResponse{Deposits: deposits, Pagination: pageRes}, nil
   242  }
   243  
   244  // TallyResult queries the tally of a proposal vote
   245  func (q Keeper) TallyResult(c context.Context, req *types.QueryTallyResultRequest) (*types.QueryTallyResultResponse, error) {
   246  	if req == nil {
   247  		return nil, status.Error(codes.InvalidArgument, "invalid request")
   248  	}
   249  
   250  	if req.ProposalId == 0 {
   251  		return nil, status.Error(codes.InvalidArgument, "proposal id can not be 0")
   252  	}
   253  
   254  	ctx := sdk.UnwrapSDKContext(c)
   255  
   256  	proposal, ok := q.GetProposal(ctx, req.ProposalId)
   257  	if !ok {
   258  		return nil, status.Errorf(codes.NotFound, "proposal %d doesn't exist", req.ProposalId)
   259  	}
   260  
   261  	var tallyResult types.TallyResult
   262  
   263  	switch {
   264  	case proposal.Status == types.StatusDepositPeriod:
   265  		tallyResult = types.EmptyTallyResult()
   266  
   267  	case proposal.Status == types.StatusPassed || proposal.Status == types.StatusRejected:
   268  		tallyResult = proposal.FinalTallyResult
   269  
   270  	default:
   271  		// proposal is in voting period
   272  		_, _, tallyResult = q.Tally(ctx, proposal)
   273  	}
   274  
   275  	return &types.QueryTallyResultResponse{Tally: tallyResult}, nil
   276  }