diff --git a/CHANGELOG.md b/CHANGELOG.md index 6543ea76..36ba7395 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +[\#596](https://github.com/Kava-Labs/kava/pull/596) Add REST client and CLI query to get module account information for the CDP module + [\#590](https://github.com/Kava-Labs/kava/pull/590) Add CLI query to return kavadist module account balance [\#584](https://github.com/Kava-Labs/kava/pulls/584) Add REST client and CLI queries for `kavadist` module diff --git a/swagger-ui/swagger.yaml b/swagger-ui/swagger.yaml index 363cf6b8..e320fb7a 100644 --- a/swagger-ui/swagger.yaml +++ b/swagger-ui/swagger.yaml @@ -599,6 +599,48 @@ description: Invalid request 500: description: Server internal error + /cdp/accounts: + get: + summary: Get the cdp module accounts + tags: + - CDP + produces: + - application/json + responses: + 200: + description: The cdp module accounts + schema: + type: object + properties: + height: + type: string + example: "100" + result: + type: array + items: + type: object + properties: + account_number: + type: number + address: + $ref: '#/definitions/Address' + coins: + type: array + items: + $ref: '#/definitions/Coin' + name: + type: string + permissions: + type: array + items: + type: string + public_key: + $ref: "#/definitions/PublicKey" + sequence: + type: number + 500: + description: Server internal error + /cdp/parameters: get: summary: Get the parameters of the cdp module diff --git a/x/cdp/client/cli/query.go b/x/cdp/client/cli/query.go index 12bb542a..4fd1c645 100644 --- a/x/cdp/client/cli/query.go +++ b/x/cdp/client/cli/query.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" + supply "github.com/cosmos/cosmos-sdk/x/supply" "github.com/kava-labs/kava/x/cdp/types" ) @@ -29,6 +30,7 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { QueryCdpsByDenomAndRatioCmd(queryRoute, cdc), QueryCdpDepositsCmd(queryRoute, cdc), QueryParamsCmd(queryRoute, cdc), + QueryGetAccounts(queryRoute, cdc), )...) return cdpQueryCmd @@ -225,3 +227,29 @@ func QueryParamsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { }, } } + +func QueryGetAccounts(queryRoute string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "accounts", + Short: "Get module accounts", + Long: "Get cdp module account addresses", + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx := context.NewCLIContext().WithCodec(cdc) + + // Query + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetAccounts), nil) + if err != nil { + return err + } + cliCtx = cliCtx.WithHeight(height) + + // Decode and print results + var out []supply.ModuleAccount + if err := cdc.UnmarshalJSON(res, &out); err != nil { + return fmt.Errorf("failed to unmarshal accounts: %w", err) + } + return cliCtx.PrintOutput(out) + }, + } +} diff --git a/x/cdp/client/rest/query.go b/x/cdp/client/rest/query.go index a92510ce..c7e49889 100644 --- a/x/cdp/client/rest/query.go +++ b/x/cdp/client/rest/query.go @@ -14,6 +14,7 @@ import ( // define routes that get registered by the main application func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) { + r.HandleFunc("/cdp/accounts", getAccountsHandlerFn(cliCtx)).Methods("GET") r.HandleFunc("/cdp/parameters", getParamsHandlerFn(cliCtx)).Methods("GET") r.HandleFunc(fmt.Sprintf("/cdp/cdps/cdp/{%s}/{%s}", types.RestOwner, types.RestCollateralDenom), queryCdpHandlerFn(cliCtx)).Methods("GET") r.HandleFunc(fmt.Sprintf("/cdp/cdps/denom/{%s}", types.RestCollateralDenom), queryCdpsHandlerFn(cliCtx)).Methods("GET") @@ -174,3 +175,21 @@ func getParamsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { rest.PostProcessResponse(w, cliCtx, res) } } + +func getAccountsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/cdp/%s", types.QueryGetAccounts), nil) + cliCtx = cliCtx.WithHeight(height) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + rest.PostProcessResponse(w, cliCtx, res) + } +} diff --git a/x/cdp/keeper/querier.go b/x/cdp/keeper/querier.go index f9f27a9f..376bf44c 100644 --- a/x/cdp/keeper/querier.go +++ b/x/cdp/keeper/querier.go @@ -6,6 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + supply "github.com/cosmos/cosmos-sdk/x/supply" "github.com/kava-labs/kava/x/cdp/types" ) @@ -24,6 +25,8 @@ func NewQuerier(keeper Keeper) sdk.Querier { return queryGetParams(ctx, req, keeper) case types.QueryGetCdpDeposits: return queryGetDeposits(ctx, req, keeper) + case types.QueryGetAccounts: + return queryGetAccounts(ctx, req, keeper) default: return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint %s", types.ModuleName, path[0]) } @@ -155,3 +158,23 @@ func queryGetParams(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]by } return bz, nil } + +// query cdp module accounts +func queryGetAccounts(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]byte, error) { + cdpAccAccount := keeper.supplyKeeper.GetModuleAccount(ctx, types.ModuleName) + liquidatorAccAccount := keeper.supplyKeeper.GetModuleAccount(ctx, types.LiquidatorMacc) + savingsRateAccAccount := keeper.supplyKeeper.GetModuleAccount(ctx, types.SavingsRateMacc) + + accounts := []supply.ModuleAccount{ + *cdpAccAccount.(*supply.ModuleAccount), + *liquidatorAccAccount.(*supply.ModuleAccount), + *savingsRateAccAccount.(*supply.ModuleAccount), + } + + // Encode results + bz, err := codec.MarshalJSONIndent(supply.ModuleCdc, accounts) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) + } + return bz, nil +} diff --git a/x/cdp/keeper/querier_test.go b/x/cdp/keeper/querier_test.go index ba224001..c242a296 100644 --- a/x/cdp/keeper/querier_test.go +++ b/x/cdp/keeper/querier_test.go @@ -11,6 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/simulation" + supply "github.com/cosmos/cosmos-sdk/x/supply" abci "github.com/tendermint/tendermint/abci/types" tmtime "github.com/tendermint/tendermint/types/time" @@ -279,6 +280,29 @@ func (suite *QuerierTestSuite) TestQueryDeposits() { } +func (suite *QuerierTestSuite) TestQueryAccounts() { + bz, err := suite.querier(suite.ctx, []string{types.QueryGetAccounts}, abci.RequestQuery{}) + suite.Require().NoError(err) + suite.Require().NotNil(bz) + + var accounts []supply.ModuleAccount + suite.Require().Nil(supply.ModuleCdc.UnmarshalJSON(bz, &accounts)) + suite.Require().Equal(3, len(accounts)) + + findByName := func(name string) bool { + for _, account := range accounts { + if account.GetName() == name { + return true + } + } + return false + } + + suite.Require().True(findByName("cdp")) + suite.Require().True(findByName("liquidator")) + suite.Require().True(findByName("savings")) +} + func TestQuerierTestSuite(t *testing.T) { suite.Run(t, new(QuerierTestSuite)) } diff --git a/x/cdp/types/querier.go b/x/cdp/types/querier.go index 77f74eaf..f1b892c0 100644 --- a/x/cdp/types/querier.go +++ b/x/cdp/types/querier.go @@ -11,6 +11,7 @@ const ( QueryGetCdps = "cdps" QueryGetCdpsByCollateralization = "ratio" QueryGetParams = "params" + QueryGetAccounts = "accounts" RestOwner = "owner" RestCollateralDenom = "collateral-denom" RestRatio = "ratio"