Skip to content

Commit

Permalink
Adding token factory specific denom endpoint (#457)
Browse files Browse the repository at this point in the history
## Describe your changes and provide context
When we create tokens using token factory, denoms are created in the
`factory/{owner_walltet_id}/{denom}` format
E.g. `factory/sei1gxskuzvhr4s8sdm2rpruaf7yx2dnmjn0zfdu9q/NEWCOIN`

When querying metadata via
`/cosmos/bank/v1beta1/denoms_metadata/{denom}` endpoint for such a denom
we are getting error like
```
{
    "code": 12,
    "message": "Not Implemented",
    "details": []
}
```
This happens, because routing logic splits the denom uri param into 3
components rather then one and hence tries to router request to a
non-existing handler. Url encoding does not help either as it still
results in same issue. We would like to add additional endpoint to
handle token factory created metadata retrieval, and move denom for the
endpoint from uri param to query param.

so then for token factory created tokens the query would be 

`/cosmos/bank/v1beta1/token_factory/denoms_metadata?denom=factory/{owner_walltet_id}/{denom}`

## Testing performed to validate your change
Note: some demom tests were disables, and I have enabled them.

- Functional testing on local node with updated source
- unit/integration tests
  • Loading branch information
dssei authored Mar 14, 2024
1 parent 0320b34 commit ca54bb7
Show file tree
Hide file tree
Showing 7 changed files with 472 additions and 86 deletions.
19 changes: 11 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,13 @@ require (
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/cosmos/gorocksdb v1.2.0 // indirect
github.com/creachadair/taskgroup v0.3.2 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/dgraph-io/badger/v3 v3.2103.2 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
github.com/felixge/httpsnoop v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gin-gonic/gin v1.7.7 // indirect
github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
Expand All @@ -97,10 +94,8 @@ require (
github.com/golang/glog v1.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/flatbuffers v1.12.1 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/orderedcode v0.0.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
Expand All @@ -126,7 +121,6 @@ require (
github.com/mtibben/percent v0.2.1 // indirect
github.com/oasisprotocol/curve25519-voi v0.0.0-20210609091139-0a56a4bca00b // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
Expand All @@ -150,13 +144,11 @@ require (
go.opencensus.io v0.23.0 // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sync v0.4.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
Expand All @@ -172,6 +164,17 @@ require (
nhooyr.io/websocket v1.8.6 // indirect
)

require (
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
github.com/gin-gonic/gin v1.7.7 // indirect
github.com/google/btree v1.1.2
github.com/google/gofuzz v1.2.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
golang.org/x/sync v0.4.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
)

replace (
github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
Expand Down
11 changes: 11 additions & 0 deletions proto/cosmos/bank/v1beta1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ service Query {
option (google.api.http).get = "/cosmos/bank/v1beta1/denoms_metadata/{denom}";
}

// TokenFactoryDenomMetadata queries the client metadata of a given token factory coin denomination.
rpc TokenFactoryDenomMetadata(QueryTokenFactoryDenomMetadataRequest) returns (QueryDenomMetadataResponse) {
option (google.api.http).get = "/cosmos/bank/v1beta1/token_factory/denoms_metadata";
}

// 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";
Expand Down Expand Up @@ -185,6 +190,12 @@ message QueryDenomMetadataRequest {
string denom = 1;
}

// QueryTokenFactoryDenomMetadataRequest is the request type for the Query/TokenFactoryDenomMetadata RPC method.
message QueryTokenFactoryDenomMetadataRequest {
// denom is the (token factory) coin denom to query the metadata for.
string denom = 1;
}

// QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC
// method.
message QueryDenomMetadataResponse {
Expand Down
5 changes: 5 additions & 0 deletions x/bank/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,8 @@ func (k BaseKeeper) DenomMetadata(c context.Context, req *types.QueryDenomMetada
Metadata: metadata,
}, nil
}

// TokenFactoryDenomMetadata implements Query/TokenFactoryDenomMetadata gRPC method.
func (k BaseKeeper) TokenFactoryDenomMetadata(c context.Context, req *types.QueryTokenFactoryDenomMetadataRequest) (*types.QueryDenomMetadataResponse, error) {
return k.DenomMetadata(c, &types.QueryDenomMetadataRequest{Denom: req.Denom})
}
81 changes: 77 additions & 4 deletions x/bank/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,10 @@ func (suite *IntegrationTestSuite) TestQueryParams() {
suite.Require().Equal(suite.app.BankKeeper.GetParams(suite.ctx), res.GetParams())
}

func (suite *IntegrationTestSuite) QueryDenomsMetadataRequest() {
func (suite *IntegrationTestSuite) TestQueryDenomsMetadataRequest() {
var (
req *types.QueryDenomsMetadataRequest
expMetadata = []types.Metadata{}
expMetadata []types.Metadata
)

testCases := []struct {
Expand Down Expand Up @@ -282,7 +282,7 @@ func (suite *IntegrationTestSuite) QueryDenomsMetadataRequest() {
}
}

func (suite *IntegrationTestSuite) QueryDenomMetadataRequest() {
func (suite *IntegrationTestSuite) TestQueryDenomMetadataRequest() {
var (
req *types.QueryDenomMetadataRequest
expMetadata = types.Metadata{}
Expand Down Expand Up @@ -312,7 +312,7 @@ func (suite *IntegrationTestSuite) QueryDenomMetadataRequest() {
{
"success",
func() {
expMetadata := types.Metadata{
expMetadata = types.Metadata{
Description: "The native staking token of the Cosmos Hub.",
DenomUnits: []*types.DenomUnit{
{
Expand Down Expand Up @@ -358,3 +358,76 @@ func (suite *IntegrationTestSuite) QueryDenomMetadataRequest() {
})
}
}

func (suite *IntegrationTestSuite) TestQueryTokenFactoryDenomMetadataRequest() {
var (
req *types.QueryTokenFactoryDenomMetadataRequest
expMetadata = types.Metadata{}
)
tokenFactoryDenom := "factory/sei1gxskuzvhr4s8sdm2rpruaf7yx2dnmjn0zfdu9q/NEWCOIN"
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{
"empty denom",
func() {
req = &types.QueryTokenFactoryDenomMetadataRequest{}
},
false,
},
{
"not found denom",
func() {
req = &types.QueryTokenFactoryDenomMetadataRequest{
Denom: tokenFactoryDenom,
}
},
false,
},
{
"success",
func() {

expMetadata = types.Metadata{
Description: "Token factory custom token",
DenomUnits: []*types.DenomUnit{
{
Denom: tokenFactoryDenom,
Exponent: 0,
Aliases: []string{tokenFactoryDenom},
},
},
Base: tokenFactoryDenom,
Display: tokenFactoryDenom,
}

suite.app.BankKeeper.SetDenomMetaData(suite.ctx, expMetadata)
req = &types.QueryTokenFactoryDenomMetadataRequest{
Denom: expMetadata.Base,
}
},
true,
},
}

for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset

tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)

res, err := suite.queryClient.TokenFactoryDenomMetadata(ctx, req)

if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expMetadata, res.Metadata)
} else {
suite.Require().Error(err)
}
})
}
}
Loading

0 comments on commit ca54bb7

Please sign in to comment.