Skip to content

Commit 48e8161

Browse files
fedekunzeAlessio Treglia
authored andcommitted
supply querier (#4592)
Add querier to the supply module. Closes: #4082
1 parent a485b9a commit 48e8161

File tree

9 files changed

+464
-4
lines changed

9 files changed

+464
-4
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#4082 supply module queriers for CLI and REST endpoints

client/lcd/statik/statik.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/lcd/swagger-ui/swagger.yaml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ tags:
2121
description: Slashing module APIs
2222
- name: Distribution
2323
description: Fee distribution module APIs
24+
- name: Supply
25+
description: Supply module APIs
26+
- name: version
2427
- name: Mint
2528
description: Minting module APIs
2629
- name: Misc
@@ -1827,6 +1830,43 @@ paths:
18271830
type: string
18281831
500:
18291832
description: Internal Server Error
1833+
/supply/total:
1834+
get:
1835+
summary: Total supply of coins in the chain
1836+
tags:
1837+
- Supply
1838+
produces:
1839+
- application/json
1840+
responses:
1841+
200:
1842+
description: OK
1843+
schema:
1844+
$ref: "#/definitions/Supply"
1845+
500:
1846+
description: Internal Server Error
1847+
/supply/total/{denomination}:
1848+
parameters:
1849+
- in: path
1850+
name: denomination
1851+
description: Coin denomination
1852+
required: true
1853+
type: string
1854+
x-example: uatom
1855+
get:
1856+
summary: Total supply of a single coin denomination
1857+
tags:
1858+
- Supply
1859+
produces:
1860+
- application/json
1861+
responses:
1862+
200:
1863+
description: OK
1864+
schema:
1865+
type: integer
1866+
400:
1867+
description: Invalid coin denomination
1868+
500:
1869+
description: Internal Server Error
18301870
definitions:
18311871
CheckTxResult:
18321872
type: object
@@ -2435,3 +2475,10 @@ definitions:
24352475
example: ""
24362476
value:
24372477
type: object
2478+
Supply:
2479+
type: object
2480+
properties:
2481+
total:
2482+
type: array
2483+
items:
2484+
$ref: "#/definitions/Coin"

x/supply/client/cli/query.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package cli
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/cosmos/cosmos-sdk/client"
8+
"github.com/cosmos/cosmos-sdk/client/context"
9+
"github.com/cosmos/cosmos-sdk/codec"
10+
sdk "github.com/cosmos/cosmos-sdk/types"
11+
"github.com/cosmos/cosmos-sdk/version"
12+
"github.com/cosmos/cosmos-sdk/x/supply/types"
13+
"github.com/spf13/cobra"
14+
)
15+
16+
// GetQueryCmd returns the cli query commands for this module
17+
func GetQueryCmd(cdc *codec.Codec) *cobra.Command {
18+
// Group supply queries under a subcommand
19+
supplyQueryCmd := &cobra.Command{
20+
Use: types.ModuleName,
21+
Short: "Querying commands for the supply module",
22+
DisableFlagParsing: true,
23+
SuggestionsMinimumDistance: 2,
24+
RunE: client.ValidateCmd,
25+
}
26+
27+
supplyQueryCmd.AddCommand(client.GetCommands(
28+
GetCmdQueryTotalSupply(cdc),
29+
)...)
30+
31+
return supplyQueryCmd
32+
}
33+
34+
// GetCmdQueryTotalSupply implements the query total supply command.
35+
func GetCmdQueryTotalSupply(cdc *codec.Codec) *cobra.Command {
36+
return &cobra.Command{
37+
Use: "total [denom]",
38+
Args: cobra.MaximumNArgs(1),
39+
Short: "Query the total supply of coins of the chain",
40+
Long: strings.TrimSpace(
41+
fmt.Sprintf(`Query total supply of coins that are held by accounts in the
42+
chain.
43+
44+
Example:
45+
$ %s query %s total
46+
47+
To query for the total supply of a specific coin denomination use:
48+
$ %s query %s total stake
49+
`,
50+
version.ClientName, types.ModuleName, version.ClientName, types.ModuleName,
51+
),
52+
),
53+
RunE: func(cmd *cobra.Command, args []string) error {
54+
cliCtx := context.NewCLIContext().WithCodec(cdc)
55+
56+
if len(args) == 0 {
57+
return queryTotalSupply(cliCtx, cdc)
58+
}
59+
return querySupplyOf(cliCtx, cdc, args[0])
60+
},
61+
}
62+
}
63+
64+
func queryTotalSupply(cliCtx context.CLIContext, cdc *codec.Codec) error {
65+
params := types.NewQueryTotalSupplyParams(1, 0) // no pagination
66+
bz, err := cdc.MarshalJSON(params)
67+
if err != nil {
68+
return err
69+
}
70+
71+
res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryTotalSupply), bz)
72+
if err != nil {
73+
return err
74+
}
75+
76+
var totalSupply sdk.Coins
77+
err = cdc.UnmarshalJSON(res, &totalSupply)
78+
if err != nil {
79+
return err
80+
}
81+
82+
return cliCtx.PrintOutput(totalSupply)
83+
}
84+
85+
func querySupplyOf(cliCtx context.CLIContext, cdc *codec.Codec, denom string) error {
86+
params := types.NewQuerySupplyOfParams(denom)
87+
bz, err := cdc.MarshalJSON(params)
88+
if err != nil {
89+
return err
90+
}
91+
92+
res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QuerySupplyOf), bz)
93+
if err != nil {
94+
return err
95+
}
96+
97+
var supply sdk.Int
98+
err = cdc.UnmarshalJSON(res, &supply)
99+
if err != nil {
100+
return err
101+
}
102+
103+
return cliCtx.PrintOutput(supply)
104+
}

x/supply/client/rest/query.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package rest
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
"github.com/gorilla/mux"
8+
9+
"github.com/cosmos/cosmos-sdk/client/context"
10+
"github.com/cosmos/cosmos-sdk/types/rest"
11+
"github.com/cosmos/cosmos-sdk/x/supply/types"
12+
)
13+
14+
// RegisterRoutes registers staking-related REST handlers to a router
15+
func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) {
16+
registerQueryRoutes(cliCtx, r)
17+
}
18+
19+
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) {
20+
// Query the total supply of coins
21+
r.HandleFunc(
22+
"/supply/total/",
23+
totalSupplyHandlerFn(cliCtx),
24+
).Methods("GET")
25+
26+
// Query the supply of a single denom
27+
r.HandleFunc(
28+
"/supply/total/{denom}",
29+
supplyOfHandlerFn(cliCtx),
30+
).Methods("GET")
31+
}
32+
33+
// HTTP request handler to query the total supply of coins
34+
func totalSupplyHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
35+
return func(w http.ResponseWriter, r *http.Request) {
36+
_, page, limit, err := rest.ParseHTTPArgsWithLimit(r, 0)
37+
if err != nil {
38+
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
39+
return
40+
}
41+
42+
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
43+
if !ok {
44+
return
45+
}
46+
47+
params := types.NewQueryTotalSupplyParams(page, limit)
48+
bz, err := cliCtx.Codec.MarshalJSON(params)
49+
if err != nil {
50+
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
51+
return
52+
}
53+
54+
res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryTotalSupply), bz)
55+
if err != nil {
56+
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
57+
return
58+
}
59+
60+
cliCtx = cliCtx.WithHeight(height)
61+
rest.PostProcessResponse(w, cliCtx, res)
62+
}
63+
}
64+
65+
// HTTP request handler to query the supply of a single denom
66+
func supplyOfHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
67+
return func(w http.ResponseWriter, r *http.Request) {
68+
denom := mux.Vars(r)["denom"]
69+
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
70+
if !ok {
71+
return
72+
}
73+
74+
params := types.NewQuerySupplyOfParams(denom)
75+
bz, err := cliCtx.Codec.MarshalJSON(params)
76+
if err != nil {
77+
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
78+
return
79+
}
80+
81+
res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QuerySupplyOf), bz)
82+
if err != nil {
83+
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
84+
return
85+
}
86+
87+
cliCtx = cliCtx.WithHeight(height)
88+
rest.PostProcessResponse(w, cliCtx, res)
89+
}
90+
}

x/supply/keeper/querier.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package keeper
2+
3+
import (
4+
"fmt"
5+
6+
abci "github.com/tendermint/tendermint/abci/types"
7+
8+
sdk "github.com/cosmos/cosmos-sdk/types"
9+
"github.com/cosmos/cosmos-sdk/x/supply/types"
10+
)
11+
12+
// NewQuerier creates a querier for supply REST endpoints
13+
func NewQuerier(k Keeper) sdk.Querier {
14+
return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
15+
switch path[0] {
16+
case types.QueryTotalSupply:
17+
return queryTotalSupply(ctx, req, k)
18+
case types.QuerySupplyOf:
19+
return querySupplyOf(ctx, req, k)
20+
default:
21+
return nil, sdk.ErrUnknownRequest("unknown supply query endpoint")
22+
}
23+
}
24+
}
25+
26+
func queryTotalSupply(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
27+
var params types.QueryTotalSupplyParams
28+
29+
err := types.ModuleCdc.UnmarshalJSON(req.Data, &params)
30+
if err != nil {
31+
return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err))
32+
}
33+
34+
totalSupply := k.GetSupply(ctx).Total
35+
totalSupplyLen := len(totalSupply)
36+
37+
if params.Limit == 0 {
38+
params.Limit = totalSupplyLen
39+
}
40+
41+
start := (params.Page - 1) * params.Limit
42+
end := params.Limit + start
43+
if end >= totalSupplyLen {
44+
end = totalSupplyLen
45+
}
46+
47+
if start >= totalSupplyLen {
48+
// page is out of bounds
49+
totalSupply = sdk.Coins{}
50+
} else {
51+
totalSupply = totalSupply[start:end]
52+
}
53+
54+
res, err := totalSupply.MarshalJSON()
55+
if err != nil {
56+
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error()))
57+
}
58+
59+
return res, nil
60+
}
61+
62+
func querySupplyOf(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
63+
var params types.QuerySupplyOfParams
64+
65+
err := types.ModuleCdc.UnmarshalJSON(req.Data, &params)
66+
if err != nil {
67+
return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err))
68+
}
69+
70+
supply := k.GetSupply(ctx).Total.AmountOf(params.Denom)
71+
72+
res, err := supply.MarshalJSON()
73+
if err != nil {
74+
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error()))
75+
}
76+
77+
return res, nil
78+
}

0 commit comments

Comments
 (0)