diff --git a/CHANGELOG.md b/CHANGELOG.md index bd12f24b..5162c331 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +[\#584](https://github.com/Kava-Labs/kava/pulls/584) Add REST client and CLI queries for `kavadist` module + [\#578](https://github.com/Kava-Labs/kava/pulls/578) Add v0.3 compatible REST client that supports ``` /v0_3/node_info diff --git a/swagger-ui/swagger.yaml b/swagger-ui/swagger.yaml index 458c5993..363cf6b8 100644 --- a/swagger-ui/swagger.yaml +++ b/swagger-ui/swagger.yaml @@ -37,9 +37,13 @@ description: Supply module APIs - name: Mint description: Minting module APIs + - name: Kavadist + description: Kavadist module APIs + - name: Misc + description: Query app version schemes: - https - host: data.kava3.kava.io + host: kava3.data.kava.io securityDefinitions: kms: type: basic @@ -872,6 +876,7 @@ - application/json parameters: - in: path + required: true name: swap-id description: the swap ID type: string @@ -896,7 +901,6 @@ - BEP3 produces: - application/json - parameters: responses: 200: description: All atomic swaps @@ -922,6 +926,8 @@ - application/json parameters: - in: path + type: string + required: true name: denom x-example: bnb responses: @@ -3233,6 +3239,28 @@ description: Invalid coin denomination 500: description: Internal Server Error + /kavadist/parameters: + get: + summary: Get the current kavadist parameter values + tags: + - Kavadist + produces: + - application/json + responses: + 200: + description: OK + schema: + type: object + properties: + active: + type: string + periods: + type: array + items: + $ref: "#/definitions/KavadistPeriod" + 500: + description: Internal Server Error + definitions: CheckTxResult: type: object @@ -4311,6 +4339,18 @@ type: string result: type: string + KavadistPeriod: + type: object + properties: + start: + type: string + example: "2020-06-01:14:00:00Z" + end: + type: string + example: "2020-06-01:14:00:00Z" + inflation: + type: string + example: "1.000000001167363430" PostStdTx: type: object properties: diff --git a/x/incentive/module.go b/x/incentive/module.go index 394e3a88..921cf0ee 100644 --- a/x/incentive/module.go +++ b/x/incentive/module.go @@ -68,22 +68,22 @@ func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command { return cli.GetTxCmd(cdc) } -// GetQueryCmd returns no root query command for the crisis module. +// GetQueryCmd returns no root query command for the incentive module. func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command { return cli.GetQueryCmd(types.StoreKey, cdc) } -// RegisterStoreDecoder registers a decoder for cdp module's types +// RegisterStoreDecoder registers a decoder for incentive module's types func (AppModuleBasic) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { sdr[StoreKey] = simulation.DecodeStore } -// GenerateGenesisState creates a randomized GenState of the cdp module +// GenerateGenesisState creates a randomized GenState of the incentive module func (AppModuleBasic) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) } -// RandomizedParams creates randomized cdp param changes for the simulator. +// RandomizedParams creates randomized incentive param changes for the simulator. func (AppModuleBasic) RandomizedParams(r *rand.Rand) []sim.ParamChange { return simulation.ParamChanges(r) } diff --git a/x/kavadist/client/cli/query.go b/x/kavadist/client/cli/query.go new file mode 100644 index 00000000..1de62a37 --- /dev/null +++ b/x/kavadist/client/cli/query.go @@ -0,0 +1,55 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/kava-labs/kava/x/kavadist/types" +) + +// GetQueryCmd returns the cli query commands for the kavadist module +func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { + kavadistQueryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the kavadist module", + } + + kavadistQueryCmd.AddCommand(flags.GetCommands( + queryParamsCmd(queryRoute, cdc), + )...) + + return kavadistQueryCmd + +} + +func queryParamsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "params", + Short: "get the kavadist module parameters", + Long: "Get the current global kavadist module parameters.", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx := context.NewCLIContext().WithCodec(cdc) + + // Query + route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetParams) + res, height, err := cliCtx.QueryWithData(route, nil) + if err != nil { + return err + } + cliCtx = cliCtx.WithHeight(height) + + // Decode and print results + var params types.Params + if err := cdc.UnmarshalJSON(res, ¶ms); err != nil { + return fmt.Errorf("failed to unmarshal params: %w", err) + } + return cliCtx.PrintOutput(params) + }, + } +} diff --git a/x/kavadist/client/rest/query.go b/x/kavadist/client/rest/query.go new file mode 100644 index 00000000..b99f448b --- /dev/null +++ b/x/kavadist/client/rest/query.go @@ -0,0 +1,37 @@ +package rest + +import ( + "fmt" + "net/http" + + "github.com/gorilla/mux" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/types/rest" + + "github.com/kava-labs/kava/x/kavadist/types" +) + +func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) { + r.HandleFunc(fmt.Sprintf("/%s/parameters", types.ModuleName), queryParamsHandlerFn(cliCtx)).Methods("GET") +} + +func queryParamsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + route := fmt.Sprintf("custom/%s/parameters", types.QuerierRoute) + + res, height, err := cliCtx.QueryWithData(route, nil) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +} diff --git a/x/kavadist/client/rest/rest.go b/x/kavadist/client/rest/rest.go new file mode 100644 index 00000000..2e9db311 --- /dev/null +++ b/x/kavadist/client/rest/rest.go @@ -0,0 +1,12 @@ +package rest + +import ( + "github.com/gorilla/mux" + + "github.com/cosmos/cosmos-sdk/client/context" +) + +// RegisterRoutes registers kavadist-related REST handlers to a router +func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { + registerQueryRoutes(cliCtx, r) +} diff --git a/x/kavadist/keeper/mint_test.go b/x/kavadist/keeper/mint_test.go index 48539c61..9266ae9e 100644 --- a/x/kavadist/keeper/mint_test.go +++ b/x/kavadist/keeper/mint_test.go @@ -16,7 +16,7 @@ import ( "github.com/kava-labs/kava/x/kavadist/types" ) -type MintTestSuite struct { +type KeeperTestSuite struct { suite.Suite keeper keeper.Keeper @@ -26,7 +26,7 @@ type MintTestSuite struct { } var ( - p = types.Periods{ + testPeriods = types.Periods{ types.Period{ Start: time.Date(2020, time.March, 1, 1, 0, 0, 0, time.UTC), End: time.Date(2021, time.March, 1, 1, 0, 0, 0, time.UTC), @@ -35,7 +35,7 @@ var ( } ) -func (suite *MintTestSuite) SetupTest() { +func (suite *KeeperTestSuite) SetupTest() { config := sdk.GetConfig() app.SetBech32AddressPrefixes(config) tApp := app.NewTestApp() @@ -46,7 +46,7 @@ func (suite *MintTestSuite) SetupTest() { ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()}) - params := types.NewParams(true, p) + params := types.NewParams(true, testPeriods) gs := app.GenesisState{types.ModuleName: types.ModuleCdc.MustMarshalJSON(types.NewGenesisState(params, types.DefaultPreviousBlockTime))} tApp.InitializeFromGenesisStates( authGS, @@ -61,7 +61,7 @@ func (suite *MintTestSuite) SetupTest() { } -func (suite *MintTestSuite) TestMintExpiredPeriod() { +func (suite *KeeperTestSuite) TestMintExpiredPeriod() { initialSupply := suite.supplyKeeper.GetSupply(suite.ctx).GetTotal().AmountOf(types.GovDenom) suite.NotPanics(func() { suite.keeper.SetPreviousBlockTime(suite.ctx, time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC)) }) ctx := suite.ctx.WithBlockTime(time.Date(2022, 1, 1, 0, 7, 0, 0, time.UTC)) @@ -71,7 +71,7 @@ func (suite *MintTestSuite) TestMintExpiredPeriod() { suite.Equal(initialSupply, finalSupply) } -func (suite *MintTestSuite) TestMintPeriodNotStarted() { +func (suite *KeeperTestSuite) TestMintPeriodNotStarted() { initialSupply := suite.supplyKeeper.GetSupply(suite.ctx).GetTotal().AmountOf(types.GovDenom) suite.NotPanics(func() { suite.keeper.SetPreviousBlockTime(suite.ctx, time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)) }) ctx := suite.ctx.WithBlockTime(time.Date(2019, 1, 1, 0, 7, 0, 0, time.UTC)) @@ -81,7 +81,7 @@ func (suite *MintTestSuite) TestMintPeriodNotStarted() { suite.Equal(initialSupply, finalSupply) } -func (suite *MintTestSuite) TestMintOngoingPeriod() { +func (suite *KeeperTestSuite) TestMintOngoingPeriod() { initialSupply := suite.supplyKeeper.GetSupply(suite.ctx).GetTotal().AmountOf(types.GovDenom) suite.NotPanics(func() { suite.keeper.SetPreviousBlockTime(suite.ctx, time.Date(2020, time.March, 1, 1, 0, 1, 0, time.UTC)) @@ -100,11 +100,11 @@ func (suite *MintTestSuite) TestMintOngoingPeriod() { suite.True(supplyError.LTE(sdk.MustNewDecFromStr("0.001"))) } -func (suite *MintTestSuite) TestMintPeriodTransition() { +func (suite *KeeperTestSuite) TestMintPeriodTransition() { initialSupply := suite.supplyKeeper.GetSupply(suite.ctx).GetTotal().AmountOf(types.GovDenom) params := suite.keeper.GetParams(suite.ctx) periods := types.Periods{ - p[0], + testPeriods[0], types.Period{ Start: time.Date(2021, time.March, 1, 1, 0, 0, 0, time.UTC), End: time.Date(2022, time.March, 1, 1, 0, 0, 0, time.UTC), @@ -125,7 +125,7 @@ func (suite *MintTestSuite) TestMintPeriodTransition() { suite.True(finalSupply.GT(initialSupply)) } -func (suite *MintTestSuite) TestMintNotActive() { +func (suite *KeeperTestSuite) TestMintNotActive() { initialSupply := suite.supplyKeeper.GetSupply(suite.ctx).GetTotal().AmountOf(types.GovDenom) params := suite.keeper.GetParams(suite.ctx) params.Active = false @@ -142,6 +142,6 @@ func (suite *MintTestSuite) TestMintNotActive() { suite.Equal(initialSupply, finalSupply) } -func TestMintTestSuite(t *testing.T) { - suite.Run(t, new(MintTestSuite)) +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) } diff --git a/x/kavadist/keeper/querier.go b/x/kavadist/keeper/querier.go new file mode 100644 index 00000000..77e87e48 --- /dev/null +++ b/x/kavadist/keeper/querier.go @@ -0,0 +1,36 @@ +package keeper + +import ( + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/kava-labs/kava/x/kavadist/types" +) + +// NewQuerier is the module level router for state queries +func NewQuerier(k Keeper) sdk.Querier { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err error) { + switch path[0] { + case types.QueryGetParams: + return queryGetParams(ctx, req, k) + default: + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint", types.ModuleName) + } + } +} + +// query params in the store +func queryGetParams(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { + // Get params + params := k.GetParams(ctx) + + // Encode results + bz, err := codec.MarshalJSONIndent(k.cdc, params) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) + } + return bz, nil +} diff --git a/x/kavadist/keeper/querier_test.go b/x/kavadist/keeper/querier_test.go new file mode 100644 index 00000000..e8997e45 --- /dev/null +++ b/x/kavadist/keeper/querier_test.go @@ -0,0 +1,20 @@ +package keeper_test + +import ( + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/kava-labs/kava/x/kavadist/keeper" + "github.com/kava-labs/kava/x/kavadist/types" +) + +func (suite *KeeperTestSuite) TestQuerier() { + querier := keeper.NewQuerier(suite.keeper) + bz, err := querier(suite.ctx, []string{types.QueryGetParams}, abci.RequestQuery{}) + suite.Require().NoError(err) + suite.NotNil(bz) + + testParams := types.NewParams(true, testPeriods) + var p types.Params + suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &p)) + suite.Require().Equal(testParams, p) +} diff --git a/x/kavadist/module.go b/x/kavadist/module.go index e91dae17..7a02058c 100644 --- a/x/kavadist/module.go +++ b/x/kavadist/module.go @@ -15,6 +15,9 @@ import ( abci "github.com/tendermint/tendermint/abci/types" + "github.com/kava-labs/kava/x/kavadist/client/cli" + "github.com/kava-labs/kava/x/kavadist/client/rest" + "github.com/kava-labs/kava/x/kavadist/keeper" "github.com/kava-labs/kava/x/kavadist/simulation" "github.com/kava-labs/kava/x/kavadist/types" ) @@ -53,14 +56,18 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { return gs.Validate() } -// RegisterRESTRoutes registers no REST routes for the crisis module. -func (AppModuleBasic) RegisterRESTRoutes(_ context.CLIContext, _ *mux.Router) {} +// RegisterRESTRoutes registers REST routes for the kavadist module. +func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) { + rest.RegisterRoutes(ctx, rtr) +} // GetTxCmd returns the root tx command for the crisis module. func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command { return nil } -// GetQueryCmd returns no root query command for the crisis module. -func (AppModuleBasic) GetQueryCmd(_ *codec.Codec) *cobra.Command { return nil } +// GetQueryCmd returns no root query command for the kavadist module. +func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command { + return cli.GetQueryCmd(types.StoreKey, cdc) +} //____________________________________________________________________________ @@ -105,7 +112,9 @@ func (AppModule) QuerierRoute() string { } // NewQuerierHandler returns no sdk.Querier. -func (AppModule) NewQuerierHandler() sdk.Querier { return nil } +func (am AppModule) NewQuerierHandler() sdk.Querier { + return keeper.NewQuerier(am.keeper) +} // InitGenesis module init-genesis func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {