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

Add gov prop handler for updating current minter #729

Merged
merged 2 commits into from
Apr 27, 2023
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
3 changes: 3 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ import (
ibchost "github.com/cosmos/ibc-go/v3/modules/core/24-host"
ibckeeper "github.com/cosmos/ibc-go/v3/modules/core/keeper"
"github.com/sei-protocol/sei-chain/x/mint"
mintclient "github.com/sei-protocol/sei-chain/x/mint/client/cli"
mintkeeper "github.com/sei-protocol/sei-chain/x/mint/keeper"
minttypes "github.com/sei-protocol/sei-chain/x/mint/types"
"github.com/spf13/cast"
Expand Down Expand Up @@ -158,6 +159,7 @@ func getGovProposalHandlers() []govclient.ProposalHandler {
ibcclientclient.UpdateClientProposalHandler,
ibcclientclient.UpgradeProposalHandler,
aclclient.ResourceDependencyProposalHandler,
mintclient.UpdateMinterHandler,
// this line is used by starport scaffolding # stargate/app/govProposalHandler
)

Expand Down Expand Up @@ -601,6 +603,7 @@ func New(
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)).
AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)).
AddRoute(dexmoduletypes.RouterKey, dexmodule.NewProposalHandler(app.DexKeeper)).
AddRoute(minttypes.RouterKey, mint.NewProposalHandler(app.MintKeeper)).
AddRoute(tokenfactorytypes.RouterKey, tokenfactorymodule.NewProposalHandler(app.TokenFactoryKeeper)).
AddRoute(acltypes.ModuleName, aclmodule.NewProposalHandler(app.AccessControlKeeper))
if len(enabledProposals) != 0 {
Expand Down
19 changes: 19 additions & 0 deletions proto/mint/v1beta1/gov.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
syntax = "proto3";
package seiprotocol.seichain.mint;

import "gogoproto/gogo.proto";
import "mint/v1beta1/mint.proto";

option go_package = "github.com/sei-protocol/sei-chain/x/mint/types";

// AddAssetMetadataProposal is a gov Content type for adding a new asset
// to the dex module's asset list.
message UpdateMinterProposal {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_stringer) = false;

string title = 1 [ (gogoproto.moretags) = "yaml:\"title\"" ];
string description = 2 [ (gogoproto.moretags) = "yaml:\"description\"" ];
mint.Minter minter = 3 [ (gogoproto.moretags) = "yaml:\"minter\"" ];
}
97 changes: 97 additions & 0 deletions x/mint/client/cli/tx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package cli

import (
"fmt"
"os"

sdk "github.com/cosmos/cosmos-sdk/types"
govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/spf13/cobra"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
mintrest "github.com/sei-protocol/sei-chain/x/mint/client/rest"
"github.com/sei-protocol/sei-chain/x/mint/types"
)

var UpdateMinterHandler = govclient.NewProposalHandler(MsgUpdateMinterProposalCmd, mintrest.UpdateResourceDependencyProposalRESTHandler)

func GetTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: types.ModuleName,
Short: fmt.Sprintf("%s transactions subcommands", types.ModuleName),
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}

updateMinterProposalCmd := MsgUpdateMinterProposalCmd()
flags.AddTxFlagsToCmd(updateMinterProposalCmd)

cmd.AddCommand(updateMinterProposalCmd)
return cmd
}

func MsgUpdateMinterProposalCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "update-minter [proposal-file]",
Args: cobra.ExactArgs(1),
Short: "Submit an UpdateMinter proposal",
Long: "Submit a proposal to update the current minter. \n" +
"E.g. $ seid tx gov submit-proposal update-minter [proposal-file]\n" +
"The proposal file should contain the following:\n" +
"{\n" +
"\t title: [title],\n" +
"\t description: [description],\n" +
"\t minter: [new minter object] \n" +
"}",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

proposal := types.UpdateMinterProposal{}

contents, err := os.ReadFile(args[0])
if err != nil {
return err
}

clientCtx.Codec.MustUnmarshalJSON(contents, &proposal)

from := clientCtx.GetFromAddress()

content := types.UpdateMinterProposal{
Title: proposal.Title,
Description: proposal.Description,
Minter: proposal.Minter,
}

depositInput, err := cmd.Flags().GetString(govcli.FlagDeposit)
if err != nil {
return err
}

deposit, err := sdk.ParseCoinsNormalized(depositInput)
if err != nil {
return err
}

msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, from)
if err != nil {

return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

cmd.Flags().String(govcli.FlagDeposit, "", "The proposal deposit")

return cmd
}
61 changes: 59 additions & 2 deletions x/mint/client/rest/rest.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,71 @@
package rest

import (
"net/http"

sdk "github.com/cosmos/cosmos-sdk/types"
govrest "github.com/cosmos/cosmos-sdk/x/gov/client/rest"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/gorilla/mux"
"github.com/sei-protocol/sei-chain/x/mint/types"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/rest"
clientrest "github.com/cosmos/cosmos-sdk/client/rest"
"github.com/cosmos/cosmos-sdk/client/tx"
typesrest "github.com/cosmos/cosmos-sdk/types/rest"
)

// RegisterRoutes registers minting module REST handlers on the provided router.
func RegisterRoutes(clientCtx client.Context, rtr *mux.Router) {
r := rest.WithHTTPDeprecationHeaders(rtr)
r := clientrest.WithHTTPDeprecationHeaders(rtr)
registerQueryRoutes(clientCtx, r)
}

// PlanRequest defines a proposal for a new upgrade plan.
type UpdateMinterRequest struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this documented any where else for how to make a proposal?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add it as apart of the x/mint module readme

BaseReq typesrest.BaseReq `json:"base_req" yaml:"base_req"`
Title string `json:"title" yaml:"title"`
Description string `json:"description" yaml:"description"`
Deposit sdk.Coins `json:"deposit" yaml:"deposit"`
Minter types.Minter `json:"minter" yaml:"minter"`
}

func UpdateResourceDependencyProposalRESTHandler(clientCtx client.Context) govrest.ProposalRESTHandler {
return govrest.ProposalRESTHandler{
SubRoute: "update_minter",
Handler: newUpdateMinterPostHandler(clientCtx),
}
}

func newUpdateMinterPostHandler(clientCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req UpdateMinterRequest

if !typesrest.ReadRESTReq(w, r, clientCtx.LegacyAmino, &req) {
return
}

req.BaseReq = req.BaseReq.Sanitize()
if !req.BaseReq.ValidateBasic(w) {
return
}

fromAddr, err := sdk.AccAddressFromBech32(req.BaseReq.From)
if typesrest.CheckBadRequestError(w, err) {
return
}

content := types.NewUpdateMinterProposalHandler(
req.Title, req.Description, req.Minter,
)
msg, err := govtypes.NewMsgSubmitProposal(content, req.Deposit, fromAddr)
if typesrest.CheckBadRequestError(w, err) {
return
}
if typesrest.CheckBadRequestError(w, msg.ValidateBasic()) {
return
}

tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg)
}
}
16 changes: 16 additions & 0 deletions x/mint/gov.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package mint

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/sei-protocol/sei-chain/x/mint/keeper"
"github.com/sei-protocol/sei-chain/x/mint/types"
)

func HandleUpdateMinterProposal(ctx sdk.Context, k *keeper.Keeper, p *types.UpdateMinterProposal) error {
err := types.ValidateMinter(*p.Minter)
if err != nil {
return err
}
k.SetMinter(ctx, *p.Minter)
return nil
}
22 changes: 20 additions & 2 deletions x/mint/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import (
"fmt"
"math/rand"

sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/gorilla/mux"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -43,10 +46,14 @@ func (AppModuleBasic) Name() string {
}

// RegisterLegacyAminoCodec registers the mint module's types on the given LegacyAmino codec.
func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {}
func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
types.RegisterCodec(cdc)
}

// RegisterInterfaces registers the module's interface types
func (b AppModuleBasic) RegisterInterfaces(_ cdctypes.InterfaceRegistry) {}
func (b AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
types.RegisterInterfaces(registry)
}

// DefaultGenesis returns default genesis state as raw bytes for the mint
// module.
Expand Down Expand Up @@ -186,3 +193,14 @@ func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
func (AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation {
return nil
}

func NewProposalHandler(k keeper.Keeper) govtypes.Handler {
return func(ctx sdk.Context, content govtypes.Content) error {
switch c := content.(type) {
case *types.UpdateMinterProposal:
return HandleUpdateMinterProposal(ctx, &k, c)
default:
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized mint proposal content type: %T", c)
}
}
}
44 changes: 44 additions & 0 deletions x/mint/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
abcitypes "github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"

"github.com/cosmos/cosmos-sdk/simapp"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/sei-protocol/sei-chain/app"
"github.com/sei-protocol/sei-chain/x/mint"
"github.com/sei-protocol/sei-chain/x/mint/types"
)

Expand All @@ -27,3 +30,44 @@ func TestItCreatesModuleAccountOnInitBlock(t *testing.T) {
acc := app.AccountKeeper.GetAccount(ctx, authtypes.NewModuleAddress(types.ModuleName))
require.NotNil(t, acc)
}

func TestNewProposalHandler(t *testing.T) {
app := app.Setup(false)

ctx := app.BaseApp.NewContext(false, tmproto.Header{})
app.MintKeeper.SetParams(ctx, types.DefaultParams())
app.MintKeeper.SetMinter(ctx, types.DefaultInitialMinter())

handler := mint.NewProposalHandler(app.MintKeeper)

newMinter := types.NewMinter(
"2023-10-05",
"2023-11-22",
"test",
12345,
)
updateMinterProposal := &types.UpdateMinterProposal{
Title: "Test Title",
Description: "Test Description",
Minter: &newMinter,
}
err := handler(ctx, updateMinterProposal)
require.NoError(t, err)
updatedMinter := app.MintKeeper.GetMinter(ctx)
require.Equal(t, newMinter, updatedMinter)

invalidMinter := types.NewMinter(
"2023-11-22",
"2023-10-05",
"test",
12345,
)
invalidProposal := &types.UpdateMinterProposal{
Title: "Invalid Minter",
Description: "Invalid Minter",
Minter: &invalidMinter,
}
err = handler(ctx, invalidProposal)
require.Error(t, err)
assert.Contains(t, err.Error(), "end date must be after start")
}
14 changes: 14 additions & 0 deletions x/mint/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package types

import (
"github.com/cosmos/cosmos-sdk/codec"
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
)

var amino = codec.NewLegacyAmino()
Expand All @@ -11,3 +13,15 @@ func init() {
cryptocodec.RegisterCrypto(amino)
amino.Seal()
}

func RegisterCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&UpdateMinterProposal{}, "mint/UpdateMinter", nil)
}

func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
registry.RegisterImplementations((*govtypes.Content)(nil),
&UpdateMinterProposal{},
)
}

var ModuleCdc = codec.NewProtoCodec(cdctypes.NewInterfaceRegistry())
Loading