Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backport: client denom metadata queries #8364

Merged
merged 4 commits into from
Jan 19, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ Ref: https://keepachangelog.com/en/1.0.0/

# Changelog

## [Unreleased]

### Improvements

* (x/bank) [\#8302](https://github.com/cosmos/cosmos-sdk/issues/8302) Add gRPC and CLI queries for client denomination metadata.

### Bug Fixes

* (x/bank) [\#8317](https://github.com/cosmos/cosmos-sdk/pull/8317) Fix panic when querying for a not found client denomination metadata.

## [v0.40.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0) - 2021-01-08

v0.40.0, known as the Stargate release of the Cosmos SDK, is one of the largest releases
Expand Down
3 changes: 2 additions & 1 deletion docs/architecture/adr-024-coin-metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ UX and remove the requirement for making any assumptions on the unit of denomina
The `x/bank` module will be updated to store and index metadata by `denom`, specifically the "base" or
smallest unit -- the unit the Cosmos SDK state-machine works with.

Metadata may also include a non-zero length list of denominations. Each entry containts the name of
Metadata may also include a non-zero length list of denominations. Each entry contains the name of
the denomination `denom`, the exponent to the base and a list of aliases. An entry is to be
interpreted as `1 denom = 10^exponent base_denom` (e.g. `1 ETH = 10^18 wei` and `1 uatom = 10^0 uatom`).

Expand Down Expand Up @@ -92,6 +92,7 @@ As an example, the ATOM's metadata can be defined as follows:
```

Given the above metadata, a client may infer the following things:

- 4.3atom = 4.3 * (10^6) = 4,300,000uatom
- The string "atom" can be used as a display name in a list of tokens.
- The balance 4300000 can be displayed as 4,300,000uatom or 4,300matom or 4.3atom.
Expand Down
69 changes: 69 additions & 0 deletions docs/core/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
- [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse)
- [QueryBalanceRequest](#cosmos.bank.v1beta1.QueryBalanceRequest)
- [QueryBalanceResponse](#cosmos.bank.v1beta1.QueryBalanceResponse)
- [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest)
- [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse)
- [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest)
- [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse)
- [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest)
- [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse)
- [QuerySupplyOfRequest](#cosmos.bank.v1beta1.QuerySupplyOfRequest)
Expand Down Expand Up @@ -1274,6 +1278,69 @@ QueryBalanceResponse is the response type for the Query/Balance RPC method.



<a name="cosmos.bank.v1beta1.QueryDenomMetadataRequest"></a>

### QueryDenomMetadataRequest
QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `denom` | [string](#string) | | denom is the coin denom to query the metadata for. |






<a name="cosmos.bank.v1beta1.QueryDenomMetadataResponse"></a>

### QueryDenomMetadataResponse
QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC
method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | | metadata describes and provides all the client information for the requested token. |






<a name="cosmos.bank.v1beta1.QueryDenomsMetadataRequest"></a>

### QueryDenomsMetadataRequest
QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. |






<a name="cosmos.bank.v1beta1.QueryDenomsMetadataResponse"></a>

### QueryDenomsMetadataResponse
QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC
method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `metadatas` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | metadata provides the client information for all the registered tokens. |
| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. |






<a name="cosmos.bank.v1beta1.QueryParamsRequest"></a>

### QueryParamsRequest
Expand Down Expand Up @@ -1374,6 +1441,8 @@ Query defines the gRPC querier service.
| `TotalSupply` | [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) | [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) | TotalSupply queries the total supply of all coins. | GET|/cosmos/bank/v1beta1/supply|
| `SupplyOf` | [QuerySupplyOfRequest](#cosmos.bank.v1beta1.QuerySupplyOfRequest) | [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) | SupplyOf queries the supply of a single coin. | GET|/cosmos/bank/v1beta1/supply/{denom}|
| `Params` | [QueryParamsRequest](#cosmos.bank.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.bank.v1beta1.QueryParamsResponse) | Params queries the parameters of x/bank module. | GET|/cosmos/bank/v1beta1/params|
| `DenomMetadata` | [QueryDenomMetadataRequest](#cosmos.bank.v1beta1.QueryDenomMetadataRequest) | [QueryDenomMetadataResponse](#cosmos.bank.v1beta1.QueryDenomMetadataResponse) | DenomsMetadata queries the client metadata of a given coin denomination. | GET|/cosmos/bank/v1beta1/denoms_metadata/{denom}|
| `DenomsMetadata` | [QueryDenomsMetadataRequest](#cosmos.bank.v1beta1.QueryDenomsMetadataRequest) | [QueryDenomsMetadataResponse](#cosmos.bank.v1beta1.QueryDenomsMetadataResponse) | DenomsMetadata queries the client metadata for all registered coin denominations. | GET|/cosmos/bank/v1beta1/denoms_metadata|

<!-- end services -->

Expand Down
3 changes: 0 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,6 @@ github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2l
github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4=
github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg=
github.com/tendermint/tendermint v0.34.0 h1:eXCfMgoqVSzrjzOj6clI9GAejcHH0LvOlRjpCmMJksU=
github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ=
github.com/tendermint/tendermint v0.34.1 h1:TsJXY8+1NThc/XIENMv1ENzazriHBJJjeP6hN3kpC8g=
github.com/tendermint/tendermint v0.34.1/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ=
Expand Down Expand Up @@ -614,7 +613,6 @@ golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 h1:phUcVbl53swtrUN8kQEXFhUxPlIlWyBfKmidCu7P95o=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
Expand Down Expand Up @@ -787,7 +785,6 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4 h1:Rt0FRalMgdSlXAVJvX4pr65KfqaxHXSLkSJRD9pw6g0=
google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d h1:HV9Z9qMhQEsdlvxNFELgQ11RkMzO3CMkjEySjCtuLes=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
Expand Down
39 changes: 39 additions & 0 deletions proto/cosmos/bank/v1beta1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ service Query {
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/cosmos/bank/v1beta1/params";
}

// DenomsMetadata queries the client metadata of a given coin denomination.
rpc DenomMetadata(QueryDenomMetadataRequest) returns (QueryDenomMetadataResponse) {
option (google.api.http).get = "/cosmos/bank/v1beta1/denoms_metadata/{denom}";
}

// DenomsMetadata queries the client metadata for all registered coin denominations.
rpc DenomsMetadata(QueryDenomsMetadataRequest) returns (QueryDenomsMetadataResponse) {
option (google.api.http).get = "/cosmos/bank/v1beta1/denoms_metadata";
}
}

// QueryBalanceRequest is the request type for the Query/Balance RPC method.
Expand Down Expand Up @@ -109,3 +119,32 @@ message QueryParamsRequest {}
message QueryParamsResponse {
Params params = 1 [(gogoproto.nullable) = false];
}

// QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method.
message QueryDenomsMetadataRequest {
// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}

// QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC
// method.
message QueryDenomsMetadataResponse {
// metadata provides the client information for all the registered tokens.
repeated Metadata metadatas = 1 [(gogoproto.nullable) = false];

// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method.
message QueryDenomMetadataRequest {
// denom is the coin denom to query the metadata for.
string denom = 1;
}

// QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC
// method.
message QueryDenomMetadataResponse {
// metadata describes and provides all the client information for the requested token.
Metadata metadata = 1 [(gogoproto.nullable) = false];
}
168 changes: 167 additions & 1 deletion x/bank/client/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,57 @@ func (s *IntegrationTestSuite) SetupSuite() {
s.T().Log("setting up integration test suite")

cfg := network.DefaultConfig()
genesisState := cfg.GenesisState
cfg.NumValidators = 1

var bankGenesis types.GenesisState
s.Require().NoError(cfg.Codec.UnmarshalJSON(genesisState[types.ModuleName], &bankGenesis))

bankGenesis.DenomMetadata = []types.Metadata{
{
Description: "The native staking token of the Cosmos Hub.",
DenomUnits: []*types.DenomUnit{
{
Denom: "uatom",
Exponent: 0,
Aliases: []string{"microatom"},
},
{
Denom: "atom",
Exponent: 6,
Aliases: []string{"ATOM"},
},
},
Base: "uatom",
Display: "atom",
},
{
Description: "Ethereum mainnet token",
DenomUnits: []*types.DenomUnit{
{
Denom: "wei",
Exponent: 0,
},
{
Denom: "eth",
Exponent: 6,
Aliases: []string{"ETH"},
},
},
Base: "wei",
Display: "eth",
},
}

bankGenesisBz, err := cfg.Codec.MarshalJSON(&bankGenesis)
s.Require().NoError(err)
genesisState[types.ModuleName] = bankGenesisBz
cfg.GenesisState = genesisState

s.cfg = cfg
s.network = network.New(s.T(), cfg)

_, err := s.network.WaitForHeight(1)
_, err = s.network.WaitForHeight(1)
s.Require().NoError(err)
}

Expand Down Expand Up @@ -181,6 +226,127 @@ func (s *IntegrationTestSuite) TestGetCmdQueryTotalSupply() {
}
}

func (s *IntegrationTestSuite) TestGetCmdQueryDenomsMetadata() {
val := s.network.Validators[0]

testCases := []struct {
name string
args []string
expectErr bool
respType proto.Message
expected proto.Message
}{
{
name: "all denoms client metadata",
args: []string{
fmt.Sprintf("--%s=1", flags.FlagHeight),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
},
respType: &types.QueryDenomsMetadataResponse{},
expected: &types.QueryDenomsMetadataResponse{
Metadatas: []types.Metadata{
{
Description: "The native staking token of the Cosmos Hub.",
DenomUnits: []*types.DenomUnit{
{
Denom: "uatom",
Exponent: 0,
Aliases: []string{"microatom"},
},
{
Denom: "atom",
Exponent: 6,
Aliases: []string{"ATOM"},
},
},
Base: "uatom",
Display: "atom",
},
{
Description: "Ethereum mainnet token",
DenomUnits: []*types.DenomUnit{
{
Denom: "wei",
Exponent: 0,
Aliases: []string{},
},
{
Denom: "eth",
Exponent: 6,
Aliases: []string{"ETH"},
},
},
Base: "wei",
Display: "eth",
},
},
Pagination: &query.PageResponse{Total: 2},
},
},
{
name: "client metadata of a specific denomination",
args: []string{
fmt.Sprintf("--%s=1", flags.FlagHeight),
fmt.Sprintf("--%s=%s", cli.FlagDenom, "uatom"),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
},
respType: &types.QueryDenomMetadataResponse{},
expected: &types.QueryDenomMetadataResponse{
Metadata: types.Metadata{
Description: "The native staking token of the Cosmos Hub.",
DenomUnits: []*types.DenomUnit{
{
Denom: "uatom",
Exponent: 0,
Aliases: []string{"microatom"},
},
{
Denom: "atom",
Exponent: 6,
Aliases: []string{"ATOM"},
},
},
Base: "uatom",
Display: "atom",
},
},
},
{
name: "client metadata of a bogus denom",
args: []string{
fmt.Sprintf("--%s=1", flags.FlagHeight),
fmt.Sprintf("--%s=foobar", cli.FlagDenom),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
},
expectErr: true,
respType: &types.QueryDenomMetadataResponse{},
expected: &types.QueryDenomMetadataResponse{
Metadata: types.Metadata{
DenomUnits: []*types.DenomUnit{},
},
},
},
}

for _, tc := range testCases {
tc := tc

s.Run(tc.name, func() {
cmd := cli.GetCmdDenomsMetadata()
clientCtx := val.ClientCtx

out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType))
s.Require().Equal(tc.expected, tc.respType)
}
})
}
}

func (s *IntegrationTestSuite) TestNewSendTxCmdGenOnly() {
val := s.network.Validators[0]

Expand Down
Loading