Merge branch 'develop' into cli-updates

This commit is contained in:
Christopher Goes 2018-08-22 12:40:23 +02:00
commit 42c03aeeec
5 changed files with 172 additions and 15 deletions

View File

@ -5,13 +5,14 @@ v If a checkbox is n/a - please still include it but + a little note why
☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -->
- [ ] Linked to github-issue with discussion and accepted design OR link to spec that describes this work.
- [ ] Updated all relevant documentation (`docs/`)
- [ ] Updated all relevant code comments
- [ ] Wrote tests
- [ ] Added entries in `PENDING.md` that include links to the relevant issue or PR that most accurately describes the change.
- [ ] Updated `cmd/gaia` and `examples/`
___________________________________
- [ ] Updated relevant documentation (`docs/`)
- [ ] Added entries in `PENDING.md` with issue #
- [ ] rereviewed `Files changed` in the github PR explorer
______
For Admin Use:
- [ ] Added appropriate labels to PR (ex. wip, ready-for-review, docs)
- [ ] Reviewers Assigned
- [ ] Squashed all commits, uses message "Merge pull request #XYZ: [title]" ([coding standards](https://github.com/tendermint/coding/blob/master/README.md#merging-a-pr))
- Added appropriate labels to PR (ex. wip, ready-for-review, docs)
- Reviewers Assigned
- Squashed all commits, uses message "Merge pull request #XYZ: [title]" ([coding standards](https://github.com/tendermint/coding/blob/master/README.md#merging-a-pr))

View File

@ -32,6 +32,7 @@ FEATURES
* Gaia CLI (`gaiacli`)
* [cli] Cmds to query staking pool and params
* [gov][cli] #2062 added `--proposal` flag to `submit-proposal` that allows a JSON file containing a proposal to be passed in
* Gaia

View File

@ -6,6 +6,23 @@ Uuse the CLI to create a new proposal:
simplegovcli propose --title="Voting Period update" --description="Should we change the proposal voting period to 3 weeks?" --deposit=300Atoms
```
Or, via a json file:
```bash
simplegovcli propose --proposal="path/to/proposal.json"
```
Where proposal.json contains:
```json
{
"title": "Voting Period Update",
"description": "Should we change the proposal voting period to 3 weeks?",
"type": "Text",
"deposit": "300Atoms"
}
```
Get the details of your newly created proposal:
```bash

View File

@ -15,6 +15,9 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"io/ioutil"
"encoding/json"
"strings"
)
const (
@ -28,18 +31,51 @@ const (
flagDepositer = "depositer"
flagStatus = "status"
flagLatestProposalIDs = "latest"
flagProposal = "proposal"
)
type proposal struct {
Title string
Description string
Type string
Deposit string
}
var proposalFlags = []string{
flagTitle,
flagDescription,
flagProposalType,
flagDeposit,
}
// GetCmdSubmitProposal implements submitting a proposal transaction command.
func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "submit-proposal",
Short: "Submit a proposal along with an initial deposit",
Long: strings.TrimSpace(`
Submit a proposal along with an initial deposit. Proposal title, description, type and deposit can be given directly or through a proposal JSON file. For example:
$ gaiacli gov submit-proposal --proposal="path/to/proposal.json"
where proposal.json contains:
{
"title": "Test Proposal",
"description": "My awesome proposal",
"type": "Text",
"deposit": "1000test"
}
is equivalent to
$ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome proposal" --type="Text" --deposit="1000test"
`),
RunE: func(cmd *cobra.Command, args []string) error {
title := viper.GetString(flagTitle)
description := viper.GetString(flagDescription)
strProposalType := viper.GetString(flagProposalType)
initialDeposit := viper.GetString(flagDeposit)
proposal, err := parseSubmitProposalFlags()
if err != nil {
return err
}
txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
@ -52,17 +88,17 @@ func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command {
return err
}
amount, err := sdk.ParseCoins(initialDeposit)
amount, err := sdk.ParseCoins(proposal.Deposit)
if err != nil {
return err
}
proposalType, err := gov.ProposalTypeFromString(strProposalType)
proposalType, err := gov.ProposalTypeFromString(proposal.Type)
if err != nil {
return err
}
msg := gov.NewMsgSubmitProposal(title, description, proposalType, fromAddr, amount)
msg := gov.NewMsgSubmitProposal(proposal.Title, proposal.Description, proposalType, fromAddr, amount)
err = msg.ValidateBasic()
if err != nil {
@ -80,10 +116,42 @@ func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command {
cmd.Flags().String(flagDescription, "", "description of proposal")
cmd.Flags().String(flagProposalType, "", "proposalType of proposal")
cmd.Flags().String(flagDeposit, "", "deposit of proposal")
cmd.Flags().String(flagProposal, "", "proposal file path (if this path is given, other proposal flags are ignored)")
return cmd
}
func parseSubmitProposalFlags() (*proposal, error) {
proposal := &proposal{}
proposalFile := viper.GetString(flagProposal)
if proposalFile == "" {
proposal.Title = viper.GetString(flagTitle)
proposal.Description = viper.GetString(flagDescription)
proposal.Type = viper.GetString(flagProposalType)
proposal.Deposit = viper.GetString(flagDeposit)
return proposal, nil
}
for _, flag := range proposalFlags {
if viper.GetString(flag) != "" {
return nil, fmt.Errorf("--%s flag provided alongside --proposal, which is a noop", flag)
}
}
contents, err := ioutil.ReadFile(proposalFile)
if err != nil {
return nil, err
}
err = json.Unmarshal(contents, proposal)
if err != nil {
return nil, err
}
return proposal, nil
}
// GetCmdDeposit implements depositing tokens for an active proposal.
func GetCmdDeposit(cdc *wire.Codec) *cobra.Command {
cmd := &cobra.Command{

View File

@ -0,0 +1,70 @@
package cli
import (
"testing"
"github.com/spf13/viper"
"io/ioutil"
"github.com/stretchr/testify/require"
)
func TestParseSubmitProposalFlags(t *testing.T) {
okJSON, err := ioutil.TempFile("", "proposal")
require.Nil(t, err, "unexpected error")
okJSON.WriteString(`
{
"title": "Test Proposal",
"description": "My awesome proposal",
"type": "Text",
"deposit": "1000test"
}
`)
badJSON, err := ioutil.TempFile("", "proposal")
require.Nil(t, err, "unexpected error")
badJSON.WriteString("bad json")
// nonexistent json
viper.Set(flagProposal, "fileDoesNotExist")
_, err = parseSubmitProposalFlags()
require.Error(t, err)
// invalid json
viper.Set(flagProposal, badJSON.Name())
_, err = parseSubmitProposalFlags()
require.Error(t, err)
// ok json
viper.Set(flagProposal, okJSON.Name())
proposal1, err := parseSubmitProposalFlags()
require.Nil(t, err, "unexpected error")
require.Equal(t, "Test Proposal", proposal1.Title)
require.Equal(t, "My awesome proposal", proposal1.Description)
require.Equal(t, "Text", proposal1.Type)
require.Equal(t, "1000test", proposal1.Deposit)
// flags that can't be used with --proposal
for _, incompatibleFlag := range proposalFlags {
viper.Set(incompatibleFlag, "some value")
_, err := parseSubmitProposalFlags()
require.Error(t, err)
viper.Set(incompatibleFlag, "")
}
// no --proposal, only flags
viper.Set(flagProposal, "")
viper.Set(flagTitle, proposal1.Title)
viper.Set(flagDescription, proposal1.Description)
viper.Set(flagProposalType, proposal1.Type)
viper.Set(flagDeposit, proposal1.Deposit)
proposal2, err := parseSubmitProposalFlags()
require.Nil(t, err, "unexpected error")
require.Equal(t, proposal1.Title, proposal2.Title)
require.Equal(t, proposal1.Description, proposal2.Description)
require.Equal(t, proposal1.Type, proposal2.Type)
require.Equal(t, proposal1.Deposit, proposal2.Deposit)
err = okJSON.Close()
require.Nil(t, err, "unexpected error")
err = badJSON.Close()
require.Nil(t, err, "unexpected error")
}