Query Hard module reserves (#843)

* implement CLI reserves query

* implement REST reserves query
This commit is contained in:
Denali Marsh 2021-02-22 21:48:52 +01:00 committed by GitHub
parent fe43c2bc41
commit 1499a89ce5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 123 additions and 0 deletions

View File

@ -42,6 +42,7 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
queryBorrowsCmd(queryRoute, cdc),
queryTotalBorrowedCmd(queryRoute, cdc),
queryInterestRateCmd(queryRoute, cdc),
queryReserves(queryRoute, cdc),
)...)
return hardQueryCmd
@ -360,3 +361,46 @@ func queryInterestRateCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd.Flags().String(flagDenom, "", "(optional) filter interest rates by denom")
return cmd
}
func queryReserves(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "reserves",
Short: "get total current Hard module reserves",
Long: strings.TrimSpace(`get the total amount of coins currently held as reserve by the Hard module:
Example:
$ kvcli q hard reserves
$ kvcli q hard reserves --denom bnb`,
),
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
denom := viper.GetString(flagDenom)
// Construct query with params
params := types.NewQueryReservesParams(denom)
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
// Execute query
route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetReserves)
res, height, err := cliCtx.QueryWithData(route, bz)
if err != nil {
return err
}
cliCtx = cliCtx.WithHeight(height)
// Decode and print results
var reserves sdk.Coins
if err := cdc.UnmarshalJSON(res, &reserves); err != nil {
return fmt.Errorf("failed to unmarshal reserve coins: %w", err)
}
return cliCtx.PrintOutput(reserves)
},
}
cmd.Flags().String(flagDenom, "", "(optional) filter reserve coins by denom")
return cmd
}

View File

@ -22,6 +22,7 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) {
r.HandleFunc(fmt.Sprintf("/%s/borrows", types.ModuleName), queryBorrowsHandlerFn(cliCtx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/%s/total-borrowed", types.ModuleName), queryTotalBorrowedHandlerFn(cliCtx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/%s/interest-rate", types.ModuleName), queryInterestRateHandlerFn(cliCtx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/%s/reserves", types.ModuleName), queryReservesHandlerFn(cliCtx)).Methods("GET")
}
func queryParamsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
@ -291,3 +292,41 @@ func queryModAccountsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
rest.PostProcessResponse(w, cliCtx, res)
}
}
func queryReservesHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
_, _, _, err := rest.ParseHTTPArgsWithLimit(r, 0)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
// Parse the query height
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
var denom string
if x := r.URL.Query().Get(RestDenom); len(x) != 0 {
denom = strings.TrimSpace(x)
}
params := types.NewQueryReservesParams(denom)
bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
route := fmt.Sprintf("custom/%s/%s", types.ModuleName, types.QueryGetReserves)
res, height, err := cliCtx.QueryWithData(route, bz)
cliCtx = cliCtx.WithHeight(height)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
rest.PostProcessResponse(w, cliCtx, res)
}
}

View File

@ -30,6 +30,8 @@ func NewQuerier(k Keeper) sdk.Querier {
return queryGetTotalBorrowed(ctx, req, k)
case types.QueryGetInterestRate:
return queryGetInterestRate(ctx, req, k)
case types.QueryGetReserves:
return queryGetReserves(ctx, req, k)
default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint", types.ModuleName)
}
@ -328,3 +330,28 @@ func queryGetInterestRate(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]b
return bz, nil
}
func queryGetReserves(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryReservesParams
err := types.ModuleCdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
reserveCoins, found := k.GetTotalReserves(ctx)
if !found {
reserveCoins = sdk.Coins{}
}
// If user specified a denom only return coins of that denom type
if len(params.Denom) > 0 {
reserveCoins = sdk.NewCoins(sdk.NewCoin(params.Denom, reserveCoins.AmountOf(params.Denom)))
}
bz, err := codec.MarshalJSONIndent(types.ModuleCdc, reserveCoins)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}

View File

@ -13,6 +13,7 @@ const (
QueryGetBorrows = "borrows"
QueryGetTotalBorrowed = "total-borrowed"
QueryGetInterestRate = "interest-rate"
QueryGetReserves = "reserves"
)
// QueryDepositsParams is the params for a filtered deposit query
@ -121,3 +122,15 @@ func NewMoneyMarketInterestRate(denom string, supplyInterestRate, borrowInterest
// MoneyMarketInterestRates is a slice of MoneyMarketInterestRate
type MoneyMarketInterestRates []MoneyMarketInterestRate
// QueryReservesParams is the params for a filtered reserves query
type QueryReservesParams struct {
Denom string `json:"denom" yaml:"denom"`
}
// NewQueryReservesParams creates a new QueryReservesParams
func NewQueryReservesParams(denom string) QueryReservesParams {
return QueryReservesParams{
Denom: denom,
}
}