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

Migrate copied nft module to cosmos sdk nft module #666

Merged
merged 3 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 4 additions & 0 deletions app/amino_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/cosmos/cosmos-sdk/x/nft"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
ibcinterchainaccountstypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller/types"
Expand All @@ -38,6 +39,9 @@ func TestLegacyAmino_ExpectedMessages(t *testing.T) {
sdk.MsgTypeURL(&banktypes.MsgUpdateParams{}): {},
sdk.MsgTypeURL(&banktypes.MsgSetSendEnabled{}): {},

// nft
sdk.MsgTypeURL(&nft.MsgSend{}): {},

// gov
sdk.MsgTypeURL(&govtypesv1.MsgExecLegacyContent{}): {},

Expand Down
20 changes: 16 additions & 4 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ import (
"github.com/CoreumFoundation/coreum/v3/x/feemodel"
feemodelkeeper "github.com/CoreumFoundation/coreum/v3/x/feemodel/keeper"
feemodeltypes "github.com/CoreumFoundation/coreum/v3/x/feemodel/types"
"github.com/CoreumFoundation/coreum/v3/x/nft"
nftkeeper "github.com/CoreumFoundation/coreum/v3/x/nft/keeper"
cnftkeeper "github.com/CoreumFoundation/coreum/v3/x/nft/keeper"
cnftmodule "github.com/CoreumFoundation/coreum/v3/x/nft/module"
wasmcustomhandler "github.com/CoreumFoundation/coreum/v3/x/wasm/handler"
"github.com/CoreumFoundation/coreum/v3/x/wbank"
wbankkeeper "github.com/CoreumFoundation/coreum/v3/x/wbank/keeper"
Expand All @@ -141,6 +141,8 @@ import (
"github.com/CoreumFoundation/coreum/v3/x/wnft"
wnftkeeper "github.com/CoreumFoundation/coreum/v3/x/wnft/keeper"
"github.com/CoreumFoundation/coreum/v3/x/wstaking"
"github.com/cosmos/cosmos-sdk/x/nft"
nftkeeper "github.com/cosmos/cosmos-sdk/x/nft/keeper"
)

const (
Expand Down Expand Up @@ -193,6 +195,7 @@ var (
wasm.AppModuleBasic{},
feemodel.AppModuleBasic{},
wnft.AppModuleBasic{},
cnftmodule.AppModuleBasic{},
assetft.AppModuleBasic{},
assetnft.AppModuleBasic{},
customparams.AppModuleBasic{},
Expand Down Expand Up @@ -318,7 +321,7 @@ func New(
authtypes.StoreKey, authz.ModuleName, banktypes.StoreKey, stakingtypes.StoreKey, crisistypes.StoreKey, minttypes.StoreKey,
distrtypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey,
feegrant.StoreKey, evidencetypes.StoreKey, capabilitytypes.StoreKey, consensusparamtypes.StoreKey, wasmtypes.StoreKey, feemodeltypes.StoreKey,
assetfttypes.StoreKey, assetnfttypes.StoreKey, nftkeeper.StoreKey, ibcexported.StoreKey, ibctransfertypes.StoreKey,
assetfttypes.StoreKey, assetnfttypes.StoreKey, cnftkeeper.StoreKey, ibcexported.StoreKey, ibctransfertypes.StoreKey,
delaytypes.StoreKey, customparamstypes.StoreKey,
)
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, feemodeltypes.TransientStoreKey)
Expand Down Expand Up @@ -491,7 +494,7 @@ func New(
app.IBCKeeper = ibckeeper.NewKeeper(appCodec, keys[ibcexported.StoreKey], app.GetSubspace(ibcexported.ModuleName),
app.StakingKeeper, app.UpgradeKeeper, app.ScopedIBCKeeper)

nftKeeper := nftkeeper.NewKeeper(keys[nftkeeper.StoreKey], appCodec, app.AccountKeeper, app.BankKeeper)
nftKeeper := nftkeeper.NewKeeper(keys[cnftkeeper.StoreKey], appCodec, app.AccountKeeper, app.BankKeeper)
app.AssetNFTKeeper = assetnftkeeper.NewKeeper(
appCodec,
keys[assetnfttypes.StoreKey],
Expand Down Expand Up @@ -1049,6 +1052,15 @@ func (app *App) RegisterAPIRoutes(apiSvr *serverapi.Server, _ serverconfig.APICo
// Register grpc-gateway routes for all modules.
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

// Regsiter cnft routes.
// We register the tx and query handlers here, since we don't want to introduce a new module to the
// list of app.Modules where we have to handle genesis registration and migraitons. we only need to
// keep these deprecated handlers around to give time to users to migrate.
cnftKeeper := cnftkeeper.NewKeeper(app.NFTKeeper)
cnftModule := cnftmodule.NewAppModule(app.AppCodec(), cnftKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry)
cnftModule.RegisterServices(app.configurator)
cnftModule.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

// register app's OpenAPI routes.
apiSvr.Router.Handle("/static/openapi.json", http.FileServer(http.FS(docs.Docs)))
apiSvr.Router.HandleFunc("/", openapi.Handler(Name, "/static/openapi.json"))
Expand Down
32 changes: 24 additions & 8 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2866,13 +2866,27 @@ Query defines the gRPC querier service.

| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `Balance` | [QueryBalanceRequest](#coreum.nft.v1beta1.QueryBalanceRequest) | [QueryBalanceResponse](#coreum.nft.v1beta1.QueryBalanceResponse) | Balance queries the number of NFTs of a given class owned by the owner, same as balanceOf in ERC721 | GET|/coreum/nft/v1beta1/balance/{owner}/{class_id}|
| `Owner` | [QueryOwnerRequest](#coreum.nft.v1beta1.QueryOwnerRequest) | [QueryOwnerResponse](#coreum.nft.v1beta1.QueryOwnerResponse) | Owner queries the owner of the NFT based on its class and id, same as ownerOf in ERC721 | GET|/coreum/nft/v1beta1/owner/{class_id}/{id}|
| `Supply` | [QuerySupplyRequest](#coreum.nft.v1beta1.QuerySupplyRequest) | [QuerySupplyResponse](#coreum.nft.v1beta1.QuerySupplyResponse) | Supply queries the number of NFTs from the given class, same as totalSupply of ERC721. | GET|/coreum/nft/v1beta1/supply/{class_id}|
| `NFTs` | [QueryNFTsRequest](#coreum.nft.v1beta1.QueryNFTsRequest) | [QueryNFTsResponse](#coreum.nft.v1beta1.QueryNFTsResponse) | NFTs queries all NFTs of a given class or owner,choose at least one of the two, similar to tokenByIndex in ERC721Enumerable | GET|/coreum/nft/v1beta1/nfts|
| `NFT` | [QueryNFTRequest](#coreum.nft.v1beta1.QueryNFTRequest) | [QueryNFTResponse](#coreum.nft.v1beta1.QueryNFTResponse) | NFT queries an NFT based on its class and id. | GET|/coreum/nft/v1beta1/nfts/{class_id}/{id}|
| `Class` | [QueryClassRequest](#coreum.nft.v1beta1.QueryClassRequest) | [QueryClassResponse](#coreum.nft.v1beta1.QueryClassResponse) | Class queries an NFT class based on its id | GET|/coreum/nft/v1beta1/classes/{class_id}|
| `Classes` | [QueryClassesRequest](#coreum.nft.v1beta1.QueryClassesRequest) | [QueryClassesResponse](#coreum.nft.v1beta1.QueryClassesResponse) | Classes queries all NFT classes | GET|/coreum/nft/v1beta1/classes|
| `Balance` | [QueryBalanceRequest](#coreum.nft.v1beta1.QueryBalanceRequest) | [QueryBalanceResponse](#coreum.nft.v1beta1.QueryBalanceResponse) | Balance queries the number of NFTs of a given class owned by the owner, same as balanceOf in ERC721

Deprecated: use cosmos-sdk/x/nft package instead | GET|/coreum/nft/v1beta1/balance/{owner}/{class_id}|
| `Owner` | [QueryOwnerRequest](#coreum.nft.v1beta1.QueryOwnerRequest) | [QueryOwnerResponse](#coreum.nft.v1beta1.QueryOwnerResponse) | Owner queries the owner of the NFT based on its class and id, same as ownerOf in ERC721

Deprecated: use cosmos-sdk/x/nft package instead | GET|/coreum/nft/v1beta1/owner/{class_id}/{id}|
| `Supply` | [QuerySupplyRequest](#coreum.nft.v1beta1.QuerySupplyRequest) | [QuerySupplyResponse](#coreum.nft.v1beta1.QuerySupplyResponse) | Supply queries the number of NFTs from the given class, same as totalSupply of ERC721.

Deprecated: use cosmos-sdk/x/nft package instead | GET|/coreum/nft/v1beta1/supply/{class_id}|
| `NFTs` | [QueryNFTsRequest](#coreum.nft.v1beta1.QueryNFTsRequest) | [QueryNFTsResponse](#coreum.nft.v1beta1.QueryNFTsResponse) | NFTs queries all NFTs of a given class or owner,choose at least one of the two, similar to tokenByIndex in ERC721Enumerable

Deprecated: use cosmos-sdk/x/nft package instead | GET|/coreum/nft/v1beta1/nfts|
| `NFT` | [QueryNFTRequest](#coreum.nft.v1beta1.QueryNFTRequest) | [QueryNFTResponse](#coreum.nft.v1beta1.QueryNFTResponse) | NFT queries an NFT based on its class and id.

Deprecated: use cosmos-sdk/x/nft package instead | GET|/coreum/nft/v1beta1/nfts/{class_id}/{id}|
| `Class` | [QueryClassRequest](#coreum.nft.v1beta1.QueryClassRequest) | [QueryClassResponse](#coreum.nft.v1beta1.QueryClassResponse) | Class queries an NFT class based on its id

Deprecated: use cosmos-sdk/x/nft package instead | GET|/coreum/nft/v1beta1/classes/{class_id}|
| `Classes` | [QueryClassesRequest](#coreum.nft.v1beta1.QueryClassesRequest) | [QueryClassesResponse](#coreum.nft.v1beta1.QueryClassesResponse) | Classes queries all NFT classes

Deprecated: use cosmos-sdk/x/nft package instead | GET|/coreum/nft/v1beta1/classes|

<!-- end services -->

Expand Down Expand Up @@ -2926,7 +2940,9 @@ Msg defines the nft Msg service.

| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `Send` | [MsgSend](#coreum.nft.v1beta1.MsgSend) | [MsgSendResponse](#coreum.nft.v1beta1.MsgSendResponse) | Send defines a method to send a nft from one account to another account. | |
| `Send` | [MsgSend](#coreum.nft.v1beta1.MsgSend) | [MsgSendResponse](#coreum.nft.v1beta1.MsgSendResponse) | Send defines a method to send a nft from one account to another account.

Deprecated: use cosmos-sdk/x/nft package instead | |

<!-- end services -->

Expand Down
7 changes: 7 additions & 0 deletions docs/static/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,7 @@
},
"/coreum/nft/v1beta1/balance/{owner}/{class_id}": {
"get": {
"description": "Deprecated: use cosmos-sdk/x/nft package instead",
"operationId": "GithubComCoreumFoundationCoreumV3XNftBalance",
"parameters": [
{
Expand Down Expand Up @@ -947,6 +948,7 @@
},
"/coreum/nft/v1beta1/classes": {
"get": {
"description": "Deprecated: use cosmos-sdk/x/nft package instead",
"operationId": "GithubComCoreumFoundationCoreumV3XNftClasses",
"parameters": [
{
Expand Down Expand Up @@ -1010,6 +1012,7 @@
},
"/coreum/nft/v1beta1/classes/{class_id}": {
"get": {
"description": "Deprecated: use cosmos-sdk/x/nft package instead",
"operationId": "GithubComCoreumFoundationCoreumV3XNftClass",
"parameters": [
{
Expand Down Expand Up @@ -1041,6 +1044,7 @@
},
"/coreum/nft/v1beta1/nfts": {
"get": {
"description": "Deprecated: use cosmos-sdk/x/nft package instead",
"operationId": "GithubComCoreumFoundationCoreumV3XNftNFTs",
"parameters": [
{
Expand Down Expand Up @@ -1116,6 +1120,7 @@
},
"/coreum/nft/v1beta1/nfts/{class_id}/{id}": {
"get": {
"description": "Deprecated: use cosmos-sdk/x/nft package instead",
"operationId": "GithubComCoreumFoundationCoreumV3XNftNFT",
"parameters": [
{
Expand Down Expand Up @@ -1153,6 +1158,7 @@
},
"/coreum/nft/v1beta1/owner/{class_id}/{id}": {
"get": {
"description": "Deprecated: use cosmos-sdk/x/nft package instead",
"operationId": "GithubComCoreumFoundationCoreumV3XNftOwner",
"parameters": [
{
Expand Down Expand Up @@ -1190,6 +1196,7 @@
},
"/coreum/nft/v1beta1/supply/{class_id}": {
"get": {
"description": "Deprecated: use cosmos-sdk/x/nft package instead",
"operationId": "GithubComCoreumFoundationCoreumV3XNftSupply",
"parameters": [
{
Expand Down
89 changes: 1 addition & 88 deletions integration-tests/modules/assetnft_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
"github.com/cosmos/cosmos-sdk/x/nft"
"github.com/cosmos/gogoproto/proto"
"github.com/samber/lo"
"github.com/stretchr/testify/assert"
Expand All @@ -27,7 +28,6 @@ import (
"github.com/CoreumFoundation/coreum/v3/testutil/event"
"github.com/CoreumFoundation/coreum/v3/testutil/integration"
assetnfttypes "github.com/CoreumFoundation/coreum/v3/x/asset/nft/types"
"github.com/CoreumFoundation/coreum/v3/x/nft"
)

// TestAssetNFTQueryParams queries parameters of asset/nft module.
Expand Down Expand Up @@ -1471,90 +1471,3 @@ func TestAssetNFTAuthZ(t *testing.T) {
requireT.NoError(err)
requireT.True(queryRes.Frozen)
}

// TestAssetNFTAminoMultisig tests that assetnft module works seamlessly with amino multisig.
func TestAssetNFTAminoMultisig(t *testing.T) {
t.Parallel()

ctx, chain := integrationtests.NewCoreumTestingContext(t)
requireT := require.New(t)
recipient := chain.GenAccount()

multisigPublicKey, keyNamesSet, err := chain.GenMultisigAccount(2, 2)
requireT.NoError(err)
multisigAddress := sdk.AccAddress(multisigPublicKey.Address())
signer1KeyName := keyNamesSet[0]
signer2KeyName := keyNamesSet[1]

nftClient := nft.NewQueryClient(chain.ClientContext)

// fund the multisig account
chain.FundAccountWithOptions(ctx, t, multisigAddress, integration.BalancesOptions{
Messages: []sdk.Msg{
&assetnfttypes.MsgIssueClass{},
&assetnfttypes.MsgMint{},
&nft.MsgSend{},
},
Amount: chain.QueryAssetNFTParams(ctx, t).MintFee.Amount,
})

// issue new NFT class
issueMsg := &assetnfttypes.MsgIssueClass{
Issuer: multisigAddress.String(),
Symbol: "NFTClassSymbol",
Features: []assetnfttypes.ClassFeature{
assetnfttypes.ClassFeature_freezing,
},
RoyaltyRate: sdk.NewDec(0),
}

_, err = chain.SignAndBroadcastMultisigTx(
ctx,
chain.ClientContext.WithFromAddress(multisigAddress),
chain.TxFactory().WithGas(chain.GasLimitByMsgs(issueMsg)),
issueMsg,
signer1KeyName, signer2KeyName)
requireT.NoError(err)

// mint new token in that class
classID := assetnfttypes.BuildClassID(issueMsg.Symbol, multisigAddress)
nftID := "id-1"
mintMsg := &assetnfttypes.MsgMint{
Sender: multisigAddress.String(),
ID: nftID,
ClassID: classID,
}

_, err = chain.SignAndBroadcastMultisigTx(
ctx,
chain.ClientContext.WithFromAddress(multisigAddress),
chain.TxFactory().WithGas(chain.GasLimitByMsgs(mintMsg)),
mintMsg,
signer1KeyName, signer2KeyName)
requireT.NoError(err)

sendMsg := &nft.MsgSend{
Sender: multisigAddress.String(),
ClassId: classID,
Id: nftID,
Receiver: recipient.String(),
}

_, err = chain.SignAndBroadcastMultisigTx(
ctx,
chain.ClientContext.WithFromAddress(multisigAddress),
chain.TxFactory().WithGas(chain.GasLimitByMsgs(sendMsg)),
sendMsg,
signer1KeyName, signer2KeyName)
requireT.NoError(err)

nftRes, err := nftClient.NFT(ctx, &nft.QueryNFTRequest{
ClassId: classID,
Id: nftID,
})
requireT.NoError(err)
requireT.Equal(&nft.NFT{
ClassId: classID,
Id: nftID,
}, nftRes.Nft)
}
Loading
Loading