Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R4R: Query-proposals CLI command #1845

Merged
merged 1 commit into from
Jul 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ FEATURES
* [tests] Remotenet commands for AWS (awsnet)
* [store] Add transient store
* [gov] Add slashing for validators who do not vote on a proposal
* [cli] added `gov query-proposals` command to CLI. Can filter by `depositer`, `voter`, and `status`

IMPROVEMENTS
* [baseapp] Allow any alphanumeric character in route
Expand Down
28 changes: 27 additions & 1 deletion cmd/gaia/cli_test/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,10 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags))
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())

// unbond a single share
proposalsQuery := tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals %v", flags))
require.Equal(t, "No matching proposals found", proposalsQuery)

// submit a test proposal
spStr := fmt.Sprintf("gaiacli gov submit-proposal %v", flags)
spStr += fmt.Sprintf(" --from=%s", "foo")
spStr += fmt.Sprintf(" --deposit=%s", "5steak")
Expand All @@ -194,6 +197,9 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
require.Equal(t, int64(1), proposal1.GetProposalID())
require.Equal(t, gov.StatusDepositPeriod, proposal1.GetStatus())

proposalsQuery = tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals %v", flags))
require.Equal(t, " 1 - Test", proposalsQuery)

depositStr := fmt.Sprintf("gaiacli gov deposit %v", flags)
depositStr += fmt.Sprintf(" --from=%s", "foo")
depositStr += fmt.Sprintf(" --deposit=%s", "10steak")
Expand Down Expand Up @@ -224,6 +230,26 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
require.Len(t, votes, 1)
require.Equal(t, int64(1), votes[0].ProposalID)
require.Equal(t, gov.OptionYes, votes[0].Option)

proposalsQuery = tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals --status=DepositPeriod %v", flags))
require.Equal(t, "No matching proposals found", proposalsQuery)

proposalsQuery = tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals --status=VotingPeriod %v", flags))
require.Equal(t, " 1 - Test", proposalsQuery)

// submit a second test proposal
spStr = fmt.Sprintf("gaiacli gov submit-proposal %v", flags)
spStr += fmt.Sprintf(" --from=%s", "foo")
spStr += fmt.Sprintf(" --deposit=%s", "5steak")
spStr += fmt.Sprintf(" --type=%s", "Text")
spStr += fmt.Sprintf(" --title=%s", "Apples")
spStr += fmt.Sprintf(" --description=%s", "test")

executeWrite(t, spStr, pass)
tests.WaitForNextNBlocksTM(2, port)

proposalsQuery = tests.ExecuteT(t, fmt.Sprintf("gaiacli gov query-proposals --latest=1 %v", flags))
require.Equal(t, " 2 - Apples", proposalsQuery)
}

//___________________________________________________________________________________
Expand Down
1 change: 1 addition & 0 deletions cmd/gaia/cmd/gaiacli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func main() {
govcmd.GetCmdQueryProposal("gov", cdc),
govcmd.GetCmdQueryVote("gov", cdc),
govcmd.GetCmdQueryVotes("gov", cdc),
govcmd.GetCmdQueryProposals("gov", cdc),
)...)
govCmd.AddCommand(
client.PostCommands(
Expand Down
122 changes: 115 additions & 7 deletions x/gov/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ import (
)

const (
flagProposalID = "proposal-id"
flagTitle = "title"
flagDescription = "description"
flagProposalType = "type"
flagDeposit = "deposit"
flagVoter = "voter"
flagOption = "option"
flagProposalID = "proposal-id"
flagTitle = "title"
flagDescription = "description"
flagProposalType = "type"
flagDeposit = "deposit"
flagVoter = "voter"
flagOption = "option"
flagDepositer = "depositer"
flagStatus = "status"
flagLatestProposalIDs = "latest"
)

// submit a proposal tx
Expand Down Expand Up @@ -203,6 +206,111 @@ func GetCmdQueryProposal(storeName string, cdc *wire.Codec) *cobra.Command {
return cmd
}

// nolint: gocyclo
// Command to Query Proposals
func GetCmdQueryProposals(storeName string, cdc *wire.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "query-proposals",
Short: "query proposals with optional filters",
RunE: func(cmd *cobra.Command, args []string) error {
bechDepositerAddr := viper.GetString(flagDepositer)
bechVoterAddr := viper.GetString(flagVoter)
strProposalStatus := viper.GetString(flagStatus)
latestProposalsIDs := viper.GetInt64(flagLatestProposalIDs)

var err error
var voterAddr sdk.AccAddress
var depositerAddr sdk.AccAddress
var proposalStatus gov.ProposalStatus

if len(bechDepositerAddr) != 0 {
depositerAddr, err = sdk.AccAddressFromBech32(bechDepositerAddr)
if err != nil {
return err
}
}

if len(bechVoterAddr) != 0 {
voterAddr, err = sdk.AccAddressFromBech32(bechVoterAddr)
if err != nil {
return err
}
}

if len(strProposalStatus) != 0 {
proposalStatus, err = gov.ProposalStatusFromString(strProposalStatus)
if err != nil {
return err
}
}

ctx := context.NewCoreContextFromViper()

res, err := ctx.QueryStore(gov.KeyNextProposalID, storeName)
if err != nil {
return err
}
var maxProposalID int64
cdc.MustUnmarshalBinary(res, &maxProposalID)

matchingProposals := []gov.Proposal{}

if latestProposalsIDs == 0 {
latestProposalsIDs = maxProposalID
}

for proposalID := maxProposalID - latestProposalsIDs; proposalID < maxProposalID; proposalID++ {
if voterAddr != nil {
res, err = ctx.QueryStore(gov.KeyVote(proposalID, voterAddr), storeName)
if err != nil || len(res) == 0 {
continue
}
}

if depositerAddr != nil {
res, err = ctx.QueryStore(gov.KeyDeposit(proposalID, depositerAddr), storeName)
if err != nil || len(res) == 0 {
continue
}
}

res, err = ctx.QueryStore(gov.KeyProposal(proposalID), storeName)
if err != nil || len(res) == 0 {
continue
}

var proposal gov.Proposal
cdc.MustUnmarshalBinary(res, &proposal)

if len(strProposalStatus) != 0 {
if proposal.GetStatus() != proposalStatus {
continue
}
}

matchingProposals = append(matchingProposals, proposal)
}

if len(matchingProposals) == 0 {
fmt.Println("No matching proposals found")
return nil
}

for _, proposal := range matchingProposals {
fmt.Printf(" %d - %s\n", proposal.GetProposalID(), proposal.GetTitle())
}
return nil
},
}

cmd.Flags().String(flagLatestProposalIDs, "", "(optional) limit to latest [number] proposals. Defaults to all proposals")
cmd.Flags().String(flagDepositer, "", "(optional) filter by proposals deposited on by depositer")
cmd.Flags().String(flagVoter, "", "(optional) filter by proposals voted on by voted")
cmd.Flags().String(flagStatus, "", "(optional) filter proposals by proposal status")

return cmd
}

// Command to Get a Proposal Information
func GetCmdQueryVote(storeName string, cdc *wire.Codec) *cobra.Command {
cmd := &cobra.Command{
Expand Down