query borrow balance (#732)

This commit is contained in:
Denali Marsh 2020-12-04 20:04:05 +01:00 committed by GitHub
parent 6aa97a8f75
commit 4dd174ea85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 114 additions and 0 deletions

View File

@ -41,6 +41,7 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
queryDepositsCmd(queryRoute, cdc), queryDepositsCmd(queryRoute, cdc),
queryClaimsCmd(queryRoute, cdc), queryClaimsCmd(queryRoute, cdc),
queryBorrowsCmd(queryRoute, cdc), queryBorrowsCmd(queryRoute, cdc),
queryBorrowCmd(queryRoute, cdc),
)...) )...)
return harvestQueryCmd return harvestQueryCmd
@ -325,3 +326,50 @@ func queryBorrowedCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
}, },
} }
} }
func queryBorrowCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "borrow",
Short: "query outstanding borrow balance for a user",
Long: strings.TrimSpace(`query outstanding borrow balance for a user:
Example:
$ kvcli q harvest borrow --owner kava1l0xsq2z7gqd7yly0g40y5836g0appumark77ny`,
),
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
var owner sdk.AccAddress
ownerBech := viper.GetString(flagOwner)
if len(ownerBech) != 0 {
borrowOwner, err := sdk.AccAddressFromBech32(ownerBech)
if err != nil {
return err
}
owner = borrowOwner
}
params := types.NewQueryBorrow(owner)
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetBorrow)
res, height, err := cliCtx.QueryWithData(route, bz)
if err != nil {
return err
}
cliCtx = cliCtx.WithHeight(height)
var balance sdk.Coins
if err := cdc.UnmarshalJSON(res, &balance); err != nil {
return fmt.Errorf("failed to unmarshal borrow balance: %w", err)
}
return cliCtx.PrintOutput(balance)
},
}
cmd.Flags().String(flagOwner, "", "filter for borrows by owner address")
return cmd
}

View File

@ -254,3 +254,34 @@ func (k Keeper) DecrementBorrowedCoins(ctx sdk.Context, coins sdk.Coins) error {
k.SetBorrowedCoins(ctx, updatedBorrowedCoins) k.SetBorrowedCoins(ctx, updatedBorrowedCoins)
return nil return nil
} }
// GetBorrowBalance gets the user's total borrow balance (borrow balance + pending interest)
func (k Keeper) GetBorrowBalance(ctx sdk.Context, borrower sdk.AccAddress) sdk.Coins {
borrowBalance := sdk.Coins{}
borrow, found := k.GetBorrow(ctx, borrower)
if found {
totalNewInterest := sdk.Coins{}
for _, coin := range borrow.Amount {
borrowIndexValue, foundBorrowIndexValue := k.GetBorrowIndex(ctx, coin.Denom)
if foundBorrowIndexValue {
// Locate the borrow index item by coin denom in the user's list of borrow indexes
foundAtIndex := -1
for i := range borrow.Index {
if borrow.Index[i].Denom == coin.Denom {
foundAtIndex = i
break
}
}
// Calculate interest owed by user for this asset
if foundAtIndex != -1 {
storedAmount := sdk.NewDecFromInt(borrow.Amount.AmountOf(coin.Denom))
userLastBorrowIndex := borrow.Index[foundAtIndex].Value
coinInterest := (storedAmount.Quo(userLastBorrowIndex).Mul(borrowIndexValue)).Sub(storedAmount)
totalNewInterest = totalNewInterest.Add(sdk.NewCoin(coin.Denom, coinInterest.TruncateInt()))
}
}
}
borrowBalance = borrow.Amount.Add(totalNewInterest...)
}
return borrowBalance
}

View File

@ -26,6 +26,8 @@ func NewQuerier(k Keeper) sdk.Querier {
return queryGetClaims(ctx, req, k) return queryGetClaims(ctx, req, k)
case types.QueryGetBorrows: case types.QueryGetBorrows:
return queryGetBorrows(ctx, req, k) return queryGetBorrows(ctx, req, k)
case types.QueryGetBorrow:
return queryGetBorrow(ctx, req, k)
case types.QueryGetBorrowed: case types.QueryGetBorrowed:
return queryGetBorrowed(ctx, req, k) return queryGetBorrowed(ctx, req, k)
default: default:
@ -289,3 +291,23 @@ func queryGetBorrowed(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte,
return bz, nil return bz, nil
} }
func queryGetBorrow(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryBorrowParams
err := types.ModuleCdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
var borrowBalance sdk.Coins
if len(params.Owner) > 0 {
borrowBalance = k.GetBorrowBalance(ctx, params.Owner)
}
bz, err := codec.MarshalJSONIndent(types.ModuleCdc, borrowBalance)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}

View File

@ -12,6 +12,7 @@ const (
QueryGetClaims = "claims" QueryGetClaims = "claims"
QueryGetBorrows = "borrows" QueryGetBorrows = "borrows"
QueryGetBorrowed = "borrowed" QueryGetBorrowed = "borrowed"
QueryGetBorrow = "borrow"
) )
// QueryDepositParams is the params for a filtered deposit query // QueryDepositParams is the params for a filtered deposit query
@ -97,3 +98,15 @@ func NewQueryBorrowedParams(denom string) QueryBorrowedParams {
Denom: denom, Denom: denom,
} }
} }
// QueryBorrow is the params for a current borrow balance query
type QueryBorrow struct {
Owner sdk.AccAddress `json:"owner" yaml:"owner"`
}
// NewQueryBorrow creates a new QueryBorrow
func NewQueryBorrow(owner sdk.AccAddress) QueryBorrow {
return QueryBorrow{
Owner: owner,
}
}