github.com/cosmos/cosmos-sdk@v0.50.10/x/gov/client/cli/util.go (about)

     1  package cli
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"os"
     7  
     8  	"github.com/spf13/cobra"
     9  	"github.com/spf13/pflag"
    10  
    11  	"github.com/cosmos/cosmos-sdk/client"
    12  	"github.com/cosmos/cosmos-sdk/codec"
    13  	sdk "github.com/cosmos/cosmos-sdk/types"
    14  	govutils "github.com/cosmos/cosmos-sdk/x/gov/client/utils"
    15  	govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
    16  )
    17  
    18  type legacyProposal struct {
    19  	Title       string
    20  	Description string
    21  	Type        string
    22  	Deposit     string
    23  }
    24  
    25  // validate the legacyProposal
    26  func (p legacyProposal) validate() error {
    27  	if p.Type == "" {
    28  		return fmt.Errorf("proposal type is required")
    29  	}
    30  
    31  	if p.Title == "" {
    32  		return fmt.Errorf("proposal title is required")
    33  	}
    34  
    35  	if p.Description == "" {
    36  		return fmt.Errorf("proposal description is required")
    37  	}
    38  	return nil
    39  }
    40  
    41  // parseSubmitLegacyProposal reads and parses the legacy proposal.
    42  func parseSubmitLegacyProposal(fs *pflag.FlagSet) (*legacyProposal, error) {
    43  	proposal := &legacyProposal{}
    44  	proposalFile, _ := fs.GetString(FlagProposal)
    45  
    46  	if proposalFile == "" {
    47  		proposalType, _ := fs.GetString(FlagProposalType)
    48  		proposal.Title, _ = fs.GetString(FlagTitle)
    49  		proposal.Description, _ = fs.GetString(FlagDescription)
    50  		proposal.Type = govutils.NormalizeProposalType(proposalType)
    51  		proposal.Deposit, _ = fs.GetString(FlagDeposit)
    52  		if err := proposal.validate(); err != nil {
    53  			return nil, err
    54  		}
    55  
    56  		return proposal, nil
    57  	}
    58  
    59  	for _, flag := range ProposalFlags {
    60  		if v, _ := fs.GetString(flag); v != "" {
    61  			return nil, fmt.Errorf("--%s flag provided alongside --proposal, which is a noop", flag)
    62  		}
    63  	}
    64  
    65  	contents, err := os.ReadFile(proposalFile)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	err = json.Unmarshal(contents, proposal)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	if err := proposal.validate(); err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	return proposal, nil
    80  }
    81  
    82  // proposal defines the new Msg-based proposal.
    83  type proposal struct {
    84  	// Msgs defines an array of sdk.Msgs proto-JSON-encoded as Anys.
    85  	Messages  []json.RawMessage `json:"messages,omitempty"`
    86  	Metadata  string            `json:"metadata"`
    87  	Deposit   string            `json:"deposit"`
    88  	Title     string            `json:"title"`
    89  	Summary   string            `json:"summary"`
    90  	Expedited bool              `json:"expedited"`
    91  }
    92  
    93  // parseSubmitProposal reads and parses the proposal.
    94  func parseSubmitProposal(cdc codec.Codec, path string) (proposal, []sdk.Msg, sdk.Coins, error) {
    95  	var proposal proposal
    96  
    97  	contents, err := os.ReadFile(path)
    98  	if err != nil {
    99  		return proposal, nil, nil, err
   100  	}
   101  
   102  	err = json.Unmarshal(contents, &proposal)
   103  	if err != nil {
   104  		return proposal, nil, nil, err
   105  	}
   106  
   107  	msgs := make([]sdk.Msg, len(proposal.Messages))
   108  	for i, anyJSON := range proposal.Messages {
   109  		var msg sdk.Msg
   110  		err := cdc.UnmarshalInterfaceJSON(anyJSON, &msg)
   111  		if err != nil {
   112  			return proposal, nil, nil, err
   113  		}
   114  
   115  		msgs[i] = msg
   116  	}
   117  
   118  	deposit, err := sdk.ParseCoinsNormalized(proposal.Deposit)
   119  	if err != nil {
   120  		return proposal, nil, nil, err
   121  	}
   122  
   123  	return proposal, msgs, deposit, nil
   124  }
   125  
   126  // AddGovPropFlagsToCmd adds flags for defining MsgSubmitProposal fields.
   127  //
   128  // See also ReadGovPropFlags.
   129  func AddGovPropFlagsToCmd(cmd *cobra.Command) {
   130  	cmd.Flags().String(FlagDeposit, "", "The deposit to include with the governance proposal")
   131  	cmd.Flags().String(FlagMetadata, "", "The metadata to include with the governance proposal")
   132  	cmd.Flags().String(FlagTitle, "", "The title to put on the governance proposal")
   133  	cmd.Flags().String(FlagSummary, "", "The summary to include with the governance proposal")
   134  }
   135  
   136  // ReadGovPropFlags parses a MsgSubmitProposal from the provided context and flags.
   137  // Setting the messages is up to the caller.
   138  //
   139  // See also AddGovPropFlagsToCmd.
   140  func ReadGovPropFlags(clientCtx client.Context, flagSet *pflag.FlagSet) (*govv1.MsgSubmitProposal, error) {
   141  	rv := &govv1.MsgSubmitProposal{}
   142  
   143  	deposit, err := flagSet.GetString(FlagDeposit)
   144  	if err != nil {
   145  		return nil, fmt.Errorf("could not read deposit: %w", err)
   146  	}
   147  	if len(deposit) > 0 {
   148  		rv.InitialDeposit, err = sdk.ParseCoinsNormalized(deposit)
   149  		if err != nil {
   150  			return nil, fmt.Errorf("invalid deposit: %w", err)
   151  		}
   152  	}
   153  
   154  	rv.Metadata, err = flagSet.GetString(FlagMetadata)
   155  	if err != nil {
   156  		return nil, fmt.Errorf("could not read metadata: %w", err)
   157  	}
   158  
   159  	rv.Title, err = flagSet.GetString(FlagTitle)
   160  	if err != nil {
   161  		return nil, fmt.Errorf("could not read title: %w", err)
   162  	}
   163  
   164  	rv.Summary, err = flagSet.GetString(FlagSummary)
   165  	if err != nil {
   166  		return nil, fmt.Errorf("could not read summary: %w", err)
   167  	}
   168  
   169  	rv.Proposer = clientCtx.GetFromAddress().String()
   170  
   171  	return rv, nil
   172  }