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

Adding tokenfactory denom metadata endpoint #1444

Merged
merged 8 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
34 changes: 34 additions & 0 deletions proto/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Code generation

To generate the code for the protobuf files, first install the `ignite` tool.
We need version v0.23.0, which is outdated, but works with the current version of the codebase.
Pull binaries from the [releases page](https://github.com/ignite/cli/releases/tag/v0.23.0) or install from source code
following instructions.

Verify the installation by running `ignite version`:

```bash
% ignite version
·
· 🛸 Ignite CLI v28.2.0 is available!
·
· To upgrade your Ignite CLI version, see the upgrade doc: https://docs.ignite.com/guide/install.html#upgrading-your-ignite-cli-installation
·
··

Ignite CLI version: v0.23.0
Ignite CLI build date: 2022-07-24T18:17:44Z
Ignite CLI source hash: 64df9aef958b3e8bc04b40d9feeb03426075ea89
Your OS: darwin
Your arch: arm64
Your go version: go version go1.22.0 darwin/arm64
Your uname -a: Darwin 23.1.0 Darwin Kernel Version 23.1.0: Mon Oct 9 21:32:11 PDT 2023; root:xnu-10002.41.9~7/RELEASE_ARM64_T6030 arm64
Your cwd: /repos/sei-chain
Is on Gitpod: false

```
Then, to generate the code, run the following command:

```bash
ignite generate proto-go

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this for generating the proto files or for generating the openapi yml?

Copy link
Contributor Author

@dssei dssei Mar 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its for both, will add another readme for docs generation in a separate PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really nicee!

```
20 changes: 20 additions & 0 deletions proto/tokenfactory/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package seiprotocol.seichain.tokenfactory;

import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "cosmos/bank/v1beta1/bank.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "tokenfactory/authorityMetadata.proto";
import "tokenfactory/params.proto";
Expand All @@ -25,6 +26,12 @@ service Query {
"/sei-protocol/seichain/tokenfactory/denoms/{denom}/authority_metadata";
}

// DenomsMetadata defines a gRPC query method for fetching
// DenomMetadata for a particular denom.
rpc DenomMetadata(QueryDenomMetadataRequest) returns (QueryDenomMetadataResponse) {
option (google.api.http).get = "/sei-protocol/seichain/tokenfactory/denoms/metadata";
}

// DenomsFromCreator defines a gRPC query method for fetching all
// denominations created by a specific admin/creator.
rpc DenomsFromCreator(QueryDenomsFromCreatorRequest)
Expand Down Expand Up @@ -70,3 +77,16 @@ message QueryDenomsFromCreatorRequest {
message QueryDenomsFromCreatorResponse {
repeated string denoms = 1 [ (gogoproto.moretags) = "yaml:\"denoms\"" ];
}

// QueryDenomMetadataRequest is the request type for the DenomMetadata gRPC 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 gRPC
// method.
message QueryDenomMetadataResponse {
// metadata describes and provides all the client information for the requested token.
cosmos.bank.v1beta1.Metadata metadata = 1 [(gogoproto.nullable) = false];
}
24 changes: 24 additions & 0 deletions x/tokenfactory/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"

sdk "github.com/cosmos/cosmos-sdk/types"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/sei-protocol/sei-chain/x/tokenfactory/types"
)
Expand Down Expand Up @@ -33,3 +35,25 @@ func (k Keeper) DenomsFromCreator(ctx context.Context, req *types.QueryDenomsFro
denoms := k.getDenomsFromCreator(sdkCtx, req.GetCreator())
return &types.QueryDenomsFromCreatorResponse{Denoms: denoms}, nil
}

// DenomMetadata implements Query/DenomMetadata gRPC method.
func (k Keeper) DenomMetadata(c context.Context, req *types.QueryDenomMetadataRequest) (*types.QueryDenomMetadataResponse, error) {
if req == nil {
return nil, status.Errorf(codes.InvalidArgument, "empty request")
}

if req.Denom == "" {
return nil, status.Error(codes.InvalidArgument, "invalid denom")
}

ctx := sdk.UnwrapSDKContext(c)

metadata, found := k.bankKeeper.GetDenomMetaData(ctx, req.Denom)
if !found {
return nil, status.Errorf(codes.NotFound, "client metadata for denom %s", req.Denom)
}

return &types.QueryDenomMetadataResponse{
Metadata: metadata,
}, nil
}
81 changes: 81 additions & 0 deletions x/tokenfactory/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package keeper_test

import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/sei-protocol/sei-chain/x/tokenfactory/types"
)

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

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

suite.App.BankKeeper.SetDenomMetaData(suite.Ctx, expMetadata)
req = &types.QueryDenomMetadataRequest{
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.DenomMetadata(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
Loading