Merge pull request #378 from Kava-Labs/develop

Add custom supply endpoints
This commit is contained in:
Kevin Davis 2020-02-25 10:56:01 -05:00 committed by GitHub
commit 7e78f37788
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 310 additions and 23 deletions

View File

@ -1,8 +1,8 @@
// nolint // nolint
// autogenerated code using github.com/rigelrozanski/multitool // autogenerated code using github.com/rigelrozanski/multitool
// aliases generated for the following subdirectories: // aliases generated for the following subdirectories:
// ALIASGEN: github.com/kava-labs/kava/x/validator-vesting/internal/types/ // ALIASGEN: github.com/kava-labs/kava/x/validator-vesting/internal/keeper
// ALIASGEN: github.com/kava-labs/kava/x/validator-vesting/internal/keeper/ // ALIASGEN: github.com/kava-labs/kava/x/validator-vesting/internal/types
package validatorvesting package validatorvesting
import ( import (
@ -11,35 +11,37 @@ import (
) )
const ( const (
ModuleName = types.ModuleName ModuleName = types.ModuleName
StoreKey = types.StoreKey StoreKey = types.StoreKey
QuerierRoute = types.QuerierRoute
QueryCirculatingSupply = types.QueryCirculatingSupply
QueryTotalSupply = types.QueryTotalSupply
) )
var ( var (
// functions aliases // functions aliases
RegisterCodec = types.RegisterCodec
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
ValidateGenesis = types.ValidateGenesis
ValidatorVestingAccountKey = types.ValidatorVestingAccountKey
CreateTestAddrs = types.CreateTestAddrs
TestAddr = types.TestAddr
CreateTestPubKeys = types.CreateTestPubKeys
NewPubKey = types.NewPubKey
NewValidatorVestingAccountRaw = types.NewValidatorVestingAccountRaw
NewValidatorVestingAccount = types.NewValidatorVestingAccount
NewKeeper = keeper.NewKeeper NewKeeper = keeper.NewKeeper
NewQuerier = keeper.NewQuerier
MakeTestCodec = keeper.MakeTestCodec MakeTestCodec = keeper.MakeTestCodec
CreateTestInput = keeper.CreateTestInput CreateTestInput = keeper.CreateTestInput
ValidatorVestingTestAccount = keeper.ValidatorVestingTestAccount ValidatorVestingTestAccount = keeper.ValidatorVestingTestAccount
ValidatorVestingTestAccounts = keeper.ValidatorVestingTestAccounts ValidatorVestingTestAccounts = keeper.ValidatorVestingTestAccounts
ValidatorVestingDelegatorTestAccount = keeper.ValidatorVestingDelegatorTestAccount ValidatorVestingDelegatorTestAccount = keeper.ValidatorVestingDelegatorTestAccount
CreateValidators = keeper.CreateValidators CreateValidators = keeper.CreateValidators
RegisterCodec = types.RegisterCodec
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
ValidateGenesis = types.ValidateGenesis
ValidatorVestingAccountKey = types.ValidatorVestingAccountKey
NewBaseQueryParams = types.NewBaseQueryParams
CreateTestAddrs = types.CreateTestAddrs
TestAddr = types.TestAddr
CreateTestPubKeys = types.CreateTestPubKeys
NewPubKey = types.NewPubKey
NewValidatorVestingAccountRaw = types.NewValidatorVestingAccountRaw
NewValidatorVestingAccount = types.NewValidatorVestingAccount
// variable aliases // variable aliases
ModuleCdc = types.ModuleCdc
BlocktimeKey = types.BlocktimeKey
ValidatorVestingAccountPrefix = types.ValidatorVestingAccountPrefix
ValOpPk1 = keeper.ValOpPk1 ValOpPk1 = keeper.ValOpPk1
ValOpPk2 = keeper.ValOpPk2 ValOpPk2 = keeper.ValOpPk2
ValOpPk3 = keeper.ValOpPk3 ValOpPk3 = keeper.ValOpPk3
@ -53,12 +55,17 @@ var (
ValConsAddr2 = keeper.ValConsAddr2 ValConsAddr2 = keeper.ValConsAddr2
ValConsAddr3 = keeper.ValConsAddr3 ValConsAddr3 = keeper.ValConsAddr3
TestAddrs = keeper.TestAddrs TestAddrs = keeper.TestAddrs
ModuleCdc = types.ModuleCdc
BlocktimeKey = types.BlocktimeKey
ValidatorVestingAccountPrefix = types.ValidatorVestingAccountPrefix
) )
type ( type (
Keeper = keeper.Keeper
GenesisState = types.GenesisState GenesisState = types.GenesisState
BaseQueryParams = types.BaseQueryParams
VestingProgress = types.VestingProgress VestingProgress = types.VestingProgress
CurrentPeriodProgress = types.CurrentPeriodProgress CurrentPeriodProgress = types.CurrentPeriodProgress
ValidatorVestingAccount = types.ValidatorVestingAccount ValidatorVestingAccount = types.ValidatorVestingAccount
Keeper = keeper.Keeper TotalCirculatingSupply = types.TotalCirculatingSupply
) )

View File

@ -0,0 +1,72 @@
package cli
import (
"fmt"
"github.com/kava-labs/kava/x/validator-vesting/internal/types"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// GetQueryCmd returns the cli query commands for this module
func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
// Group nameservice queries under a subcommand
queryValidatorVestingCmd := &cobra.Command{
Use: "validator-vesting",
Short: "Querying commands for the validator vesting module",
}
queryValidatorVestingCmd.AddCommand(client.GetCommands(
QueryCirculatingSupplyCmd(queryRoute, cdc),
QueryTotalSupplyCmd(queryRoute, cdc),
)...)
return queryValidatorVestingCmd
}
// QueryCirculatingSupplyCmd queries the total circulating supply
func QueryCirculatingSupplyCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "circulating-supply",
Short: "Query circulating supply information",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryCirculatingSupply), nil)
if err != nil {
fmt.Printf("could not get total circulating supply\n")
return err
}
var out sdk.Dec
cdc.MustUnmarshalJSON(res, &out)
return cliCtx.PrintOutput(out)
},
}
}
// QueryTotalSupplyCmd queries the total supply of ukava
func QueryTotalSupplyCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "total-supply",
Short: "Query total supply information",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryTotalSupply), nil)
if err != nil {
fmt.Printf("could not get total supply\n")
return err
}
var out sdk.Dec
cdc.MustUnmarshalJSON(res, &out)
return cliCtx.PrintOutput(out)
},
}
}

View File

@ -0,0 +1,88 @@
package rest
import (
"fmt"
"net/http"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/types/rest"
"github.com/gorilla/mux"
"github.com/kava-labs/kava/x/validator-vesting/internal/types"
)
// define routes that get registered by the main application
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) {
r.HandleFunc("/vesting/circulatingsupply", getCirculatingSupplyHandlerFn(cliCtx)).Methods("GET")
r.HandleFunc("/vesting/totalsupply", getTotalSupplyHandlerFn(cliCtx)).Methods("GET")
}
func getTotalSupplyHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
_, page, limit, err := rest.ParseHTTPArgsWithLimit(r, 0)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewBaseQueryParams(page, limit)
bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
return
}
route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryTotalSupply)
res, height, err := cliCtx.QueryWithData(route, bz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
cliCtx = cliCtx.WithHeight(height)
// directly write output instead of putting in json
w.Write(res)
// rest.PostProcessResponse(w, cliCtx, res)
}
}
func getCirculatingSupplyHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
_, page, limit, err := rest.ParseHTTPArgsWithLimit(r, 0)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewBaseQueryParams(page, limit)
bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err))
return
}
route := fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryCirculatingSupply)
res, height, err := cliCtx.QueryWithData(route, bz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
cliCtx = cliCtx.WithHeight(height)
// directly write output instead of putting in json
w.Write(res)
// rest.PostProcessResponse(w, cliCtx, res)
}
}

View File

@ -0,0 +1,13 @@
package rest
import (
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/gorilla/mux"
)
// RegisterRoutes - Central function to define routes that get registered by the main application
func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) {
registerQueryRoutes(cliCtx, r)
}

View File

@ -0,0 +1,74 @@
package keeper
import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
supplyexported "github.com/cosmos/cosmos-sdk/x/supply/exported"
"github.com/kava-labs/kava/x/validator-vesting/internal/types"
abci "github.com/tendermint/tendermint/abci/types"
)
// NewQuerier returns a new querier function
func NewQuerier(keeper Keeper) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
switch path[0] {
case types.QueryCirculatingSupply:
return queryGetCirculatingSupply(ctx, req, keeper)
case types.QueryTotalSupply:
return queryGetTotalSupply(ctx, req, keeper)
default:
return nil, sdk.ErrUnknownRequest("unknown cdp query endpoint")
}
}
}
func queryGetTotalSupply(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
totalSupply := keeper.supplyKeeper.GetSupply(ctx).GetTotal().AmountOf("ukava")
supplyDec := sdk.NewDecFromInt(totalSupply).Mul(sdk.MustNewDecFromStr("0.000001"))
bz, err := codec.MarshalJSONIndent(keeper.cdc, supplyDec)
if err != nil {
return nil, sdk.ErrInternal(err.Error())
}
return bz, nil
}
func queryGetCirculatingSupply(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
circulatingSupply := sdk.ZeroInt()
keeper.ak.IterateAccounts(ctx,
func(acc authexported.Account) (stop bool) {
// exclude module account
_, ok := acc.(supplyexported.ModuleAccountI)
if ok {
return false
}
// periodic vesting account
vacc, ok := acc.(vesting.PeriodicVestingAccount)
if ok {
balance := vacc.GetCoins().AmountOf("ukava")
if balance.IsZero() {
return false
}
spendableBalance := vacc.SpendableCoins(ctx.BlockTime()).AmountOf("ukava")
circulatingSupply = circulatingSupply.Add(sdk.MinInt(balance, spendableBalance))
return false
}
// base account
bacc, ok := acc.(*auth.BaseAccount)
if ok {
// add all coins
circulatingSupply = circulatingSupply.Add(bacc.GetCoins().AmountOf("ukava"))
}
return false
})
supplyDec := sdk.NewDecFromInt(circulatingSupply).Mul(sdk.MustNewDecFromStr("0.000001"))
bz, err := codec.MarshalJSONIndent(keeper.cdc, supplyDec)
if err != nil {
return nil, sdk.ErrInternal(err.Error())
}
return bz, nil
}

View File

@ -14,6 +14,7 @@ type AccountKeeper interface {
GetAccount(sdk.Context, sdk.AccAddress) authexported.Account GetAccount(sdk.Context, sdk.AccAddress) authexported.Account
SetAccount(sdk.Context, authexported.Account) SetAccount(sdk.Context, authexported.Account)
GetAllAccounts(ctx sdk.Context) (accounts []authexported.Account) GetAllAccounts(ctx sdk.Context) (accounts []authexported.Account)
IterateAccounts(ctx sdk.Context, cb func(account authexported.Account) (stop bool))
} }
// BankKeeper defines the expected bank keeper (noalias) // BankKeeper defines the expected bank keeper (noalias)
@ -35,4 +36,5 @@ type SupplyKeeper interface {
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error
BurnCoins(ctx sdk.Context, name string, amt sdk.Coins) sdk.Error BurnCoins(ctx sdk.Context, name string, amt sdk.Coins) sdk.Error
SetModuleAccount(sdk.Context, supplyexported.ModuleAccountI) SetModuleAccount(sdk.Context, supplyexported.ModuleAccountI)
GetSupply(ctx sdk.Context) (supply supplyexported.SupplyI)
} }

View File

@ -10,6 +10,9 @@ const (
// StoreKey to be used when creating the KVStore // StoreKey to be used when creating the KVStore
StoreKey = ModuleName StoreKey = ModuleName
// QuerierRoute should be set to module name
QuerierRoute = ModuleName
) )
var ( var (

View File

@ -0,0 +1,17 @@
package types
// Querier routes for the validator vesting module
const (
QueryCirculatingSupply = "circulating-supply"
QueryTotalSupply = "total-supply"
)
// QueryCirculatingSupplyParams defines the parameters necessary for querying for all Evidence.
type BaseQueryParams struct {
Page int `json:"page" yaml:"page"`
Limit int `json:"limit" yaml:"limit"`
}
func NewBaseQueryParams(page, limit int) BaseQueryParams {
return BaseQueryParams{Page: page, Limit: limit}
}

View File

@ -68,6 +68,11 @@ type ValidatorVestingAccount struct {
DebtAfterFailedVesting sdk.Coins `json:"debt_after_failed_vesting" yaml:"debt_after_failed_vesting"` DebtAfterFailedVesting sdk.Coins `json:"debt_after_failed_vesting" yaml:"debt_after_failed_vesting"`
} }
// TotalCirculatingSupply represents the total circulating supply of Kava
type TotalCirculatingSupply struct {
TotalSupply uint64 `json:"total_supply" yaml:"total_supply"` // total circulating supply
}
// NewValidatorVestingAccountRaw creates a new ValidatorVestingAccount object from BaseVestingAccount // NewValidatorVestingAccountRaw creates a new ValidatorVestingAccount object from BaseVestingAccount
func NewValidatorVestingAccountRaw(bva *vestingtypes.BaseVestingAccount, func NewValidatorVestingAccountRaw(bva *vestingtypes.BaseVestingAccount,
startTime int64, periods vestingtypes.Periods, validatorAddress sdk.ConsAddress, returnAddress sdk.AccAddress, signingThreshold int64) *ValidatorVestingAccount { startTime int64, periods vestingtypes.Periods, validatorAddress sdk.ConsAddress, returnAddress sdk.AccAddress, signingThreshold int64) *ValidatorVestingAccount {

View File

@ -13,6 +13,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/types/module"
sim "github.com/cosmos/cosmos-sdk/x/simulation" sim "github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/kava-labs/kava/x/validator-vesting/client/cli"
"github.com/kava-labs/kava/x/validator-vesting/client/rest"
"github.com/kava-labs/kava/x/validator-vesting/internal/types" "github.com/kava-labs/kava/x/validator-vesting/internal/types"
"github.com/kava-labs/kava/x/validator-vesting/simulation" "github.com/kava-labs/kava/x/validator-vesting/simulation"
) )
@ -52,13 +54,17 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
} }
// RegisterRESTRoutes registers no REST routes for the crisis module. // RegisterRESTRoutes registers no REST routes for the crisis module.
func (AppModuleBasic) RegisterRESTRoutes(_ context.CLIContext, _ *mux.Router) {} func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) {
rest.RegisterRoutes(ctx, rtr)
}
// GetTxCmd returns no root tx command for the validator-vesting module. // GetTxCmd returns no root tx command for the validator-vesting module.
func (AppModuleBasic) GetTxCmd(_ *codec.Codec) *cobra.Command { return nil } func (AppModuleBasic) GetTxCmd(_ *codec.Codec) *cobra.Command { return nil }
// GetQueryCmd returns no root query command for the validator-vesting module. // GetQueryCmd returns no root query command for the validator-vesting module.
func (AppModuleBasic) GetQueryCmd(_ *codec.Codec) *cobra.Command { return nil } func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetQueryCmd(StoreKey, cdc)
}
// AppModuleSimulation defines the module simulation functions used by the auth module. // AppModuleSimulation defines the module simulation functions used by the auth module.
type AppModuleSimulation struct{} type AppModuleSimulation struct{}
@ -112,12 +118,12 @@ func (AppModule) NewHandler() sdk.Handler { return nil }
// QuerierRoute returns the auth module's querier route name. // QuerierRoute returns the auth module's querier route name.
func (AppModule) QuerierRoute() string { func (AppModule) QuerierRoute() string {
return "" return ModuleName
} }
// NewQuerierHandler returns the auth module sdk.Querier. // NewQuerierHandler returns the auth module sdk.Querier.
func (am AppModule) NewQuerierHandler() sdk.Querier { func (am AppModule) NewQuerierHandler() sdk.Querier {
return nil return NewQuerier(am.keeper)
} }
// InitGenesis performs genesis initialization for the auth module. It returns // InitGenesis performs genesis initialization for the auth module. It returns