Merge PR #4011: Mint/Inflation Querier, LCD and CLI

* A few godoc updates

* More minor tweaks and reformatting

* Implement initial minting querier

* Implement stringer interface for minting params

* Minor cleanup

* Add minting CLI commands

* Implement inflation query command

* Implement annual provisions query and CLI command

* Update x/mint/client/module_client.go

Co-Authored-By: alexanderbez <alexanderbez@users.noreply.github.com>

* Update x/mint/client/module_client.go

Co-Authored-By: alexanderbez <alexanderbez@users.noreply.github.com>

* Update x/mint/client/module_client.go

Co-Authored-By: alexanderbez <alexanderbez@users.noreply.github.com>

* Update x/mint/querier.go

Co-Authored-By: alexanderbez <alexanderbez@users.noreply.github.com>

* Add minting REST client routes/handlers

* Fix build issues

* Implement querier unit tests

* Update gaiacli docs

* Implement LCD tests

* Update Swagger docs

* Add pending log entry

* add examples

Signed-off-by: Karoly Albert Szabo <szabo.karoly.a@gmail.com>

* revert adding examples

Signed-off-by: Karoly Albert Szabo <szabo.karoly.a@gmail.com>
This commit is contained in:
Alexander Bezobchuk 2019-04-01 13:28:36 -04:00 committed by Jack Zampolin
parent 120e08f12d
commit b95ade93bd
17 changed files with 635 additions and 30 deletions

View File

@ -0,0 +1 @@
#3886 Implement minting module querier and CLI/REST clients.

View File

@ -11,6 +11,8 @@ import (
"testing"
"time"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client"
@ -1005,3 +1007,29 @@ func TestDistributionFlow(t *testing.T) {
resultTx = doWithdrawDelegatorAllRewards(t, port, seed, name1, pw, addr, fees)
require.Equal(t, uint32(0), resultTx.Code)
}
func TestMintingQueries(t *testing.T) {
kb, err := keys.NewKeyBaseFromDir(InitClientHome(t, ""))
require.NoError(t, err)
addr, _ := CreateAddr(t, name1, pw, kb)
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}, true)
defer cleanup()
res, body := Request(t, port, "GET", "/minting/parameters", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var params mint.Params
require.NoError(t, cdc.UnmarshalJSON([]byte(body), &params))
res, body = Request(t, port, "GET", "/minting/inflation", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var inflation sdk.Dec
require.NoError(t, cdc.UnmarshalJSON([]byte(body), &inflation))
res, body = Request(t, port, "GET", "/minting/annual-provisions", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var annualProvisions sdk.Dec
require.NoError(t, cdc.UnmarshalJSON([]byte(body), &annualProvisions))
}

View File

@ -122,6 +122,7 @@ paths:
description: Block height
required: true
type: number
x-example: 1
responses:
200:
description: The block at a specific height
@ -167,6 +168,7 @@ paths:
description: Block height
required: true
type: number
x-example: 1
responses:
200:
description: The validator set at a specific block height
@ -198,6 +200,7 @@ paths:
description: Tx hash
required: true
type: string
x-example: 88D6B85EAB87D43CDF50F39C22FC2237A37FEDC4CE723200AD0AF48CBEDBC317
responses:
200:
description: Tx with the provided hash
@ -219,14 +222,17 @@ paths:
type: string
description: "transaction tags such as 'action=submit-proposal' and 'proposer=cosmos1g9ahr6xhht5rmqven628nklxluzyv8z9jqjcmc' which results in the following endpoint: 'GET /txs?action=submit-proposal&proposer=cosmos1g9ahr6xhht5rmqven628nklxluzyv8z9jqjcmc'"
required: true
x-example: 'TODO'
- in: query
name: page
description: Page number
type: integer
x-example: 1
- in: query
name: limit
description: Maximum number of items per page
type: integer
x-example: 1
responses:
200:
description: All txs matching the provided tags
@ -313,6 +319,7 @@ paths:
description: Account address in bech32 format
required: true
type: string
x-example: cosmos16gdxm24ht2mxtpz9cma6tr6a6d47x63hlq4pxt
responses:
200:
description: Account balances
@ -339,6 +346,7 @@ paths:
description: Account address in bech32 format
required: true
type: string
x-example: cosmos16gdxm24ht2mxtpz9cma6tr6a6d47x63hlq4pxt
- in: body
name: account
description: The sender and tx information
@ -374,6 +382,7 @@ paths:
description: Account address
required: true
type: string
x-example: cosmos16gdxm24ht2mxtpz9cma6tr6a6d47x63hlq4pxt
responses:
200:
description: Account information on the blockchain
@ -408,6 +417,7 @@ paths:
description: Bech32 AccAddress of Delegator
required: true
type: string
x-example: cosmos167w96tdvmazakdwkw2u57227eduula2cy572lf
get:
summary: Get all delegations from a delegator
tags:
@ -466,11 +476,13 @@ paths:
description: Bech32 AccAddress of Delegator
required: true
type: string
x-example: cosmos167w96tdvmazakdwkw2u57227eduula2cy572lf
- in: path
name: validatorAddr
description: Bech32 OperatorAddress of validator
required: true
type: string
x-example: cosmosvaloper1qwl879nx9t6kef4supyazayf7vjhennyh568ys
get:
summary: Query the current delegation between a delegator and a validator
tags:
@ -493,6 +505,7 @@ paths:
description: Bech32 AccAddress of Delegator
required: true
type: string
x-example: cosmos167w96tdvmazakdwkw2u57227eduula2cy572lf
get:
summary: Get all unbonding delegations from a delegator
tags:
@ -552,11 +565,13 @@ paths:
description: Bech32 AccAddress of Delegator
required: true
type: string
x-example: cosmos167w96tdvmazakdwkw2u57227eduula2cy572lf
- in: path
name: validatorAddr
description: Bech32 OperatorAddress of validator
required: true
type: string
x-example: cosmosvaloper1qwl879nx9t6kef4supyazayf7vjhennyh568ys
get:
summary: Query all unbonding delegations between a delegator and a validator
tags:
@ -613,6 +628,7 @@ paths:
description: Bech32 AccAddress of Delegator
required: true
type: string
x-example: cosmos167w96tdvmazakdwkw2u57227eduula2cy572lf
post:
summary: Submit a redelegation
parameters:
@ -655,6 +671,7 @@ paths:
description: Bech32 AccAddress of Delegator
required: true
type: string
x-example: cosmos167w96tdvmazakdwkw2u57227eduula2cy572lf
get:
summary: Query all validators that a delegator is bonded to
tags:
@ -679,11 +696,13 @@ paths:
description: Bech32 AccAddress of Delegator
required: true
type: string
x-example: cosmos167w96tdvmazakdwkw2u57227eduula2cy572lf
- in: path
name: validatorAddr
description: Bech32 ValAddress of Delegator
required: true
type: string
x-example: cosmosvaloper1qwl879nx9t6kef4supyazayf7vjhennyh568ys
get:
summary: Query a validator that a delegator is bonded to
tags:
@ -706,6 +725,7 @@ paths:
description: Bech32 AccAddress of Delegator
required: true
type: string
x-example: cosmos167w96tdvmazakdwkw2u57227eduula2cy572lf
get:
summary: Get all staking txs (i.e msgs) from a delegator
tags:
@ -748,6 +768,7 @@ paths:
description: Bech32 OperatorAddress of validator
required: true
type: string
x-example: cosmosvaloper1qwl879nx9t6kef4supyazayf7vjhennyh568ys
get:
summary: Query the information from a single validator
tags:
@ -770,6 +791,7 @@ paths:
description: Bech32 OperatorAddress of validator
required: true
type: string
x-example: cosmosvaloper1qwl879nx9t6kef4supyazayf7vjhennyh568ys
get:
summary: Get all delegations from a validator
tags:
@ -794,6 +816,7 @@ paths:
description: Bech32 OperatorAddress of validator
required: true
type: string
x-example: cosmosvaloper1qwl879nx9t6kef4supyazayf7vjhennyh568ys
get:
summary: Get all unbonding delegations from a validator
tags:
@ -881,6 +904,7 @@ paths:
name: validatorPubKey
required: true
in: path
x-example: cosmosvalconspub1zcjduepq7mft6gfls57a0a42d7uhx656cckhfvtrlmw744jv4q0mvlv0dypskehfk8
responses:
200:
description: OK
@ -906,11 +930,13 @@ paths:
description: Page number
type: integer
required: true
x-example: 1
- in: query
name: limit
description: Maximum number of items per page
type: integer
required: true
x-example: 5
responses:
200:
description: OK
@ -940,6 +966,7 @@ paths:
name: validatorAddr
required: true
in: path
x-example: cosmosvaloper1qwl879nx9t6kef4supyazayf7vjhennyh568ys
- description: ""
name: UnjailBody
in: body
@ -1076,6 +1103,7 @@ paths:
name: proposalId
required: true
in: path
x-example: '1'
responses:
200:
description: OK
@ -1098,6 +1126,7 @@ paths:
name: proposalId
required: true
in: path
x-example: '1'
responses:
200:
description: OK
@ -1120,6 +1149,7 @@ paths:
name: proposalId
required: true
in: path
x-example: '1'
responses:
200:
description: OK
@ -1146,6 +1176,7 @@ paths:
name: proposalId
required: true
in: path
x-example: '1'
- description: ""
name: post_deposit_body
in: body
@ -1186,11 +1217,13 @@ paths:
name: proposalId
required: true
in: path
x-example: '1'
- type: string
description: Bech32 depositor address
name: depositor
required: true
in: path
x-example: cosmos1xl6453f6q6dv5770c9ue6hspdc0vxfuqtudkhz
responses:
200:
description: OK
@ -1216,6 +1249,7 @@ paths:
name: proposalId
required: true
in: path
x-example: '1'
responses:
200:
description: OK
@ -1242,6 +1276,7 @@ paths:
name: proposalId
required: true
in: path
x-example: '1'
- description: valid value of `"option"` field can be `"yes"`, `"no"`, `"no_with_veto"` and `"abstain"`
name: post_vote_body
in: body
@ -1281,11 +1316,13 @@ paths:
name: proposalId
required: true
in: path
x-example: '1'
- type: string
description: Bech32 voter address
name: voter
required: true
in: path
x-example: cosmos1qwl879nx9t6kef4supyazayf7vjhennyjqwjgr
responses:
200:
description: OK
@ -1311,6 +1348,7 @@ paths:
name: proposalId
required: true
in: path
x-example: '1'
responses:
200:
description: OK
@ -1404,6 +1442,7 @@ paths:
description: Bech32 AccAddress of Delegator
required: true
type: string
x-example: cosmos167w96tdvmazakdwkw2u57227eduula2cy572lf
get:
summary: Get the total rewards balance from all delegations
description: Get the sum of all the rewards earned by delegations by a single delegator
@ -1456,11 +1495,13 @@ paths:
description: Bech32 AccAddress of Delegator
required: true
type: string
x-example: cosmos167w96tdvmazakdwkw2u57227eduula2cy572lf
- in: path
name: validatorAddr
description: Bech32 OperatorAddress of validator
required: true
type: string
x-example: cosmosvaloper1qwl879nx9t6kef4supyazayf7vjhennyh568ys
get:
summary: Query a delegation reward
description: Query a single delegation reward by a delegator
@ -1513,6 +1554,7 @@ paths:
description: Bech32 AccAddress of Delegator
required: true
type: string
x-example: cosmos167w96tdvmazakdwkw2u57227eduula2cy572lf
get:
summary: Get the rewards withdrawal address
description: Get the delegations' rewards withdrawal address. This is the address in which the user will receive the reward funds
@ -1565,6 +1607,7 @@ paths:
description: Bech32 OperatorAddress of validator
required: true
type: string
x-example: cosmosvaloper1qwl879nx9t6kef4supyazayf7vjhennyh568ys
get:
summary: Validator distribution information
description: Query the distribution information of a single validator
@ -1588,6 +1631,7 @@ paths:
description: Bech32 OperatorAddress of validator
required: true
type: string
x-example: cosmosvaloper1qwl879nx9t6kef4supyazayf7vjhennyh568ys
get:
summary: Fee distribution outstanding rewards of a single validator
tags:
@ -1610,6 +1654,7 @@ paths:
description: Bech32 OperatorAddress of validator
required: true
type: string
x-example: cosmosvaloper1qwl879nx9t6kef4supyazayf7vjhennyh568ys
get:
summary: Commission and self-delegation rewards of a single validator
description: Query the commission and self-delegation rewards of validator.
@ -1691,6 +1736,54 @@ paths:
type: string
500:
description: Internal Server Error
/minting/parameters:
get:
summary: Minting module parameters
produces:
- application/json
responses:
200:
description: OK
schema:
properties:
mint_denom:
type: string
inflation_rate_change:
type: string
inflation_max:
type: string
inflation_min:
type: string
goal_bonded:
type: string
blocks_per_year:
type: integer
500:
description: Internal Server Error
/minting/inflation:
get:
summary: Current minting inflation value
produces:
- application/json
responses:
200:
description: OK
schema:
type: string
500:
description: Internal Server Error
/minting/annual-provisions:
get:
summary: Current minting annual provisions value
produces:
- application/json
responses:
200:
description: OK
schema:
type: string
500:
description: Internal Server Error
definitions:
CheckTxResult:
type: object

View File

@ -42,6 +42,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov"
govrest "github.com/cosmos/cosmos-sdk/x/gov/client/rest"
gcutils "github.com/cosmos/cosmos-sdk/x/gov/client/utils"
mintrest "github.com/cosmos/cosmos-sdk/x/mint/client/rest"
"github.com/cosmos/cosmos-sdk/x/slashing"
slashingrest "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
"github.com/cosmos/cosmos-sdk/x/staking"
@ -411,6 +412,7 @@ func registerRoutes(rs *RestServer) {
stakingrest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
slashingrest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
govrest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
mintrest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
}
// Request makes a test LCD test request. It returns a response object and a

View File

@ -179,7 +179,8 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest,
AddRoute(distr.QuerierRoute, distr.NewQuerier(app.distrKeeper)).
AddRoute(gov.QuerierRoute, gov.NewQuerier(app.govKeeper)).
AddRoute(slashing.QuerierRoute, slashing.NewQuerier(app.slashingKeeper, app.cdc)).
AddRoute(staking.QuerierRoute, staking.NewQuerier(app.stakingKeeper, app.cdc))
AddRoute(staking.QuerierRoute, staking.NewQuerier(app.stakingKeeper, app.cdc)).
AddRoute(mint.QuerierRoute, mint.NewQuerier(app.mintKeeper))
// initialize BaseApp
app.MountStores(app.keyMain, app.keyAccount, app.keyStaking, app.keyMint, app.keyDistr,

View File

@ -6,11 +6,13 @@ import (
"os"
"path"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/rakyll/statik/fs"
"github.com/spf13/cobra"
"github.com/spf13/viper"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/cli"
"github.com/cosmos/cosmos-sdk/client"
@ -28,6 +30,7 @@ import (
dist "github.com/cosmos/cosmos-sdk/x/distribution/client/rest"
gv "github.com/cosmos/cosmos-sdk/x/gov"
gov "github.com/cosmos/cosmos-sdk/x/gov/client/rest"
mintrest "github.com/cosmos/cosmos-sdk/x/mint/client/rest"
sl "github.com/cosmos/cosmos-sdk/x/slashing"
slashing "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
st "github.com/cosmos/cosmos-sdk/x/staking"
@ -39,8 +42,9 @@ import (
distcmd "github.com/cosmos/cosmos-sdk/x/distribution"
distClient "github.com/cosmos/cosmos-sdk/x/distribution/client"
govClient "github.com/cosmos/cosmos-sdk/x/gov/client"
slashingClient "github.com/cosmos/cosmos-sdk/x/slashing/client"
stakingClient "github.com/cosmos/cosmos-sdk/x/staking/client"
mintclient "github.com/cosmos/cosmos-sdk/x/mint/client"
slashingclient "github.com/cosmos/cosmos-sdk/x/slashing/client"
stakingclient "github.com/cosmos/cosmos-sdk/x/staking/client"
_ "github.com/cosmos/cosmos-sdk/client/lcd/statik"
)
@ -68,8 +72,9 @@ func main() {
mc := []sdk.ModuleClients{
govClient.NewModuleClient(gv.StoreKey, cdc),
distClient.NewModuleClient(distcmd.StoreKey, cdc),
stakingClient.NewModuleClient(st.StoreKey, cdc),
slashingClient.NewModuleClient(sl.StoreKey, cdc),
stakingclient.NewModuleClient(st.StoreKey, cdc),
mintclient.NewModuleClient(mint.StoreKey, cdc),
slashingclient.NewModuleClient(sl.StoreKey, cdc),
crisisclient.NewModuleClient(sl.StoreKey, cdc),
}
@ -171,6 +176,7 @@ func registerRoutes(rs *lcd.RestServer) {
staking.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
slashing.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
gov.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
mintrest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
}
func registerSwaggerUI(rs *lcd.RestServer) {

View File

@ -327,6 +327,26 @@ You can get the current slashing parameters via:
gaiacli query slashing params
```
### Minting
You can query for the minting/inflation parameters via:
```bash
gaiacli query minting params
```
To query for the current inflation value:
```bash
gaiacli query minting inflation
```
To query for the current annual provisions value:
```bash
gaiacli query minting annual-provisions
```
### Staking
#### Set up a Validator

View File

@ -0,0 +1,89 @@
package cli
import (
"fmt"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/spf13/cobra"
)
// GetCmdQueryParams implements a command to return the current minting
// parameters.
func GetCmdQueryParams(cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "params",
Short: "Query the current minting parameters",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
route := fmt.Sprintf("custom/%s/%s", mint.QuerierRoute, mint.QueryParameters)
res, err := cliCtx.QueryWithData(route, nil)
if err != nil {
return err
}
var params mint.Params
if err := cdc.UnmarshalJSON(res, &params); err != nil {
return err
}
return cliCtx.PrintOutput(params)
},
}
}
// GetCmdQueryInflation implements a command to return the current minting
// inflation value.
func GetCmdQueryInflation(cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "inflation",
Short: "Query the current minting inflation value",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
route := fmt.Sprintf("custom/%s/%s", mint.QuerierRoute, mint.QueryInflation)
res, err := cliCtx.QueryWithData(route, nil)
if err != nil {
return err
}
var inflation sdk.Dec
if err := cdc.UnmarshalJSON(res, &inflation); err != nil {
return err
}
return cliCtx.PrintOutput(inflation)
},
}
}
// GetCmdQueryAnnualProvisions implements a command to return the current minting
// annual provisions value.
func GetCmdQueryAnnualProvisions(cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "annual-provisions",
Short: "Query the current minting annual provisions value",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
route := fmt.Sprintf("custom/%s/%s", mint.QuerierRoute, mint.QueryAnnualProvisions)
res, err := cliCtx.QueryWithData(route, nil)
if err != nil {
return err
}
var inflation sdk.Dec
if err := cdc.UnmarshalJSON(res, &inflation); err != nil {
return err
}
return cliCtx.PrintOutput(inflation)
},
}
}

View File

@ -0,0 +1,47 @@
package clientpackage
import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/mint/client/cli"
"github.com/spf13/cobra"
"github.com/tendermint/go-amino"
)
// ModuleClient exports all CLI client functionality from the minting module.
type ModuleClient struct {
storeKey string
cdc *amino.Codec
}
func NewModuleClient(storeKey string, cdc *amino.Codec) ModuleClient {
return ModuleClient{storeKey, cdc}
}
// GetQueryCmd returns the cli query commands for the minting module.
func (mc ModuleClient) GetQueryCmd() *cobra.Command {
mintingQueryCmd := &cobra.Command{
Use: mint.ModuleName,
Short: "Querying commands for the minting module",
}
mintingQueryCmd.AddCommand(
client.GetCommands(
cli.GetCmdQueryParams(mc.cdc),
cli.GetCmdQueryInflation(mc.cdc),
cli.GetCmdQueryAnnualProvisions(mc.cdc),
)...,
)
return mintingQueryCmd
}
// GetTxCmd returns the transaction commands for the minting module.
func (mc ModuleClient) GetTxCmd() *cobra.Command {
mintTxCmd := &cobra.Command{
Use: mint.ModuleName,
Short: "Minting transaction subcommands",
}
return mintTxCmd
}

View File

@ -0,0 +1,71 @@
package rest
import (
"fmt"
"net/http"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/types/rest"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/gorilla/mux"
)
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec) {
r.HandleFunc(
"/minting/parameters",
queryParamsHandlerFn(cdc, cliCtx),
).Methods("GET")
r.HandleFunc(
"/minting/inflation",
queryInflationHandlerFn(cdc, cliCtx),
).Methods("GET")
r.HandleFunc(
"/minting/annual-provisions",
queryAnnualProvisionsHandlerFn(cdc, cliCtx),
).Methods("GET")
}
func queryParamsHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
route := fmt.Sprintf("custom/%s/%s", mint.QuerierRoute, mint.QueryParameters)
res, err := cliCtx.QueryWithData(route, nil)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
rest.PostProcessResponse(w, cdc, res, cliCtx.Indent)
}
}
func queryInflationHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
route := fmt.Sprintf("custom/%s/%s", mint.QuerierRoute, mint.QueryInflation)
res, err := cliCtx.QueryWithData(route, nil)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
rest.PostProcessResponse(w, cdc, res, cliCtx.Indent)
}
}
func queryAnnualProvisionsHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
route := fmt.Sprintf("custom/%s/%s", mint.QuerierRoute, mint.QueryAnnualProvisions)
res, err := cliCtx.QueryWithData(route, nil)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
rest.PostProcessResponse(w, cdc, res, cliCtx.Indent)
}
}

View File

@ -0,0 +1,12 @@
package rest
import (
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/gorilla/mux"
)
// RegisterRoutes registers minting module REST handlers on the provided router.
func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec) {
registerQueryRoutes(cliCtx, r, cdc)
}

View File

@ -6,6 +6,20 @@ import (
"github.com/cosmos/cosmos-sdk/x/params"
)
const (
// ModuleName is the name of the module
ModuleName = "minting"
// default paramspace for params keeper
DefaultParamspace = "mint"
// StoreKey is the default store key for mint
StoreKey = "mint"
// QuerierRoute is the querier route for the minting store.
QuerierRoute = StoreKey
)
// keeper of the staking store
type Keeper struct {
storeKey sdk.StoreKey
@ -45,14 +59,6 @@ func ParamKeyTable() params.KeyTable {
)
}
const (
// default paramspace for params keeper
DefaultParamspace = "mint"
// StoreKey is the default store key for mint
StoreKey = "mint"
)
//______________________________________________________________________
// get the minter

View File

@ -6,22 +6,22 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Minter represents the minting state
// Minter represents the minting state.
type Minter struct {
Inflation sdk.Dec `json:"inflation"` // current annual inflation rate
AnnualProvisions sdk.Dec `json:"annual_provisions"` // current annual expected provisions
}
// Create a new minter object
// NewMinter returns a new Minter object with the given inflation and annual
// provisions values.
func NewMinter(inflation, annualProvisions sdk.Dec) Minter {
return Minter{
Inflation: inflation,
AnnualProvisions: annualProvisions,
}
}
// minter object for a new chain
// InitialMinter returns an initial Minter object with a given inflation value.
func InitialMinter(inflation sdk.Dec) Minter {
return NewMinter(
inflation,
@ -29,8 +29,8 @@ func InitialMinter(inflation sdk.Dec) Minter {
)
}
// default initial minter object for a new chain
// which uses an inflation rate of 13%
// DefaultInitialMinter returns a default initial Minter object for a new chain
// which uses an inflation rate of 13%.
func DefaultInitialMinter() Minter {
return InitialMinter(
sdk.NewDecWithPrec(13, 2),
@ -45,10 +45,8 @@ func validateMinter(minter Minter) error {
return nil
}
// get the new inflation rate for the next hour
func (m Minter) NextInflationRate(params Params, bondedRatio sdk.Dec) (
inflation sdk.Dec) {
// NextInflationRate returns the new inflation rate for the next hour.
func (m Minter) NextInflationRate(params Params, bondedRatio sdk.Dec) sdk.Dec {
// The target annual inflation rate is recalculated for each previsions cycle. The
// inflation is also subject to a rate change (positive or negative) depending on
// the distance from the desired ratio (67%). The maximum rate change possible is
@ -62,7 +60,7 @@ func (m Minter) NextInflationRate(params Params, bondedRatio sdk.Dec) (
inflationRateChange := inflationRateChangePerYear.Quo(sdk.NewDec(int64(params.BlocksPerYear)))
// adjust the new annual inflation for this next cycle
inflation = m.Inflation.Add(inflationRateChange) // note inflationRateChange may be negative
inflation := m.Inflation.Add(inflationRateChange) // note inflationRateChange may be negative
if inflation.GT(params.InflationMax) {
inflation = params.InflationMax
}
@ -73,14 +71,14 @@ func (m Minter) NextInflationRate(params Params, bondedRatio sdk.Dec) (
return inflation
}
// calculate the annual provisions based on current total supply and inflation rate
func (m Minter) NextAnnualProvisions(params Params, totalSupply sdk.Int) (
provisions sdk.Dec) {
// NextAnnualProvisions returns the annual provisions based on current total
// supply and inflation rate.
func (m Minter) NextAnnualProvisions(_ Params, totalSupply sdk.Int) sdk.Dec {
return m.Inflation.MulInt(totalSupply)
}
// get the provisions for a block based on the annual provisions rate
// BlockProvision returns the provisions for a block based on the annual
// provisions rate.
func (m Minter) BlockProvision(params Params) sdk.Coin {
provisionAmt := m.AnnualProvisions.QuoInt(sdk.NewInt(int64(params.BlocksPerYear)))
return sdk.NewCoin(params.MintDenom, provisionAmt.TruncateInt())

View File

@ -56,3 +56,17 @@ func validateParams(params Params) error {
}
return nil
}
func (p Params) String() string {
return fmt.Sprintf(`Minting Params:
Mint Denom: %s
Inflation Rate Change: %s
Inflation Max: %s
Inflation Min: %s
Goal Bonded: %s
Blocks Per Year: %d
`,
p.MintDenom, p.InflationRateChange, p.InflationMax,
p.InflationMin, p.GoalBonded, p.BlocksPerYear,
)
}

68
x/mint/querier.go Normal file
View File

@ -0,0 +1,68 @@
package mint
import (
"fmt"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
)
// Query endpoints supported by the minting querier
const (
QueryParameters = "parameters"
QueryInflation = "inflation"
QueryAnnualProvisions = "annual_provisions"
)
// NewQuerier returns a minting Querier handler.
func NewQuerier(k Keeper) sdk.Querier {
return func(ctx sdk.Context, path []string, _ abci.RequestQuery) ([]byte, sdk.Error) {
switch path[0] {
case QueryParameters:
return queryParams(ctx, k)
case QueryInflation:
return queryInflation(ctx, k)
case QueryAnnualProvisions:
return queryAnnualProvisions(ctx, k)
default:
return nil, sdk.ErrUnknownRequest(fmt.Sprintf("unknown minting query endpoint: %s", path[0]))
}
}
}
func queryParams(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) {
params := k.GetParams(ctx)
res, err := codec.MarshalJSONIndent(k.cdc, params)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to marshal JSON", err.Error()))
}
return res, nil
}
func queryInflation(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) {
minter := k.GetMinter(ctx)
res, err := codec.MarshalJSONIndent(k.cdc, minter.Inflation)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to marshal JSON", err.Error()))
}
return res, nil
}
func queryAnnualProvisions(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) {
minter := k.GetMinter(ctx)
res, err := codec.MarshalJSONIndent(k.cdc, minter.AnnualProvisions)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to marshal JSON", err.Error()))
}
return res, nil
}

74
x/mint/querier_test.go Normal file
View File

@ -0,0 +1,74 @@
package mint
import (
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
)
func TestNewQuerier(t *testing.T) {
input := newTestInput(t)
querier := NewQuerier(input.mintKeeper)
query := abci.RequestQuery{
Path: "",
Data: []byte{},
}
_, err := querier(input.ctx, []string{QueryParameters}, query)
require.NoError(t, err)
_, err = querier(input.ctx, []string{QueryInflation}, query)
require.NoError(t, err)
_, err = querier(input.ctx, []string{QueryAnnualProvisions}, query)
require.NoError(t, err)
_, err = querier(input.ctx, []string{"foo"}, query)
require.Error(t, err)
}
func TestQueryParams(t *testing.T) {
input := newTestInput(t)
var params Params
res, sdkErr := queryParams(input.ctx, input.mintKeeper)
require.NoError(t, sdkErr)
err := input.cdc.UnmarshalJSON(res, &params)
require.NoError(t, err)
require.Equal(t, input.mintKeeper.GetParams(input.ctx), params)
}
func TestQueryInflation(t *testing.T) {
input := newTestInput(t)
var inflation sdk.Dec
res, sdkErr := queryInflation(input.ctx, input.mintKeeper)
require.NoError(t, sdkErr)
err := input.cdc.UnmarshalJSON(res, &inflation)
require.NoError(t, err)
require.Equal(t, input.mintKeeper.GetMinter(input.ctx).Inflation, inflation)
}
func TestQueryAnnualProvisions(t *testing.T) {
input := newTestInput(t)
var annualProvisions sdk.Dec
res, sdkErr := queryAnnualProvisions(input.ctx, input.mintKeeper)
require.NoError(t, sdkErr)
err := input.cdc.UnmarshalJSON(res, &annualProvisions)
require.NoError(t, err)
require.Equal(t, input.mintKeeper.GetMinter(input.ctx).AnnualProvisions, annualProvisions)
}

75
x/mint/test_common.go Normal file
View File

@ -0,0 +1,75 @@
package mint
import (
"os"
"testing"
"time"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/cosmos/cosmos-sdk/x/staking"
dbm "github.com/tendermint/tendermint/libs/db"
)
type testInput struct {
ctx sdk.Context
cdc *codec.Codec
mintKeeper Keeper
}
func createTestCodec() *codec.Codec {
cdc := codec.New()
codec.RegisterCrypto(cdc)
return cdc
}
func newTestInput(t *testing.T) testInput {
cdc := createTestCodec()
db := dbm.NewMemDB()
keyAcc := sdk.NewKVStoreKey(auth.StoreKey)
keyStaking := sdk.NewKVStoreKey(staking.StoreKey)
tkeyStaking := sdk.NewTransientStoreKey(staking.TStoreKey)
keyParams := sdk.NewKVStoreKey(params.StoreKey)
tkeyParams := sdk.NewTransientStoreKey(params.TStoreKey)
keyFeeCollection := sdk.NewKVStoreKey(auth.FeeStoreKey)
keyMint := sdk.NewKVStoreKey(StoreKey)
ms := store.NewCommitMultiStore(db)
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(tkeyStaking, sdk.StoreTypeTransient, nil)
ms.MountStoreWithDB(keyStaking, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyFeeCollection, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyMint, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db)
err := ms.LoadLatestVersion()
require.Nil(t, err)
paramsKeeper := params.NewKeeper(cdc, keyParams, tkeyParams)
feeCollectionKeeper := auth.NewFeeCollectionKeeper(cdc, keyFeeCollection)
accountKeeper := auth.NewAccountKeeper(cdc, keyAcc, paramsKeeper.Subspace(auth.DefaultParamspace), auth.ProtoBaseAccount)
bankKeeper := bank.NewBaseKeeper(accountKeeper, paramsKeeper.Subspace(bank.DefaultParamspace), bank.DefaultCodespace)
stakingKeeper := staking.NewKeeper(
cdc, keyStaking, tkeyStaking, bankKeeper, paramsKeeper.Subspace(staking.DefaultParamspace), staking.DefaultCodespace,
)
mintKeeper := NewKeeper(
cdc, keyMint, paramsKeeper.Subspace(DefaultParamspace), &stakingKeeper, feeCollectionKeeper,
)
ctx := sdk.NewContext(ms, abci.Header{Time: time.Unix(0, 0)}, false, log.NewTMLogger(os.Stdout))
mintKeeper.SetParams(ctx, DefaultParams())
mintKeeper.SetMinter(ctx, DefaultInitialMinter())
return testInput{ctx, cdc, mintKeeper}
}