From f3af2f22f1f2a6e363200ee3838c3845a9558a99 Mon Sep 17 00:00:00 2001 From: Wojtek <103407812+wojtek-coreum@users.noreply.github.com> Date: Wed, 25 Oct 2023 09:28:11 +0200 Subject: [PATCH 1/4] Testing transfers to non-whitelisted smart contract (#676) # Description Funds might be transferred to smart contract in 3 ways: 1. regular bank send 2. smart contract call 3. smart contract instantiation In this PR, tests are added to verify that in all 3 cases transfer fails if smart contract is not whitelisted. # Reviewers checklist: - [ ] Try to write more meaningful comments with clear actions to be taken. - [ ] Nit-picking should be unblocking. Focus on core issues. # Authors checklist - [x] Provide a concise and meaningful description - [x] Review the code yourself first, before making the PR. - [x] Annotate your PR in places that require explanation. - [x] Think and try to split the PR to smaller PR if it is big. --- integration-tests/modules/assetft_test.go | 204 ++++++++++++++++++++++ 1 file changed, 204 insertions(+) diff --git a/integration-tests/modules/assetft_test.go b/integration-tests/modules/assetft_test.go index 1215f6d77..8a7a982e7 100644 --- a/integration-tests/modules/assetft_test.go +++ b/integration-tests/modules/assetft_test.go @@ -2382,6 +2382,210 @@ func TestAssetFTWhitelistIssuerAccount(t *testing.T) { requireT.ErrorIs(err, cosmoserrors.ErrUnauthorized) } +// TestAssetFTSendingToNonWhitelistedSmartContractIsDenied verifies that this is not possible to send token to smart contract +// if it is not whitelisted. +func TestAssetFTSendingToNonWhitelistedSmartContractIsDenied(t *testing.T) { + t.Parallel() + + ctx, chain := integrationtests.NewCoreumTestingContext(t) + + issuer := chain.GenAccount() + + requireT := require.New(t) + chain.Faucet.FundAccounts(ctx, t, + integration.NewFundedAccount(issuer, chain.NewCoin(sdkmath.NewInt(5000000000))), + ) + + clientCtx := chain.ClientContext + + // Issue a fungible token which cannot be sent to the smart contract + issueMsg := &assetfttypes.MsgIssue{ + Issuer: issuer.String(), + Symbol: "ABC", + Subunit: "abc", + Precision: 6, + InitialAmount: sdkmath.NewInt(1000), + Description: "ABC Description", + Features: []assetfttypes.Feature{ + assetfttypes.Feature_whitelisting, + }, + BurnRate: sdk.ZeroDec(), + SendCommissionRate: sdk.ZeroDec(), + } + + _, err := client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(issuer), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(issueMsg)), + issueMsg, + ) + + requireT.NoError(err) + denom := assetfttypes.BuildDenom(issueMsg.Subunit, issuer) + + initialPayload, err := json.Marshal(moduleswasm.SimpleState{ + Count: 1337, + }) + requireT.NoError(err) + + contractAddr, _, err := chain.Wasm.DeployAndInstantiateWASMContract( + ctx, + chain.TxFactory().WithSimulateAndExecute(true), + issuer, + moduleswasm.SimpleStateWASM, + integration.InstantiateConfig{ + AccessType: wasmtypes.AccessTypeUnspecified, + Payload: initialPayload, + Label: "simple_state", + }, + ) + requireT.NoError(err) + + // sending coins to the smart contract should fail + sendMsg := &banktypes.MsgSend{ + FromAddress: issuer.String(), + ToAddress: contractAddr, + Amount: sdk.NewCoins(sdk.NewInt64Coin(denom, 100)), + } + _, err = client.BroadcastTx( + ctx, + clientCtx.WithFromAddress(issuer), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(sendMsg)), + sendMsg, + ) + requireT.ErrorIs(err, assetfttypes.ErrWhitelistedLimitExceeded) +} + +// TestAssetFTAttachingToNonWhitelistedSmartContractCallIsDenied verifies that this is not possible to attach token to smart contract call +// if contract is not whitelisted. +func TestAssetFTAttachingToNonWhitelistedSmartContractCallIsDenied(t *testing.T) { + t.Parallel() + + ctx, chain := integrationtests.NewCoreumTestingContext(t) + + issuer := chain.GenAccount() + + requireT := require.New(t) + chain.Faucet.FundAccounts(ctx, t, + integration.NewFundedAccount(issuer, chain.NewCoin(sdkmath.NewInt(5000000000))), + ) + + txf := chain.TxFactory(). + WithSimulateAndExecute(true) + + // Issue a fungible token which cannot be sent to the smart contract + issueMsg := &assetfttypes.MsgIssue{ + Issuer: issuer.String(), + Symbol: "ABC", + Subunit: "abc", + Precision: 6, + InitialAmount: sdkmath.NewInt(1000), + Description: "ABC Description", + Features: []assetfttypes.Feature{ + assetfttypes.Feature_whitelisting, + }, + BurnRate: sdk.ZeroDec(), + SendCommissionRate: sdk.ZeroDec(), + } + + _, err := client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(issuer), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(issueMsg)), + issueMsg, + ) + + requireT.NoError(err) + denom := assetfttypes.BuildDenom(issueMsg.Subunit, issuer) + + initialPayload, err := json.Marshal(moduleswasm.SimpleState{ + Count: 1337, + }) + requireT.NoError(err) + + contractAddr, _, err := chain.Wasm.DeployAndInstantiateWASMContract( + ctx, + txf, + issuer, + moduleswasm.SimpleStateWASM, + integration.InstantiateConfig{ + AccessType: wasmtypes.AccessTypeUnspecified, + Payload: initialPayload, + Label: "simple_state", + }, + ) + requireT.NoError(err) + + // Executing smart contract - this operation should fail because coins are attached to it + incrementPayload, err := moduleswasm.MethodToEmptyBodyPayload(moduleswasm.SimpleIncrement) + requireT.NoError(err) + _, err = chain.Wasm.ExecuteWASMContract(ctx, txf, issuer, contractAddr, incrementPayload, sdk.NewInt64Coin(denom, 100)) + requireT.ErrorContains(err, "whitelisted limit exceeded") +} + +// TestAssetFTAttachingToNonWhitelistedSmartContractInstantiationIsDenied verifies that this is not possible to attach token to smart contract instantiation +// if contract is not whitelisted. +func TestAssetFTAttachingToNonWhitelistedSmartContractInstantiationIsDenied(t *testing.T) { + t.Parallel() + + ctx, chain := integrationtests.NewCoreumTestingContext(t) + + issuer := chain.GenAccount() + + requireT := require.New(t) + chain.Faucet.FundAccounts(ctx, t, + integration.NewFundedAccount(issuer, chain.NewCoin(sdkmath.NewInt(5000000000))), + ) + + txf := chain.TxFactory(). + WithSimulateAndExecute(true) + + // Issue a fungible token which cannot be sent to the smart contract + issueMsg := &assetfttypes.MsgIssue{ + Issuer: issuer.String(), + Symbol: "ABC", + Subunit: "abc", + Precision: 6, + InitialAmount: sdkmath.NewInt(1000), + Description: "ABC Description", + Features: []assetfttypes.Feature{ + assetfttypes.Feature_whitelisting, + }, + BurnRate: sdk.ZeroDec(), + SendCommissionRate: sdk.ZeroDec(), + } + + _, err := client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(issuer), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(issueMsg)), + issueMsg, + ) + + requireT.NoError(err) + denom := assetfttypes.BuildDenom(issueMsg.Subunit, issuer) + + initialPayload, err := json.Marshal(moduleswasm.SimpleState{ + Count: 1337, + }) + requireT.NoError(err) + + // This operation should fail due to coins being attached to it + _, _, err = chain.Wasm.DeployAndInstantiateWASMContract( + ctx, + txf, + issuer, + moduleswasm.SimpleStateWASM, + integration.InstantiateConfig{ + AccessType: wasmtypes.AccessTypeUnspecified, + Payload: initialPayload, + Amount: sdk.NewInt64Coin(denom, 100), + Label: "simple_state", + }, + ) + requireT.ErrorContains(err, "whitelisted limit exceeded") +} + // TestBareToken checks none of the features will work if the flags are not set. func TestBareToken(t *testing.T) { t.Parallel() From 915968ee7173bf18829bcec6824a826ff43629ac Mon Sep 17 00:00:00 2001 From: milad Date: Wed, 25 Oct 2023 13:59:19 +0330 Subject: [PATCH 2/4] Added SendAuthorization for sending specific NFTs. (#678) # Description # Reviewers checklist: - [ ] Try to write more meaningful comments with clear actions to be taken. - [ ] Nit-picking should be unblocking. Focus on core issues. # Authors checklist - [x] Provide a concise and meaningful description - [x] Review the code yourself first, before making the PR. - [x] Annotate your PR in places that require explanation. - [x] Think and try to split the PR to smaller PR if it is big. --- docs/api.md | 51 ++ integration-tests/modules/assetnft_test.go | 140 +++++ proto/coreum/asset/nft/v1/authz.proto | 25 + x/asset/nft/types/authz.pb.go | 563 +++++++++++++++++++ x/asset/nft/types/codec.go | 5 + x/asset/nft/types/send_authorization.go | 70 +++ x/asset/nft/types/send_authorization_test.go | 95 ++++ 7 files changed, 949 insertions(+) create mode 100644 proto/coreum/asset/nft/v1/authz.proto create mode 100644 x/asset/nft/types/authz.pb.go create mode 100644 x/asset/nft/types/send_authorization.go create mode 100644 x/asset/nft/types/send_authorization_test.go diff --git a/docs/api.md b/docs/api.md index 2a9aa0884..e2bf4da92 100644 --- a/docs/api.md +++ b/docs/api.md @@ -69,6 +69,10 @@ - [Msg](#coreum.asset.ft.v1.Msg) +- [coreum/asset/nft/v1/authz.proto](#coreum/asset/nft/v1/authz.proto) + - [NFTIdentifier](#coreum.asset.nft.v1.NFTIdentifier) + - [SendAuthorization](#coreum.asset.nft.v1.SendAuthorization) + - [coreum/asset/nft/v1/event.proto](#coreum/asset/nft/v1/event.proto) - [EventAddedToClassWhitelist](#coreum.asset.nft.v1.EventAddedToClassWhitelist) - [EventAddedToWhitelist](#coreum.asset.nft.v1.EventAddedToWhitelist) @@ -1224,6 +1228,53 @@ Msg defines the Msg service. + +

Top

+ +## coreum/asset/nft/v1/authz.proto + + + + + +### NFTIdentifier + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `class_id` | [string](#string) | | class_id defines the unique identifier of the nft classification, similar to the contract address of ERC721 | +| `id` | [string](#string) | | id defines the unique identification of nft | + + + + + + + + +### SendAuthorization +SendAuthorization allows the grantee to send specific NFTs from the granter's account. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `nfts` | [NFTIdentifier](#coreum.asset.nft.v1.NFTIdentifier) | repeated | | + + + + + + + + + + + + + + +

Top

diff --git a/integration-tests/modules/assetnft_test.go b/integration-tests/modules/assetnft_test.go index d054a9c8f..0f364edfa 100644 --- a/integration-tests/modules/assetnft_test.go +++ b/integration-tests/modules/assetnft_test.go @@ -1875,3 +1875,143 @@ func TestAssetNFTClassWhitelist(t *testing.T) { ) requireT.NoError(err) } + +// TestAssetNFTSendAuthorization tests that assetnft SendAuthorization works as expected. +func TestAssetNFTSendAuthorization(t *testing.T) { + t.Parallel() + + ctx, chain := integrationtests.NewCoreumTestingContext(t) + + requireT := require.New(t) + granter := chain.GenAccount() + grantee := chain.GenAccount() + recipient := chain.GenAccount() + nftClient := nft.NewQueryClient(chain.ClientContext) + authzClient := authztypes.NewQueryClient(chain.ClientContext) + + chain.FundAccountWithOptions(ctx, t, granter, integration.BalancesOptions{ + Messages: []sdk.Msg{ + &assetnfttypes.MsgIssueClass{}, + &assetnfttypes.MsgMint{}, + &authztypes.MsgGrant{}, + }, + Amount: chain.QueryAssetNFTParams(ctx, t).MintFee.Amount, + }) + + chain.FundAccountWithOptions(ctx, t, grantee, integration.BalancesOptions{ + Amount: sdk.NewInt(1), + }) + + // issue new NFT class + issueMsg := &assetnfttypes.MsgIssueClass{ + Issuer: granter.String(), + Symbol: "NFTClassSymbol", + Features: []assetnfttypes.ClassFeature{}, + } + + // mint new token in that class + classID := assetnfttypes.BuildClassID(issueMsg.Symbol, granter) + nftID := "id-1" + mintMsg1 := &assetnfttypes.MsgMint{ + Sender: granter.String(), + ID: nftID, + ClassID: classID, + } + + msgList := []sdk.Msg{issueMsg, mintMsg1} + _, err := client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(granter), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(msgList...)), + msgList..., + ) + requireT.NoError(err) + + // try to send before grant + sendMsg := &nft.MsgSend{ + ClassId: classID, + Id: nftID, + Sender: granter.String(), + Receiver: recipient.String(), + } + execMsg := authztypes.NewMsgExec(grantee, []sdk.Msg{sendMsg}) + + chain.FundAccountWithOptions(ctx, t, grantee, integration.BalancesOptions{ + Messages: []sdk.Msg{ + &execMsg, + &execMsg, + }, + }) + + _, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(grantee), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(&execMsg)), + &execMsg, + ) + requireT.Error(err) + requireT.ErrorIs(err, authztypes.ErrNoAuthorizationFound) + + // grant authorization to send nft + grantMsg, err := authztypes.NewMsgGrant( + granter, + grantee, + assetnfttypes.NewSendAuthorization([]assetnfttypes.NFTIdentifier{ + {ClassId: classID, Id: nftID}, + {ClassId: classID, Id: "not-minted-yet"}, + }), + lo.ToPtr(time.Now().Add(time.Minute)), + ) + requireT.NoError(err) + _, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(granter), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(grantMsg)), + grantMsg, + ) + requireT.NoError(err) + + // assert granted + gransRes, err := authzClient.Grants(ctx, &authztypes.QueryGrantsRequest{ + Granter: granter.String(), + Grantee: grantee.String(), + }) + requireT.NoError(err) + requireT.Equal(1, len(gransRes.Grants)) + updatedGrant := assetnfttypes.SendAuthorization{} + chain.ClientContext.Codec().MustUnmarshal(gransRes.Grants[0].Authorization.Value, &updatedGrant) + requireT.ElementsMatch([]assetnfttypes.NFTIdentifier{ + {ClassId: classID, Id: nftID}, + {ClassId: classID, Id: "not-minted-yet"}, + }, updatedGrant.Nfts) + + // try to send after grant + _, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(grantee), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(&execMsg)), + &execMsg, + ) + requireT.NoError(err) + + // assert transfer of ownership + ownerResp, err := nftClient.Owner(ctx, &nft.QueryOwnerRequest{ + ClassId: classID, + Id: nftID, + }) + requireT.NoError(err) + requireT.EqualValues(ownerResp.Owner, recipient.String()) + + // assert granted + gransRes, err = authzClient.Grants(ctx, &authztypes.QueryGrantsRequest{ + Granter: granter.String(), + Grantee: grantee.String(), + }) + requireT.NoError(err) + requireT.Equal(1, len(gransRes.Grants)) + updatedGrant = assetnfttypes.SendAuthorization{} + chain.ClientContext.Codec().MustUnmarshal(gransRes.Grants[0].Authorization.Value, &updatedGrant) + requireT.ElementsMatch([]assetnfttypes.NFTIdentifier{ + {ClassId: classID, Id: "not-minted-yet"}, + }, updatedGrant.Nfts) +} diff --git a/proto/coreum/asset/nft/v1/authz.proto b/proto/coreum/asset/nft/v1/authz.proto new file mode 100644 index 000000000..a3aac4c86 --- /dev/null +++ b/proto/coreum/asset/nft/v1/authz.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; +package coreum.asset.nft.v1; + +import "amino/amino.proto"; +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; + +option go_package = "github.com/CoreumFoundation/coreum/v3/x/asset/nft/types"; + +// SendAuthorization allows the grantee to send specific NFTs from the granter's account. +message SendAuthorization { + option (cosmos_proto.implements_interface) = "cosmos.authz.v1beta1.Authorization"; + option (amino.name) = "cosmos-sdk/nft/SendAuthorization"; + repeated NFTIdentifier nfts = 1 [ + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true + ]; +} + +message NFTIdentifier { + // class_id defines the unique identifier of the nft classification, similar to the contract address of ERC721 + string class_id = 1; + // id defines the unique identification of nft + string id = 2; +} diff --git a/x/asset/nft/types/authz.pb.go b/x/asset/nft/types/authz.pb.go new file mode 100644 index 000000000..0608493c8 --- /dev/null +++ b/x/asset/nft/types/authz.pb.go @@ -0,0 +1,563 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: coreum/asset/nft/v1/authz.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// SendAuthorization allows the grantee to send specific NFTs from the granter's account. +type SendAuthorization struct { + Nfts []NFTIdentifier `protobuf:"bytes,1,rep,name=nfts,proto3" json:"nfts"` +} + +func (m *SendAuthorization) Reset() { *m = SendAuthorization{} } +func (m *SendAuthorization) String() string { return proto.CompactTextString(m) } +func (*SendAuthorization) ProtoMessage() {} +func (*SendAuthorization) Descriptor() ([]byte, []int) { + return fileDescriptor_58d9031136e2b4ca, []int{0} +} +func (m *SendAuthorization) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SendAuthorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SendAuthorization.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SendAuthorization) XXX_Merge(src proto.Message) { + xxx_messageInfo_SendAuthorization.Merge(m, src) +} +func (m *SendAuthorization) XXX_Size() int { + return m.Size() +} +func (m *SendAuthorization) XXX_DiscardUnknown() { + xxx_messageInfo_SendAuthorization.DiscardUnknown(m) +} + +var xxx_messageInfo_SendAuthorization proto.InternalMessageInfo + +func (m *SendAuthorization) GetNfts() []NFTIdentifier { + if m != nil { + return m.Nfts + } + return nil +} + +type NFTIdentifier struct { + // class_id defines the unique identifier of the nft classification, similar to the contract address of ERC721 + ClassId string `protobuf:"bytes,1,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` + // id defines the unique identification of nft + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` +} + +func (m *NFTIdentifier) Reset() { *m = NFTIdentifier{} } +func (m *NFTIdentifier) String() string { return proto.CompactTextString(m) } +func (*NFTIdentifier) ProtoMessage() {} +func (*NFTIdentifier) Descriptor() ([]byte, []int) { + return fileDescriptor_58d9031136e2b4ca, []int{1} +} +func (m *NFTIdentifier) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NFTIdentifier) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NFTIdentifier.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NFTIdentifier) XXX_Merge(src proto.Message) { + xxx_messageInfo_NFTIdentifier.Merge(m, src) +} +func (m *NFTIdentifier) XXX_Size() int { + return m.Size() +} +func (m *NFTIdentifier) XXX_DiscardUnknown() { + xxx_messageInfo_NFTIdentifier.DiscardUnknown(m) +} + +var xxx_messageInfo_NFTIdentifier proto.InternalMessageInfo + +func (m *NFTIdentifier) GetClassId() string { + if m != nil { + return m.ClassId + } + return "" +} + +func (m *NFTIdentifier) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func init() { + proto.RegisterType((*SendAuthorization)(nil), "coreum.asset.nft.v1.SendAuthorization") + proto.RegisterType((*NFTIdentifier)(nil), "coreum.asset.nft.v1.NFTIdentifier") +} + +func init() { proto.RegisterFile("coreum/asset/nft/v1/authz.proto", fileDescriptor_58d9031136e2b4ca) } + +var fileDescriptor_58d9031136e2b4ca = []byte{ + // 329 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xce, 0x2f, 0x4a, + 0x2d, 0xcd, 0xd5, 0x4f, 0x2c, 0x2e, 0x4e, 0x2d, 0xd1, 0xcf, 0x4b, 0x2b, 0xd1, 0x2f, 0x33, 0xd4, + 0x4f, 0x2c, 0x2d, 0xc9, 0xa8, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x86, 0x28, 0xd0, + 0x03, 0x2b, 0xd0, 0xcb, 0x4b, 0x2b, 0xd1, 0x2b, 0x33, 0x94, 0x12, 0x4c, 0xcc, 0xcd, 0xcc, 0xcb, + 0xd7, 0x07, 0x93, 0x10, 0x75, 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9, 0x60, 0xa6, 0x3e, 0x88, 0x05, + 0x15, 0x95, 0x4c, 0xce, 0x2f, 0xce, 0xcd, 0x2f, 0x8e, 0x87, 0x48, 0x40, 0x38, 0x10, 0x29, 0xa5, + 0xc5, 0x8c, 0x5c, 0x82, 0xc1, 0xa9, 0x79, 0x29, 0x8e, 0xa5, 0x25, 0x19, 0xf9, 0x45, 0x99, 0x55, + 0x89, 0x25, 0x99, 0xf9, 0x79, 0x42, 0x8e, 0x5c, 0x2c, 0x79, 0x69, 0x25, 0xc5, 0x12, 0x8c, 0x0a, + 0xcc, 0x1a, 0xdc, 0x46, 0x4a, 0x7a, 0x58, 0x6c, 0xd7, 0xf3, 0x73, 0x0b, 0xf1, 0x4c, 0x49, 0xcd, + 0x2b, 0xc9, 0x4c, 0xcb, 0x4c, 0x2d, 0x72, 0xe2, 0x3c, 0x71, 0x4f, 0x9e, 0x61, 0xc5, 0xf3, 0x0d, + 0x5a, 0x8c, 0x41, 0x60, 0xad, 0x56, 0xde, 0xa7, 0xb6, 0xe8, 0x2a, 0x41, 0xad, 0x82, 0xf8, 0xa4, + 0xcc, 0x30, 0x29, 0xb5, 0x24, 0xd1, 0x50, 0x0f, 0xc5, 0xaa, 0xae, 0xe7, 0x1b, 0xb4, 0x14, 0x20, + 0xca, 0x74, 0x8b, 0x53, 0xb2, 0xc1, 0x7e, 0xc7, 0x70, 0x8f, 0x92, 0x15, 0x17, 0x2f, 0x8a, 0x75, + 0x42, 0x92, 0x5c, 0x1c, 0xc9, 0x39, 0x89, 0xc5, 0xc5, 0xf1, 0x99, 0x29, 0x12, 0x8c, 0x0a, 0x8c, + 0x1a, 0x9c, 0x41, 0xec, 0x60, 0xbe, 0x67, 0x8a, 0x10, 0x1f, 0x17, 0x53, 0x66, 0x8a, 0x04, 0x13, + 0x58, 0x90, 0x29, 0x33, 0xc5, 0x29, 0xf0, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, + 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, + 0xa2, 0xcc, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x9d, 0xc1, 0x3e, + 0x74, 0xcb, 0x2f, 0xcd, 0x4b, 0x01, 0x5b, 0xa9, 0x0f, 0x8d, 0x91, 0x32, 0x63, 0xfd, 0x0a, 0xa4, + 0x68, 0x29, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0x87, 0x9d, 0x31, 0x20, 0x00, 0x00, 0xff, + 0xff, 0x35, 0xc4, 0xa2, 0x3c, 0xb7, 0x01, 0x00, 0x00, +} + +func (m *SendAuthorization) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SendAuthorization) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SendAuthorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Nfts) > 0 { + for iNdEx := len(m.Nfts) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Nfts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthz(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *NFTIdentifier) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NFTIdentifier) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NFTIdentifier) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = encodeVarintAuthz(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0x12 + } + if len(m.ClassId) > 0 { + i -= len(m.ClassId) + copy(dAtA[i:], m.ClassId) + i = encodeVarintAuthz(dAtA, i, uint64(len(m.ClassId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintAuthz(dAtA []byte, offset int, v uint64) int { + offset -= sovAuthz(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *SendAuthorization) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Nfts) > 0 { + for _, e := range m.Nfts { + l = e.Size() + n += 1 + l + sovAuthz(uint64(l)) + } + } + return n +} + +func (m *NFTIdentifier) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClassId) + if l > 0 { + n += 1 + l + sovAuthz(uint64(l)) + } + l = len(m.Id) + if l > 0 { + n += 1 + l + sovAuthz(uint64(l)) + } + return n +} + +func sovAuthz(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozAuthz(x uint64) (n int) { + return sovAuthz(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *SendAuthorization) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SendAuthorization: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SendAuthorization: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Nfts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Nfts = append(m.Nfts, NFTIdentifier{}) + if err := m.Nfts[len(m.Nfts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthz(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthz + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NFTIdentifier) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NFTIdentifier: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NFTIdentifier: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthz(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthz + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipAuthz(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAuthz + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAuthz + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAuthz + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthAuthz + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupAuthz + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthAuthz + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthAuthz = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowAuthz = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupAuthz = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/asset/nft/types/codec.go b/x/asset/nft/types/codec.go index 543ee8b3d..c68e2dfe4 100644 --- a/x/asset/nft/types/codec.go +++ b/x/asset/nft/types/codec.go @@ -4,6 +4,7 @@ import ( cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" + "github.com/cosmos/cosmos-sdk/x/authz" "github.com/cosmos/gogoproto/proto" ) @@ -19,5 +20,9 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { &MsgAddToWhitelist{}, &MsgRemoveFromWhitelist{}, ) + registry.RegisterImplementations( + (*authz.Authorization)(nil), + &SendAuthorization{}, + ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } diff --git a/x/asset/nft/types/send_authorization.go b/x/asset/nft/types/send_authorization.go new file mode 100644 index 000000000..1d8bd7cfc --- /dev/null +++ b/x/asset/nft/types/send_authorization.go @@ -0,0 +1,70 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/authz" + "github.com/cosmos/cosmos-sdk/x/nft" +) + +var _ authz.Authorization = &SendAuthorization{} + +// NewSendAuthorization returns a new SendAuthorization object. +func NewSendAuthorization(nfts []NFTIdentifier) *SendAuthorization { + return &SendAuthorization{ + Nfts: nfts, + } +} + +// MsgTypeURL implements Authorization.MsgTypeURL. +func (a SendAuthorization) MsgTypeURL() string { + return sdk.MsgTypeURL(&nft.MsgSend{}) +} + +// Accept implements Authorization.Accept. +func (a SendAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.AcceptResponse, error) { + mSend, ok := msg.(*nft.MsgSend) + if !ok { + return authz.AcceptResponse{}, sdkerrors.ErrInvalidType.Wrap("type mismatch") + } + + exists := a.findAndRemoveNFT(mSend.ClassId, mSend.Id) + if !exists { + return authz.AcceptResponse{}, sdkerrors.ErrUnauthorized.Wrapf("requested NFT does not have transfer grant") + } + + return authz.AcceptResponse{ + Accept: true, + Delete: len(a.Nfts) == 0, + Updated: &a, + }, nil +} + +// ValidateBasic implements Authorization.ValidateBasic. +func (a SendAuthorization) ValidateBasic() error { + if len(a.Nfts) == 0 { + return ErrInvalidInput.Wrap("empty NFT list") + } + + for _, nft := range a.Nfts { + if err := ValidateTokenID(nft.Id); err != nil { + return ErrInvalidInput.Wrap(err.Error()) + } + + if _, _, err := DeconstructClassID(nft.ClassId); err != nil { + return ErrInvalidInput.Wrap(err.Error()) + } + } + + return nil +} + +func (a *SendAuthorization) findAndRemoveNFT(classID, nftID string) bool { + for index, nft := range a.Nfts { + if nft.ClassId == classID && nft.Id == nftID { + a.Nfts = append(a.Nfts[:index], a.Nfts[index+1:]...) + return true + } + } + return false +} diff --git a/x/asset/nft/types/send_authorization_test.go b/x/asset/nft/types/send_authorization_test.go new file mode 100644 index 000000000..6085b9b63 --- /dev/null +++ b/x/asset/nft/types/send_authorization_test.go @@ -0,0 +1,95 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFindAndRemoveNFT(t *testing.T) { + testCases := []struct { + name string + nfts []NFTIdentifier + classID string + nftID string + expectedNfts []NFTIdentifier + found bool + }{ + { + "nft not found", + []NFTIdentifier{ + {"class1", "nft1"}, + {"class2", "nft2"}, + {"class3", "nft3"}, + }, + "class", "nft", + []NFTIdentifier{ + {"class1", "nft1"}, + {"class2", "nft2"}, + {"class3", "nft3"}, + }, + false, + }, + { + "single element in list", + []NFTIdentifier{ + {"class1", "nft1"}, + }, + "class1", "nft1", + []NFTIdentifier{}, + true, + }, + { + "match start of the list", + []NFTIdentifier{ + {"class1", "nft1"}, + {"class2", "nft2"}, + {"class3", "nft3"}, + }, + "class1", "nft1", + []NFTIdentifier{ + {"class2", "nft2"}, + {"class3", "nft3"}, + }, + true, + }, + { + "match end of the list", + []NFTIdentifier{ + {"class1", "nft1"}, + {"class2", "nft2"}, + {"class3", "nft3"}, + }, + "class3", "nft3", + []NFTIdentifier{ + {"class1", "nft1"}, + {"class2", "nft2"}, + }, + true, + }, + { + "match middle of the list", + []NFTIdentifier{ + {"class1", "nft1"}, + {"class2", "nft2"}, + {"class3", "nft3"}, + }, + "class2", "nft2", + []NFTIdentifier{ + {"class1", "nft1"}, + {"class3", "nft3"}, + }, + true, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + a := NewSendAuthorization(tc.nfts) + found := a.findAndRemoveNFT(tc.classID, tc.nftID) + assert.EqualValues(t, tc.found, found) + assert.EqualValues(t, tc.expectedNfts, a.Nfts) + }) + } +} From 91a852d59b21dc82701a40bd86f860341b8737ed Mon Sep 17 00:00:00 2001 From: milad Date: Wed, 25 Oct 2023 16:20:16 +0330 Subject: [PATCH 3/4] Implement class freeze for NFTs (#680) # Description # Reviewers checklist: - [ ] Try to write more meaningful comments with clear actions to be taken. - [ ] Nit-picking should be unblocking. Focus on core issues. # Authors checklist - [x] Provide a concise and meaningful description - [x] Review the code yourself first, before making the PR. - [x] Annotate your PR in places that require explanation. - [x] Think and try to split the PR to smaller PR if it is big. --- docs/api.md | 159 +++ docs/static/openapi.json | 129 +++ integration-tests/modules/assetnft_test.go | 178 +++ proto/coreum/asset/nft/v1/event.proto | 11 + proto/coreum/asset/nft/v1/genesis.proto | 6 + proto/coreum/asset/nft/v1/query.proto | 31 + proto/coreum/asset/nft/v1/tx.proto | 18 + x/asset/nft/client/cli/query.go | 88 ++ x/asset/nft/client/cli/query_test.go | 1 + x/asset/nft/client/cli/tx.go | 82 ++ x/asset/nft/client/cli/tx_test.go | 69 ++ x/asset/nft/genesis.go | 22 + x/asset/nft/genesis_test.go | 27 + x/asset/nft/keeper/grpc_query.go | 25 + x/asset/nft/keeper/keeper.go | 182 ++- x/asset/nft/keeper/keeper_test.go | 185 +++ x/asset/nft/keeper/msg_server.go | 42 + x/asset/nft/types/codec.go | 4 + x/asset/nft/types/event.pb.go | 520 ++++++++- x/asset/nft/types/genesis.go | 14 + x/asset/nft/types/genesis.pb.go | 357 +++++- x/asset/nft/types/keys.go | 29 +- x/asset/nft/types/msgs.go | 84 ++ x/asset/nft/types/query.pb.go | 1191 +++++++++++++++++--- x/asset/nft/types/query.pb.gw.go | 242 ++++ x/asset/nft/types/tx.pb.go | 714 ++++++++++-- x/deterministicgas/config.go | 2 + x/deterministicgas/config_test.go | 2 +- x/deterministicgas/spec/README.md | 2 + 29 files changed, 4143 insertions(+), 273 deletions(-) diff --git a/docs/api.md b/docs/api.md index e2bf4da92..05d369124 100644 --- a/docs/api.md +++ b/docs/api.md @@ -76,7 +76,9 @@ - [coreum/asset/nft/v1/event.proto](#coreum/asset/nft/v1/event.proto) - [EventAddedToClassWhitelist](#coreum.asset.nft.v1.EventAddedToClassWhitelist) - [EventAddedToWhitelist](#coreum.asset.nft.v1.EventAddedToWhitelist) + - [EventClassFrozen](#coreum.asset.nft.v1.EventClassFrozen) - [EventClassIssued](#coreum.asset.nft.v1.EventClassIssued) + - [EventClassUnfrozen](#coreum.asset.nft.v1.EventClassUnfrozen) - [EventFrozen](#coreum.asset.nft.v1.EventFrozen) - [EventRemovedFromClassWhitelist](#coreum.asset.nft.v1.EventRemovedFromClassWhitelist) - [EventRemovedFromWhitelist](#coreum.asset.nft.v1.EventRemovedFromWhitelist) @@ -84,6 +86,7 @@ - [coreum/asset/nft/v1/genesis.proto](#coreum/asset/nft/v1/genesis.proto) - [BurntNFT](#coreum.asset.nft.v1.BurntNFT) + - [ClassFrozenAccounts](#coreum.asset.nft.v1.ClassFrozenAccounts) - [ClassWhitelistedAccounts](#coreum.asset.nft.v1.ClassWhitelistedAccounts) - [FrozenNFT](#coreum.asset.nft.v1.FrozenNFT) - [GenesisState](#coreum.asset.nft.v1.GenesisState) @@ -103,6 +106,10 @@ - [QueryBurntNFTResponse](#coreum.asset.nft.v1.QueryBurntNFTResponse) - [QueryBurntNFTsInClassRequest](#coreum.asset.nft.v1.QueryBurntNFTsInClassRequest) - [QueryBurntNFTsInClassResponse](#coreum.asset.nft.v1.QueryBurntNFTsInClassResponse) + - [QueryClassFrozenAccountsRequest](#coreum.asset.nft.v1.QueryClassFrozenAccountsRequest) + - [QueryClassFrozenAccountsResponse](#coreum.asset.nft.v1.QueryClassFrozenAccountsResponse) + - [QueryClassFrozenRequest](#coreum.asset.nft.v1.QueryClassFrozenRequest) + - [QueryClassFrozenResponse](#coreum.asset.nft.v1.QueryClassFrozenResponse) - [QueryClassRequest](#coreum.asset.nft.v1.QueryClassRequest) - [QueryClassResponse](#coreum.asset.nft.v1.QueryClassResponse) - [QueryClassWhitelistedAccountsRequest](#coreum.asset.nft.v1.QueryClassWhitelistedAccountsRequest) @@ -125,6 +132,8 @@ - [MsgAddToClassWhitelist](#coreum.asset.nft.v1.MsgAddToClassWhitelist) - [MsgAddToWhitelist](#coreum.asset.nft.v1.MsgAddToWhitelist) - [MsgBurn](#coreum.asset.nft.v1.MsgBurn) + - [MsgClassFreeze](#coreum.asset.nft.v1.MsgClassFreeze) + - [MsgClassUnfreeze](#coreum.asset.nft.v1.MsgClassUnfreeze) - [MsgFreeze](#coreum.asset.nft.v1.MsgFreeze) - [MsgIssueClass](#coreum.asset.nft.v1.MsgIssueClass) - [MsgMint](#coreum.asset.nft.v1.MsgMint) @@ -1315,6 +1324,22 @@ SendAuthorization allows the grantee to send specific NFTs from the granter's ac + + +### EventClassFrozen + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `class_id` | [string](#string) | | | +| `account` | [string](#string) | | | + + + + + + ### EventClassIssued @@ -1338,6 +1363,22 @@ EventClassIssued is emitted on MsgIssueClass. + + +### EventClassUnfrozen + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `class_id` | [string](#string) | | | +| `account` | [string](#string) | | | + + + + + + ### EventFrozen @@ -1437,6 +1478,22 @@ EventClassIssued is emitted on MsgIssueClass. + + +### ClassFrozenAccounts + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `classID` | [string](#string) | | | +| `accounts` | [string](#string) | repeated | | + + + + + + ### ClassWhitelistedAccounts @@ -1483,6 +1540,7 @@ GenesisState defines the nftasset module's genesis state. | `whitelisted_nft_accounts` | [WhitelistedNFTAccounts](#coreum.asset.nft.v1.WhitelistedNFTAccounts) | repeated | | | `burnt_nfts` | [BurntNFT](#coreum.asset.nft.v1.BurntNFT) | repeated | | | `class_whitelisted_accounts` | [ClassWhitelistedAccounts](#coreum.asset.nft.v1.ClassWhitelistedAccounts) | repeated | | +| `class_frozen_accounts` | [ClassFrozenAccounts](#coreum.asset.nft.v1.ClassFrozenAccounts) | repeated | | @@ -1688,6 +1746,69 @@ Params store gov manageable parameters. + + +### QueryClassFrozenAccountsRequest + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `class_id` | [string](#string) | | | + + + + + + + + +### QueryClassFrozenAccountsResponse + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `accounts` | [string](#string) | repeated | | + + + + + + + + +### QueryClassFrozenRequest + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `class_id` | [string](#string) | | | +| `account` | [string](#string) | | | + + + + + + + + +### QueryClassFrozenResponse + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `frozen` | [bool](#bool) | | | + + + + + + ### QueryClassRequest @@ -1920,6 +2041,8 @@ Query defines the gRPC querier service. | `Class` | [QueryClassRequest](#coreum.asset.nft.v1.QueryClassRequest) | [QueryClassResponse](#coreum.asset.nft.v1.QueryClassResponse) | Class queries the non-fungible token class of the module. | GET|/coreum/asset/nft/v1/classes/{id}| | `Classes` | [QueryClassesRequest](#coreum.asset.nft.v1.QueryClassesRequest) | [QueryClassesResponse](#coreum.asset.nft.v1.QueryClassesResponse) | Classes queries the non-fungible token classes of the module. | GET|/coreum/asset/nft/v1/classes| | `Frozen` | [QueryFrozenRequest](#coreum.asset.nft.v1.QueryFrozenRequest) | [QueryFrozenResponse](#coreum.asset.nft.v1.QueryFrozenResponse) | Frozen queries to check if an NFT is frozen or not. | GET|/coreum/asset/nft/v1/classes/{class_id}/nfts/{id}/frozen| +| `ClassFrozen` | [QueryClassFrozenRequest](#coreum.asset.nft.v1.QueryClassFrozenRequest) | [QueryClassFrozenResponse](#coreum.asset.nft.v1.QueryClassFrozenResponse) | ClassFrozen queries to check if an account if frozen for an NFT class. | GET|/coreum/asset/nft/v1/classes/{class_id}/frozen/{account}| +| `ClassFrozenAccounts` | [QueryClassFrozenAccountsRequest](#coreum.asset.nft.v1.QueryClassFrozenAccountsRequest) | [QueryClassFrozenAccountsResponse](#coreum.asset.nft.v1.QueryClassFrozenAccountsResponse) | QueryClassFrozenAccountsRequest returns the list of accounts which are frozen to hold NFTs in this class. | GET|/coreum/asset/nft/v1/classes/{class_id}/frozen| | `Whitelisted` | [QueryWhitelistedRequest](#coreum.asset.nft.v1.QueryWhitelistedRequest) | [QueryWhitelistedResponse](#coreum.asset.nft.v1.QueryWhitelistedResponse) | Whitelisted queries to check if an account is whitelited to hold an NFT or not. | GET|/coreum/asset/nft/v1/classes/{class_id}/nfts/{id}/whitelisted/{account}| | `WhitelistedAccountsForNFT` | [QueryWhitelistedAccountsForNFTRequest](#coreum.asset.nft.v1.QueryWhitelistedAccountsForNFTRequest) | [QueryWhitelistedAccountsForNFTResponse](#coreum.asset.nft.v1.QueryWhitelistedAccountsForNFTResponse) | WhitelistedAccountsForNFT returns the list of accounts which are whitelisted to hold this NFT. | GET|/coreum/asset/nft/v1/classes/{class_id}/nfts/{id}/whitelisted| | `ClassWhitelistedAccounts` | [QueryClassWhitelistedAccountsRequest](#coreum.asset.nft.v1.QueryClassWhitelistedAccountsRequest) | [QueryClassWhitelistedAccountsResponse](#coreum.asset.nft.v1.QueryClassWhitelistedAccountsResponse) | ClassWhitelistedAccounts returns the list of accounts which are whitelisted to hold NFTs in this class. | GET|/coreum/asset/nft/v1/classes/{class_id}/whitelisted| @@ -1999,6 +2122,40 @@ MsgBurn defines message for the Burn method. + + +### MsgClassFreeze + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `sender` | [string](#string) | | | +| `class_id` | [string](#string) | | | +| `account` | [string](#string) | | | + + + + + + + + +### MsgClassUnfreeze + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `sender` | [string](#string) | | | +| `class_id` | [string](#string) | | | +| `account` | [string](#string) | | | + + + + + + ### MsgFreeze @@ -2150,6 +2307,8 @@ Msg defines the Msg service. | `RemoveFromWhitelist` | [MsgRemoveFromWhitelist](#coreum.asset.nft.v1.MsgRemoveFromWhitelist) | [EmptyResponse](#coreum.asset.nft.v1.EmptyResponse) | RemoveFromWhitelist removes an account from whitelisted list of the NFT | | | `AddToClassWhitelist` | [MsgAddToClassWhitelist](#coreum.asset.nft.v1.MsgAddToClassWhitelist) | [EmptyResponse](#coreum.asset.nft.v1.EmptyResponse) | AddToClassWhitelist adds account as whitelist for all the NFTs in the class NOTE: class whitelist does not affect the individual nft whitelisting. | | | `RemoveFromClassWhitelist` | [MsgRemoveFromClassWhitelist](#coreum.asset.nft.v1.MsgRemoveFromClassWhitelist) | [EmptyResponse](#coreum.asset.nft.v1.EmptyResponse) | RemoveFromClassWhitelist removes account as whitelist for the entire class NOTE: class whitelist does not affect the individual nft whitelisting. ie. if specific whitelist is granted for an NFT, that whitelist will still be valid, ater we add and remove it from the class whitelist. | | +| `ClassFreeze` | [MsgClassFreeze](#coreum.asset.nft.v1.MsgClassFreeze) | [EmptyResponse](#coreum.asset.nft.v1.EmptyResponse) | ClassFreeze freezes all NFTs of a class held by an account. | | +| `ClassUnfreeze` | [MsgClassUnfreeze](#coreum.asset.nft.v1.MsgClassUnfreeze) | [EmptyResponse](#coreum.asset.nft.v1.EmptyResponse) | ClassUnfreeze removes class-freeze on an account for an NFT class. NOTE: class unfreeze does not affect the individual nft freeze. | | | `UpdateParams` | [MsgUpdateParams](#coreum.asset.nft.v1.MsgUpdateParams) | [EmptyResponse](#coreum.asset.nft.v1.EmptyResponse) | UpdateParams is a governance operation that sets the parameters of the module. NOTE: all parameters must be provided. | | diff --git a/docs/static/openapi.json b/docs/static/openapi.json index 325065c25..637008364 100644 --- a/docs/static/openapi.json +++ b/docs/static/openapi.json @@ -597,6 +597,112 @@ ] } }, + "/coreum/asset/nft/v1/classes/{class_id}/frozen": { + "get": { + "operationId": "GithubComCoreumFoundationCoreumV3XAssetNftTypesClassFrozenAccounts", + "parameters": [ + { + "name": "class_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "pagination.key", + "description": "key is a value returned in PageResponse.next_key to begin\nquerying the next page most efficiently. Only one of offset or key\nshould be set.", + "in": "query", + "required": false, + "type": "string", + "format": "byte" + }, + { + "name": "pagination.offset", + "description": "offset is a numeric offset that can be used when key is unavailable.\nIt is less efficient than using key. Only one of offset or key should\nbe set.", + "in": "query", + "required": false, + "type": "string", + "format": "uint64" + }, + { + "name": "pagination.limit", + "description": "limit is the total number of results to be returned in the result page.\nIf left empty it will default to a value to be set by each app.", + "in": "query", + "required": false, + "type": "string", + "format": "uint64" + }, + { + "name": "pagination.count_total", + "description": "count_total is set to true to indicate that the result set should include\na count of the total number of items available for pagination in UIs.\ncount_total is only respected when offset is used. It is ignored when key\nis set.", + "in": "query", + "required": false, + "type": "boolean" + }, + { + "name": "pagination.reverse", + "description": "reverse is set to true if results are to be returned in the descending order.\n\nSince: cosmos-sdk 0.43", + "in": "query", + "required": false, + "type": "boolean" + } + ], + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/coreum.asset.nft.v1.QueryClassFrozenAccountsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/google.rpc.Status" + } + } + }, + "summary": "QueryClassFrozenAccountsRequest returns the list of accounts which are frozen to hold NFTs in this class.", + "tags": [ + "Query" + ] + } + }, + "/coreum/asset/nft/v1/classes/{class_id}/frozen/{account}": { + "get": { + "operationId": "GithubComCoreumFoundationCoreumV3XAssetNftTypesClassFrozen", + "parameters": [ + { + "name": "class_id", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "account", + "in": "path", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/coreum.asset.nft.v1.QueryClassFrozenResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/google.rpc.Status" + } + } + }, + "summary": "ClassFrozen queries to check if an account if frozen for an NFT class.", + "tags": [ + "Query" + ] + } + }, "/coreum/asset/nft/v1/classes/{class_id}/nfts/{id}/frozen": { "get": { "operationId": "GithubComCoreumFoundationCoreumV3XAssetNftTypesFrozen", @@ -7212,6 +7318,29 @@ } } }, + "coreum.asset.nft.v1.QueryClassFrozenAccountsResponse": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/definitions/cosmos.base.query.v1beta1.PageResponse", + "description": "pagination defines the pagination in the response." + }, + "accounts": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "coreum.asset.nft.v1.QueryClassFrozenResponse": { + "type": "object", + "properties": { + "frozen": { + "type": "boolean" + } + } + }, "coreum.asset.nft.v1.QueryClassResponse": { "type": "object", "properties": { diff --git a/integration-tests/modules/assetnft_test.go b/integration-tests/modules/assetnft_test.go index 0f364edfa..e0f92ac78 100644 --- a/integration-tests/modules/assetnft_test.go +++ b/integration-tests/modules/assetnft_test.go @@ -1048,6 +1048,184 @@ func TestAssetNFTBurnFrozen_Issuer(t *testing.T) { requireT.Contains(err.Error(), "not found nft") } +// TestAssetNFTClassFreeze tests non-fungible token class freezing. +func TestAssetNFTClassFreeze(t *testing.T) { + t.Parallel() + + ctx, chain := integrationtests.NewCoreumTestingContext(t) + + requireT := require.New(t) + issuer := chain.GenAccount() + recipient1 := chain.GenAccount() + nftClient := assetnfttypes.NewQueryClient(chain.ClientContext) + + chain.FundAccountWithOptions(ctx, t, issuer, integration.BalancesOptions{ + Messages: []sdk.Msg{ + &assetnfttypes.MsgIssueClass{}, + &assetnfttypes.MsgMint{}, + &nft.MsgSend{}, + &assetnfttypes.MsgClassFreeze{}, + &assetnfttypes.MsgClassUnfreeze{}, + }, + Amount: chain.QueryAssetNFTParams(ctx, t).MintFee.Amount, + }) + + chain.FundAccountWithOptions(ctx, t, recipient1, integration.BalancesOptions{ + Messages: []sdk.Msg{ + &nft.MsgSend{}, + &nft.MsgSend{}, + &nft.MsgSend{}, + }, + }) + + // issue new NFT class + issueMsg := &assetnfttypes.MsgIssueClass{ + Issuer: issuer.String(), + Symbol: "NFTClassSymbol", + Features: []assetnfttypes.ClassFeature{ + assetnfttypes.ClassFeature_freezing, + }, + } + _, err := client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(issuer), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(issueMsg)), + issueMsg, + ) + requireT.NoError(err) + + // mint new token in that class + classID := assetnfttypes.BuildClassID(issueMsg.Symbol, issuer) + nftID := "id-1" + mintMsg := &assetnfttypes.MsgMint{ + Sender: issuer.String(), + ID: nftID, + ClassID: classID, + Recipient: recipient1.String(), + } + res, err := client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(issuer), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(mintMsg)), + mintMsg, + ) + requireT.NoError(err) + requireT.Equal(chain.GasLimitByMsgs(mintMsg), uint64(res.GasUsed)) + + // class freeze the NFT + msgFreeze := &assetnfttypes.MsgClassFreeze{ + Sender: issuer.String(), + ClassID: classID, + Account: recipient1.String(), + } + res, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(issuer), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(msgFreeze)), + msgFreeze, + ) + requireT.NoError(err) + requireT.EqualValues(int64(chain.GasLimitByMsgs(msgFreeze)), res.GasUsed) + + queryRes, err := nftClient.Frozen(ctx, &assetnfttypes.QueryFrozenRequest{ + ClassId: classID, + Id: nftID, + }) + requireT.NoError(err) + requireT.True(queryRes.Frozen) + + // assert the freezing event + frozenEvents, err := event.FindTypedEvents[*assetnfttypes.EventClassFrozen](res.Events) + requireT.NoError(err) + frozenEvent := frozenEvents[0] + requireT.Equal(&assetnfttypes.EventClassFrozen{ + ClassId: classID, + Account: recipient1.String(), + }, frozenEvent) + + // send from recipient1 to recipient2 (send is not allowed since it is frozen) + recipient2 := chain.GenAccount() + sendMsg := &nft.MsgSend{ + Sender: recipient1.String(), + ClassId: classID, + Id: nftID, + Receiver: recipient2.String(), + } + + _, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(recipient1), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(sendMsg)), + sendMsg, + ) + requireT.Error(err) + requireT.ErrorIs(err, cosmoserrors.ErrUnauthorized) + + // send from recipient1 to issuer (send is not allowed since it is frozen) + sendMsg = &nft.MsgSend{ + Sender: recipient1.String(), + ClassId: classID, + Id: nftID, + Receiver: issuer.String(), + } + + _, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(recipient1), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(sendMsg)), + sendMsg, + ) + requireT.Error(err) + requireT.True(cosmoserrors.ErrUnauthorized.Is(err)) + + // unfreeze the NFT + msgUnfreeze := &assetnfttypes.MsgClassUnfreeze{ + Sender: issuer.String(), + ClassID: classID, + Account: recipient1.String(), + } + res, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(issuer), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(msgUnfreeze)), + msgUnfreeze, + ) + requireT.NoError(err) + requireT.EqualValues(int64(chain.GasLimitByMsgs(msgUnfreeze)), res.GasUsed) + + queryRes, err = nftClient.Frozen(ctx, &assetnfttypes.QueryFrozenRequest{ + ClassId: classID, + Id: nftID, + }) + requireT.NoError(err) + requireT.False(queryRes.Frozen) + + // assert the unfreezing event + unFrozenEvents, err := event.FindTypedEvents[*assetnfttypes.EventClassUnfrozen](res.Events) + requireT.NoError(err) + unfrozenEvent := unFrozenEvents[0] + requireT.Equal(&assetnfttypes.EventClassUnfrozen{ + ClassId: classID, + Account: recipient1.String(), + }, unfrozenEvent) + + // send from recipient1 to recipient2 (send is allowed since it is not frozen) + sendMsg = &nft.MsgSend{ + Sender: recipient1.String(), + ClassId: classID, + Id: nftID, + Receiver: recipient2.String(), + } + + _, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(recipient1), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(sendMsg)), + sendMsg, + ) + requireT.NoError(err) +} + // TestAssetNFTFreeze tests non-fungible token freezing. func TestAssetNFTFreeze(t *testing.T) { t.Parallel() diff --git a/proto/coreum/asset/nft/v1/event.proto b/proto/coreum/asset/nft/v1/event.proto index 519c43eae..66fdb32cf 100644 --- a/proto/coreum/asset/nft/v1/event.proto +++ b/proto/coreum/asset/nft/v1/event.proto @@ -35,6 +35,17 @@ message EventUnfrozen { string owner = 3; } +message EventClassFrozen { + string class_id = 1; + string account = 3; +} + +message EventClassUnfrozen { + string class_id = 1; + string account = 3; +} + + message EventAddedToWhitelist { string class_id = 1; string id = 2; diff --git a/proto/coreum/asset/nft/v1/genesis.proto b/proto/coreum/asset/nft/v1/genesis.proto index 2d4eb7305..f19c6a6cb 100644 --- a/proto/coreum/asset/nft/v1/genesis.proto +++ b/proto/coreum/asset/nft/v1/genesis.proto @@ -18,6 +18,7 @@ message GenesisState { repeated WhitelistedNFTAccounts whitelisted_nft_accounts = 4 [(gogoproto.nullable) = false, (gogoproto.customname) = "WhitelistedNFTAccounts"]; repeated BurntNFT burnt_nfts = 5 [(gogoproto.nullable) = false, (gogoproto.customname) = "BurntNFTs"]; repeated ClassWhitelistedAccounts class_whitelisted_accounts = 6 [(gogoproto.nullable) = false]; + repeated ClassFrozenAccounts class_frozen_accounts = 7 [(gogoproto.nullable) = false]; } message FrozenNFT { @@ -36,6 +37,11 @@ message ClassWhitelistedAccounts { repeated string accounts = 2; } +message ClassFrozenAccounts { + string classID = 1; + repeated string accounts = 2; +} + message BurntNFT { string classID = 1; repeated string nftIDs = 2; diff --git a/proto/coreum/asset/nft/v1/query.proto b/proto/coreum/asset/nft/v1/query.proto index 7f3162d73..431d24894 100644 --- a/proto/coreum/asset/nft/v1/query.proto +++ b/proto/coreum/asset/nft/v1/query.proto @@ -32,6 +32,16 @@ service Query { option (google.api.http).get = "/coreum/asset/nft/v1/classes/{class_id}/nfts/{id}/frozen"; } + // ClassFrozen queries to check if an account if frozen for an NFT class. + rpc ClassFrozen (QueryClassFrozenRequest) returns (QueryClassFrozenResponse) { + option (google.api.http).get = "/coreum/asset/nft/v1/classes/{class_id}/frozen/{account}"; + } + + // QueryClassFrozenAccountsRequest returns the list of accounts which are frozen to hold NFTs in this class. + rpc ClassFrozenAccounts (QueryClassFrozenAccountsRequest) returns (QueryClassFrozenAccountsResponse) { + option (google.api.http).get = "/coreum/asset/nft/v1/classes/{class_id}/frozen"; + } + // Whitelisted queries to check if an account is whitelited to hold an NFT or not. rpc Whitelisted (QueryWhitelistedRequest) returns (QueryWhitelistedResponse) { option (google.api.http).get = "/coreum/asset/nft/v1/classes/{class_id}/nfts/{id}/whitelisted/{account}"; @@ -99,6 +109,15 @@ message QueryFrozenResponse { bool frozen = 1; } +message QueryClassFrozenRequest { + string class_id = 1; + string account = 2; +} + +message QueryClassFrozenResponse { + bool frozen = 1; +} + message QueryWhitelistedRequest { string id = 1; string class_id = 2; @@ -134,6 +153,18 @@ message QueryClassWhitelistedAccountsResponse { repeated string accounts = 2; } +message QueryClassFrozenAccountsRequest { + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 1; + string class_id = 2; +} + +message QueryClassFrozenAccountsResponse { + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 1; + repeated string accounts = 2; +} + message QueryBurntNFTRequest { string class_id = 1; string nft_id = 2; diff --git a/proto/coreum/asset/nft/v1/tx.proto b/proto/coreum/asset/nft/v1/tx.proto index 66a087cd4..9d2f8c0d3 100644 --- a/proto/coreum/asset/nft/v1/tx.proto +++ b/proto/coreum/asset/nft/v1/tx.proto @@ -38,6 +38,12 @@ service Msg { // ie. if specific whitelist is granted for an NFT, that whitelist will // still be valid, ater we add and remove it from the class whitelist. rpc RemoveFromClassWhitelist(MsgRemoveFromClassWhitelist) returns (EmptyResponse); + // ClassFreeze freezes all NFTs of a class held by an account. + rpc ClassFreeze(MsgClassFreeze) returns (EmptyResponse); + // ClassUnfreeze removes class-freeze on an account for an NFT class. + // NOTE: + // class unfreeze does not affect the individual nft freeze. + rpc ClassUnfreeze(MsgClassUnfreeze) returns (EmptyResponse); // UpdateParams is a governance operation that sets the parameters of the module. // NOTE: all parameters must be provided. rpc UpdateParams(MsgUpdateParams) returns (EmptyResponse); @@ -89,6 +95,18 @@ message MsgBurn { string id = 3 [(gogoproto.customname) = "ID"]; } + message MsgClassFreeze { + string sender = 1; + string class_id = 2 [(gogoproto.customname) = "ClassID"]; + string account = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + } + + message MsgClassUnfreeze { + string sender = 1; + string class_id = 2 [(gogoproto.customname) = "ClassID"]; + string account = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + } + message MsgAddToWhitelist { string sender = 1; string class_id = 2 [(gogoproto.customname) = "ClassID"]; diff --git a/x/asset/nft/client/cli/query.go b/x/asset/nft/client/cli/query.go index f75c16f3e..da96a3867 100644 --- a/x/asset/nft/client/cli/query.go +++ b/x/asset/nft/client/cli/query.go @@ -34,6 +34,8 @@ func GetQueryCmd() *cobra.Command { CmdQueryClass(), CmdQueryClasses(), CmdQueryFrozen(), + CmdQueryClassFrozen(), + CmdQueryClassFrozenAccounts(), CmdQueryWhitelisted(), CmdQueryWhitelistedAccounts(), CmdQueryClassWhitelistedAccounts(), @@ -165,6 +167,90 @@ $ %[1]s query %s frozen [class-id] [id] return cmd } +// CmdQueryClassFrozen return the QueryClassFrozen cobra command. +func CmdQueryClassFrozen() *cobra.Command { + cmd := &cobra.Command{ + Use: "class-frozen [class-id] [account]", + Args: cobra.ExactArgs(2), + Short: "Query if non-fungible token class is frozen for account", + Long: strings.TrimSpace( + fmt.Sprintf(`Query if non-fungible token class is frozen for account. + +Example: +$ %[1]s query %s class-frozen [class-id] [account] +`, + version.AppName, types.ModuleName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + queryClient := types.NewQueryClient(clientCtx) + + classID := args[0] + account := args[1] + res, err := queryClient.ClassFrozen(cmd.Context(), &types.QueryClassFrozenRequest{ + Account: account, + ClassId: classID, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// CmdQueryClassFrozenAccounts return the QueryClassFrozenAccounts cobra command. +// +//nolint:dupl // creating abstraction for cli here will make it less maintainable. +func CmdQueryClassFrozenAccounts() *cobra.Command { + cmd := &cobra.Command{ + Use: "class-frozen-accounts [class-id]", + Args: cobra.ExactArgs(1), + Short: "Query for frozen accounts for a class of non-fungible tokens", + Long: strings.TrimSpace( + fmt.Sprintf(`Query for frozen accounts for a class of non-fungible tokens. + +Example: +$ %s query %s class-frozen-accounts [class-id] +`, + version.AppName, types.ModuleName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + queryClient := types.NewQueryClient(clientCtx) + + classID := args[0] + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + res, err := queryClient.ClassFrozenAccounts(cmd.Context(), &types.QueryClassFrozenAccountsRequest{ + Pagination: pageReq, + ClassId: classID, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "whitelisted accounts") + + return cmd +} + // CmdQueryWhitelisted return the CmdQueryWhitelisted cobra command. func CmdQueryWhitelisted() *cobra.Command { cmd := &cobra.Command{ @@ -252,6 +338,8 @@ $ %s query %s whitelisted-accounts [class-id] [id] } // CmdQueryClassWhitelistedAccounts return the CmdQueryWhitelistedAccounts cobra command. +// +//nolint:dupl // creating abstraction for cli here will make it less maintainable. func CmdQueryClassWhitelistedAccounts() *cobra.Command { cmd := &cobra.Command{ Use: "class-whitelisted-accounts [class-id]", diff --git a/x/asset/nft/client/cli/query_test.go b/x/asset/nft/client/cli/query_test.go index 98ae96039..87b3b7dd5 100644 --- a/x/asset/nft/client/cli/query_test.go +++ b/x/asset/nft/client/cli/query_test.go @@ -138,6 +138,7 @@ func TestCmdQueryParams(t *testing.T) { requireT.Equal(expectedMintFee, resp.Params.MintFee) } +//nolint:unparam // using constant values here will make this function less flexible. func mint( requireT *require.Assertions, ctx client.Context, diff --git a/x/asset/nft/client/cli/tx.go b/x/asset/nft/client/cli/tx.go index 2921fdaa9..36c9e51b3 100644 --- a/x/asset/nft/client/cli/tx.go +++ b/x/asset/nft/client/cli/tx.go @@ -39,6 +39,8 @@ func GetTxCmd() *cobra.Command { CmdTxBurn(), CmdTxFreeze(), CmdTxUnfreeze(), + CmdTxClassFreeze(), + CmdTxClassUnfreeze(), CmdTxWhitelist(), CmdTxUnwhitelist(), CmdTxClassWhitelist(), @@ -460,3 +462,83 @@ $ %s tx %s class-unwhitelist abc-%[3]s %[3]s --from [sender] return cmd } + +// CmdTxClassFreeze returns ClassFreeze cobra command. +func CmdTxClassFreeze() *cobra.Command { + cmd := &cobra.Command{ + Use: "class-freeze [class-id] [account] --from [sender]", + Args: cobra.ExactArgs(2), + Short: "Freeze an account for a class of non-fungible tokens", + Long: strings.TrimSpace( + fmt.Sprintf(`Freeze an account for a class of non-fungible tokens. + +Example: +$ %s tx %s class-freeze abc-%[3]s %[3]s --from [sender] +`, + version.AppName, types.ModuleName, constant.AddressSampleTest, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return errors.WithStack(err) + } + + sender := clientCtx.GetFromAddress() + classID := args[0] + account := args[1] + + msg := &types.MsgClassFreeze{ + Sender: sender.String(), + ClassID: classID, + Account: account, + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// CmdTxClassUnfreeze returns ClassUnfreeze cobra command. +func CmdTxClassUnfreeze() *cobra.Command { + cmd := &cobra.Command{ + Use: "class-unfreeze [class-id] [account] --from [sender]", + Args: cobra.ExactArgs(2), + Short: "Unfreeze an account for a class of non-fungible tokens", + Long: strings.TrimSpace( + fmt.Sprintf(`Unfreeze an account for a class of non-fungible tokens. + +Example: +$ %s tx %s class-unfreeze abc-%[3]s %[3]s --from [sender] +`, + version.AppName, types.ModuleName, constant.AddressSampleTest, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return errors.WithStack(err) + } + + sender := clientCtx.GetFromAddress() + classID := args[0] + account := args[1] + + msg := &types.MsgClassUnfreeze{ + Sender: sender.String(), + ClassID: classID, + Account: account, + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/asset/nft/client/cli/tx_test.go b/x/asset/nft/client/cli/tx_test.go index 4b49c3946..2bb87ff67 100644 --- a/x/asset/nft/client/cli/tx_test.go +++ b/x/asset/nft/client/cli/tx_test.go @@ -263,6 +263,75 @@ func TestCmdClassWhitelist(t *testing.T) { requireT.False(whitelistedResp.Whitelisted) } +func TestCmdClassFreeze(t *testing.T) { + requireT := require.New(t) + testNetwork := network.New(t) + + symbol := "nft" + uuid.NewString()[:4] + validator := testNetwork.Validators[0] + ctx := validator.ClientCtx + account := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) + + // create class + classID := issueClass( + requireT, + ctx, + symbol, + "class name", + "class description", + "https://my-class-meta.invalid/1", + "", + testNetwork, + "0.0", + types.ClassFeature_freezing, + ) + // mint nft + mint( + requireT, + ctx, + classID, + nftID, + "https://my-nft-meta.invalid/1", + "9309e7e6e96150afbf181d308fe88343ab1cbec391b7717150a7fb217b4cf0a9", + testNetwork, + ) + + // class-freeze + args := []string{classID, account.String()} + args = append(args, txValidator1Args(testNetwork)...) + _, err := coreumclitestutil.ExecTxCmd(ctx, testNetwork, cli.CmdTxClassFreeze(), args) + requireT.NoError(err) + + // query class frozen + var classFrozenResp types.QueryFrozenResponse + args = []string{classID, account.String()} + requireT.NoError(coreumclitestutil.ExecQueryCmd(ctx, cli.CmdQueryClassFrozen(), args, &classFrozenResp)) + requireT.True(classFrozenResp.Frozen) + + // query frozen + var frozenResp types.QueryFrozenResponse + args = []string{classID, nftID} + requireT.NoError(coreumclitestutil.ExecQueryCmd(ctx, cli.CmdQueryFrozen(), args, &frozenResp)) + requireT.False(frozenResp.Frozen) + + // query with pagination + var resPage types.QueryClassFrozenAccountsResponse + args = []string{classID} + requireT.NoError(coreumclitestutil.ExecQueryCmd(ctx, cli.CmdQueryClassFrozenAccounts(), args, &resPage)) + requireT.ElementsMatch([]string{account.String()}, resPage.Accounts) + + // unfreeze + args = []string{classID, account.String()} + args = append(args, txValidator1Args(testNetwork)...) + _, err = coreumclitestutil.ExecTxCmd(ctx, testNetwork, cli.CmdTxClassUnfreeze(), args) + requireT.NoError(err) + + // query class frozen + args = []string{classID, account.String()} + requireT.NoError(coreumclitestutil.ExecQueryCmd(ctx, cli.CmdQueryClassFrozen(), args, &classFrozenResp)) + requireT.False(classFrozenResp.Frozen) +} + func txValidator1Args(testNetwork *network.Network) []string { return []string{ fmt.Sprintf("--%s=%s", flags.FlagFrom, testNetwork.Validators[0].Address.String()), diff --git a/x/asset/nft/genesis.go b/x/asset/nft/genesis.go index c8da84305..005006e1f 100644 --- a/x/asset/nft/genesis.go +++ b/x/asset/nft/genesis.go @@ -63,6 +63,22 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) } } + for _, classFrozen := range genState.ClassFrozenAccounts { + if err := classFrozen.Validate(); err != nil { + panic(err) + } + for _, account := range classFrozen.Accounts { + if err := k.SetClassFrozen( + ctx, + classFrozen.ClassID, + sdk.MustAccAddressFromBech32(account), + true, + ); err != nil { + panic(err) + } + } + } + for _, burnt := range genState.BurntNFTs { if err := burnt.Validate(); err != nil { panic(err) @@ -97,6 +113,11 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { panic(err) } + classFrozen, _, err := k.GetAllClassFrozenAccounts(ctx, &query.PageRequest{Limit: query.MaxLimit}) + if err != nil { + panic(err) + } + burnt, _, err := k.GetBurntNFTs(ctx, &query.PageRequest{Limit: query.MaxLimit}) if err != nil { panic(err) @@ -108,6 +129,7 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { FrozenNFTs: frozen, WhitelistedNFTAccounts: whitelisted, ClassWhitelistedAccounts: classWhitelisted, + ClassFrozenAccounts: classFrozen, BurntNFTs: burnt, } } diff --git a/x/asset/nft/genesis_test.go b/x/asset/nft/genesis_test.go index 900d10949..90f4b1c29 100644 --- a/x/asset/nft/genesis_test.go +++ b/x/asset/nft/genesis_test.go @@ -119,6 +119,21 @@ func TestInitAndExportGenesis(t *testing.T) { ) } + // ClassFrozen + var classFrozen []types.ClassFrozenAccounts + for i := 0; i < 5; i++ { + classFrozen = append(classFrozen, + types.ClassFrozenAccounts{ + ClassID: fmt.Sprintf("classid%d-%s", i, issuer), + Accounts: []string{ + sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String(), + sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String(), + sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String(), + }, + }, + ) + } + // Burnt NFTs var burnt []types.BurntNFT for i := 0; i < 5; i++ { @@ -137,6 +152,7 @@ func TestInitAndExportGenesis(t *testing.T) { FrozenNFTs: frozen, WhitelistedNFTAccounts: whitelisted, ClassWhitelistedAccounts: classWhitelisted, + ClassFrozenAccounts: classFrozen, BurntNFTs: burnt, } @@ -169,13 +185,24 @@ func TestInitAndExportGenesis(t *testing.T) { sort.Strings(st.Accounts) } + // sort whitelisting accounts for _, st := range genState.ClassWhitelistedAccounts { sort.Strings(st.Accounts) } for _, st := range exportedGenState.ClassWhitelistedAccounts { sort.Strings(st.Accounts) } + + // sort frozen accounts + for _, st := range genState.ClassFrozenAccounts { + sort.Strings(st.Accounts) + } + for _, st := range exportedGenState.ClassFrozenAccounts { + sort.Strings(st.Accounts) + } + assertT.ElementsMatch(genState.WhitelistedNFTAccounts, exportedGenState.WhitelistedNFTAccounts) assertT.ElementsMatch(genState.ClassWhitelistedAccounts, exportedGenState.ClassWhitelistedAccounts) + assertT.ElementsMatch(genState.ClassFrozenAccounts, exportedGenState.ClassFrozenAccounts) assertT.ElementsMatch(genState.BurntNFTs, exportedGenState.BurntNFTs) } diff --git a/x/asset/nft/keeper/grpc_query.go b/x/asset/nft/keeper/grpc_query.go index 55195e0fb..f4b07128f 100644 --- a/x/asset/nft/keeper/grpc_query.go +++ b/x/asset/nft/keeper/grpc_query.go @@ -13,14 +13,18 @@ import ( var _ types.QueryServer = QueryService{} // QueryKeeper defines subscope of keeper methods required by query service. +// +//nolint:interfacebloat // breaking down this interface is not beneficial. type QueryKeeper interface { GetParams(ctx sdk.Context) types.Params GetClass(ctx sdk.Context, classID string) (types.Class, error) GetClasses(ctx sdk.Context, issuer *sdk.AccAddress, pagination *query.PageRequest) ([]types.Class, *query.PageResponse, error) IsFrozen(ctx sdk.Context, classID, nftID string) (bool, error) + IsClassFrozen(ctx sdk.Context, classID string, account sdk.AccAddress) (bool, error) IsWhitelisted(ctx sdk.Context, classID, nftID string, account sdk.AccAddress) (bool, error) GetWhitelistedAccountsForNFT(ctx sdk.Context, classID, nftID string, q *query.PageRequest) ([]string, *query.PageResponse, error) GetClassWhitelistedAccounts(ctx sdk.Context, classID string, q *query.PageRequest) ([]string, *query.PageResponse, error) + GetClassFrozenAccounts(ctx sdk.Context, classID string, q *query.PageRequest) ([]string, *query.PageResponse, error) GetBurntByClass(ctx sdk.Context, classID string, q *query.PageRequest) (*query.PageResponse, []string, error) IsBurnt(ctx sdk.Context, classID, nftID string) (bool, error) } @@ -83,6 +87,18 @@ func (qs QueryService) Frozen(ctx context.Context, req *types.QueryFrozenRequest }, err } +// ClassFrozen queries to check if an account if frozen for an NFT class. +func (qs QueryService) ClassFrozen(ctx context.Context, req *types.QueryClassFrozenRequest) (*types.QueryClassFrozenResponse, error) { + accountAddress, err := sdk.AccAddressFromBech32(req.Account) + if err != nil { + return nil, sdkerrors.Wrap(types.ErrInvalidInput, "invalid account address") + } + frozen, err := qs.keeper.IsClassFrozen(sdk.UnwrapSDKContext(ctx), req.ClassId, accountAddress) + return &types.QueryClassFrozenResponse{ + Frozen: frozen, + }, err +} + // Whitelisted checks to see if an account is whitelisted for an NFT. func (qs QueryService) Whitelisted(ctx context.Context, req *types.QueryWhitelistedRequest) (*types.QueryWhitelistedResponse, error) { account, err := sdk.AccAddressFromBech32(req.Account) @@ -117,6 +133,15 @@ func (qs QueryService) ClassWhitelistedAccounts(ctx context.Context, req *types. }, err } +// ClassFrozenAccounts returns the list of accounts which are whitelited to hold this NFTs in this class. +func (qs QueryService) ClassFrozenAccounts(ctx context.Context, req *types.QueryClassFrozenAccountsRequest) (*types.QueryClassFrozenAccountsResponse, error) { + accounts, pageRes, err := qs.keeper.GetClassFrozenAccounts(sdk.UnwrapSDKContext(ctx), req.ClassId, req.Pagination) + return &types.QueryClassFrozenAccountsResponse{ + Pagination: pageRes, + Accounts: accounts, + }, err +} + // BurntNFT checks if an NFT is burnt or not. func (qs QueryService) BurntNFT(ctx context.Context, req *types.QueryBurntNFTRequest) (*types.QueryBurntNFTResponse, error) { isBurnt, err := qs.keeper.IsBurnt(sdk.UnwrapSDKContext(ctx), req.ClassId, req.NftId) diff --git a/x/asset/nft/keeper/keeper.go b/x/asset/nft/keeper/keeper.go index 8d8780218..0fc3957be 100644 --- a/x/asset/nft/keeper/keeper.go +++ b/x/asset/nft/keeper/keeper.go @@ -512,6 +512,32 @@ func (k Keeper) SetFrozen(ctx sdk.Context, classID, nftID string, frozen bool) e return nil } +// ClassFreeze freezes a non-fungible token. +func (k Keeper) ClassFreeze(ctx sdk.Context, sender, account sdk.AccAddress, classID string) error { + return k.classFreezeOrUnfreeze(ctx, sender, account, classID, true) +} + +// ClassUnfreeze unfreezes a non-fungible token. +func (k Keeper) ClassUnfreeze(ctx sdk.Context, sender, account sdk.AccAddress, classID string) error { + return k.classFreezeOrUnfreeze(ctx, sender, account, classID, false) +} + +// SetClassFrozen marks the nft class as for an account, but does not make any checks +// should not be used directly outside the module except for genesis. +func (k Keeper) SetClassFrozen(ctx sdk.Context, classID string, account sdk.AccAddress, frozen bool) error { + key, err := types.CreateClassFreezingKey(classID, account) + if err != nil { + return err + } + s := ctx.KVStore(k.storeKey) + if frozen { + s.Set(key, types.StoreTrue) + } else { + s.Delete(key) + } + return nil +} + // IsFrozen return whether a non-fungible token is frozen or not. func (k Keeper) IsFrozen(ctx sdk.Context, classID, nftID string) (bool, error) { classDefinition, err := k.GetClassDefinition(ctx, classID) @@ -532,6 +558,39 @@ func (k Keeper) IsFrozen(ctx sdk.Context, classID, nftID string) (bool, error) { return false, err } + if bytes.Equal(ctx.KVStore(k.storeKey).Get(key), types.StoreTrue) { + return true, nil + } + + owner := k.nftKeeper.GetOwner(ctx, classID, nftID) + key, err = types.CreateClassFreezingKey(classID, owner) + if err != nil { + return false, err + } + + return bytes.Equal(ctx.KVStore(k.storeKey).Get(key), types.StoreTrue), nil +} + +// IsClassFrozen return whether an account is frozen for an NFT class . +func (k Keeper) IsClassFrozen(ctx sdk.Context, classID string, account sdk.AccAddress) (bool, error) { + classDefinition, err := k.GetClassDefinition(ctx, classID) + if err != nil { + return false, err + } + + if !classDefinition.IsFeatureEnabled(types.ClassFeature_freezing) { + return false, sdkerrors.Wrapf(types.ErrFeatureDisabled, `feature "freezing" is disabled`) + } + + if !k.nftKeeper.HasClass(ctx, classID) { + return false, sdkerrors.Wrapf(types.ErrNFTNotFound, "class with ID:%s not found", classID) + } + + key, err := types.CreateClassFreezingKey(classID, account) + if err != nil { + return false, err + } + return bytes.Equal(ctx.KVStore(k.storeKey).Get(key), types.StoreTrue), nil } @@ -568,6 +627,68 @@ func (k Keeper) GetFrozenNFTs(ctx sdk.Context, q *query.PageRequest) ([]types.Fr return frozen, pageRes, nil } +// GetAllClassFrozenAccounts returns all frozen accounts for all NFTs. +// +//nolint:dupl // although there is duplicaiton, merging the code under a common abstraction will make it less maintainable. +func (k Keeper) GetAllClassFrozenAccounts(ctx sdk.Context, q *query.PageRequest) ([]types.ClassFrozenAccounts, *query.PageResponse, error) { + mp := make(map[string][]string, 0) + pageRes, err := query.Paginate(prefix.NewStore(ctx.KVStore(k.storeKey), types.NFTClassFreezingKeyPrefix), + q, func(key, value []byte) error { + if !bytes.Equal(value, types.StoreTrue) { + return sdkerrors.Wrapf(types.ErrInvalidState, "value stored in whitelisting store is not %x, value %x", types.StoreTrue, value) + } + classID, account, err := types.ParseClassFreezingKey(key) + if err != nil { + return err + } + if !k.nftKeeper.HasClass(ctx, classID) { + return nil + } + + accountString := account.String() + mp[classID] = append(mp[classID], accountString) + return nil + }) + if err != nil { + return nil, nil, err + } + + frozen := make([]types.ClassFrozenAccounts, 0, len(mp)) + for classID, accounts := range mp { + frozen = append(frozen, types.ClassFrozenAccounts{ + ClassID: classID, + Accounts: accounts, + }) + } + + return frozen, pageRes, nil +} + +// GetClassFrozenAccounts returns all class frozen accounts for the class. +func (k Keeper) GetClassFrozenAccounts(ctx sdk.Context, classID string, q *query.PageRequest) ([]string, *query.PageResponse, error) { + compositeKey, err := store.JoinKeysWithLength([]byte(classID)) + if err != nil { + return nil, nil, sdkerrors.Wrapf(types.ErrInvalidKey, "failed to create a composite key for nft, err: %s", err) + } + key := store.JoinKeys(types.NFTClassFreezingKeyPrefix, compositeKey) + accounts := []string{} + pageRes, err := query.Paginate(prefix.NewStore(ctx.KVStore(k.storeKey), key), + q, func(key, value []byte) error { + if !bytes.Equal(value, types.StoreTrue) { + return sdkerrors.Wrapf(types.ErrInvalidState, "value stored in whitelisting store is not %x, value %x", types.StoreTrue, value) + } + + account := sdk.AccAddress(key[1:]) // the first byte contains the length prefix + accounts = append(accounts, account.String()) + return nil + }) + if err != nil { + return nil, nil, err + } + + return accounts, pageRes, nil +} + // IsWhitelisted checks to see if an account is whitelisted for an NFT. func (k Keeper) IsWhitelisted(ctx sdk.Context, classID, nftID string, account sdk.AccAddress) (bool, error) { classDefinition, err := k.GetClassDefinition(ctx, classID) @@ -691,6 +812,8 @@ func (k Keeper) GetWhitelistedAccounts(ctx sdk.Context, q *query.PageRequest) ([ } // GetAllClassWhitelistedAccounts returns all whitelisted accounts for all NFTs. +// +//nolint:dupl // although there is duplicaiton, merging the code under a common abstraction will make it less maintainable. func (k Keeper) GetAllClassWhitelistedAccounts(ctx sdk.Context, q *query.PageRequest) ([]types.ClassWhitelistedAccounts, *query.PageResponse, error) { mp := make(map[string][]string, 0) pageRes, err := query.Paginate(prefix.NewStore(ctx.KVStore(k.storeKey), types.NFTClassWhitelistingKeyPrefix), @@ -824,16 +947,27 @@ func (k Keeper) isNFTSendable(ctx sdk.Context, classID, nftID string) error { return sdkerrors.Wrapf(cosmoserrors.ErrUnauthorized, "nft with classID:%s and ID:%s has sending disabled", classID, nftID) } - frozen, err := k.IsFrozen(ctx, classID, nftID) + isFrozen, err := k.IsFrozen(ctx, classID, nftID) if err != nil { if errors.Is(err, types.ErrFeatureDisabled) { return nil } return err } - if frozen { + if isFrozen { return sdkerrors.Wrapf(cosmoserrors.ErrUnauthorized, "nft with classID:%s and ID:%s is frozen", classID, nftID) } + + isClassFrozen, err := k.IsClassFrozen(ctx, classID, owner) + if err != nil { + if errors.Is(err, types.ErrFeatureDisabled) { + return nil + } + return err + } + if isClassFrozen { + return sdkerrors.Wrapf(cosmoserrors.ErrUnauthorized, "nft with classID:%s and ID:%s is class frozen", classID, nftID) + } return nil } @@ -854,7 +988,7 @@ func (k Keeper) isNFTReceivable(ctx sdk.Context, classID, nftID string, receiver } // always allow issuer to receive NFTs issued by them. - if classDefinition.Issuer == receiver.String() { + if classDefinition.IsIssuer(receiver) { return nil } @@ -913,6 +1047,48 @@ func (k Keeper) freezeOrUnfreeze(ctx sdk.Context, sender sdk.AccAddress, classID return nil } +func (k Keeper) classFreezeOrUnfreeze(ctx sdk.Context, sender, account sdk.AccAddress, classID string, setFrozen bool) error { + classDefinition, err := k.GetClassDefinition(ctx, classID) + if err != nil { + return err + } + + if err = classDefinition.CheckFeatureAllowed(sender, types.ClassFeature_freezing); err != nil { + return err + } + + if classDefinition.Issuer == account.String() { + return sdkerrors.Wrap(cosmoserrors.ErrUnauthorized, "setting class-freezing for the nft class issuer is forbidden") + } + + if !k.nftKeeper.HasClass(ctx, classID) { + return sdkerrors.Wrapf(types.ErrClassNotFound, "classID:%s not found", classID) + } + + if err := k.SetClassFrozen(ctx, classID, account, setFrozen); err != nil { + return err + } + + var event proto.Message + if setFrozen { + event = &types.EventClassFrozen{ + ClassId: classID, + Account: account.String(), + } + } else { + event = &types.EventClassUnfrozen{ + ClassId: classID, + Account: account.String(), + } + } + + if err = ctx.EventManager().EmitTypedEvent(event); err != nil { + return sdkerrors.Wrapf(types.ErrInvalidState, "failed to emit event: %v, err: %s", event, err) + } + + return nil +} + func (k Keeper) addToWhitelistOrRemoveFromWhitelistClass(ctx sdk.Context, classID string, sender, account sdk.AccAddress, setWhitelisted bool) error { classDefinition, err := k.GetClassDefinition(ctx, classID) if err != nil { diff --git a/x/asset/nft/keeper/keeper_test.go b/x/asset/nft/keeper/keeper_test.go index f6fa6530e..e8bab54a2 100644 --- a/x/asset/nft/keeper/keeper_test.go +++ b/x/asset/nft/keeper/keeper_test.go @@ -1102,6 +1102,185 @@ func TestKeeper_ClassWhitelist_NonExistent(t *testing.T) { requireT.ErrorIs(err, types.ErrClassNotFound) } +func TestKeeper_ClassFreeze(t *testing.T) { + requireT := require.New(t) + testApp := simapp.New() + ctx := testApp.NewContext(false, tmproto.Header{}) + assetNFTKeeper := testApp.AssetNFTKeeper + nftKeeper := testApp.NFTKeeper + + nftParams := types.Params{ + MintFee: sdk.NewInt64Coin(constant.DenomDev, 0), + } + requireT.NoError(assetNFTKeeper.SetParams(ctx, nftParams)) + + issuer := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + classSettings := types.IssueClassSettings{ + Issuer: issuer, + Symbol: "symbol", + Features: []types.ClassFeature{ + types.ClassFeature_freezing, + }, + } + + classID, err := assetNFTKeeper.IssueClass(ctx, classSettings) + requireT.NoError(err) + + // class-freezing issuer is not allowed + err = assetNFTKeeper.ClassFreeze(ctx, issuer, issuer, classID) + requireT.Error(err) + requireT.ErrorIs(err, cosmoserrors.ErrUnauthorized) + + // mint NFT + recipient := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + settings := types.MintSettings{ + Sender: issuer, + Recipient: recipient, + ClassID: classID, + ID: "my-id", + URI: "https://my-nft-meta.invalid/1", + URIHash: "content-hash", + } + + requireT.NoError(assetNFTKeeper.Mint(ctx, settings)) + nftID := settings.ID + + // class-freeze recipient + requireT.NoError(assetNFTKeeper.ClassFreeze(ctx, issuer, recipient, classID)) + + isClassFrozen, err := assetNFTKeeper.IsClassFrozen(ctx, classID, recipient) + requireT.NoError(err) + requireT.True(isClassFrozen) + + frozenAccounts, _, err := assetNFTKeeper.GetClassFrozenAccounts(ctx, classID, &query.PageRequest{}) + requireT.NoError(err) + requireT.ElementsMatch([]string{recipient.String()}, frozenAccounts) + + // transfer must be rejected + recipient2 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + err = nftKeeper.Transfer(ctx, classID, nftID, recipient2) + requireT.Error(err) + requireT.ErrorIs(err, cosmoserrors.ErrUnauthorized) + + // class-unfreeze + requireT.NoError(assetNFTKeeper.ClassUnfreeze(ctx, issuer, recipient, classID)) + + // transfer again, must succeed + err = nftKeeper.Transfer(ctx, classID, nftID, recipient2) + requireT.NoError(err) +} + +func TestKeeper_ClassFreeze_And_NFTFreeze(t *testing.T) { + requireT := require.New(t) + testApp := simapp.New() + ctx := testApp.NewContext(false, tmproto.Header{}) + assetNFTKeeper := testApp.AssetNFTKeeper + + issuer := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + recipient := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + classSettings := types.IssueClassSettings{ + Issuer: issuer, + Symbol: "symbol", + Features: []types.ClassFeature{ + types.ClassFeature_freezing, + }, + } + + classID, err := assetNFTKeeper.IssueClass(ctx, classSettings) + requireT.NoError(err) + + // mint 2 NFTs + settings := types.MintSettings{ + Sender: issuer, + Recipient: recipient, + ClassID: classID, + ID: "my-id", + URI: "https://my-nft-meta.invalid/1", + URIHash: "content-hash", + } + requireT.NoError(assetNFTKeeper.Mint(ctx, settings)) + nftID1 := settings.ID + + settings.ID += "2" + nftID2 := settings.ID + requireT.NoError(assetNFTKeeper.Mint(ctx, settings)) + + // freeze the recipient for nft1 + requireT.NoError(assetNFTKeeper.Freeze(ctx, issuer, classID, nftID1)) + assertFrozen(t, ctx, assetNFTKeeper, classID, nftID1, true) + assertFrozen(t, ctx, assetNFTKeeper, classID, nftID2, false) + + // freeze the whole class + requireT.NoError(assetNFTKeeper.ClassFreeze(ctx, issuer, recipient, classID)) + assertFrozen(t, ctx, assetNFTKeeper, classID, nftID1, true) + assertFrozen(t, ctx, assetNFTKeeper, classID, nftID2, true) + + // unfreeze the whole class + requireT.NoError(assetNFTKeeper.ClassUnfreeze(ctx, issuer, recipient, classID)) + assertFrozen(t, ctx, assetNFTKeeper, classID, nftID1, true) + assertFrozen(t, ctx, assetNFTKeeper, classID, nftID2, false) +} + +func TestKeeper_ClassFreeze_Unfreezable(t *testing.T) { + requireT := require.New(t) + testApp := simapp.New() + ctx := testApp.NewContext(false, tmproto.Header{}) + assetNFTKeeper := testApp.AssetNFTKeeper + + nftParams := types.Params{ + MintFee: sdk.NewInt64Coin(constant.DenomDev, 0), + } + requireT.NoError(assetNFTKeeper.SetParams(ctx, nftParams)) + + issuer := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + account := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + classSettings := types.IssueClassSettings{ + Issuer: issuer, + Symbol: "symbol", + Features: []types.ClassFeature{}, + } + + classID, err := assetNFTKeeper.IssueClass(ctx, classSettings) + requireT.NoError(err) + + requireT.NoError(err) + settings := types.MintSettings{ + Sender: issuer, + Recipient: issuer, + ClassID: classID, + ID: "my-id", + URI: "https://my-nft-meta.invalid/1", + URIHash: "content-hash", + } + + // mint NFT + requireT.NoError(assetNFTKeeper.Mint(ctx, settings)) + + // class freeze NFT + err = assetNFTKeeper.ClassFreeze(ctx, issuer, account, classID) + requireT.Error(err) + requireT.True(types.ErrFeatureDisabled.Is(err)) +} + +func TestKeeper_ClassFreeze_Nonexistent(t *testing.T) { + requireT := require.New(t) + testApp := simapp.New() + ctx := testApp.NewContext(false, tmproto.Header{}) + assetNFTKeeper := testApp.AssetNFTKeeper + issuer := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + account := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + + nftParams := types.Params{ + MintFee: sdk.NewInt64Coin(constant.DenomDev, 0), + } + requireT.NoError(assetNFTKeeper.SetParams(ctx, nftParams)) + + // try to class freeze when NFT does not exists + err := assetNFTKeeper.ClassFreeze(ctx, issuer, account, types.BuildClassID("symbol", issuer)) + requireT.Error(err) + requireT.ErrorIs(err, types.ErrClassNotFound) +} + func genNFTData(requireT *require.Assertions) *codectypes.Any { dataString := "metadata" dataValue, err := codectypes.NewAnyWithValue(&types.DataBytes{Data: []byte(dataString)}) @@ -1124,3 +1303,9 @@ func assertWhitelisting(t *testing.T, ctx sdk.Context, k keeper.Keeper, classID, require.NoError(t, err) require.EqualValues(t, isWhitelisted, expectedWhitelisting) } + +func assertFrozen(t *testing.T, ctx sdk.Context, k keeper.Keeper, classID, nftID string, expected bool) { + frozen, err := k.IsFrozen(ctx, classID, nftID) + require.NoError(t, err) + require.EqualValues(t, frozen, expected) +} diff --git a/x/asset/nft/keeper/msg_server.go b/x/asset/nft/keeper/msg_server.go index a33603585..ec1112aef 100644 --- a/x/asset/nft/keeper/msg_server.go +++ b/x/asset/nft/keeper/msg_server.go @@ -12,12 +12,16 @@ import ( var _ types.MsgServer = MsgServer{} // MsgKeeper defines subscope of keeper methods required by msg service. +// +//nolint:interfacebloat // We accept the fact that this interface declares more than 10 methods. type MsgKeeper interface { IssueClass(ctx sdk.Context, settings types.IssueClassSettings) (string, error) Mint(ctx sdk.Context, settings types.MintSettings) error Burn(ctx sdk.Context, owner sdk.AccAddress, classID, ID string) error Freeze(ctx sdk.Context, sender sdk.AccAddress, classID, nftID string) error Unfreeze(ctx sdk.Context, sender sdk.AccAddress, classID, nftID string) error + ClassFreeze(ctx sdk.Context, sender, account sdk.AccAddress, classID string) error + ClassUnfreeze(ctx sdk.Context, sender, account sdk.AccAddress, classID string) error AddToWhitelist(ctx sdk.Context, classID, nftID string, sender, account sdk.AccAddress) error RemoveFromWhitelist(ctx sdk.Context, classID, nftID string, sender, account sdk.AccAddress) error AddToClassWhitelist(ctx sdk.Context, classID string, sender, account sdk.AccAddress) error @@ -222,6 +226,44 @@ func (ms MsgServer) RemoveFromClassWhitelist(ctx context.Context, req *types.Msg return &types.EmptyResponse{}, nil } +// ClassFreeze freezes all NFTs of a class held by an account. +func (ms MsgServer) ClassFreeze(ctx context.Context, req *types.MsgClassFreeze) (*types.EmptyResponse, error) { + sender, err := sdk.AccAddressFromBech32(req.Sender) + if err != nil { + return nil, sdkerrors.Wrap(types.ErrInvalidInput, "invalid sender") + } + + account, err := sdk.AccAddressFromBech32(req.Account) + if err != nil { + return nil, sdkerrors.Wrap(types.ErrInvalidInput, "invalid account") + } + + if err := ms.keeper.ClassFreeze(sdk.UnwrapSDKContext(ctx), sender, account, req.ClassID); err != nil { + return nil, err + } + + return &types.EmptyResponse{}, nil +} + +// ClassUnfreeze removes class-freeze of all NFTs held by an account. +func (ms MsgServer) ClassUnfreeze(ctx context.Context, req *types.MsgClassUnfreeze) (*types.EmptyResponse, error) { + sender, err := sdk.AccAddressFromBech32(req.Sender) + if err != nil { + return nil, sdkerrors.Wrap(types.ErrInvalidInput, "invalid sender") + } + + account, err := sdk.AccAddressFromBech32(req.Account) + if err != nil { + return nil, sdkerrors.Wrap(types.ErrInvalidInput, "invalid account") + } + + if err := ms.keeper.ClassUnfreeze(sdk.UnwrapSDKContext(ctx), sender, account, req.ClassID); err != nil { + return nil, err + } + + return &types.EmptyResponse{}, nil +} + // UpdateParams is a governance operation that sets parameters of the module. func (ms MsgServer) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.EmptyResponse, error) { if err := ms.keeper.UpdateParams(sdk.UnwrapSDKContext(goCtx), req.Authority, req.Params); err != nil { diff --git a/x/asset/nft/types/codec.go b/x/asset/nft/types/codec.go index c68e2dfe4..17159eb99 100644 --- a/x/asset/nft/types/codec.go +++ b/x/asset/nft/types/codec.go @@ -19,6 +19,10 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { &MsgUnfreeze{}, &MsgAddToWhitelist{}, &MsgRemoveFromWhitelist{}, + &MsgAddToClassWhitelist{}, + &MsgRemoveFromClassWhitelist{}, + &MsgClassFreeze{}, + &MsgClassUnfreeze{}, ) registry.RegisterImplementations( (*authz.Authorization)(nil), diff --git a/x/asset/nft/types/event.pb.go b/x/asset/nft/types/event.pb.go index f7b806e68..7b315f411 100644 --- a/x/asset/nft/types/event.pb.go +++ b/x/asset/nft/types/event.pb.go @@ -246,6 +246,110 @@ func (m *EventUnfrozen) GetOwner() string { return "" } +type EventClassFrozen struct { + ClassId string `protobuf:"bytes,1,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` + Account string `protobuf:"bytes,3,opt,name=account,proto3" json:"account,omitempty"` +} + +func (m *EventClassFrozen) Reset() { *m = EventClassFrozen{} } +func (m *EventClassFrozen) String() string { return proto.CompactTextString(m) } +func (*EventClassFrozen) ProtoMessage() {} +func (*EventClassFrozen) Descriptor() ([]byte, []int) { + return fileDescriptor_fef75aa7da633196, []int{3} +} +func (m *EventClassFrozen) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventClassFrozen) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventClassFrozen.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EventClassFrozen) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventClassFrozen.Merge(m, src) +} +func (m *EventClassFrozen) XXX_Size() int { + return m.Size() +} +func (m *EventClassFrozen) XXX_DiscardUnknown() { + xxx_messageInfo_EventClassFrozen.DiscardUnknown(m) +} + +var xxx_messageInfo_EventClassFrozen proto.InternalMessageInfo + +func (m *EventClassFrozen) GetClassId() string { + if m != nil { + return m.ClassId + } + return "" +} + +func (m *EventClassFrozen) GetAccount() string { + if m != nil { + return m.Account + } + return "" +} + +type EventClassUnfrozen struct { + ClassId string `protobuf:"bytes,1,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` + Account string `protobuf:"bytes,3,opt,name=account,proto3" json:"account,omitempty"` +} + +func (m *EventClassUnfrozen) Reset() { *m = EventClassUnfrozen{} } +func (m *EventClassUnfrozen) String() string { return proto.CompactTextString(m) } +func (*EventClassUnfrozen) ProtoMessage() {} +func (*EventClassUnfrozen) Descriptor() ([]byte, []int) { + return fileDescriptor_fef75aa7da633196, []int{4} +} +func (m *EventClassUnfrozen) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventClassUnfrozen) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventClassUnfrozen.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EventClassUnfrozen) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventClassUnfrozen.Merge(m, src) +} +func (m *EventClassUnfrozen) XXX_Size() int { + return m.Size() +} +func (m *EventClassUnfrozen) XXX_DiscardUnknown() { + xxx_messageInfo_EventClassUnfrozen.DiscardUnknown(m) +} + +var xxx_messageInfo_EventClassUnfrozen proto.InternalMessageInfo + +func (m *EventClassUnfrozen) GetClassId() string { + if m != nil { + return m.ClassId + } + return "" +} + +func (m *EventClassUnfrozen) GetAccount() string { + if m != nil { + return m.Account + } + return "" +} + type EventAddedToWhitelist struct { ClassId string `protobuf:"bytes,1,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` @@ -256,7 +360,7 @@ func (m *EventAddedToWhitelist) Reset() { *m = EventAddedToWhitelist{} } func (m *EventAddedToWhitelist) String() string { return proto.CompactTextString(m) } func (*EventAddedToWhitelist) ProtoMessage() {} func (*EventAddedToWhitelist) Descriptor() ([]byte, []int) { - return fileDescriptor_fef75aa7da633196, []int{3} + return fileDescriptor_fef75aa7da633196, []int{5} } func (m *EventAddedToWhitelist) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -316,7 +420,7 @@ func (m *EventRemovedFromWhitelist) Reset() { *m = EventRemovedFromWhite func (m *EventRemovedFromWhitelist) String() string { return proto.CompactTextString(m) } func (*EventRemovedFromWhitelist) ProtoMessage() {} func (*EventRemovedFromWhitelist) Descriptor() ([]byte, []int) { - return fileDescriptor_fef75aa7da633196, []int{4} + return fileDescriptor_fef75aa7da633196, []int{6} } func (m *EventRemovedFromWhitelist) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -375,7 +479,7 @@ func (m *EventAddedToClassWhitelist) Reset() { *m = EventAddedToClassWhi func (m *EventAddedToClassWhitelist) String() string { return proto.CompactTextString(m) } func (*EventAddedToClassWhitelist) ProtoMessage() {} func (*EventAddedToClassWhitelist) Descriptor() ([]byte, []int) { - return fileDescriptor_fef75aa7da633196, []int{5} + return fileDescriptor_fef75aa7da633196, []int{7} } func (m *EventAddedToClassWhitelist) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -427,7 +531,7 @@ func (m *EventRemovedFromClassWhitelist) Reset() { *m = EventRemovedFrom func (m *EventRemovedFromClassWhitelist) String() string { return proto.CompactTextString(m) } func (*EventRemovedFromClassWhitelist) ProtoMessage() {} func (*EventRemovedFromClassWhitelist) Descriptor() ([]byte, []int) { - return fileDescriptor_fef75aa7da633196, []int{6} + return fileDescriptor_fef75aa7da633196, []int{8} } func (m *EventRemovedFromClassWhitelist) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -474,6 +578,8 @@ func init() { proto.RegisterType((*EventClassIssued)(nil), "coreum.asset.nft.v1.EventClassIssued") proto.RegisterType((*EventFrozen)(nil), "coreum.asset.nft.v1.EventFrozen") proto.RegisterType((*EventUnfrozen)(nil), "coreum.asset.nft.v1.EventUnfrozen") + proto.RegisterType((*EventClassFrozen)(nil), "coreum.asset.nft.v1.EventClassFrozen") + proto.RegisterType((*EventClassUnfrozen)(nil), "coreum.asset.nft.v1.EventClassUnfrozen") proto.RegisterType((*EventAddedToWhitelist)(nil), "coreum.asset.nft.v1.EventAddedToWhitelist") proto.RegisterType((*EventRemovedFromWhitelist)(nil), "coreum.asset.nft.v1.EventRemovedFromWhitelist") proto.RegisterType((*EventAddedToClassWhitelist)(nil), "coreum.asset.nft.v1.EventAddedToClassWhitelist") @@ -483,40 +589,42 @@ func init() { func init() { proto.RegisterFile("coreum/asset/nft/v1/event.proto", fileDescriptor_fef75aa7da633196) } var fileDescriptor_fef75aa7da633196 = []byte{ - // 525 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0x41, 0x6f, 0xd3, 0x30, - 0x14, 0xc7, 0xdb, 0x74, 0x6b, 0x3a, 0x17, 0x26, 0x14, 0x06, 0xf2, 0x2a, 0x91, 0x94, 0x1e, 0xa6, - 0x5d, 0x48, 0x34, 0x76, 0xe0, 0xc4, 0x81, 0x6d, 0x54, 0xf4, 0x82, 0xa8, 0x45, 0x85, 0x84, 0x90, - 0x8a, 0x1b, 0xbb, 0xad, 0x45, 0x13, 0x57, 0xb6, 0x53, 0x28, 0x9f, 0x82, 0x8f, 0xb5, 0xe3, 0x8e, - 0x88, 0x43, 0x85, 0x52, 0xf1, 0x3d, 0x90, 0x5f, 0x32, 0x54, 0xd0, 0x0e, 0x4c, 0xea, 0x29, 0x7e, - 0xff, 0xf7, 0xfc, 0x7b, 0xf6, 0x3f, 0x7e, 0x28, 0x88, 0xa5, 0xe2, 0x59, 0x12, 0x51, 0xad, 0xb9, - 0x89, 0xd2, 0xb1, 0x89, 0x16, 0x27, 0x11, 0x5f, 0xf0, 0xd4, 0x84, 0x73, 0x25, 0x8d, 0xf4, 0xee, - 0x17, 0x05, 0x21, 0x14, 0x84, 0xe9, 0xd8, 0x84, 0x8b, 0x93, 0xd6, 0xc1, 0x44, 0x4e, 0x24, 0xe4, - 0x23, 0xbb, 0x2a, 0x4a, 0x5b, 0x8f, 0x6e, 0x62, 0xd9, 0x1d, 0x90, 0xee, 0xfc, 0x72, 0xd0, 0xbd, - 0x97, 0x96, 0x7c, 0x3e, 0xa3, 0x5a, 0xf7, 0xb4, 0xce, 0x38, 0xf3, 0x1e, 0x22, 0x47, 0x30, 0x5c, - 0x6d, 0x57, 0x8f, 0xf7, 0xce, 0xea, 0xf9, 0x2a, 0x70, 0x7a, 0x17, 0xc4, 0x11, 0x56, 0xaf, 0x0b, - 0x5b, 0xa1, 0xb0, 0x63, 0x73, 0xa4, 0x8c, 0xac, 0xae, 0x97, 0xc9, 0x48, 0xce, 0x70, 0xad, 0xd0, - 0x8b, 0xc8, 0xf3, 0xd0, 0x4e, 0x4a, 0x13, 0x8e, 0x77, 0x40, 0x85, 0xb5, 0xd7, 0x46, 0x4d, 0xc6, - 0x75, 0xac, 0xc4, 0xdc, 0x08, 0x99, 0xe2, 0x5d, 0x48, 0x6d, 0x4a, 0xde, 0x21, 0xaa, 0x65, 0x4a, - 0xe0, 0x3a, 0xb4, 0x77, 0xf3, 0x55, 0x50, 0x1b, 0x90, 0x1e, 0xb1, 0x9a, 0x77, 0x84, 0x1a, 0x99, - 0x12, 0xc3, 0x29, 0xd5, 0x53, 0xec, 0x42, 0xbe, 0x99, 0xaf, 0x02, 0x77, 0x40, 0x7a, 0xaf, 0xa8, - 0x9e, 0x12, 0x37, 0x53, 0xc2, 0x2e, 0xbc, 0xe7, 0xa8, 0x31, 0xe6, 0xd4, 0x64, 0x8a, 0x6b, 0xdc, - 0x68, 0xd7, 0x8e, 0xf7, 0x9f, 0x3e, 0x0e, 0x6f, 0xb0, 0x2c, 0x84, 0x4b, 0x77, 0x8b, 0x4a, 0xf2, - 0x67, 0x8b, 0xd7, 0x47, 0x77, 0x94, 0x5c, 0xd2, 0x99, 0x59, 0x0e, 0x15, 0x35, 0x1c, 0xef, 0x41, - 0xab, 0xf0, 0x72, 0x15, 0x54, 0x7e, 0xac, 0x82, 0xa3, 0x89, 0x30, 0xd3, 0x6c, 0x14, 0xc6, 0x32, - 0x89, 0x62, 0xa9, 0x13, 0xa9, 0xcb, 0xcf, 0x13, 0xcd, 0x3e, 0x45, 0x66, 0x39, 0xe7, 0x3a, 0xbc, - 0xe0, 0x31, 0x69, 0x96, 0x0c, 0x42, 0x0d, 0xef, 0xbc, 0x46, 0x4d, 0xb0, 0xb9, 0xab, 0xe4, 0x57, - 0x6e, 0xef, 0xd8, 0x88, 0x6d, 0xef, 0xe1, 0xb5, 0xcf, 0xc4, 0x85, 0xb8, 0xc7, 0xbc, 0x7d, 0x30, - 0xbf, 0x30, 0xd8, 0x9a, 0x7e, 0x80, 0x76, 0xe5, 0xe7, 0x94, 0xab, 0xd2, 0xdb, 0x22, 0xe8, 0xbc, - 0x41, 0x77, 0x81, 0x37, 0x48, 0xc7, 0x5b, 0x22, 0x7e, 0x40, 0x0f, 0x80, 0xf8, 0x82, 0x31, 0xce, - 0xde, 0xca, 0x77, 0x53, 0x61, 0xf8, 0x4c, 0x68, 0x73, 0x1b, 0x32, 0x46, 0x2e, 0x8d, 0x63, 0x99, - 0xa5, 0xa6, 0x64, 0x5f, 0x87, 0x9d, 0x8f, 0xe8, 0x10, 0xe8, 0x84, 0x27, 0x72, 0xc1, 0x59, 0x57, - 0xc9, 0x64, 0xcb, 0x1d, 0xfa, 0xa8, 0xb5, 0x79, 0x7e, 0xf8, 0xb5, 0xff, 0xd5, 0x62, 0x03, 0xe9, - 0xfc, 0x8d, 0x1c, 0x20, 0xff, 0xdf, 0x43, 0x6f, 0x01, 0x7b, 0xd6, 0xbf, 0xcc, 0xfd, 0xea, 0x55, - 0xee, 0x57, 0x7f, 0xe6, 0x7e, 0xf5, 0xdb, 0xda, 0xaf, 0x5c, 0xad, 0xfd, 0xca, 0xf7, 0xb5, 0x5f, - 0x79, 0xff, 0x6c, 0xe3, 0x69, 0x9d, 0xc3, 0x7b, 0xed, 0xca, 0x2c, 0x65, 0xd4, 0xce, 0x45, 0x54, - 0x0e, 0xf2, 0xe2, 0x34, 0xfa, 0xb2, 0x31, 0xcd, 0xf0, 0xde, 0x46, 0x75, 0x98, 0xe6, 0xd3, 0xdf, - 0x01, 0x00, 0x00, 0xff, 0xff, 0xe6, 0x79, 0x4e, 0xe8, 0x3a, 0x04, 0x00, 0x00, + // 545 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xc1, 0x6f, 0xd3, 0x3e, + 0x14, 0xc7, 0xdb, 0x74, 0x6b, 0x3a, 0xf7, 0xf7, 0x9b, 0x90, 0x19, 0x28, 0xab, 0x44, 0x52, 0x7a, + 0x98, 0x76, 0x21, 0xd1, 0xd8, 0x81, 0x13, 0x07, 0xb6, 0x51, 0xc8, 0x05, 0x51, 0x8b, 0x0a, 0x09, + 0x21, 0x15, 0x37, 0x76, 0x5b, 0x8b, 0x26, 0xae, 0x6c, 0xa7, 0x50, 0xfe, 0x0a, 0xfe, 0xac, 0x1d, + 0x77, 0x44, 0x1c, 0x22, 0x94, 0x8a, 0xff, 0x03, 0xd9, 0xc9, 0x20, 0xa0, 0x4d, 0x0c, 0xa9, 0xa7, + 0xf8, 0x7d, 0xdf, 0xcb, 0xe7, 0x3d, 0x7f, 0x65, 0x1b, 0x78, 0x11, 0x17, 0x34, 0x8d, 0x03, 0x2c, + 0x25, 0x55, 0x41, 0x32, 0x51, 0xc1, 0xf2, 0x28, 0xa0, 0x4b, 0x9a, 0x28, 0x7f, 0x21, 0xb8, 0xe2, + 0xf0, 0x76, 0x51, 0xe0, 0x9b, 0x02, 0x3f, 0x99, 0x28, 0x7f, 0x79, 0xd4, 0xd9, 0x9b, 0xf2, 0x29, + 0x37, 0xf9, 0x40, 0xaf, 0x8a, 0xd2, 0xce, 0xbd, 0xab, 0x58, 0xfa, 0x0f, 0x93, 0xee, 0x7d, 0xb7, + 0xc0, 0xad, 0xa7, 0x9a, 0x7c, 0x3a, 0xc7, 0x52, 0x86, 0x52, 0xa6, 0x94, 0xc0, 0xbb, 0xc0, 0x62, + 0xc4, 0xa9, 0x77, 0xeb, 0x87, 0x3b, 0x27, 0xcd, 0x3c, 0xf3, 0xac, 0xf0, 0x0c, 0x59, 0x4c, 0xeb, + 0x4d, 0xa6, 0x2b, 0x84, 0x63, 0xe9, 0x1c, 0x2a, 0x23, 0xad, 0xcb, 0x55, 0x3c, 0xe6, 0x73, 0xa7, + 0x51, 0xe8, 0x45, 0x04, 0x21, 0xd8, 0x4a, 0x70, 0x4c, 0x9d, 0x2d, 0xa3, 0x9a, 0x35, 0xec, 0x82, + 0x36, 0xa1, 0x32, 0x12, 0x6c, 0xa1, 0x18, 0x4f, 0x9c, 0x6d, 0x93, 0xaa, 0x4a, 0x70, 0x1f, 0x34, + 0x52, 0xc1, 0x9c, 0xa6, 0x69, 0x6f, 0xe7, 0x99, 0xd7, 0x18, 0xa2, 0x10, 0x69, 0x0d, 0x1e, 0x80, + 0x56, 0x2a, 0xd8, 0x68, 0x86, 0xe5, 0xcc, 0xb1, 0x4d, 0xbe, 0x9d, 0x67, 0x9e, 0x3d, 0x44, 0xe1, + 0x73, 0x2c, 0x67, 0xc8, 0x4e, 0x05, 0xd3, 0x0b, 0xf8, 0x18, 0xb4, 0x26, 0x14, 0xab, 0x54, 0x50, + 0xe9, 0xb4, 0xba, 0x8d, 0xc3, 0xdd, 0x87, 0xf7, 0xfd, 0x2b, 0x2c, 0xf3, 0xcd, 0xa6, 0xfb, 0x45, + 0x25, 0xfa, 0xf9, 0x0b, 0x1c, 0x80, 0xff, 0x04, 0x5f, 0xe1, 0xb9, 0x5a, 0x8d, 0x04, 0x56, 0xd4, + 0xd9, 0x31, 0xad, 0xfc, 0xf3, 0xcc, 0xab, 0x7d, 0xcd, 0xbc, 0x83, 0x29, 0x53, 0xb3, 0x74, 0xec, + 0x47, 0x3c, 0x0e, 0x22, 0x2e, 0x63, 0x2e, 0xcb, 0xcf, 0x03, 0x49, 0xde, 0x07, 0x6a, 0xb5, 0xa0, + 0xd2, 0x3f, 0xa3, 0x11, 0x6a, 0x97, 0x0c, 0x84, 0x15, 0xed, 0xbd, 0x00, 0x6d, 0x63, 0x73, 0x5f, + 0xf0, 0x4f, 0x54, 0xef, 0xb1, 0x15, 0xe9, 0xde, 0xa3, 0x4b, 0x9f, 0x91, 0x6d, 0xe2, 0x90, 0xc0, + 0x5d, 0x63, 0x7e, 0x61, 0xb0, 0x36, 0x7d, 0x0f, 0x6c, 0xf3, 0x0f, 0x09, 0x15, 0xa5, 0xb7, 0x45, + 0xd0, 0x7b, 0x09, 0xfe, 0x37, 0xbc, 0x61, 0x32, 0xd9, 0x10, 0xf1, 0x59, 0xf5, 0x20, 0xfc, 0x7d, + 0x4c, 0x07, 0xd8, 0x38, 0x8a, 0x78, 0x9a, 0xa8, 0x12, 0x73, 0x19, 0xf6, 0x42, 0x00, 0x7f, 0x81, + 0x6e, 0x32, 0xdf, 0xf5, 0xa8, 0xb7, 0xe0, 0x8e, 0x41, 0x3d, 0x21, 0x84, 0x92, 0x57, 0xfc, 0xf5, + 0x8c, 0x29, 0x3a, 0x67, 0x52, 0xfd, 0xcb, 0x6e, 0xaf, 0xa7, 0xbf, 0x03, 0xfb, 0x86, 0x8e, 0x68, + 0xcc, 0x97, 0x94, 0xf4, 0x05, 0x8f, 0x37, 0xdc, 0x61, 0x00, 0x3a, 0xd5, 0xf9, 0x8d, 0x23, 0x37, + 0x6a, 0x51, 0x41, 0x5a, 0xbf, 0x23, 0x87, 0xc0, 0xfd, 0x73, 0xe8, 0x0d, 0x60, 0x4f, 0x06, 0xe7, + 0xb9, 0x5b, 0xbf, 0xc8, 0xdd, 0xfa, 0xb7, 0xdc, 0xad, 0x7f, 0x5e, 0xbb, 0xb5, 0x8b, 0xb5, 0x5b, + 0xfb, 0xb2, 0x76, 0x6b, 0x6f, 0x1e, 0x55, 0x8e, 0xfb, 0xa9, 0xb9, 0x43, 0x7d, 0x9e, 0x26, 0x04, + 0xeb, 0xbb, 0x1a, 0x94, 0x8f, 0xcb, 0xf2, 0x38, 0xf8, 0x58, 0x79, 0x61, 0xcc, 0x1d, 0x18, 0x37, + 0xcd, 0x0b, 0x73, 0xfc, 0x23, 0x00, 0x00, 0xff, 0xff, 0x73, 0x4f, 0xbd, 0xb6, 0xce, 0x04, 0x00, + 0x00, } func (m *EventClassIssued) Marshal() (dAtA []byte, err error) { @@ -707,6 +815,80 @@ func (m *EventUnfrozen) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *EventClassFrozen) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EventClassFrozen) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventClassFrozen) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Account) > 0 { + i -= len(m.Account) + copy(dAtA[i:], m.Account) + i = encodeVarintEvent(dAtA, i, uint64(len(m.Account))) + i-- + dAtA[i] = 0x1a + } + if len(m.ClassId) > 0 { + i -= len(m.ClassId) + copy(dAtA[i:], m.ClassId) + i = encodeVarintEvent(dAtA, i, uint64(len(m.ClassId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventClassUnfrozen) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EventClassUnfrozen) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventClassUnfrozen) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Account) > 0 { + i -= len(m.Account) + copy(dAtA[i:], m.Account) + i = encodeVarintEvent(dAtA, i, uint64(len(m.Account))) + i-- + dAtA[i] = 0x1a + } + if len(m.ClassId) > 0 { + i -= len(m.ClassId) + copy(dAtA[i:], m.ClassId) + i = encodeVarintEvent(dAtA, i, uint64(len(m.ClassId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *EventAddedToWhitelist) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -968,6 +1150,40 @@ func (m *EventUnfrozen) Size() (n int) { return n } +func (m *EventClassFrozen) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClassId) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = len(m.Account) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + return n +} + +func (m *EventClassUnfrozen) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClassId) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = len(m.Account) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + return n +} + func (m *EventAddedToWhitelist) Size() (n int) { if m == nil { return 0 @@ -1719,6 +1935,234 @@ func (m *EventUnfrozen) Unmarshal(dAtA []byte) error { } return nil } +func (m *EventClassFrozen) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EventClassFrozen: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventClassFrozen: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Account", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Account = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvent(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvent + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventClassUnfrozen) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EventClassUnfrozen: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventClassUnfrozen: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Account", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Account = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvent(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvent + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *EventAddedToWhitelist) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/asset/nft/types/genesis.go b/x/asset/nft/types/genesis.go index 43f604d98..9e7e95502 100644 --- a/x/asset/nft/types/genesis.go +++ b/x/asset/nft/types/genesis.go @@ -96,6 +96,20 @@ func (c ClassWhitelistedAccounts) Validate() error { return nil } +// Validate performs basic validation on the fields of WhitelistedNFTAccounts. +func (c ClassFrozenAccounts) Validate() error { + if _, _, err := DeconstructClassID(c.ClassID); err != nil { + return err + } + + for _, acc := range c.Accounts { + if _, err := sdk.AccAddressFromBech32(acc); err != nil { + return err + } + } + return nil +} + // Validate performs basic validation on the fields of BurntNFT. func (b BurntNFT) Validate() error { if _, _, err := DeconstructClassID(b.ClassID); err != nil { diff --git a/x/asset/nft/types/genesis.pb.go b/x/asset/nft/types/genesis.pb.go index 20f54286f..d949eb18e 100644 --- a/x/asset/nft/types/genesis.pb.go +++ b/x/asset/nft/types/genesis.pb.go @@ -33,6 +33,7 @@ type GenesisState struct { WhitelistedNFTAccounts []WhitelistedNFTAccounts `protobuf:"bytes,4,rep,name=whitelisted_nft_accounts,json=whitelistedNftAccounts,proto3" json:"whitelisted_nft_accounts"` BurntNFTs []BurntNFT `protobuf:"bytes,5,rep,name=burnt_nfts,json=burntNfts,proto3" json:"burnt_nfts"` ClassWhitelistedAccounts []ClassWhitelistedAccounts `protobuf:"bytes,6,rep,name=class_whitelisted_accounts,json=classWhitelistedAccounts,proto3" json:"class_whitelisted_accounts"` + ClassFrozenAccounts []ClassFrozenAccounts `protobuf:"bytes,7,rep,name=class_frozen_accounts,json=classFrozenAccounts,proto3" json:"class_frozen_accounts"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -110,6 +111,13 @@ func (m *GenesisState) GetClassWhitelistedAccounts() []ClassWhitelistedAccounts return nil } +func (m *GenesisState) GetClassFrozenAccounts() []ClassFrozenAccounts { + if m != nil { + return m.ClassFrozenAccounts + } + return nil +} + type FrozenNFT struct { ClassID string `protobuf:"bytes,1,opt,name=classID,proto3" json:"classID,omitempty"` NftIDs []string `protobuf:"bytes,2,rep,name=nftIDs,proto3" json:"nftIDs,omitempty"` @@ -274,6 +282,58 @@ func (m *ClassWhitelistedAccounts) GetAccounts() []string { return nil } +type ClassFrozenAccounts struct { + ClassID string `protobuf:"bytes,1,opt,name=classID,proto3" json:"classID,omitempty"` + Accounts []string `protobuf:"bytes,2,rep,name=accounts,proto3" json:"accounts,omitempty"` +} + +func (m *ClassFrozenAccounts) Reset() { *m = ClassFrozenAccounts{} } +func (m *ClassFrozenAccounts) String() string { return proto.CompactTextString(m) } +func (*ClassFrozenAccounts) ProtoMessage() {} +func (*ClassFrozenAccounts) Descriptor() ([]byte, []int) { + return fileDescriptor_3abcf08d60f6fbfd, []int{4} +} +func (m *ClassFrozenAccounts) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ClassFrozenAccounts) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ClassFrozenAccounts.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ClassFrozenAccounts) XXX_Merge(src proto.Message) { + xxx_messageInfo_ClassFrozenAccounts.Merge(m, src) +} +func (m *ClassFrozenAccounts) XXX_Size() int { + return m.Size() +} +func (m *ClassFrozenAccounts) XXX_DiscardUnknown() { + xxx_messageInfo_ClassFrozenAccounts.DiscardUnknown(m) +} + +var xxx_messageInfo_ClassFrozenAccounts proto.InternalMessageInfo + +func (m *ClassFrozenAccounts) GetClassID() string { + if m != nil { + return m.ClassID + } + return "" +} + +func (m *ClassFrozenAccounts) GetAccounts() []string { + if m != nil { + return m.Accounts + } + return nil +} + type BurntNFT struct { ClassID string `protobuf:"bytes,1,opt,name=classID,proto3" json:"classID,omitempty"` NftIDs []string `protobuf:"bytes,2,rep,name=nftIDs,proto3" json:"nftIDs,omitempty"` @@ -283,7 +343,7 @@ func (m *BurntNFT) Reset() { *m = BurntNFT{} } func (m *BurntNFT) String() string { return proto.CompactTextString(m) } func (*BurntNFT) ProtoMessage() {} func (*BurntNFT) Descriptor() ([]byte, []int) { - return fileDescriptor_3abcf08d60f6fbfd, []int{4} + return fileDescriptor_3abcf08d60f6fbfd, []int{5} } func (m *BurntNFT) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -331,45 +391,48 @@ func init() { proto.RegisterType((*FrozenNFT)(nil), "coreum.asset.nft.v1.FrozenNFT") proto.RegisterType((*WhitelistedNFTAccounts)(nil), "coreum.asset.nft.v1.WhitelistedNFTAccounts") proto.RegisterType((*ClassWhitelistedAccounts)(nil), "coreum.asset.nft.v1.ClassWhitelistedAccounts") + proto.RegisterType((*ClassFrozenAccounts)(nil), "coreum.asset.nft.v1.ClassFrozenAccounts") proto.RegisterType((*BurntNFT)(nil), "coreum.asset.nft.v1.BurntNFT") } func init() { proto.RegisterFile("coreum/asset/nft/v1/genesis.proto", fileDescriptor_3abcf08d60f6fbfd) } var fileDescriptor_3abcf08d60f6fbfd = []byte{ - // 507 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0x4d, 0x6f, 0xd3, 0x40, - 0x10, 0x8d, 0xd3, 0x34, 0xd4, 0x13, 0x0e, 0x74, 0xa9, 0xa2, 0x95, 0x51, 0xdd, 0x10, 0x71, 0xa8, - 0x84, 0xb0, 0xd5, 0xf6, 0x80, 0x90, 0xe0, 0x80, 0x1b, 0x05, 0xf5, 0x12, 0x8a, 0x5b, 0xa9, 0x12, - 0x97, 0xc8, 0x71, 0xd6, 0xa9, 0xa5, 0x66, 0x37, 0x78, 0xd7, 0xe1, 0xe3, 0xce, 0x9d, 0xff, 0xc4, - 0xa5, 0xc7, 0x1e, 0x39, 0x55, 0x28, 0xf9, 0x23, 0xc8, 0xb3, 0x8e, 0x71, 0x91, 0x53, 0x89, 0xdb, - 0xce, 0xcc, 0x9b, 0xf7, 0xf6, 0xed, 0xec, 0xc0, 0xd3, 0x50, 0x24, 0x2c, 0x9d, 0xba, 0x81, 0x94, - 0x4c, 0xb9, 0x3c, 0x52, 0xee, 0xfc, 0xc0, 0x9d, 0x30, 0xce, 0x64, 0x2c, 0x9d, 0x59, 0x22, 0x94, - 0x20, 0x8f, 0x35, 0xc4, 0x41, 0x88, 0xc3, 0x23, 0xe5, 0xcc, 0x0f, 0xac, 0x9d, 0x89, 0x98, 0x08, - 0xac, 0xbb, 0xd9, 0x49, 0x43, 0xad, 0x4e, 0x15, 0xdb, 0x2c, 0x48, 0x82, 0x69, 0x4e, 0x66, 0xed, - 0x56, 0x21, 0x32, 0x4e, 0x2c, 0x77, 0x7f, 0x36, 0xe0, 0xe1, 0x3b, 0xad, 0x7e, 0xa6, 0x02, 0xc5, - 0xc8, 0x2b, 0x68, 0xea, 0x7e, 0x6a, 0x74, 0x8c, 0xfd, 0xd6, 0xe1, 0x13, 0xa7, 0xe2, 0x36, 0xce, - 0x29, 0x42, 0xbc, 0xc6, 0xf5, 0xed, 0x5e, 0xcd, 0xcf, 0x1b, 0xc8, 0x05, 0x6c, 0x87, 0x57, 0x81, - 0x94, 0xc3, 0x31, 0x8b, 0x62, 0x1e, 0xab, 0x58, 0x70, 0x49, 0xeb, 0x9d, 0x8d, 0xfd, 0xd6, 0xe1, - 0xb3, 0x4a, 0x96, 0xe3, 0x0c, 0xdd, 0x2b, 0xc0, 0x39, 0xdd, 0xa3, 0xf0, 0x6e, 0x5a, 0x92, 0x33, - 0x68, 0x45, 0x89, 0xf8, 0xc6, 0xf8, 0x90, 0x47, 0x4a, 0xd2, 0x0d, 0xa4, 0xb4, 0x2b, 0x29, 0xfb, - 0x88, 0x1b, 0xf4, 0xcf, 0x3d, 0x92, 0x91, 0x2d, 0x6e, 0xf7, 0xa0, 0x48, 0x49, 0x1f, 0x34, 0xcd, - 0x20, 0x52, 0x92, 0x7c, 0x37, 0x80, 0x7e, 0xbe, 0x8c, 0x15, 0xbb, 0x8a, 0xa5, 0x62, 0xe3, 0x8c, - 0x7a, 0x18, 0x84, 0xa1, 0x48, 0xb9, 0x92, 0xb4, 0x81, 0x12, 0xcf, 0x2b, 0x25, 0x2e, 0xfe, 0x36, - 0x0d, 0xfa, 0xe7, 0x6f, 0xf3, 0x16, 0xcf, 0xce, 0xf5, 0xda, 0xd5, 0x75, 0xbf, 0x5d, 0x12, 0x1b, - 0x44, 0x6a, 0x95, 0x27, 0xef, 0x01, 0x46, 0x69, 0xc2, 0x95, 0xf6, 0xb6, 0x89, 0xc2, 0xbb, 0x95, - 0xc2, 0x5e, 0x06, 0xcb, 0xac, 0x6d, 0xe7, 0x52, 0xe6, 0x2a, 0x23, 0x7d, 0x13, 0x39, 0xd0, 0xd8, - 0x27, 0xb0, 0xf4, 0x18, 0xca, 0xee, 0x0a, 0x67, 0x4d, 0x14, 0x78, 0xb1, 0x7e, 0x1e, 0xa5, 0xeb, - 0x17, 0xde, 0xf4, 0x60, 0x68, 0xb8, 0xa6, 0xde, 0x7d, 0x03, 0x66, 0xf1, 0xca, 0x84, 0xc2, 0x03, - 0x04, 0x9e, 0xf4, 0xf0, 0x0b, 0x99, 0xfe, 0x2a, 0x24, 0x6d, 0x68, 0xf2, 0x48, 0x9d, 0xf4, 0xf4, - 0xaf, 0x30, 0xfd, 0x3c, 0xea, 0x8e, 0x61, 0xcd, 0xa3, 0xdd, 0xc3, 0xb5, 0x03, 0x9b, 0xd8, 0x4d, - 0xeb, 0x98, 0xd7, 0x01, 0xb1, 0x60, 0xeb, 0xce, 0x0c, 0x4d, 0xbf, 0x88, 0xbb, 0xa7, 0x40, 0xd7, - 0x19, 0xbc, 0x47, 0xa7, 0xcc, 0x58, 0xff, 0x87, 0xf1, 0x35, 0x6c, 0xad, 0x26, 0xf0, 0xff, 0xae, - 0xbd, 0x0f, 0xd7, 0x0b, 0xdb, 0xb8, 0x59, 0xd8, 0xc6, 0xef, 0x85, 0x6d, 0xfc, 0x58, 0xda, 0xb5, - 0x9b, 0xa5, 0x5d, 0xfb, 0xb5, 0xb4, 0x6b, 0x1f, 0x5f, 0x4e, 0x62, 0x75, 0x99, 0x8e, 0x9c, 0x50, - 0x4c, 0xdd, 0x63, 0x9c, 0x53, 0x5f, 0xa4, 0x7c, 0x1c, 0x64, 0xdb, 0xe0, 0xe6, 0xfb, 0x3c, 0x3f, - 0x72, 0xbf, 0x94, 0x96, 0x5a, 0x7d, 0x9d, 0x31, 0x39, 0x6a, 0xe2, 0x52, 0x1f, 0xfd, 0x09, 0x00, - 0x00, 0xff, 0xff, 0x6a, 0xc5, 0x5d, 0xf6, 0x65, 0x04, 0x00, 0x00, + // 541 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0x8d, 0xd3, 0x26, 0xad, 0x27, 0x1c, 0xe8, 0xa6, 0x44, 0x96, 0x51, 0xdd, 0x10, 0x71, 0x88, + 0x84, 0xb0, 0xd5, 0xf6, 0x80, 0x90, 0xe0, 0x80, 0x1b, 0x05, 0x55, 0x48, 0xa1, 0xb8, 0x95, 0x2a, + 0x71, 0x89, 0x1c, 0x67, 0x9d, 0x5a, 0x6a, 0x76, 0x83, 0x77, 0x1d, 0x3e, 0xee, 0xdc, 0xf9, 0x17, + 0xfc, 0x95, 0x1e, 0x7b, 0xe4, 0x54, 0xa1, 0xe4, 0x8f, 0x20, 0xef, 0x3a, 0xc6, 0x2d, 0xeb, 0x4a, + 0xf4, 0xe6, 0x99, 0x79, 0xf3, 0xde, 0xce, 0xbe, 0xf1, 0xc2, 0x93, 0x80, 0xc6, 0x38, 0x99, 0x3a, + 0x3e, 0x63, 0x98, 0x3b, 0x24, 0xe4, 0xce, 0x7c, 0xcf, 0x99, 0x60, 0x82, 0x59, 0xc4, 0xec, 0x59, + 0x4c, 0x39, 0x45, 0x4d, 0x09, 0xb1, 0x05, 0xc4, 0x26, 0x21, 0xb7, 0xe7, 0x7b, 0xe6, 0xf6, 0x84, + 0x4e, 0xa8, 0xa8, 0x3b, 0xe9, 0x97, 0x84, 0x9a, 0x6d, 0x15, 0xdb, 0xcc, 0x8f, 0xfd, 0x69, 0x46, + 0x66, 0xee, 0xa8, 0x10, 0x29, 0xa7, 0x28, 0x77, 0x7e, 0xd6, 0xe0, 0xc1, 0x5b, 0xa9, 0x7e, 0xc2, + 0x7d, 0x8e, 0xd1, 0x4b, 0xa8, 0xcb, 0x7e, 0x43, 0x6b, 0x6b, 0xdd, 0xc6, 0xfe, 0x63, 0x5b, 0x71, + 0x1a, 0xfb, 0x58, 0x40, 0xdc, 0xf5, 0xcb, 0xeb, 0xdd, 0x8a, 0x97, 0x35, 0xa0, 0x33, 0xd8, 0x0a, + 0x2e, 0x7c, 0xc6, 0x86, 0x63, 0x1c, 0x46, 0x24, 0xe2, 0x11, 0x25, 0xcc, 0xa8, 0xb6, 0xd7, 0xba, + 0x8d, 0xfd, 0xa7, 0x4a, 0x96, 0xc3, 0x14, 0xdd, 0xcb, 0xc1, 0x19, 0xdd, 0xc3, 0xe0, 0x66, 0x9a, + 0xa1, 0x13, 0x68, 0x84, 0x31, 0xfd, 0x86, 0xc9, 0x90, 0x84, 0x9c, 0x19, 0x6b, 0x82, 0xd2, 0x52, + 0x52, 0xf6, 0x05, 0x6e, 0xd0, 0x3f, 0x75, 0x51, 0x4a, 0xb6, 0xb8, 0xde, 0x85, 0x3c, 0xc5, 0x3c, + 0x90, 0x34, 0x83, 0x90, 0x33, 0xf4, 0x5d, 0x03, 0xe3, 0xf3, 0x79, 0xc4, 0xf1, 0x45, 0xc4, 0x38, + 0x1e, 0xa7, 0xd4, 0x43, 0x3f, 0x08, 0x68, 0x42, 0x38, 0x33, 0xd6, 0x85, 0xc4, 0x33, 0xa5, 0xc4, + 0xd9, 0xdf, 0xa6, 0x41, 0xff, 0xf4, 0x4d, 0xd6, 0xe2, 0x5a, 0x99, 0x5e, 0x4b, 0x5d, 0xf7, 0x5a, + 0x05, 0xb1, 0x41, 0xc8, 0x57, 0x79, 0xf4, 0x1e, 0x60, 0x94, 0xc4, 0x84, 0xcb, 0xd9, 0x6a, 0x42, + 0x78, 0x47, 0x29, 0xec, 0xa6, 0xb0, 0x74, 0xb4, 0xad, 0x4c, 0x4a, 0x5f, 0x65, 0x98, 0xa7, 0x0b, + 0x0e, 0x31, 0xd8, 0x27, 0x30, 0xa5, 0x0d, 0xc5, 0xe9, 0xf2, 0xc9, 0xea, 0x42, 0xe0, 0x79, 0xb9, + 0x1f, 0x85, 0xe3, 0xe7, 0xb3, 0x49, 0x63, 0x8c, 0xa0, 0xa4, 0x8e, 0x46, 0xf0, 0x48, 0x4a, 0x66, + 0x36, 0xe5, 0x6a, 0x1b, 0x42, 0xad, 0x5b, 0xae, 0x26, 0xcd, 0xb9, 0x25, 0xd4, 0x0c, 0xfe, 0x2d, + 0x75, 0x5e, 0x83, 0x9e, 0x3b, 0x89, 0x0c, 0xd8, 0x10, 0x98, 0xa3, 0x9e, 0x58, 0x53, 0xdd, 0x5b, + 0x85, 0xa8, 0x05, 0x75, 0x12, 0xf2, 0xa3, 0x9e, 0xdc, 0x3c, 0xdd, 0xcb, 0xa2, 0xce, 0x18, 0x4a, + 0x8c, 0xb9, 0x83, 0x6b, 0x1b, 0x6a, 0xa2, 0xdb, 0xa8, 0x8a, 0xbc, 0x0c, 0x90, 0x09, 0x9b, 0x37, + 0xf6, 0x44, 0xf7, 0xf2, 0xb8, 0x73, 0x0c, 0x46, 0xd9, 0x25, 0xde, 0xa1, 0x53, 0x64, 0xac, 0xde, + 0x62, 0x7c, 0x07, 0x4d, 0xc5, 0x45, 0xdd, 0x93, 0xec, 0x15, 0x6c, 0xae, 0x56, 0xe6, 0xff, 0xaf, + 0xd0, 0xfd, 0x70, 0xb9, 0xb0, 0xb4, 0xab, 0x85, 0xa5, 0xfd, 0x5e, 0x58, 0xda, 0x8f, 0xa5, 0x55, + 0xb9, 0x5a, 0x5a, 0x95, 0x5f, 0x4b, 0xab, 0xf2, 0xf1, 0xc5, 0x24, 0xe2, 0xe7, 0xc9, 0xc8, 0x0e, + 0xe8, 0xd4, 0x39, 0x14, 0x56, 0xf7, 0x69, 0x42, 0xc6, 0x7e, 0xfa, 0xfb, 0x3a, 0xd9, 0x03, 0x34, + 0x3f, 0x70, 0xbe, 0x14, 0x5e, 0x21, 0xfe, 0x75, 0x86, 0xd9, 0xa8, 0x2e, 0x5e, 0xa1, 0x83, 0x3f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0xc5, 0x38, 0x7d, 0x87, 0x16, 0x05, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -392,6 +455,20 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.ClassFrozenAccounts) > 0 { + for iNdEx := len(m.ClassFrozenAccounts) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ClassFrozenAccounts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + } if len(m.ClassWhitelistedAccounts) > 0 { for iNdEx := len(m.ClassWhitelistedAccounts) - 1; iNdEx >= 0; iNdEx-- { { @@ -599,6 +676,45 @@ func (m *ClassWhitelistedAccounts) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *ClassFrozenAccounts) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ClassFrozenAccounts) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ClassFrozenAccounts) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Accounts) > 0 { + for iNdEx := len(m.Accounts) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Accounts[iNdEx]) + copy(dAtA[i:], m.Accounts[iNdEx]) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Accounts[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(m.ClassID) > 0 { + i -= len(m.ClassID) + copy(dAtA[i:], m.ClassID) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.ClassID))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *BurntNFT) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -687,6 +803,12 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } + if len(m.ClassFrozenAccounts) > 0 { + for _, e := range m.ClassFrozenAccounts { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } return n } @@ -751,6 +873,25 @@ func (m *ClassWhitelistedAccounts) Size() (n int) { return n } +func (m *ClassFrozenAccounts) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClassID) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if len(m.Accounts) > 0 { + for _, s := range m.Accounts { + l = len(s) + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + func (m *BurntNFT) Size() (n int) { if m == nil { return 0 @@ -1008,6 +1149,40 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassFrozenAccounts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassFrozenAccounts = append(m.ClassFrozenAccounts, ClassFrozenAccounts{}) + if err := m.ClassFrozenAccounts[len(m.ClassFrozenAccounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) @@ -1403,6 +1578,120 @@ func (m *ClassWhitelistedAccounts) Unmarshal(dAtA []byte) error { } return nil } +func (m *ClassFrozenAccounts) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ClassFrozenAccounts: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ClassFrozenAccounts: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Accounts", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Accounts = append(m.Accounts, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *BurntNFT) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/asset/nft/types/keys.go b/x/asset/nft/types/keys.go index b81182e19..d7147644f 100644 --- a/x/asset/nft/types/keys.go +++ b/x/asset/nft/types/keys.go @@ -35,6 +35,8 @@ var ( ParamsKey = []byte{0x05} // NFTClassWhitelistingKeyPrefix defines the key prefix to track whitelisted account for class. NFTClassWhitelistingKeyPrefix = []byte{0x06} + // NFTClassFreezingKeyPrefix defines the key prefix to track frozen account for NFT class. + NFTClassFreezingKeyPrefix = []byte{0x07} ) // StoreTrue keeps a value used by stores to indicate that key is present. @@ -81,12 +83,35 @@ func ParseFreezingKey(key []byte) (string, string, error) { return "", "", sdkerrors.Wrapf(ErrInvalidKey, "failed to parse a freezing key, err: %s", err) } if len(parsedKeys) != 2 { - err = sdkerrors.Wrapf(ErrInvalidKey, "freezing key must be composed to 2 length prefixed keys") + err = sdkerrors.Wrapf(ErrInvalidKey, "freezing key must be composed of 2 length prefixed keys") return "", "", err } return string(parsedKeys[0]), string(parsedKeys[1]), nil } +// CreateClassFreezingKey constructs the key for the class freezing of NFT class. +func CreateClassFreezingKey(classID string, account sdk.AccAddress) ([]byte, error) { + compositeKey, err := store.JoinKeysWithLength([]byte(classID), account) + if err != nil { + return nil, sdkerrors.Wrapf(ErrInvalidKey, "failed to create a freezing key, err: %s", err) + } + + return store.JoinKeys(NFTClassFreezingKeyPrefix, compositeKey), nil +} + +// ParseClassFreezingKey parses key back to class id and account. +func ParseClassFreezingKey(key []byte) (string, sdk.AccAddress, error) { + parsedKeys, err := store.ParseLengthPrefixedKeys(key) + if err != nil { + return "", nil, sdkerrors.Wrapf(ErrInvalidKey, "failed to parse class freezing key, err: %s", err) + } + if len(parsedKeys) != 2 { + err = sdkerrors.Wrapf(ErrInvalidKey, "key must be composed of 2 length prefixed keys") + return "", nil, err + } + return string(parsedKeys[0]), parsedKeys[1], nil +} + // CreateWhitelistingKey constructs the key for the whitelisting of non-fungible token. func CreateWhitelistingKey(classID, nftID string, account sdk.AccAddress) ([]byte, error) { compositeKey, err := store.JoinKeysWithLength([]byte(classID), []byte(nftID), account) @@ -160,7 +185,7 @@ func ParseBurningKey(key []byte) (string, string, error) { return "", "", sdkerrors.Wrapf(ErrInvalidKey, "failed to parse a burning key, err: %s", err) } if len(parsedKeys) != 2 { - err = sdkerrors.Wrapf(ErrInvalidKey, "burning key must be composed to 2 length prefixed keys") + err = sdkerrors.Wrapf(ErrInvalidKey, "burning key must be composed of 2 length prefixed keys") return "", "", err } return string(parsedKeys[0]), string(parsedKeys[1]), nil diff --git a/x/asset/nft/types/msgs.go b/x/asset/nft/types/msgs.go index 5599b622e..a5056fb42 100644 --- a/x/asset/nft/types/msgs.go +++ b/x/asset/nft/types/msgs.go @@ -23,6 +23,8 @@ const ( TypeMsgRemoveFromWhitelist = "remove-from-whitelist" TypeMsgAddToClassWhitelist = "class-whitelist" TypeMsgRemoveFromClassWhitelist = "remove-from-class-whitelist" + TypeMsgClassFreeze = "class-freeze" + TypeMsgClassUnfreeze = "class-unfreeze" TypeMsgUpdateParams = "update-params" ) @@ -41,6 +43,8 @@ var ( _ msgAndLegacyMsg = &MsgRemoveFromWhitelist{} _ msgAndLegacyMsg = &MsgAddToClassWhitelist{} _ msgAndLegacyMsg = &MsgRemoveFromClassWhitelist{} + _ msgAndLegacyMsg = &MsgClassFreeze{} + _ msgAndLegacyMsg = &MsgClassUnfreeze{} _ msgAndLegacyMsg = &MsgUpdateParams{} ) @@ -64,6 +68,8 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgRemoveFromWhitelist{}, fmt.Sprintf("%s/MsgRemoveFromWhitelist", ModuleName), nil) cdc.RegisterConcrete(&MsgAddToClassWhitelist{}, fmt.Sprintf("%s/MsgAddToClassWhitelist", ModuleName), nil) cdc.RegisterConcrete(&MsgRemoveFromClassWhitelist{}, fmt.Sprintf("%s/MsgRemoveFromClassWhitelist", ModuleName), nil) + cdc.RegisterConcrete(&MsgClassFreeze{}, fmt.Sprintf("%s/MsgClassFreeze", ModuleName), nil) + cdc.RegisterConcrete(&MsgClassUnfreeze{}, fmt.Sprintf("%s/MsgClassUnfreeze", ModuleName), nil) cdc.RegisterConcrete(&MsgUpdateParams{}, fmt.Sprintf("%s/MsgUpdateParams", ModuleName), nil) } @@ -385,6 +391,84 @@ func (m MsgRemoveFromWhitelist) Type() string { return TypeMsgRemoveFromWhitelist } +// ValidateBasic checks that message fields are valid. +func (m *MsgClassFreeze) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(m.Sender); err != nil { + return sdkerrors.Wrapf(cosmoserrors.ErrInvalidAddress, "invalid sender account %s", m.Sender) + } + + if _, err := sdk.AccAddressFromBech32(m.Account); err != nil { + return sdkerrors.Wrapf(cosmoserrors.ErrInvalidAddress, "invalid account %s", m.Sender) + } + + if _, _, err := DeconstructClassID(m.ClassID); err != nil { + return sdkerrors.Wrap(ErrInvalidInput, err.Error()) + } + + return nil +} + +// GetSigners returns the required signers of this message type. +func (m *MsgClassFreeze) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{ + sdk.MustAccAddressFromBech32(m.Sender), + } +} + +// GetSignBytes returns sign bytes for LegacyMsg. +func (m MsgClassFreeze) GetSignBytes() []byte { + return sdk.MustSortJSON(moduleAminoCdc.MustMarshalJSON(&m)) +} + +// Route returns message route for LegacyMsg. +func (m MsgClassFreeze) Route() string { + return RouterKey +} + +// Type returns message type for LegacyMsg. +func (m MsgClassFreeze) Type() string { + return TypeMsgClassFreeze +} + +// ValidateBasic checks that message fields are valid. +func (m *MsgClassUnfreeze) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(m.Sender); err != nil { + return sdkerrors.Wrapf(cosmoserrors.ErrInvalidAddress, "invalid sender account %s", m.Sender) + } + + if _, err := sdk.AccAddressFromBech32(m.Account); err != nil { + return sdkerrors.Wrapf(cosmoserrors.ErrInvalidAddress, "invalid account %s", m.Sender) + } + + if _, _, err := DeconstructClassID(m.ClassID); err != nil { + return sdkerrors.Wrap(ErrInvalidInput, err.Error()) + } + + return nil +} + +// GetSigners returns the required signers of this message type. +func (m *MsgClassUnfreeze) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{ + sdk.MustAccAddressFromBech32(m.Sender), + } +} + +// GetSignBytes returns sign bytes for LegacyMsg. +func (m MsgClassUnfreeze) GetSignBytes() []byte { + return sdk.MustSortJSON(moduleAminoCdc.MustMarshalJSON(&m)) +} + +// Route returns message route for LegacyMsg. +func (m MsgClassUnfreeze) Route() string { + return RouterKey +} + +// Type returns message type for LegacyMsg. +func (m MsgClassUnfreeze) Type() string { + return TypeMsgClassUnfreeze +} + // ValidateBasic checks that message fields are valid. func (m MsgUpdateParams) ValidateBasic() error { if _, err := sdk.AccAddressFromBech32(m.Authority); err != nil { diff --git a/x/asset/nft/types/query.pb.go b/x/asset/nft/types/query.pb.go index f545c5c20..1a571a08e 100644 --- a/x/asset/nft/types/query.pb.go +++ b/x/asset/nft/types/query.pb.go @@ -406,6 +406,102 @@ func (m *QueryFrozenResponse) GetFrozen() bool { return false } +type QueryClassFrozenRequest struct { + ClassId string `protobuf:"bytes,1,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` + Account string `protobuf:"bytes,2,opt,name=account,proto3" json:"account,omitempty"` +} + +func (m *QueryClassFrozenRequest) Reset() { *m = QueryClassFrozenRequest{} } +func (m *QueryClassFrozenRequest) String() string { return proto.CompactTextString(m) } +func (*QueryClassFrozenRequest) ProtoMessage() {} +func (*QueryClassFrozenRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_97b36b7d05006cb3, []int{8} +} +func (m *QueryClassFrozenRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassFrozenRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassFrozenRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassFrozenRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassFrozenRequest.Merge(m, src) +} +func (m *QueryClassFrozenRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryClassFrozenRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassFrozenRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassFrozenRequest proto.InternalMessageInfo + +func (m *QueryClassFrozenRequest) GetClassId() string { + if m != nil { + return m.ClassId + } + return "" +} + +func (m *QueryClassFrozenRequest) GetAccount() string { + if m != nil { + return m.Account + } + return "" +} + +type QueryClassFrozenResponse struct { + Frozen bool `protobuf:"varint,1,opt,name=frozen,proto3" json:"frozen,omitempty"` +} + +func (m *QueryClassFrozenResponse) Reset() { *m = QueryClassFrozenResponse{} } +func (m *QueryClassFrozenResponse) String() string { return proto.CompactTextString(m) } +func (*QueryClassFrozenResponse) ProtoMessage() {} +func (*QueryClassFrozenResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_97b36b7d05006cb3, []int{9} +} +func (m *QueryClassFrozenResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassFrozenResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassFrozenResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassFrozenResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassFrozenResponse.Merge(m, src) +} +func (m *QueryClassFrozenResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryClassFrozenResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassFrozenResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassFrozenResponse proto.InternalMessageInfo + +func (m *QueryClassFrozenResponse) GetFrozen() bool { + if m != nil { + return m.Frozen + } + return false +} + type QueryWhitelistedRequest struct { Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` ClassId string `protobuf:"bytes,2,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` @@ -416,7 +512,7 @@ func (m *QueryWhitelistedRequest) Reset() { *m = QueryWhitelistedRequest func (m *QueryWhitelistedRequest) String() string { return proto.CompactTextString(m) } func (*QueryWhitelistedRequest) ProtoMessage() {} func (*QueryWhitelistedRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_97b36b7d05006cb3, []int{8} + return fileDescriptor_97b36b7d05006cb3, []int{10} } func (m *QueryWhitelistedRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -474,7 +570,7 @@ func (m *QueryWhitelistedResponse) Reset() { *m = QueryWhitelistedRespon func (m *QueryWhitelistedResponse) String() string { return proto.CompactTextString(m) } func (*QueryWhitelistedResponse) ProtoMessage() {} func (*QueryWhitelistedResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_97b36b7d05006cb3, []int{9} + return fileDescriptor_97b36b7d05006cb3, []int{11} } func (m *QueryWhitelistedResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -521,7 +617,7 @@ func (m *QueryWhitelistedAccountsForNFTRequest) Reset() { *m = QueryWhit func (m *QueryWhitelistedAccountsForNFTRequest) String() string { return proto.CompactTextString(m) } func (*QueryWhitelistedAccountsForNFTRequest) ProtoMessage() {} func (*QueryWhitelistedAccountsForNFTRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_97b36b7d05006cb3, []int{10} + return fileDescriptor_97b36b7d05006cb3, []int{12} } func (m *QueryWhitelistedAccountsForNFTRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -583,7 +679,7 @@ func (m *QueryWhitelistedAccountsForNFTResponse) Reset() { func (m *QueryWhitelistedAccountsForNFTResponse) String() string { return proto.CompactTextString(m) } func (*QueryWhitelistedAccountsForNFTResponse) ProtoMessage() {} func (*QueryWhitelistedAccountsForNFTResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_97b36b7d05006cb3, []int{11} + return fileDescriptor_97b36b7d05006cb3, []int{13} } func (m *QueryWhitelistedAccountsForNFTResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -636,7 +732,7 @@ func (m *QueryClassWhitelistedAccountsRequest) Reset() { *m = QueryClass func (m *QueryClassWhitelistedAccountsRequest) String() string { return proto.CompactTextString(m) } func (*QueryClassWhitelistedAccountsRequest) ProtoMessage() {} func (*QueryClassWhitelistedAccountsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_97b36b7d05006cb3, []int{12} + return fileDescriptor_97b36b7d05006cb3, []int{14} } func (m *QueryClassWhitelistedAccountsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -689,7 +785,7 @@ func (m *QueryClassWhitelistedAccountsResponse) Reset() { *m = QueryClas func (m *QueryClassWhitelistedAccountsResponse) String() string { return proto.CompactTextString(m) } func (*QueryClassWhitelistedAccountsResponse) ProtoMessage() {} func (*QueryClassWhitelistedAccountsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_97b36b7d05006cb3, []int{13} + return fileDescriptor_97b36b7d05006cb3, []int{15} } func (m *QueryClassWhitelistedAccountsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -732,6 +828,112 @@ func (m *QueryClassWhitelistedAccountsResponse) GetAccounts() []string { return nil } +type QueryClassFrozenAccountsRequest struct { + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` + ClassId string `protobuf:"bytes,2,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` +} + +func (m *QueryClassFrozenAccountsRequest) Reset() { *m = QueryClassFrozenAccountsRequest{} } +func (m *QueryClassFrozenAccountsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryClassFrozenAccountsRequest) ProtoMessage() {} +func (*QueryClassFrozenAccountsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_97b36b7d05006cb3, []int{16} +} +func (m *QueryClassFrozenAccountsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassFrozenAccountsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassFrozenAccountsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassFrozenAccountsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassFrozenAccountsRequest.Merge(m, src) +} +func (m *QueryClassFrozenAccountsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryClassFrozenAccountsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassFrozenAccountsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassFrozenAccountsRequest proto.InternalMessageInfo + +func (m *QueryClassFrozenAccountsRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +func (m *QueryClassFrozenAccountsRequest) GetClassId() string { + if m != nil { + return m.ClassId + } + return "" +} + +type QueryClassFrozenAccountsResponse struct { + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` + Accounts []string `protobuf:"bytes,2,rep,name=accounts,proto3" json:"accounts,omitempty"` +} + +func (m *QueryClassFrozenAccountsResponse) Reset() { *m = QueryClassFrozenAccountsResponse{} } +func (m *QueryClassFrozenAccountsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryClassFrozenAccountsResponse) ProtoMessage() {} +func (*QueryClassFrozenAccountsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_97b36b7d05006cb3, []int{17} +} +func (m *QueryClassFrozenAccountsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassFrozenAccountsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassFrozenAccountsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassFrozenAccountsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassFrozenAccountsResponse.Merge(m, src) +} +func (m *QueryClassFrozenAccountsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryClassFrozenAccountsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassFrozenAccountsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassFrozenAccountsResponse proto.InternalMessageInfo + +func (m *QueryClassFrozenAccountsResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +func (m *QueryClassFrozenAccountsResponse) GetAccounts() []string { + if m != nil { + return m.Accounts + } + return nil +} + type QueryBurntNFTRequest struct { ClassId string `protobuf:"bytes,1,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` NftId string `protobuf:"bytes,2,opt,name=nft_id,json=nftId,proto3" json:"nft_id,omitempty"` @@ -741,7 +943,7 @@ func (m *QueryBurntNFTRequest) Reset() { *m = QueryBurntNFTRequest{} } func (m *QueryBurntNFTRequest) String() string { return proto.CompactTextString(m) } func (*QueryBurntNFTRequest) ProtoMessage() {} func (*QueryBurntNFTRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_97b36b7d05006cb3, []int{14} + return fileDescriptor_97b36b7d05006cb3, []int{18} } func (m *QueryBurntNFTRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -792,7 +994,7 @@ func (m *QueryBurntNFTResponse) Reset() { *m = QueryBurntNFTResponse{} } func (m *QueryBurntNFTResponse) String() string { return proto.CompactTextString(m) } func (*QueryBurntNFTResponse) ProtoMessage() {} func (*QueryBurntNFTResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_97b36b7d05006cb3, []int{15} + return fileDescriptor_97b36b7d05006cb3, []int{19} } func (m *QueryBurntNFTResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -837,7 +1039,7 @@ func (m *QueryBurntNFTsInClassRequest) Reset() { *m = QueryBurntNFTsInCl func (m *QueryBurntNFTsInClassRequest) String() string { return proto.CompactTextString(m) } func (*QueryBurntNFTsInClassRequest) ProtoMessage() {} func (*QueryBurntNFTsInClassRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_97b36b7d05006cb3, []int{16} + return fileDescriptor_97b36b7d05006cb3, []int{20} } func (m *QueryBurntNFTsInClassRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -889,7 +1091,7 @@ func (m *QueryBurntNFTsInClassResponse) Reset() { *m = QueryBurntNFTsInC func (m *QueryBurntNFTsInClassResponse) String() string { return proto.CompactTextString(m) } func (*QueryBurntNFTsInClassResponse) ProtoMessage() {} func (*QueryBurntNFTsInClassResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_97b36b7d05006cb3, []int{17} + return fileDescriptor_97b36b7d05006cb3, []int{21} } func (m *QueryBurntNFTsInClassResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -941,12 +1143,16 @@ func init() { proto.RegisterType((*QueryClassesResponse)(nil), "coreum.asset.nft.v1.QueryClassesResponse") proto.RegisterType((*QueryFrozenRequest)(nil), "coreum.asset.nft.v1.QueryFrozenRequest") proto.RegisterType((*QueryFrozenResponse)(nil), "coreum.asset.nft.v1.QueryFrozenResponse") + proto.RegisterType((*QueryClassFrozenRequest)(nil), "coreum.asset.nft.v1.QueryClassFrozenRequest") + proto.RegisterType((*QueryClassFrozenResponse)(nil), "coreum.asset.nft.v1.QueryClassFrozenResponse") proto.RegisterType((*QueryWhitelistedRequest)(nil), "coreum.asset.nft.v1.QueryWhitelistedRequest") proto.RegisterType((*QueryWhitelistedResponse)(nil), "coreum.asset.nft.v1.QueryWhitelistedResponse") proto.RegisterType((*QueryWhitelistedAccountsForNFTRequest)(nil), "coreum.asset.nft.v1.QueryWhitelistedAccountsForNFTRequest") proto.RegisterType((*QueryWhitelistedAccountsForNFTResponse)(nil), "coreum.asset.nft.v1.QueryWhitelistedAccountsForNFTResponse") proto.RegisterType((*QueryClassWhitelistedAccountsRequest)(nil), "coreum.asset.nft.v1.QueryClassWhitelistedAccountsRequest") proto.RegisterType((*QueryClassWhitelistedAccountsResponse)(nil), "coreum.asset.nft.v1.QueryClassWhitelistedAccountsResponse") + proto.RegisterType((*QueryClassFrozenAccountsRequest)(nil), "coreum.asset.nft.v1.QueryClassFrozenAccountsRequest") + proto.RegisterType((*QueryClassFrozenAccountsResponse)(nil), "coreum.asset.nft.v1.QueryClassFrozenAccountsResponse") proto.RegisterType((*QueryBurntNFTRequest)(nil), "coreum.asset.nft.v1.QueryBurntNFTRequest") proto.RegisterType((*QueryBurntNFTResponse)(nil), "coreum.asset.nft.v1.QueryBurntNFTResponse") proto.RegisterType((*QueryBurntNFTsInClassRequest)(nil), "coreum.asset.nft.v1.QueryBurntNFTsInClassRequest") @@ -956,68 +1162,74 @@ func init() { func init() { proto.RegisterFile("coreum/asset/nft/v1/query.proto", fileDescriptor_97b36b7d05006cb3) } var fileDescriptor_97b36b7d05006cb3 = []byte{ - // 969 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x41, 0x6f, 0x1b, 0x45, - 0x14, 0xce, 0x38, 0xd8, 0x49, 0x5f, 0x24, 0x04, 0xaf, 0x69, 0xeb, 0x6e, 0x13, 0x37, 0x6c, 0x4a, - 0x92, 0x56, 0x64, 0x47, 0x49, 0xd4, 0xd2, 0xa6, 0x40, 0x21, 0x15, 0x2e, 0x91, 0x10, 0xa4, 0x16, - 0x12, 0x12, 0x07, 0xd0, 0xda, 0x5e, 0xbb, 0x2b, 0x25, 0x3b, 0xae, 0x67, 0x36, 0x50, 0xa2, 0x48, - 0x14, 0xb8, 0x20, 0x81, 0x84, 0xc4, 0x0d, 0xc4, 0x81, 0x7f, 0xc0, 0x9d, 0x3f, 0xd0, 0x13, 0xaa, - 0xc4, 0x05, 0x09, 0x09, 0xa1, 0x84, 0x7f, 0xc1, 0x05, 0xed, 0xcc, 0xdb, 0x64, 0xd7, 0xd9, 0xb5, - 0x9d, 0x36, 0xea, 0xcd, 0x33, 0xf3, 0xde, 0xfb, 0xbe, 0xef, 0xcd, 0xdb, 0xf9, 0x64, 0xb8, 0xd8, - 0x10, 0x5d, 0x2f, 0xdc, 0xe2, 0xae, 0x94, 0x9e, 0xe2, 0x41, 0x4b, 0xf1, 0xed, 0x25, 0x7e, 0x3f, - 0xf4, 0xba, 0x0f, 0x9c, 0x4e, 0x57, 0x28, 0x81, 0xa7, 0x4d, 0x80, 0xa3, 0x03, 0x9c, 0xa0, 0xa5, - 0x9c, 0xed, 0x25, 0x6b, 0xb2, 0x2d, 0xda, 0x42, 0x9f, 0xf3, 0xe8, 0x97, 0x09, 0xb5, 0xa6, 0xda, - 0x42, 0xb4, 0x37, 0x3d, 0xee, 0x76, 0x7c, 0xee, 0x06, 0x81, 0x50, 0xae, 0xf2, 0x45, 0x20, 0xe9, - 0x74, 0x3a, 0x0b, 0x29, 0xaa, 0x67, 0x8e, 0x67, 0xb2, 0x8e, 0x3b, 0x6e, 0xd7, 0xdd, 0x8a, 0x0b, - 0x5c, 0x69, 0x08, 0xb9, 0x25, 0x24, 0xaf, 0xbb, 0xd2, 0x33, 0x14, 0xf9, 0xf6, 0x52, 0xdd, 0x53, - 0x6e, 0x14, 0xd7, 0xf6, 0x03, 0x8d, 0x66, 0x62, 0xed, 0x49, 0xc0, 0xbb, 0x51, 0xc4, 0x86, 0x2e, - 0x50, 0xf3, 0xee, 0x87, 0x9e, 0x54, 0xf6, 0x06, 0x9c, 0x4e, 0xed, 0xca, 0x8e, 0x08, 0xa4, 0x87, - 0x37, 0xa0, 0x64, 0x80, 0xca, 0x6c, 0x86, 0x2d, 0x4c, 0x2c, 0x5f, 0x70, 0x32, 0x34, 0x3b, 0x26, - 0x69, 0xed, 0xb9, 0x47, 0x7f, 0x5f, 0x1c, 0xa9, 0x51, 0x82, 0x3d, 0x0b, 0x2f, 0xea, 0x8a, 0xb7, - 0x37, 0x5d, 0x19, 0xc3, 0xe0, 0xf3, 0x50, 0xf0, 0x9b, 0xba, 0xd6, 0xa9, 0x5a, 0xc1, 0x6f, 0xda, - 0xef, 0x12, 0x19, 0x0a, 0x22, 0xd4, 0x6b, 0x50, 0x6c, 0x44, 0x1b, 0x04, 0x6a, 0x65, 0x82, 0xea, - 0x14, 0xc2, 0x34, 0xe1, 0x76, 0x48, 0x22, 0xf4, 0x91, 0x77, 0x00, 0x5a, 0x05, 0x38, 0xec, 0x02, - 0xd5, 0x9c, 0x73, 0x4c, 0xcb, 0x9c, 0xa8, 0x65, 0x8e, 0xb9, 0x55, 0x6a, 0x99, 0xb3, 0xe1, 0xb6, - 0x3d, 0xca, 0xad, 0x25, 0x32, 0xf1, 0x2c, 0x94, 0x7c, 0x29, 0x43, 0xaf, 0x5b, 0x2e, 0x68, 0x01, - 0xb4, 0xb2, 0x7f, 0x62, 0x30, 0x99, 0xc6, 0x25, 0x1d, 0x77, 0x32, 0x80, 0xe7, 0x07, 0x02, 0x9b, - 0xe4, 0x14, 0xf2, 0x2a, 0x8c, 0x35, 0x4c, 0xed, 0x72, 0x61, 0x66, 0x74, 0xa8, 0x96, 0xc4, 0x09, - 0xf6, 0x2d, 0x6a, 0x71, 0xb5, 0x2b, 0x3e, 0xf7, 0x82, 0x9c, 0x8b, 0xc0, 0xf3, 0x30, 0xae, 0x13, - 0x3e, 0xf1, 0x9b, 0xa4, 0xce, 0x14, 0x58, 0x6f, 0xda, 0x8b, 0xd4, 0xd5, 0xb8, 0x00, 0x89, 0x3b, - 0x0b, 0xa5, 0x96, 0xde, 0xd1, 0x55, 0xc6, 0x6b, 0xb4, 0xb2, 0x3f, 0x86, 0x73, 0x3a, 0xfc, 0xc3, - 0x7b, 0xbe, 0xf2, 0x36, 0x7d, 0xa9, 0xbc, 0xe6, 0xf1, 0x41, 0xb1, 0x0c, 0x63, 0x6e, 0xa3, 0x21, - 0xc2, 0x40, 0x95, 0x47, 0xcd, 0x09, 0x2d, 0xed, 0xd7, 0xa0, 0x7c, 0xb4, 0x3e, 0x71, 0x9a, 0x81, - 0x89, 0x4f, 0x0f, 0xb7, 0x89, 0x58, 0x72, 0xcb, 0xfe, 0x91, 0xc1, 0xcb, 0xbd, 0xe9, 0x6f, 0x99, - 0xca, 0xb2, 0x2a, 0xba, 0xef, 0x55, 0x3f, 0x38, 0xe9, 0xa9, 0x31, 0xa2, 0x0b, 0x99, 0xa2, 0x47, - 0xd3, 0x9d, 0xfe, 0x8e, 0xc1, 0xdc, 0x20, 0x72, 0x27, 0x3d, 0x5a, 0x16, 0x8c, 0x53, 0x67, 0xcd, - 0x6c, 0x9d, 0xaa, 0x1d, 0xac, 0xed, 0x6f, 0x18, 0x5c, 0x3a, 0x1c, 0xec, 0x0c, 0x52, 0x27, 0xdd, - 0xab, 0x3e, 0x53, 0xf8, 0x6d, 0x7c, 0x71, 0xf9, 0x5c, 0x9e, 0x65, 0x6b, 0xde, 0xa1, 0x4f, 0x7e, - 0x2d, 0xec, 0x06, 0x2a, 0x31, 0x35, 0x49, 0x05, 0x2c, 0x3d, 0xd2, 0x67, 0xa0, 0x14, 0xb4, 0xd4, - 0xa1, 0xb4, 0x62, 0xd0, 0x52, 0xfa, 0xf3, 0x3a, 0xd3, 0x53, 0x89, 0x74, 0x4c, 0x42, 0xb1, 0x1e, - 0xed, 0xd1, 0x18, 0x9b, 0x85, 0xfd, 0x90, 0xc1, 0x54, 0x2a, 0x5e, 0xae, 0x07, 0xa9, 0x27, 0xf6, - 0x19, 0xdc, 0xc5, 0x43, 0x06, 0xd3, 0x39, 0x1c, 0x4e, 0xfa, 0x0e, 0xce, 0xc1, 0x98, 0x69, 0x5a, - 0x7c, 0x05, 0x25, 0xdd, 0x35, 0xb9, 0xfc, 0xdf, 0x04, 0x14, 0x35, 0x07, 0xfc, 0x82, 0x41, 0xc9, - 0x38, 0x10, 0xce, 0x67, 0x3e, 0x8b, 0x47, 0xed, 0xce, 0x5a, 0x18, 0x1c, 0x68, 0xc8, 0xd8, 0xb3, - 0x5f, 0xfe, 0xf1, 0xef, 0x0f, 0x85, 0x69, 0xbc, 0xc0, 0xf3, 0x5d, 0x18, 0xbf, 0x62, 0x50, 0xd4, - 0x0d, 0xc0, 0xb9, 0xfc, 0xc2, 0xc9, 0x5b, 0xb2, 0xe6, 0x07, 0xc6, 0x11, 0xfe, 0x65, 0x8d, 0x3f, - 0x8b, 0x2f, 0x65, 0xe2, 0xd3, 0x23, 0xcf, 0x77, 0xfc, 0xe6, 0x2e, 0x7e, 0xcd, 0x60, 0x8c, 0x2c, - 0x08, 0x17, 0x06, 0xd4, 0x3f, 0x70, 0x47, 0xeb, 0xf2, 0x10, 0x91, 0xc4, 0xe5, 0x92, 0xe6, 0x52, - 0xc1, 0xa9, 0x7e, 0x5c, 0xf0, 0x67, 0x06, 0x25, 0xe3, 0x15, 0xfd, 0xee, 0x23, 0x65, 0x47, 0xfd, - 0xee, 0x23, 0x6d, 0x3b, 0xf6, 0x9b, 0x9a, 0xc3, 0x2a, 0x5e, 0xef, 0xdf, 0x8f, 0x78, 0x74, 0x77, - 0xa3, 0x13, 0xd3, 0x1f, 0x6e, 0x0c, 0x0a, 0x7f, 0x63, 0x30, 0x91, 0x78, 0x3f, 0xf0, 0x95, 0x7c, - 0xec, 0xa3, 0x1e, 0x66, 0x2d, 0x0e, 0x19, 0x4d, 0x74, 0xdf, 0xd7, 0x74, 0xd7, 0xf1, 0xce, 0xf1, - 0xe9, 0x26, 0x6c, 0x8b, 0xef, 0xd0, 0xc3, 0xb3, 0x8b, 0x7f, 0x31, 0x38, 0x9f, 0x6b, 0x0f, 0xb8, - 0x3a, 0x14, 0xbb, 0x4c, 0xc3, 0xb3, 0x6e, 0x3e, 0x51, 0x2e, 0xe9, 0x7c, 0x5b, 0xeb, 0xbc, 0x85, - 0xaf, 0x3f, 0x95, 0x4e, 0xfc, 0x9d, 0x41, 0x39, 0xef, 0x81, 0xc7, 0x1b, 0x03, 0x26, 0x35, 0xdf, - 0xa0, 0xac, 0xd5, 0x27, 0x49, 0x25, 0x69, 0x37, 0xb5, 0xb4, 0xab, 0xb8, 0x32, 0xac, 0xb4, 0xa4, - 0xa0, 0x5f, 0x18, 0x8c, 0xc7, 0xaf, 0x24, 0xf6, 0xf9, 0xd4, 0x7a, 0x7c, 0xc4, 0xba, 0x32, 0x4c, - 0x28, 0x11, 0x7c, 0x43, 0x13, 0xbc, 0x8e, 0xd7, 0x86, 0x25, 0xa8, 0x9d, 0x84, 0xef, 0x98, 0x87, - 0x75, 0x17, 0x7f, 0x65, 0xf0, 0x42, 0xef, 0x4b, 0x8e, 0x4b, 0x83, 0x09, 0xf4, 0x38, 0x8f, 0xb5, - 0x7c, 0x9c, 0x14, 0xe2, 0x7e, 0x55, 0x73, 0xe7, 0xb8, 0x78, 0x2c, 0xee, 0x6b, 0x77, 0x1f, 0xed, - 0x55, 0xd8, 0xe3, 0xbd, 0x0a, 0xfb, 0x67, 0xaf, 0xc2, 0xbe, 0xdf, 0xaf, 0x8c, 0x3c, 0xde, 0xaf, - 0x8c, 0xfc, 0xb9, 0x5f, 0x19, 0xf9, 0xe8, 0xd5, 0xb6, 0xaf, 0xee, 0x85, 0x75, 0xa7, 0x21, 0xb6, - 0xf8, 0x6d, 0x5d, 0xb2, 0x2a, 0xc2, 0xa0, 0xa9, 0xdd, 0x24, 0xc6, 0xd8, 0x5e, 0xe1, 0x9f, 0x25, - 0x80, 0xd4, 0x83, 0x8e, 0x27, 0xeb, 0x25, 0xfd, 0xf7, 0x68, 0xe5, 0xff, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xea, 0x1b, 0xdc, 0xba, 0xf7, 0x0d, 0x00, 0x00, + // 1057 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0xdf, 0x6b, 0x1c, 0x55, + 0x14, 0xce, 0xdd, 0xb8, 0x9b, 0xf4, 0x04, 0x8a, 0x9e, 0xa4, 0xed, 0x76, 0x9a, 0x6c, 0xd6, 0x49, + 0x4d, 0xd2, 0x62, 0x66, 0x4c, 0x62, 0x62, 0x9b, 0xaa, 0xd5, 0x14, 0xb7, 0x06, 0xa4, 0xa6, 0x8b, + 0x20, 0xf8, 0xa0, 0xcc, 0xee, 0xce, 0x6e, 0x07, 0x92, 0xb9, 0xdb, 0xbd, 0xb3, 0xd1, 0x1a, 0x02, + 0x56, 0x0b, 0x22, 0x28, 0x08, 0xbe, 0x29, 0x3e, 0xf8, 0xee, 0x83, 0xcf, 0xfa, 0x0f, 0xf4, 0x49, + 0x0a, 0xbe, 0x08, 0x82, 0x48, 0x22, 0xf8, 0x6f, 0xc8, 0xde, 0x7b, 0x26, 0x3b, 0xb3, 0x99, 0x1f, + 0xbb, 0x31, 0xc4, 0xb7, 0x9d, 0x7b, 0xcf, 0x39, 0xdf, 0x77, 0xbe, 0x73, 0xef, 0x3d, 0x87, 0x85, + 0xe9, 0x2a, 0x6f, 0xd9, 0xed, 0x6d, 0xd3, 0x12, 0xc2, 0xf6, 0x4c, 0xb7, 0xee, 0x99, 0x3b, 0x8b, + 0xe6, 0xfd, 0xb6, 0xdd, 0x7a, 0x60, 0x34, 0x5b, 0xdc, 0xe3, 0x38, 0xae, 0x0c, 0x0c, 0x69, 0x60, + 0xb8, 0x75, 0xcf, 0xd8, 0x59, 0xd4, 0x26, 0x1a, 0xbc, 0xc1, 0xe5, 0xbe, 0xd9, 0xf9, 0xa5, 0x4c, + 0xb5, 0xc9, 0x06, 0xe7, 0x8d, 0x2d, 0xdb, 0xb4, 0x9a, 0x8e, 0x69, 0xb9, 0x2e, 0xf7, 0x2c, 0xcf, + 0xe1, 0xae, 0xa0, 0xdd, 0xa9, 0x28, 0xa4, 0x4e, 0x3c, 0xb5, 0x5d, 0x8c, 0xda, 0x6e, 0x5a, 0x2d, + 0x6b, 0xdb, 0x0f, 0x70, 0xb5, 0xca, 0xc5, 0x36, 0x17, 0x66, 0xc5, 0x12, 0xb6, 0xa2, 0x68, 0xee, + 0x2c, 0x56, 0x6c, 0xcf, 0xea, 0xd8, 0x35, 0x1c, 0x57, 0xa2, 0x29, 0x5b, 0x7d, 0x02, 0xf0, 0x6e, + 0xc7, 0x62, 0x53, 0x06, 0x28, 0xdb, 0xf7, 0xdb, 0xb6, 0xf0, 0xf4, 0x4d, 0x18, 0x0f, 0xad, 0x8a, + 0x26, 0x77, 0x85, 0x8d, 0xd7, 0x21, 0xa7, 0x80, 0xf2, 0xac, 0xc8, 0xe6, 0xc7, 0x96, 0x2e, 0x19, + 0x11, 0x39, 0x1b, 0xca, 0x69, 0xfd, 0xa9, 0xc7, 0x7f, 0x4e, 0x0f, 0x95, 0xc9, 0x41, 0x9f, 0x81, + 0x67, 0x64, 0xc4, 0x5b, 0x5b, 0x96, 0xf0, 0x61, 0xf0, 0x2c, 0x64, 0x9c, 0x9a, 0x8c, 0x75, 0xa6, + 0x9c, 0x71, 0x6a, 0xfa, 0x5b, 0x44, 0x86, 0x8c, 0x08, 0x75, 0x15, 0xb2, 0xd5, 0xce, 0x02, 0x81, + 0x6a, 0x91, 0xa0, 0xd2, 0x85, 0x30, 0x95, 0xb9, 0xde, 0xa6, 0x24, 0xe4, 0x96, 0x7d, 0x08, 0x5a, + 0x02, 0xe8, 0xaa, 0x40, 0x31, 0x67, 0x0d, 0x25, 0x99, 0xd1, 0x91, 0xcc, 0x50, 0x55, 0x25, 0xc9, + 0x8c, 0x4d, 0xab, 0x61, 0x93, 0x6f, 0x39, 0xe0, 0x89, 0xe7, 0x21, 0xe7, 0x08, 0xd1, 0xb6, 0x5b, + 0xf9, 0x8c, 0x4c, 0x80, 0xbe, 0xf4, 0xef, 0x18, 0x4c, 0x84, 0x71, 0x29, 0x8f, 0xdb, 0x11, 0xc0, + 0x73, 0xa9, 0xc0, 0xca, 0x39, 0x84, 0xbc, 0x06, 0x23, 0x55, 0x15, 0x3b, 0x9f, 0x29, 0x0e, 0xf7, + 0x25, 0x89, 0xef, 0xa0, 0xdf, 0x24, 0x89, 0x4b, 0x2d, 0xfe, 0xb1, 0xed, 0xc6, 0x14, 0x02, 0x2f, + 0xc2, 0xa8, 0x74, 0xf8, 0xc0, 0xa9, 0x51, 0x76, 0x2a, 0xc0, 0x46, 0x4d, 0x5f, 0x20, 0x55, 0xfd, + 0x00, 0x94, 0xdc, 0x79, 0xc8, 0xd5, 0xe5, 0x8a, 0x8c, 0x32, 0x5a, 0xa6, 0x2f, 0xfd, 0x0e, 0x5c, + 0xe8, 0x8a, 0x11, 0x06, 0x0d, 0x82, 0xb0, 0x10, 0x08, 0xe6, 0x61, 0xc4, 0xaa, 0x56, 0x79, 0xdb, + 0xf5, 0x7c, 0x78, 0xfa, 0xd4, 0x97, 0x20, 0x7f, 0x34, 0x5e, 0x0a, 0x87, 0xf7, 0x89, 0xc3, 0xbb, + 0xf7, 0x1c, 0xcf, 0xde, 0x72, 0x84, 0x67, 0xd7, 0x06, 0x4f, 0x3c, 0xc8, 0x69, 0x38, 0xcc, 0xe9, + 0x65, 0xe2, 0x14, 0x8a, 0x4f, 0x9c, 0x8a, 0x30, 0xf6, 0x61, 0x77, 0x99, 0x88, 0x05, 0x97, 0xf4, + 0x6f, 0x19, 0x3c, 0xd7, 0xeb, 0xfe, 0xba, 0x8a, 0x2c, 0x4a, 0xbc, 0x75, 0xa7, 0xf4, 0xce, 0x49, + 0x9f, 0x5c, 0x95, 0x74, 0x26, 0x32, 0xe9, 0xe1, 0x70, 0xb5, 0xbf, 0x62, 0x30, 0x9b, 0x46, 0xee, + 0xa4, 0x8f, 0xb7, 0x06, 0xa3, 0xa4, 0xac, 0x3a, 0xdf, 0x67, 0xca, 0x87, 0xdf, 0xfa, 0x17, 0x0c, + 0x2e, 0x77, 0xeb, 0x1f, 0x41, 0xea, 0xa4, 0xb5, 0x4a, 0xb8, 0x09, 0x5f, 0xfa, 0x85, 0x8b, 0xe7, + 0x72, 0x9a, 0xd2, 0x3c, 0x62, 0x30, 0xdd, 0x7b, 0x35, 0xfe, 0x07, 0x55, 0x3e, 0x67, 0x50, 0x8c, + 0xa7, 0x71, 0x9a, 0x82, 0xbc, 0x49, 0xef, 0xf0, 0x7a, 0xbb, 0xe5, 0x7a, 0x81, 0x6b, 0x94, 0xf0, + 0xee, 0x9c, 0x83, 0x9c, 0x5b, 0xf7, 0xba, 0x59, 0x65, 0xdd, 0xba, 0x27, 0xdf, 0xbc, 0x73, 0x3d, + 0x91, 0x28, 0x8f, 0x09, 0xc8, 0x56, 0x3a, 0x6b, 0x74, 0xaf, 0xd5, 0x87, 0xfe, 0x90, 0xc1, 0x64, + 0xc8, 0x5e, 0x6c, 0xb8, 0xa1, 0xbe, 0x77, 0x0a, 0x65, 0x78, 0xc8, 0x60, 0x2a, 0x86, 0xc3, 0x49, + 0xd7, 0xe0, 0x02, 0x8c, 0x28, 0xd1, 0xfc, 0x12, 0xe4, 0xa4, 0x6a, 0x62, 0xe9, 0x9f, 0xb3, 0x90, + 0x95, 0x1c, 0xf0, 0x13, 0x06, 0x39, 0x35, 0x16, 0xe0, 0x5c, 0x64, 0xaf, 0x3a, 0x3a, 0x83, 0x68, + 0xf3, 0xe9, 0x86, 0x8a, 0x8c, 0x3e, 0xf3, 0xe9, 0x6f, 0x7f, 0x7f, 0x93, 0x99, 0xc2, 0x4b, 0x66, + 0xfc, 0x68, 0x84, 0x9f, 0x31, 0xc8, 0x4a, 0x01, 0x70, 0x36, 0x3e, 0x70, 0xb0, 0x4a, 0xda, 0x5c, + 0xaa, 0x1d, 0xe1, 0x5f, 0x91, 0xf8, 0x33, 0xf8, 0x6c, 0x24, 0x3e, 0x75, 0x5e, 0x73, 0xd7, 0xa9, + 0xed, 0xe1, 0x23, 0x06, 0x23, 0x34, 0x17, 0xe0, 0x7c, 0x4a, 0xfc, 0xc3, 0x91, 0x45, 0xbb, 0xd2, + 0x87, 0x25, 0x71, 0xb9, 0x2c, 0xb9, 0x14, 0x70, 0x32, 0x89, 0x0b, 0x7e, 0xcf, 0x20, 0xa7, 0xae, + 0x66, 0x52, 0x3d, 0x42, 0xed, 0x3a, 0xa9, 0x1e, 0xe1, 0x3e, 0xac, 0xbf, 0x26, 0x39, 0xac, 0xe1, + 0xb5, 0x64, 0x3d, 0xfc, 0xa3, 0xbb, 0xd7, 0xd9, 0x51, 0xfa, 0x98, 0xaa, 0x63, 0xe3, 0x8f, 0x0c, + 0xc6, 0x02, 0xef, 0x07, 0x3e, 0x9f, 0x22, 0x40, 0x98, 0xe9, 0x42, 0x9f, 0xd6, 0xc7, 0xa5, 0xab, + 0x48, 0x9a, 0xbb, 0xf4, 0xd2, 0xec, 0xe1, 0xcf, 0x0c, 0xc6, 0x23, 0x9e, 0x3b, 0x7c, 0xb1, 0x2f, + 0x22, 0x3d, 0x8f, 0xb4, 0xb6, 0x32, 0xa0, 0x17, 0xa5, 0xb1, 0x2a, 0xd3, 0x78, 0x01, 0x8d, 0xc1, + 0xd2, 0xc0, 0x5f, 0x18, 0x8c, 0x05, 0x9a, 0x57, 0x92, 0xd6, 0x47, 0x07, 0xa8, 0x24, 0xad, 0x23, + 0xc6, 0x21, 0xfd, 0x6d, 0x49, 0x72, 0x03, 0x6f, 0x0f, 0x7e, 0x34, 0x02, 0x33, 0x53, 0x40, 0xfa, + 0x3f, 0x18, 0x5c, 0x8c, 0x9d, 0x4d, 0x70, 0xad, 0x2f, 0x76, 0x91, 0xd3, 0x96, 0x76, 0xe3, 0x58, + 0xbe, 0x94, 0xe7, 0x1b, 0x32, 0xcf, 0x9b, 0xf8, 0xca, 0x7f, 0xca, 0x13, 0x7f, 0x65, 0x90, 0x8f, + 0x9b, 0x2e, 0xf0, 0x7a, 0xca, 0x39, 0x89, 0x9f, 0x8e, 0xb4, 0xb5, 0xe3, 0xb8, 0x52, 0x6a, 0x37, + 0x64, 0x6a, 0x2b, 0xb8, 0xdc, 0x6f, 0x6a, 0xc1, 0x84, 0x7e, 0x60, 0x30, 0xea, 0x77, 0x24, 0x4c, + 0x78, 0xd6, 0x7a, 0x7a, 0xb6, 0x76, 0xb5, 0x1f, 0x53, 0x22, 0xf8, 0xaa, 0x24, 0x78, 0x0d, 0x57, + 0xfb, 0x25, 0x28, 0xbb, 0xb6, 0xb9, 0xab, 0x9a, 0xd8, 0x1e, 0xfe, 0xc4, 0xe0, 0xe9, 0xde, 0xae, + 0x89, 0x8b, 0xe9, 0x04, 0x7a, 0xba, 0xbc, 0xb6, 0x34, 0x88, 0x0b, 0x71, 0x5f, 0x91, 0xdc, 0x4d, + 0x5c, 0x18, 0x88, 0xfb, 0xfa, 0xdd, 0xc7, 0xfb, 0x05, 0xf6, 0x64, 0xbf, 0xc0, 0xfe, 0xda, 0x2f, + 0xb0, 0xaf, 0x0f, 0x0a, 0x43, 0x4f, 0x0e, 0x0a, 0x43, 0xbf, 0x1f, 0x14, 0x86, 0xde, 0x7b, 0xa9, + 0xe1, 0x78, 0xf7, 0xda, 0x15, 0xa3, 0xca, 0xb7, 0xcd, 0x5b, 0x32, 0x64, 0x89, 0xb7, 0xdd, 0x9a, + 0xec, 0xdc, 0x3e, 0xc6, 0xce, 0xb2, 0xf9, 0x51, 0x00, 0xc8, 0x7b, 0xd0, 0xb4, 0x45, 0x25, 0x27, + 0xff, 0x1f, 0x58, 0xfe, 0x37, 0x00, 0x00, 0xff, 0xff, 0xa5, 0x31, 0xb2, 0x2c, 0xf8, 0x10, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1040,6 +1252,10 @@ type QueryClient interface { Classes(ctx context.Context, in *QueryClassesRequest, opts ...grpc.CallOption) (*QueryClassesResponse, error) // Frozen queries to check if an NFT is frozen or not. Frozen(ctx context.Context, in *QueryFrozenRequest, opts ...grpc.CallOption) (*QueryFrozenResponse, error) + // ClassFrozen queries to check if an account if frozen for an NFT class. + ClassFrozen(ctx context.Context, in *QueryClassFrozenRequest, opts ...grpc.CallOption) (*QueryClassFrozenResponse, error) + // QueryClassFrozenAccountsRequest returns the list of accounts which are frozen to hold NFTs in this class. + ClassFrozenAccounts(ctx context.Context, in *QueryClassFrozenAccountsRequest, opts ...grpc.CallOption) (*QueryClassFrozenAccountsResponse, error) // Whitelisted queries to check if an account is whitelited to hold an NFT or not. Whitelisted(ctx context.Context, in *QueryWhitelistedRequest, opts ...grpc.CallOption) (*QueryWhitelistedResponse, error) // WhitelistedAccountsForNFT returns the list of accounts which are whitelisted to hold this NFT. @@ -1096,6 +1312,24 @@ func (c *queryClient) Frozen(ctx context.Context, in *QueryFrozenRequest, opts . return out, nil } +func (c *queryClient) ClassFrozen(ctx context.Context, in *QueryClassFrozenRequest, opts ...grpc.CallOption) (*QueryClassFrozenResponse, error) { + out := new(QueryClassFrozenResponse) + err := c.cc.Invoke(ctx, "/coreum.asset.nft.v1.Query/ClassFrozen", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) ClassFrozenAccounts(ctx context.Context, in *QueryClassFrozenAccountsRequest, opts ...grpc.CallOption) (*QueryClassFrozenAccountsResponse, error) { + out := new(QueryClassFrozenAccountsResponse) + err := c.cc.Invoke(ctx, "/coreum.asset.nft.v1.Query/ClassFrozenAccounts", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) Whitelisted(ctx context.Context, in *QueryWhitelistedRequest, opts ...grpc.CallOption) (*QueryWhitelistedResponse, error) { out := new(QueryWhitelistedResponse) err := c.cc.Invoke(ctx, "/coreum.asset.nft.v1.Query/Whitelisted", in, out, opts...) @@ -1151,6 +1385,10 @@ type QueryServer interface { Classes(context.Context, *QueryClassesRequest) (*QueryClassesResponse, error) // Frozen queries to check if an NFT is frozen or not. Frozen(context.Context, *QueryFrozenRequest) (*QueryFrozenResponse, error) + // ClassFrozen queries to check if an account if frozen for an NFT class. + ClassFrozen(context.Context, *QueryClassFrozenRequest) (*QueryClassFrozenResponse, error) + // QueryClassFrozenAccountsRequest returns the list of accounts which are frozen to hold NFTs in this class. + ClassFrozenAccounts(context.Context, *QueryClassFrozenAccountsRequest) (*QueryClassFrozenAccountsResponse, error) // Whitelisted queries to check if an account is whitelited to hold an NFT or not. Whitelisted(context.Context, *QueryWhitelistedRequest) (*QueryWhitelistedResponse, error) // WhitelistedAccountsForNFT returns the list of accounts which are whitelisted to hold this NFT. @@ -1179,6 +1417,12 @@ func (*UnimplementedQueryServer) Classes(ctx context.Context, req *QueryClassesR func (*UnimplementedQueryServer) Frozen(ctx context.Context, req *QueryFrozenRequest) (*QueryFrozenResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Frozen not implemented") } +func (*UnimplementedQueryServer) ClassFrozen(ctx context.Context, req *QueryClassFrozenRequest) (*QueryClassFrozenResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClassFrozen not implemented") +} +func (*UnimplementedQueryServer) ClassFrozenAccounts(ctx context.Context, req *QueryClassFrozenAccountsRequest) (*QueryClassFrozenAccountsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClassFrozenAccounts not implemented") +} func (*UnimplementedQueryServer) Whitelisted(ctx context.Context, req *QueryWhitelistedRequest) (*QueryWhitelistedResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Whitelisted not implemented") } @@ -1271,6 +1515,42 @@ func _Query_Frozen_Handler(srv interface{}, ctx context.Context, dec func(interf return interceptor(ctx, in, info, handler) } +func _Query_ClassFrozen_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryClassFrozenRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ClassFrozen(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/coreum.asset.nft.v1.Query/ClassFrozen", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ClassFrozen(ctx, req.(*QueryClassFrozenRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_ClassFrozenAccounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryClassFrozenAccountsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ClassFrozenAccounts(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/coreum.asset.nft.v1.Query/ClassFrozenAccounts", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ClassFrozenAccounts(ctx, req.(*QueryClassFrozenAccountsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_Whitelisted_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryWhitelistedRequest) if err := dec(in); err != nil { @@ -1381,6 +1661,14 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "Frozen", Handler: _Query_Frozen_Handler, }, + { + MethodName: "ClassFrozen", + Handler: _Query_ClassFrozen_Handler, + }, + { + MethodName: "ClassFrozenAccounts", + Handler: _Query_ClassFrozenAccounts_Handler, + }, { MethodName: "Whitelisted", Handler: _Query_Whitelisted_Handler, @@ -1686,7 +1974,7 @@ func (m *QueryFrozenResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *QueryWhitelistedRequest) Marshal() (dAtA []byte, err error) { +func (m *QueryClassFrozenRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1696,12 +1984,12 @@ func (m *QueryWhitelistedRequest) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryWhitelistedRequest) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryClassFrozenRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryWhitelistedRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryClassFrozenRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -1711,26 +1999,19 @@ func (m *QueryWhitelistedRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) copy(dAtA[i:], m.Account) i = encodeVarintQuery(dAtA, i, uint64(len(m.Account))) i-- - dAtA[i] = 0x1a + dAtA[i] = 0x12 } if len(m.ClassId) > 0 { i -= len(m.ClassId) copy(dAtA[i:], m.ClassId) i = encodeVarintQuery(dAtA, i, uint64(len(m.ClassId))) i-- - dAtA[i] = 0x12 - } - if len(m.Id) > 0 { - i -= len(m.Id) - copy(dAtA[i:], m.Id) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Id))) - i-- dAtA[i] = 0xa } return len(dAtA) - i, nil } -func (m *QueryWhitelistedResponse) Marshal() (dAtA []byte, err error) { +func (m *QueryClassFrozenResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1740,19 +2021,19 @@ func (m *QueryWhitelistedResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryWhitelistedResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryClassFrozenResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryWhitelistedResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryClassFrozenResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if m.Whitelisted { + if m.Frozen { i-- - if m.Whitelisted { + if m.Frozen { dAtA[i] = 1 } else { dAtA[i] = 0 @@ -1763,7 +2044,7 @@ func (m *QueryWhitelistedResponse) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } -func (m *QueryWhitelistedAccountsForNFTRequest) Marshal() (dAtA []byte, err error) { +func (m *QueryWhitelistedRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1773,46 +2054,41 @@ func (m *QueryWhitelistedAccountsForNFTRequest) Marshal() (dAtA []byte, err erro return dAtA[:n], nil } -func (m *QueryWhitelistedAccountsForNFTRequest) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryWhitelistedRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryWhitelistedAccountsForNFTRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryWhitelistedRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l + if len(m.Account) > 0 { + i -= len(m.Account) + copy(dAtA[i:], m.Account) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Account))) + i-- + dAtA[i] = 0x1a + } if len(m.ClassId) > 0 { i -= len(m.ClassId) copy(dAtA[i:], m.ClassId) i = encodeVarintQuery(dAtA, i, uint64(len(m.ClassId))) i-- - dAtA[i] = 0x1a + dAtA[i] = 0x12 } if len(m.Id) > 0 { i -= len(m.Id) copy(dAtA[i:], m.Id) i = encodeVarintQuery(dAtA, i, uint64(len(m.Id))) i-- - dAtA[i] = 0x12 - } - if m.Pagination != nil { - { - size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- dAtA[i] = 0xa } return len(dAtA) - i, nil } -func (m *QueryWhitelistedAccountsForNFTResponse) Marshal() (dAtA []byte, err error) { +func (m *QueryWhitelistedResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -1822,22 +2098,104 @@ func (m *QueryWhitelistedAccountsForNFTResponse) Marshal() (dAtA []byte, err err return dAtA[:n], nil } -func (m *QueryWhitelistedAccountsForNFTResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryWhitelistedResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryWhitelistedAccountsForNFTResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryWhitelistedResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if len(m.Accounts) > 0 { - for iNdEx := len(m.Accounts) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.Accounts[iNdEx]) - copy(dAtA[i:], m.Accounts[iNdEx]) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Accounts[iNdEx]))) - i-- + if m.Whitelisted { + i-- + if m.Whitelisted { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryWhitelistedAccountsForNFTRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryWhitelistedAccountsForNFTRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryWhitelistedAccountsForNFTRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ClassId) > 0 { + i -= len(m.ClassId) + copy(dAtA[i:], m.ClassId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ClassId))) + i-- + dAtA[i] = 0x1a + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0x12 + } + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryWhitelistedAccountsForNFTResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryWhitelistedAccountsForNFTResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryWhitelistedAccountsForNFTResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Accounts) > 0 { + for iNdEx := len(m.Accounts) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Accounts[iNdEx]) + copy(dAtA[i:], m.Accounts[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Accounts[iNdEx]))) + i-- dAtA[i] = 0x12 } } @@ -1942,6 +2300,92 @@ func (m *QueryClassWhitelistedAccountsResponse) MarshalToSizedBuffer(dAtA []byte return len(dAtA) - i, nil } +func (m *QueryClassFrozenAccountsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClassFrozenAccountsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClassFrozenAccountsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ClassId) > 0 { + i -= len(m.ClassId) + copy(dAtA[i:], m.ClassId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ClassId))) + i-- + dAtA[i] = 0x12 + } + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryClassFrozenAccountsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClassFrozenAccountsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClassFrozenAccountsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Accounts) > 0 { + for iNdEx := len(m.Accounts) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Accounts[iNdEx]) + copy(dAtA[i:], m.Accounts[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Accounts[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *QueryBurntNFTRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -2218,6 +2662,35 @@ func (m *QueryFrozenResponse) Size() (n int) { return n } +func (m *QueryClassFrozenRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClassId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Account) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryClassFrozenResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Frozen { + n += 2 + } + return n +} + func (m *QueryWhitelistedRequest) Size() (n int) { if m == nil { return 0 @@ -2327,6 +2800,42 @@ func (m *QueryClassWhitelistedAccountsResponse) Size() (n int) { return n } +func (m *QueryClassFrozenAccountsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.ClassId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryClassFrozenAccountsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + if len(m.Accounts) > 0 { + for _, s := range m.Accounts { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + func (m *QueryBurntNFTRequest) Size() (n int) { if m == nil { return 0 @@ -3118,7 +3627,7 @@ func (m *QueryFrozenResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryWhitelistedRequest) Unmarshal(dAtA []byte) error { +func (m *QueryClassFrozenRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3141,15 +3650,15 @@ func (m *QueryWhitelistedRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryWhitelistedRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryClassFrozenRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryWhitelistedRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryClassFrozenRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ClassId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -3177,11 +3686,11 @@ func (m *QueryWhitelistedRequest) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Id = string(dAtA[iNdEx:postIndex]) + m.ClassId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClassId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Account", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -3209,20 +3718,204 @@ func (m *QueryWhitelistedRequest) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ClassId = string(dAtA[iNdEx:postIndex]) + m.Account = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Account", wireType) + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryClassFrozenResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassFrozenResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassFrozenResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Frozen", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Frozen = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryWhitelistedRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryWhitelistedRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryWhitelistedRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Account", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } b := dAtA[iNdEx] iNdEx++ stringLen |= uint64(b&0x7F) << shift @@ -3838,6 +4531,242 @@ func (m *QueryClassWhitelistedAccountsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryClassFrozenAccountsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassFrozenAccountsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassFrozenAccountsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryClassFrozenAccountsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassFrozenAccountsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassFrozenAccountsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Accounts", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Accounts = append(m.Accounts, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *QueryBurntNFTRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/asset/nft/types/query.pb.gw.go b/x/asset/nft/types/query.pb.gw.go index b8afe2408..dee585388 100644 --- a/x/asset/nft/types/query.pb.gw.go +++ b/x/asset/nft/types/query.pb.gw.go @@ -217,6 +217,154 @@ func local_request_Query_Frozen_0(ctx context.Context, marshaler runtime.Marshal } +func request_Query_ClassFrozen_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassFrozenRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["class_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "class_id") + } + + protoReq.ClassId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "class_id", err) + } + + val, ok = pathParams["account"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "account") + } + + protoReq.Account, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "account", err) + } + + msg, err := client.ClassFrozen(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ClassFrozen_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassFrozenRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["class_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "class_id") + } + + protoReq.ClassId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "class_id", err) + } + + val, ok = pathParams["account"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "account") + } + + protoReq.Account, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "account", err) + } + + msg, err := server.ClassFrozen(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_ClassFrozenAccounts_0 = &utilities.DoubleArray{Encoding: map[string]int{"class_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_ClassFrozenAccounts_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassFrozenAccountsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["class_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "class_id") + } + + protoReq.ClassId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "class_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ClassFrozenAccounts_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ClassFrozenAccounts(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ClassFrozenAccounts_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassFrozenAccountsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["class_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "class_id") + } + + protoReq.ClassId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "class_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ClassFrozenAccounts_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ClassFrozenAccounts(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Whitelisted_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryWhitelistedRequest var metadata runtime.ServerMetadata @@ -727,6 +875,52 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_ClassFrozen_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClassFrozen_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassFrozen_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ClassFrozenAccounts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClassFrozenAccounts_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassFrozenAccounts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_Whitelisted_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -963,6 +1157,46 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_ClassFrozen_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ClassFrozen_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassFrozen_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ClassFrozenAccounts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ClassFrozenAccounts_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassFrozenAccounts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_Whitelisted_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1075,6 +1309,10 @@ var ( pattern_Query_Frozen_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"coreum", "asset", "nft", "v1", "classes", "class_id", "nfts", "id", "frozen"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ClassFrozen_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7}, []string{"coreum", "asset", "nft", "v1", "classes", "class_id", "frozen", "account"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_ClassFrozenAccounts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"coreum", "asset", "nft", "v1", "classes", "class_id", "frozen"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Whitelisted_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"coreum", "asset", "nft", "v1", "classes", "class_id", "nfts", "id", "whitelisted", "account"}, "", runtime.AssumeColonVerbOpt(true))) pattern_Query_WhitelistedAccountsForNFT_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"coreum", "asset", "nft", "v1", "classes", "class_id", "nfts", "id", "whitelisted"}, "", runtime.AssumeColonVerbOpt(true))) @@ -1095,6 +1333,10 @@ var ( forward_Query_Frozen_0 = runtime.ForwardResponseMessage + forward_Query_ClassFrozen_0 = runtime.ForwardResponseMessage + + forward_Query_ClassFrozenAccounts_0 = runtime.ForwardResponseMessage + forward_Query_Whitelisted_0 = runtime.ForwardResponseMessage forward_Query_WhitelistedAccountsForNFT_0 = runtime.ForwardResponseMessage diff --git a/x/asset/nft/types/tx.pb.go b/x/asset/nft/types/tx.pb.go index ce0e79e63..5bdf3bc57 100644 --- a/x/asset/nft/types/tx.pb.go +++ b/x/asset/nft/types/tx.pb.go @@ -241,6 +241,84 @@ func (m *MsgUnfreeze) XXX_DiscardUnknown() { var xxx_messageInfo_MsgUnfreeze proto.InternalMessageInfo +type MsgClassFreeze struct { + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` + ClassID string `protobuf:"bytes,2,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` + Account string `protobuf:"bytes,3,opt,name=account,proto3" json:"account,omitempty"` +} + +func (m *MsgClassFreeze) Reset() { *m = MsgClassFreeze{} } +func (m *MsgClassFreeze) String() string { return proto.CompactTextString(m) } +func (*MsgClassFreeze) ProtoMessage() {} +func (*MsgClassFreeze) Descriptor() ([]byte, []int) { + return fileDescriptor_e850acc149a7cfa7, []int{5} +} +func (m *MsgClassFreeze) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgClassFreeze) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgClassFreeze.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgClassFreeze) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgClassFreeze.Merge(m, src) +} +func (m *MsgClassFreeze) XXX_Size() int { + return m.Size() +} +func (m *MsgClassFreeze) XXX_DiscardUnknown() { + xxx_messageInfo_MsgClassFreeze.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgClassFreeze proto.InternalMessageInfo + +type MsgClassUnfreeze struct { + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` + ClassID string `protobuf:"bytes,2,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` + Account string `protobuf:"bytes,3,opt,name=account,proto3" json:"account,omitempty"` +} + +func (m *MsgClassUnfreeze) Reset() { *m = MsgClassUnfreeze{} } +func (m *MsgClassUnfreeze) String() string { return proto.CompactTextString(m) } +func (*MsgClassUnfreeze) ProtoMessage() {} +func (*MsgClassUnfreeze) Descriptor() ([]byte, []int) { + return fileDescriptor_e850acc149a7cfa7, []int{6} +} +func (m *MsgClassUnfreeze) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgClassUnfreeze) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgClassUnfreeze.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgClassUnfreeze) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgClassUnfreeze.Merge(m, src) +} +func (m *MsgClassUnfreeze) XXX_Size() int { + return m.Size() +} +func (m *MsgClassUnfreeze) XXX_DiscardUnknown() { + xxx_messageInfo_MsgClassUnfreeze.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgClassUnfreeze proto.InternalMessageInfo + type MsgAddToWhitelist struct { Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` ClassID string `protobuf:"bytes,2,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` @@ -252,7 +330,7 @@ func (m *MsgAddToWhitelist) Reset() { *m = MsgAddToWhitelist{} } func (m *MsgAddToWhitelist) String() string { return proto.CompactTextString(m) } func (*MsgAddToWhitelist) ProtoMessage() {} func (*MsgAddToWhitelist) Descriptor() ([]byte, []int) { - return fileDescriptor_e850acc149a7cfa7, []int{5} + return fileDescriptor_e850acc149a7cfa7, []int{7} } func (m *MsgAddToWhitelist) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -292,7 +370,7 @@ func (m *MsgRemoveFromWhitelist) Reset() { *m = MsgRemoveFromWhitelist{} func (m *MsgRemoveFromWhitelist) String() string { return proto.CompactTextString(m) } func (*MsgRemoveFromWhitelist) ProtoMessage() {} func (*MsgRemoveFromWhitelist) Descriptor() ([]byte, []int) { - return fileDescriptor_e850acc149a7cfa7, []int{6} + return fileDescriptor_e850acc149a7cfa7, []int{8} } func (m *MsgRemoveFromWhitelist) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -331,7 +409,7 @@ func (m *MsgAddToClassWhitelist) Reset() { *m = MsgAddToClassWhitelist{} func (m *MsgAddToClassWhitelist) String() string { return proto.CompactTextString(m) } func (*MsgAddToClassWhitelist) ProtoMessage() {} func (*MsgAddToClassWhitelist) Descriptor() ([]byte, []int) { - return fileDescriptor_e850acc149a7cfa7, []int{7} + return fileDescriptor_e850acc149a7cfa7, []int{9} } func (m *MsgAddToClassWhitelist) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -370,7 +448,7 @@ func (m *MsgRemoveFromClassWhitelist) Reset() { *m = MsgRemoveFromClassW func (m *MsgRemoveFromClassWhitelist) String() string { return proto.CompactTextString(m) } func (*MsgRemoveFromClassWhitelist) ProtoMessage() {} func (*MsgRemoveFromClassWhitelist) Descriptor() ([]byte, []int) { - return fileDescriptor_e850acc149a7cfa7, []int{8} + return fileDescriptor_e850acc149a7cfa7, []int{10} } func (m *MsgRemoveFromClassWhitelist) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -408,7 +486,7 @@ func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } func (*MsgUpdateParams) ProtoMessage() {} func (*MsgUpdateParams) Descriptor() ([]byte, []int) { - return fileDescriptor_e850acc149a7cfa7, []int{9} + return fileDescriptor_e850acc149a7cfa7, []int{11} } func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -444,7 +522,7 @@ func (m *EmptyResponse) Reset() { *m = EmptyResponse{} } func (m *EmptyResponse) String() string { return proto.CompactTextString(m) } func (*EmptyResponse) ProtoMessage() {} func (*EmptyResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_e850acc149a7cfa7, []int{10} + return fileDescriptor_e850acc149a7cfa7, []int{12} } func (m *EmptyResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -479,6 +557,8 @@ func init() { proto.RegisterType((*MsgBurn)(nil), "coreum.asset.nft.v1.MsgBurn") proto.RegisterType((*MsgFreeze)(nil), "coreum.asset.nft.v1.MsgFreeze") proto.RegisterType((*MsgUnfreeze)(nil), "coreum.asset.nft.v1.MsgUnfreeze") + proto.RegisterType((*MsgClassFreeze)(nil), "coreum.asset.nft.v1.MsgClassFreeze") + proto.RegisterType((*MsgClassUnfreeze)(nil), "coreum.asset.nft.v1.MsgClassUnfreeze") proto.RegisterType((*MsgAddToWhitelist)(nil), "coreum.asset.nft.v1.MsgAddToWhitelist") proto.RegisterType((*MsgRemoveFromWhitelist)(nil), "coreum.asset.nft.v1.MsgRemoveFromWhitelist") proto.RegisterType((*MsgAddToClassWhitelist)(nil), "coreum.asset.nft.v1.MsgAddToClassWhitelist") @@ -490,64 +570,68 @@ func init() { func init() { proto.RegisterFile("coreum/asset/nft/v1/tx.proto", fileDescriptor_e850acc149a7cfa7) } var fileDescriptor_e850acc149a7cfa7 = []byte{ - // 906 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x56, 0x4f, 0x6f, 0x1b, 0x45, - 0x14, 0xf7, 0xda, 0xae, 0x1d, 0x3f, 0xf7, 0x8f, 0xba, 0x8d, 0xc2, 0x36, 0x0d, 0xb6, 0xb1, 0x50, - 0x14, 0xb5, 0xca, 0x2e, 0x4d, 0x25, 0x10, 0x48, 0x1c, 0xe2, 0x86, 0xa8, 0x96, 0xb0, 0x54, 0x96, - 0x46, 0x20, 0x84, 0x14, 0x4d, 0x76, 0xc7, 0xeb, 0x11, 0xde, 0x99, 0xd5, 0xcc, 0x6c, 0xa8, 0x39, - 0x22, 0x71, 0xa0, 0x27, 0x3e, 0x4a, 0x25, 0xf8, 0x10, 0x39, 0x56, 0x9c, 0x10, 0x07, 0x0b, 0x9c, - 0x43, 0x2f, 0x1c, 0xf9, 0x00, 0x68, 0x67, 0xd6, 0x8d, 0x5d, 0xed, 0x92, 0x15, 0xc2, 0x70, 0xb1, - 0xf7, 0xbd, 0xdf, 0x9b, 0xdf, 0x7b, 0xf3, 0x9b, 0xdd, 0x37, 0x0f, 0xb6, 0x3c, 0xc6, 0x71, 0x1c, - 0x3a, 0x48, 0x08, 0x2c, 0x1d, 0x3a, 0x94, 0xce, 0xe9, 0x7d, 0x47, 0x3e, 0xb5, 0x23, 0xce, 0x24, - 0x33, 0x6f, 0x69, 0xd4, 0x56, 0xa8, 0x4d, 0x87, 0xd2, 0x3e, 0xbd, 0xbf, 0x79, 0x13, 0x85, 0x84, - 0x32, 0x47, 0xfd, 0xea, 0xb8, 0xcd, 0x37, 0x3c, 0x26, 0x42, 0x26, 0x9c, 0x50, 0x04, 0xc9, 0xfa, - 0x50, 0x04, 0x29, 0x70, 0x5b, 0x03, 0xc7, 0xca, 0x72, 0xb4, 0x91, 0x42, 0xeb, 0x01, 0x0b, 0x98, - 0xf6, 0x27, 0x4f, 0xf3, 0x05, 0x01, 0x63, 0xc1, 0x18, 0x3b, 0xca, 0x3a, 0x89, 0x87, 0x0e, 0xa2, - 0x93, 0x14, 0x7a, 0x33, 0xab, 0xd4, 0xa4, 0x26, 0x0d, 0x77, 0xb2, 0xe0, 0x08, 0x71, 0x14, 0xa6, - 0x19, 0xbb, 0x7f, 0x96, 0xe1, 0xda, 0x40, 0x04, 0x7d, 0x21, 0x62, 0xfc, 0x70, 0x8c, 0x84, 0x30, - 0x37, 0xa0, 0x46, 0x12, 0x8b, 0x5b, 0x46, 0xc7, 0xd8, 0x69, 0xb8, 0xa9, 0x95, 0xf8, 0xc5, 0x24, - 0x3c, 0x61, 0x63, 0xab, 0xac, 0xfd, 0xda, 0x32, 0x4d, 0xa8, 0x52, 0x14, 0x62, 0xab, 0xa2, 0xbc, - 0xea, 0xd9, 0xec, 0x40, 0xd3, 0xc7, 0xc2, 0xe3, 0x24, 0x92, 0x84, 0x51, 0xab, 0xaa, 0xa0, 0x45, - 0x97, 0x79, 0x1b, 0x2a, 0x31, 0x27, 0xd6, 0x95, 0x04, 0xe9, 0xd5, 0x67, 0xd3, 0x76, 0xe5, 0xc8, - 0xed, 0xbb, 0x89, 0xcf, 0xdc, 0x86, 0xb5, 0x98, 0x93, 0xe3, 0x11, 0x12, 0x23, 0xab, 0xa6, 0xf0, - 0xe6, 0x6c, 0xda, 0xae, 0x1f, 0xb9, 0xfd, 0x47, 0x48, 0x8c, 0xdc, 0x7a, 0xcc, 0x49, 0xf2, 0x60, - 0xee, 0x40, 0xd5, 0x47, 0x12, 0x59, 0xf5, 0x8e, 0xb1, 0xd3, 0xdc, 0x5b, 0xb7, 0xb5, 0x4a, 0xf6, - 0x5c, 0x25, 0x7b, 0x9f, 0x4e, 0x5c, 0x15, 0x61, 0x7e, 0x08, 0x6b, 0x43, 0x8c, 0x64, 0xcc, 0xb1, - 0xb0, 0xd6, 0x3a, 0x95, 0x9d, 0xeb, 0x7b, 0x6f, 0xd9, 0x19, 0xa7, 0x68, 0x2b, 0x01, 0x0e, 0x75, - 0xa4, 0xfb, 0x6a, 0x89, 0xf9, 0x09, 0x5c, 0xe5, 0x6c, 0x82, 0xc6, 0x72, 0x72, 0xcc, 0x91, 0xc4, - 0x56, 0x43, 0x15, 0x65, 0x9f, 0x4d, 0xdb, 0xa5, 0x5f, 0xa7, 0xed, 0xed, 0x80, 0xc8, 0x51, 0x7c, - 0x62, 0x7b, 0x2c, 0x4c, 0x0f, 0x33, 0xfd, 0xdb, 0x15, 0xfe, 0x57, 0x8e, 0x9c, 0x44, 0x58, 0xd8, - 0x07, 0xd8, 0x73, 0x9b, 0x29, 0x87, 0x8b, 0x24, 0xee, 0xfe, 0x61, 0x40, 0x7d, 0x20, 0x82, 0x01, - 0xa1, 0x52, 0x09, 0x8b, 0xa9, 0x7f, 0x21, 0xb8, 0xb6, 0x12, 0x1d, 0xbc, 0xa4, 0xa0, 0x63, 0xe2, - 0x6b, 0xc9, 0xb5, 0x0e, 0xaa, 0xc8, 0xfe, 0x81, 0x5b, 0x57, 0x60, 0xdf, 0x37, 0x37, 0xa0, 0x4c, - 0x7c, 0x2d, 0x7f, 0xaf, 0x36, 0x9b, 0xb6, 0xcb, 0xfd, 0x03, 0xb7, 0x4c, 0xfc, 0xb9, 0xc4, 0xd5, - 0x4b, 0x24, 0xbe, 0x52, 0x40, 0xe2, 0xda, 0xa5, 0x12, 0x6f, 0x41, 0x83, 0x63, 0x8f, 0x44, 0x04, - 0x53, 0xa9, 0x4e, 0xa4, 0xe1, 0x5e, 0x38, 0xba, 0x48, 0xed, 0xb6, 0x17, 0x73, 0xba, 0xaa, 0xdd, - 0x76, 0x3d, 0x68, 0x0c, 0x44, 0x70, 0xc8, 0x31, 0xfe, 0x06, 0xaf, 0x2c, 0x09, 0x86, 0xe6, 0x40, - 0x04, 0x47, 0x74, 0xb8, 0xda, 0x34, 0xdf, 0x19, 0x70, 0x73, 0x20, 0x82, 0x7d, 0xdf, 0x7f, 0xc2, - 0x3e, 0x1b, 0x11, 0x89, 0xc7, 0x44, 0xac, 0xee, 0x3d, 0xb1, 0xa0, 0x8e, 0x3c, 0x8f, 0xc5, 0x54, - 0xa6, 0x1f, 0xea, 0xdc, 0xec, 0x3e, 0x33, 0x60, 0x63, 0x20, 0x02, 0x17, 0x87, 0xec, 0x14, 0x1f, - 0x72, 0x16, 0xfe, 0x9f, 0xc5, 0x70, 0x55, 0x8b, 0xd2, 0x44, 0xb1, 0xfd, 0x7b, 0xb5, 0x2c, 0xe4, - 0xac, 0x2c, 0xe7, 0xfc, 0x1a, 0xee, 0x2c, 0xed, 0xff, 0x3f, 0x4b, 0xfc, 0xa3, 0x01, 0x37, 0x92, - 0x37, 0x2d, 0xf2, 0x91, 0xc4, 0x8f, 0x55, 0xc3, 0x36, 0xdf, 0x85, 0x06, 0x8a, 0xe5, 0x88, 0x71, - 0x22, 0x27, 0x3a, 0x61, 0xcf, 0xfa, 0xf9, 0xa7, 0xdd, 0xf5, 0xf4, 0x06, 0xd9, 0xf7, 0x7d, 0x8e, - 0x85, 0xf8, 0x54, 0x72, 0x42, 0x03, 0xf7, 0x22, 0xd4, 0x7c, 0x1f, 0x6a, 0xba, 0xe5, 0xab, 0x5a, - 0x9a, 0x7b, 0x77, 0x32, 0x7b, 0x9f, 0x4e, 0xd2, 0xab, 0x26, 0x5d, 0xcd, 0x4d, 0x17, 0x7c, 0xb0, - 0xfb, 0xed, 0xcb, 0xe7, 0x77, 0x2f, 0xa8, 0x9e, 0xbd, 0x7c, 0x7e, 0x77, 0x73, 0xa1, 0xb9, 0xbd, - 0x56, 0x61, 0xf7, 0x06, 0x5c, 0xfb, 0x28, 0x8c, 0xe4, 0xc4, 0xc5, 0x22, 0x62, 0x54, 0xe0, 0xbd, - 0xef, 0xeb, 0x50, 0x19, 0x88, 0xc0, 0x7c, 0x02, 0xb0, 0x70, 0xc3, 0x74, 0x33, 0x0b, 0x58, 0xba, - 0x85, 0x36, 0xb3, 0x63, 0x96, 0xd8, 0xcd, 0x47, 0x50, 0x55, 0x0d, 0x74, 0x2b, 0x8f, 0x2f, 0x41, - 0x8b, 0x32, 0xa9, 0xe6, 0x94, 0xcb, 0x94, 0xa0, 0x85, 0x98, 0x3e, 0x86, 0x5a, 0xda, 0x83, 0x5a, - 0x79, 0x5c, 0x1a, 0x2f, 0xc4, 0xf6, 0x18, 0xd6, 0x5e, 0x35, 0x9b, 0x4e, 0x1e, 0xdf, 0x3c, 0xa2, - 0x10, 0xe3, 0x97, 0x70, 0xfd, 0xb5, 0xb6, 0xb2, 0x9d, 0xc7, 0xbb, 0x1c, 0x57, 0x88, 0x7d, 0x08, - 0xb7, 0xb2, 0x9a, 0xc5, 0xbd, 0xbc, 0x14, 0x19, 0xc1, 0x45, 0xf3, 0x64, 0x35, 0x82, 0x7b, 0x7f, - 0xbb, 0x95, 0xe5, 0xe0, 0x42, 0x79, 0x22, 0xb0, 0x72, 0x3f, 0xfe, 0x77, 0x2e, 0xdf, 0xd4, 0x3f, - 0xc8, 0xf8, 0x39, 0x5c, 0x5d, 0xfa, 0xe8, 0xdf, 0xce, 0x3d, 0xf5, 0x85, 0xa8, 0x22, 0xcc, 0xbd, - 0xa3, 0xb3, 0xdf, 0x5b, 0xa5, 0xb3, 0x59, 0xcb, 0x78, 0x31, 0x6b, 0x19, 0xbf, 0xcd, 0x5a, 0xc6, - 0x0f, 0xe7, 0xad, 0xd2, 0x8b, 0xf3, 0x56, 0xe9, 0x97, 0xf3, 0x56, 0xe9, 0x8b, 0xf7, 0x16, 0xa6, - 0x98, 0x87, 0x8a, 0xeb, 0x90, 0xc5, 0xd4, 0x47, 0xc9, 0xb0, 0xe6, 0xa4, 0x53, 0xe4, 0xe9, 0x03, - 0xe7, 0xe9, 0xc2, 0x28, 0xa9, 0x46, 0x9b, 0x93, 0x9a, 0x1a, 0x06, 0x1e, 0xfc, 0x15, 0x00, 0x00, - 0xff, 0xff, 0xc9, 0xb3, 0xdc, 0xf0, 0x35, 0x0b, 0x00, 0x00, + // 966 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0xcf, 0x6f, 0x1b, 0x45, + 0x14, 0xf6, 0xda, 0xae, 0x7f, 0x3c, 0x37, 0x29, 0xdd, 0x46, 0x61, 0x9b, 0x06, 0xdb, 0x18, 0x88, + 0xa2, 0x56, 0xd9, 0xa5, 0xae, 0x04, 0x02, 0x89, 0x43, 0xdc, 0x10, 0xd5, 0x12, 0x96, 0xca, 0xd2, + 0x00, 0xaa, 0x90, 0xa2, 0xc9, 0xee, 0x78, 0x3d, 0xc2, 0xbb, 0x63, 0xcd, 0xcc, 0x86, 0x9a, 0x23, + 0x02, 0x0e, 0x3d, 0xf1, 0xa7, 0x54, 0x82, 0x2b, 0xf7, 0x1c, 0x2b, 0x4e, 0x88, 0x83, 0x05, 0xce, + 0xa1, 0x17, 0x8e, 0xfc, 0x01, 0x68, 0x67, 0xd6, 0xb1, 0x1d, 0x79, 0x93, 0xa5, 0x4a, 0xe8, 0xc5, + 0xde, 0x79, 0xdf, 0x9b, 0xef, 0x7d, 0xf3, 0x66, 0xf6, 0xbd, 0x59, 0x58, 0x77, 0x28, 0xc3, 0xa1, + 0x6f, 0x21, 0xce, 0xb1, 0xb0, 0x82, 0xae, 0xb0, 0x0e, 0xef, 0x5a, 0xe2, 0x89, 0x39, 0x60, 0x54, + 0x50, 0xfd, 0x86, 0x42, 0x4d, 0x89, 0x9a, 0x41, 0x57, 0x98, 0x87, 0x77, 0xd7, 0xae, 0x23, 0x9f, + 0x04, 0xd4, 0x92, 0xbf, 0xca, 0x6f, 0xed, 0x75, 0x87, 0x72, 0x9f, 0x72, 0xcb, 0xe7, 0x5e, 0x34, + 0xdf, 0xe7, 0x5e, 0x0c, 0xdc, 0x54, 0xc0, 0xbe, 0x1c, 0x59, 0x6a, 0x10, 0x43, 0x2b, 0x1e, 0xf5, + 0xa8, 0xb2, 0x47, 0x4f, 0x93, 0x09, 0x1e, 0xa5, 0x5e, 0x1f, 0x5b, 0x72, 0x74, 0x10, 0x76, 0x2d, + 0x14, 0x0c, 0x63, 0xe8, 0x8d, 0x45, 0x52, 0x23, 0x4d, 0x0a, 0xae, 0x2f, 0x82, 0x07, 0x88, 0x21, + 0x3f, 0x8e, 0xd8, 0xf8, 0x27, 0x0b, 0x4b, 0x1d, 0xee, 0xb5, 0x39, 0x0f, 0xf1, 0xfd, 0x3e, 0xe2, + 0x5c, 0x5f, 0x85, 0x02, 0x89, 0x46, 0xcc, 0xd0, 0xea, 0xda, 0x66, 0xd9, 0x8e, 0x47, 0x91, 0x9d, + 0x0f, 0xfd, 0x03, 0xda, 0x37, 0xb2, 0xca, 0xae, 0x46, 0xba, 0x0e, 0xf9, 0x00, 0xf9, 0xd8, 0xc8, + 0x49, 0xab, 0x7c, 0xd6, 0xeb, 0x50, 0x71, 0x31, 0x77, 0x18, 0x19, 0x08, 0x42, 0x03, 0x23, 0x2f, + 0xa1, 0x59, 0x93, 0x7e, 0x13, 0x72, 0x21, 0x23, 0xc6, 0x95, 0x08, 0x69, 0x15, 0xc7, 0xa3, 0x5a, + 0x6e, 0xcf, 0x6e, 0xdb, 0x91, 0x4d, 0xdf, 0x80, 0x52, 0xc8, 0xc8, 0x7e, 0x0f, 0xf1, 0x9e, 0x51, + 0x90, 0x78, 0x65, 0x3c, 0xaa, 0x15, 0xf7, 0xec, 0xf6, 0x03, 0xc4, 0x7b, 0x76, 0x31, 0x64, 0x24, + 0x7a, 0xd0, 0x37, 0x21, 0xef, 0x22, 0x81, 0x8c, 0x62, 0x5d, 0xdb, 0xac, 0x34, 0x57, 0x4c, 0x95, + 0x25, 0x73, 0x92, 0x25, 0x73, 0x3b, 0x18, 0xda, 0xd2, 0x43, 0xff, 0x08, 0x4a, 0x5d, 0x8c, 0x44, + 0xc8, 0x30, 0x37, 0x4a, 0xf5, 0xdc, 0xe6, 0x72, 0xf3, 0x4d, 0x73, 0xc1, 0x2e, 0x9a, 0x32, 0x01, + 0xbb, 0xca, 0xd3, 0x3e, 0x99, 0xa2, 0x7f, 0x0a, 0x57, 0x19, 0x1d, 0xa2, 0xbe, 0x18, 0xee, 0x33, + 0x24, 0xb0, 0x51, 0x96, 0xa2, 0xcc, 0xa3, 0x51, 0x2d, 0xf3, 0xc7, 0xa8, 0xb6, 0xe1, 0x11, 0xd1, + 0x0b, 0x0f, 0x4c, 0x87, 0xfa, 0xf1, 0x66, 0xc6, 0x7f, 0x5b, 0xdc, 0xfd, 0xda, 0x12, 0xc3, 0x01, + 0xe6, 0xe6, 0x0e, 0x76, 0xec, 0x4a, 0xcc, 0x61, 0x23, 0x81, 0x1b, 0x7f, 0x6b, 0x50, 0xec, 0x70, + 0xaf, 0x43, 0x02, 0x21, 0x13, 0x8b, 0x03, 0x77, 0x9a, 0x70, 0x35, 0x8a, 0xf2, 0xe0, 0x44, 0x82, + 0xf6, 0x89, 0xab, 0x52, 0xae, 0xf2, 0x20, 0x45, 0xb6, 0x77, 0xec, 0xa2, 0x04, 0xdb, 0xae, 0xbe, + 0x0a, 0x59, 0xe2, 0xaa, 0xf4, 0xb7, 0x0a, 0xe3, 0x51, 0x2d, 0xdb, 0xde, 0xb1, 0xb3, 0xc4, 0x9d, + 0xa4, 0x38, 0x7f, 0x4e, 0x8a, 0xaf, 0xa4, 0x48, 0x71, 0xe1, 0xdc, 0x14, 0xaf, 0x43, 0x99, 0x61, + 0x87, 0x0c, 0x08, 0x0e, 0x84, 0xdc, 0x91, 0xb2, 0x3d, 0x35, 0x34, 0x90, 0x5c, 0x6d, 0x2b, 0x64, + 0xc1, 0x65, 0xad, 0xb6, 0xe1, 0x40, 0xb9, 0xc3, 0xbd, 0x5d, 0x86, 0xf1, 0xb7, 0xf8, 0xd2, 0x82, + 0x60, 0xa8, 0x74, 0xb8, 0xb7, 0x17, 0x74, 0x2f, 0x37, 0xcc, 0xf7, 0x1a, 0x2c, 0x77, 0xb8, 0xa7, + 0x8e, 0xe3, 0xc5, 0x84, 0x6a, 0x42, 0x11, 0x39, 0x0e, 0x0d, 0x03, 0x11, 0xc7, 0x33, 0x7e, 0xfb, + 0x65, 0x6b, 0x25, 0x2e, 0x3e, 0xdb, 0xae, 0xcb, 0x30, 0xe7, 0x9f, 0x09, 0x46, 0x02, 0xcf, 0x9e, + 0x38, 0x36, 0x7e, 0xd4, 0xe0, 0xb5, 0x89, 0x8c, 0x0b, 0x5b, 0xf3, 0xcb, 0x08, 0xf9, 0x41, 0x83, + 0xeb, 0x1d, 0xee, 0x6d, 0xbb, 0xee, 0x23, 0xfa, 0x45, 0x8f, 0x08, 0xdc, 0x27, 0xfc, 0xf2, 0xde, + 0x1b, 0x63, 0xaa, 0x50, 0x15, 0xae, 0x13, 0x1d, 0x4f, 0x35, 0x58, 0xed, 0x70, 0xcf, 0xc6, 0x3e, + 0x3d, 0xc4, 0xbb, 0x8c, 0xfa, 0xaf, 0x52, 0x0c, 0x93, 0x5a, 0x64, 0x4e, 0x24, 0xdb, 0xc5, 0x69, + 0x31, 0x4e, 0x6d, 0xd1, 0x34, 0xe6, 0x37, 0x70, 0x6b, 0x6e, 0xfd, 0xff, 0x5b, 0xe0, 0x9f, 0x35, + 0xb8, 0x16, 0xbd, 0x79, 0x03, 0x17, 0x09, 0xfc, 0x50, 0x36, 0x30, 0xfd, 0x3d, 0x28, 0xa3, 0x50, + 0xf4, 0x28, 0x23, 0x62, 0xa8, 0x02, 0x9e, 0x71, 0x96, 0xa6, 0xae, 0xfa, 0x07, 0x50, 0x50, 0x2d, + 0x50, 0x6a, 0xa9, 0x34, 0x6f, 0x2d, 0xec, 0x05, 0x2a, 0x48, 0x2b, 0x1f, 0x55, 0x79, 0x3b, 0x9e, + 0xf0, 0xe1, 0xd6, 0x77, 0x2f, 0x9e, 0xdd, 0x9e, 0x52, 0x3d, 0x7d, 0xf1, 0xec, 0xf6, 0xda, 0x4c, + 0xb1, 0x3f, 0xa5, 0xb0, 0x71, 0x0d, 0x96, 0x3e, 0xf6, 0x07, 0x62, 0x68, 0x63, 0x3e, 0xa0, 0x01, + 0xc7, 0xcd, 0x5f, 0x4b, 0x90, 0xeb, 0x70, 0x4f, 0x7f, 0x04, 0x30, 0xd3, 0x71, 0x1b, 0x0b, 0x05, + 0xcc, 0x75, 0xe5, 0xb5, 0xc5, 0x3e, 0x73, 0xec, 0xfa, 0x03, 0xc8, 0xcb, 0x86, 0xb2, 0x9e, 0xc4, + 0x17, 0xa1, 0x69, 0x99, 0x64, 0xb1, 0x4e, 0x64, 0x8a, 0xd0, 0x54, 0x4c, 0x9f, 0x40, 0x21, 0xae, + 0x60, 0xd5, 0x24, 0x2e, 0x85, 0xa7, 0x62, 0x7b, 0x08, 0xa5, 0x93, 0x42, 0x54, 0x4f, 0xe2, 0x9b, + 0x78, 0xa4, 0x62, 0xfc, 0x0a, 0x96, 0x4f, 0x95, 0x95, 0x8d, 0x24, 0xde, 0x79, 0xbf, 0x54, 0xec, + 0x5d, 0xb8, 0xb1, 0xa8, 0x58, 0xdc, 0x49, 0x0a, 0xb1, 0xc0, 0x39, 0x6d, 0x9c, 0x45, 0x85, 0xe0, + 0xce, 0x99, 0x4b, 0x99, 0x77, 0x4e, 0x15, 0x67, 0x00, 0x46, 0xe2, 0xcb, 0xff, 0xee, 0xf9, 0x8b, + 0x7a, 0x89, 0x88, 0x9f, 0x43, 0x65, 0xb6, 0x0d, 0xbe, 0x95, 0x14, 0x64, 0xc6, 0x29, 0x15, 0xef, + 0x63, 0x58, 0x9a, 0xef, 0x6b, 0xef, 0x9c, 0xc9, 0xfc, 0x9f, 0xce, 0xd4, 0x97, 0x70, 0x75, 0xae, + 0x50, 0xbd, 0x9d, 0x78, 0x52, 0x67, 0xbc, 0xd2, 0x30, 0xb7, 0xf6, 0x8e, 0xfe, 0xaa, 0x66, 0x8e, + 0xc6, 0x55, 0xed, 0xf9, 0xb8, 0xaa, 0xfd, 0x39, 0xae, 0x6a, 0x3f, 0x1d, 0x57, 0x33, 0xcf, 0x8f, + 0xab, 0x99, 0xdf, 0x8f, 0xab, 0x99, 0xc7, 0xef, 0xcf, 0xdc, 0x44, 0xef, 0x4b, 0xae, 0x5d, 0x1a, + 0x06, 0x2e, 0x8a, 0x2e, 0xdc, 0x56, 0xfc, 0x25, 0x70, 0x78, 0xcf, 0x7a, 0x32, 0xf3, 0x39, 0x20, + 0xaf, 0xa7, 0x07, 0x05, 0x79, 0xa1, 0xbb, 0xf7, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5d, 0x2e, + 0x1c, 0xf8, 0xf9, 0x0c, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -585,6 +669,12 @@ type MsgClient interface { // ie. if specific whitelist is granted for an NFT, that whitelist will // still be valid, ater we add and remove it from the class whitelist. RemoveFromClassWhitelist(ctx context.Context, in *MsgRemoveFromClassWhitelist, opts ...grpc.CallOption) (*EmptyResponse, error) + // ClassFreeze freezes all NFTs of a class held by an account. + ClassFreeze(ctx context.Context, in *MsgClassFreeze, opts ...grpc.CallOption) (*EmptyResponse, error) + // ClassUnfreeze removes class-freeze on an account for an NFT class. + // NOTE: + // class unfreeze does not affect the individual nft freeze. + ClassUnfreeze(ctx context.Context, in *MsgClassUnfreeze, opts ...grpc.CallOption) (*EmptyResponse, error) // UpdateParams is a governance operation that sets the parameters of the module. // NOTE: all parameters must be provided. UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*EmptyResponse, error) @@ -679,6 +769,24 @@ func (c *msgClient) RemoveFromClassWhitelist(ctx context.Context, in *MsgRemoveF return out, nil } +func (c *msgClient) ClassFreeze(ctx context.Context, in *MsgClassFreeze, opts ...grpc.CallOption) (*EmptyResponse, error) { + out := new(EmptyResponse) + err := c.cc.Invoke(ctx, "/coreum.asset.nft.v1.Msg/ClassFreeze", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) ClassUnfreeze(ctx context.Context, in *MsgClassUnfreeze, opts ...grpc.CallOption) (*EmptyResponse, error) { + out := new(EmptyResponse) + err := c.cc.Invoke(ctx, "/coreum.asset.nft.v1.Msg/ClassUnfreeze", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*EmptyResponse, error) { out := new(EmptyResponse) err := c.cc.Invoke(ctx, "/coreum.asset.nft.v1.Msg/UpdateParams", in, out, opts...) @@ -713,6 +821,12 @@ type MsgServer interface { // ie. if specific whitelist is granted for an NFT, that whitelist will // still be valid, ater we add and remove it from the class whitelist. RemoveFromClassWhitelist(context.Context, *MsgRemoveFromClassWhitelist) (*EmptyResponse, error) + // ClassFreeze freezes all NFTs of a class held by an account. + ClassFreeze(context.Context, *MsgClassFreeze) (*EmptyResponse, error) + // ClassUnfreeze removes class-freeze on an account for an NFT class. + // NOTE: + // class unfreeze does not affect the individual nft freeze. + ClassUnfreeze(context.Context, *MsgClassUnfreeze) (*EmptyResponse, error) // UpdateParams is a governance operation that sets the parameters of the module. // NOTE: all parameters must be provided. UpdateParams(context.Context, *MsgUpdateParams) (*EmptyResponse, error) @@ -749,6 +863,12 @@ func (*UnimplementedMsgServer) AddToClassWhitelist(ctx context.Context, req *Msg func (*UnimplementedMsgServer) RemoveFromClassWhitelist(ctx context.Context, req *MsgRemoveFromClassWhitelist) (*EmptyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RemoveFromClassWhitelist not implemented") } +func (*UnimplementedMsgServer) ClassFreeze(ctx context.Context, req *MsgClassFreeze) (*EmptyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClassFreeze not implemented") +} +func (*UnimplementedMsgServer) ClassUnfreeze(ctx context.Context, req *MsgClassUnfreeze) (*EmptyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClassUnfreeze not implemented") +} func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*EmptyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") } @@ -919,6 +1039,42 @@ func _Msg_RemoveFromClassWhitelist_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _Msg_ClassFreeze_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgClassFreeze) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).ClassFreeze(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/coreum.asset.nft.v1.Msg/ClassFreeze", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).ClassFreeze(ctx, req.(*MsgClassFreeze)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_ClassUnfreeze_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgClassUnfreeze) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).ClassUnfreeze(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/coreum.asset.nft.v1.Msg/ClassUnfreeze", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).ClassUnfreeze(ctx, req.(*MsgClassUnfreeze)) + } + return interceptor(ctx, in, info, handler) +} + func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(MsgUpdateParams) if err := dec(in); err != nil { @@ -977,6 +1133,14 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "RemoveFromClassWhitelist", Handler: _Msg_RemoveFromClassWhitelist_Handler, }, + { + MethodName: "ClassFreeze", + Handler: _Msg_ClassFreeze_Handler, + }, + { + MethodName: "ClassUnfreeze", + Handler: _Msg_ClassUnfreeze_Handler, + }, { MethodName: "UpdateParams", Handler: _Msg_UpdateParams_Handler, @@ -1300,6 +1464,94 @@ func (m *MsgUnfreeze) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *MsgClassFreeze) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgClassFreeze) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgClassFreeze) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Account) > 0 { + i -= len(m.Account) + copy(dAtA[i:], m.Account) + i = encodeVarintTx(dAtA, i, uint64(len(m.Account))) + i-- + dAtA[i] = 0x1a + } + if len(m.ClassID) > 0 { + i -= len(m.ClassID) + copy(dAtA[i:], m.ClassID) + i = encodeVarintTx(dAtA, i, uint64(len(m.ClassID))) + i-- + dAtA[i] = 0x12 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgClassUnfreeze) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgClassUnfreeze) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgClassUnfreeze) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Account) > 0 { + i -= len(m.Account) + copy(dAtA[i:], m.Account) + i = encodeVarintTx(dAtA, i, uint64(len(m.Account))) + i-- + dAtA[i] = 0x1a + } + if len(m.ClassID) > 0 { + i -= len(m.ClassID) + copy(dAtA[i:], m.ClassID) + i = encodeVarintTx(dAtA, i, uint64(len(m.ClassID))) + i-- + dAtA[i] = 0x12 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *MsgAddToWhitelist) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1710,6 +1962,48 @@ func (m *MsgUnfreeze) Size() (n int) { return n } +func (m *MsgClassFreeze) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ClassID) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Account) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgClassUnfreeze) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ClassID) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Account) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + func (m *MsgAddToWhitelist) Size() (n int) { if m == nil { return 0 @@ -2929,6 +3223,298 @@ func (m *MsgUnfreeze) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgClassFreeze) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgClassFreeze: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgClassFreeze: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Account", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Account = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgClassUnfreeze) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgClassUnfreeze: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgClassUnfreeze: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Account", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Account = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *MsgAddToWhitelist) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/deterministicgas/config.go b/x/deterministicgas/config.go index 2c11dd839..58dfa3846 100644 --- a/x/deterministicgas/config.go +++ b/x/deterministicgas/config.go @@ -87,6 +87,8 @@ func DefaultConfig() Config { MsgToMsgURL(&assetnfttypes.MsgMint{}): constantGasFunc(39000), MsgToMsgURL(&assetnfttypes.MsgFreeze{}): constantGasFunc(8000), MsgToMsgURL(&assetnfttypes.MsgUnfreeze{}): constantGasFunc(5000), + MsgToMsgURL(&assetnfttypes.MsgClassFreeze{}): constantGasFunc(8000), + MsgToMsgURL(&assetnfttypes.MsgClassUnfreeze{}): constantGasFunc(5000), MsgToMsgURL(&assetnfttypes.MsgAddToWhitelist{}): constantGasFunc(7000), MsgToMsgURL(&assetnfttypes.MsgRemoveFromWhitelist{}): constantGasFunc(3500), MsgToMsgURL(&assetnfttypes.MsgAddToClassWhitelist{}): constantGasFunc(7000), diff --git a/x/deterministicgas/config_test.go b/x/deterministicgas/config_test.go index 9eb249113..56be3f761 100644 --- a/x/deterministicgas/config_test.go +++ b/x/deterministicgas/config_test.go @@ -191,7 +191,7 @@ func TestDeterministicGas_DeterministicMessages(t *testing.T) { // we assert length to be equal to exact number, so each change requires // explicit adjustment of tests. assert.Equal(t, 60, len(nondeterministicMsgs)) - assert.Equal(t, 48, len(deterministicMsgs)) + assert.Equal(t, 50, len(deterministicMsgs)) for _, sdkMsg := range deterministicMsgs { sdkMsg := sdkMsg diff --git a/x/deterministicgas/spec/README.md b/x/deterministicgas/spec/README.md index 155f7e24e..8f1a1ee8a 100644 --- a/x/deterministicgas/spec/README.md +++ b/x/deterministicgas/spec/README.md @@ -84,6 +84,8 @@ TotalGas = 65000 + 2 * 70000 + 2 * 1000 + max(0, 2050-2048) * 10 | `/coreum.asset.nft.v1.MsgAddToClassWhitelist` | 7000 | | `/coreum.asset.nft.v1.MsgAddToWhitelist` | 7000 | | `/coreum.asset.nft.v1.MsgBurn` | 26000 | +| `/coreum.asset.nft.v1.MsgClassFreeze` | 8000 | +| `/coreum.asset.nft.v1.MsgClassUnfreeze` | 5000 | | `/coreum.asset.nft.v1.MsgFreeze` | 8000 | | `/coreum.asset.nft.v1.MsgIssueClass` | 16000 | | `/coreum.asset.nft.v1.MsgMint` | 39000 | From e839aab8c76444c892aabf51ec0e0770863b05c3 Mon Sep 17 00:00:00 2001 From: Dzmitry Hil Date: Thu, 26 Oct 2023 12:38:18 +0300 Subject: [PATCH 4/4] Integrate MsgCancelUnbondingDelegation, MsgCreatePeriodicVestingAccount, MsgCreatePermanentLockedAccount with deterministic gas. (#682) # Description Integrate MsgCancelUnbondingDelegation, MsgCreatePeriodicVestingAccount, MsgCreatePermanentLockedAccount with deterministic gas. --- app/app.go | 5 +- integration-tests/modules/staking_test.go | 110 ++++++++++++- integration-tests/modules/vesting_test.go | 187 +++++++++++++++++++++- x/asset/nft/types/expected_keepers.go | 2 +- x/deterministicgas/config.go | 23 ++- x/deterministicgas/config_test.go | 9 +- x/deterministicgas/spec/README.md | 6 +- x/wnft/types/exptected_keepers.go | 2 +- 8 files changed, 302 insertions(+), 42 deletions(-) diff --git a/app/app.go b/app/app.go index 941db77de..2701bde0d 100644 --- a/app/app.go +++ b/app/app.go @@ -76,6 +76,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/mint" mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/cosmos/cosmos-sdk/x/nft" + nftkeeper "github.com/cosmos/cosmos-sdk/x/nft/keeper" "github.com/cosmos/cosmos-sdk/x/params" paramsclient "github.com/cosmos/cosmos-sdk/x/params/client" paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" @@ -104,9 +106,6 @@ import ( "github.com/pkg/errors" "github.com/spf13/cast" - "github.com/cosmos/cosmos-sdk/x/nft" - nftkeeper "github.com/cosmos/cosmos-sdk/x/nft/keeper" - "github.com/CoreumFoundation/coreum/v3/app/openapi" appupgrade "github.com/CoreumFoundation/coreum/v3/app/upgrade" appupgradev1 "github.com/CoreumFoundation/coreum/v3/app/upgrade/v1" diff --git a/integration-tests/modules/staking_test.go b/integration-tests/modules/staking_test.go index e18cfdec9..4592a5e9d 100644 --- a/integration-tests/modules/staking_test.go +++ b/integration-tests/modules/staking_test.go @@ -10,6 +10,7 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + cosmoserrors "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -145,15 +146,14 @@ func TestStakingValidatorCRUDAndStaking(t *testing.T) { Messages: []sdk.Msg{editValidatorMsg}, }) - _, err = client.BroadcastTx( + editValidatorRes, err := client.BroadcastTx( ctx, chain.ClientContext.WithFromAddress(validatorAccAddress), chain.TxFactory().WithGas(chain.GasLimitByMsgs(editValidatorMsg)), editValidatorMsg, ) require.NoError(t, err) - // FIXME(v47-deterministic) uncomment after deterministic gas fix - // assert.EqualValues(t, int64(chain.GasLimitByMsgs(editValidatorMsg)), editValidatorRes.GasUsed) + assert.EqualValues(t, int64(chain.GasLimitByMsgs(editValidatorMsg)), editValidatorRes.GasUsed) valResp, err := stakingClient.Validator(ctx, &stakingtypes.QueryValidatorRequest{ ValidatorAddr: validatorAddress.String(), @@ -163,7 +163,11 @@ func TestStakingValidatorCRUDAndStaking(t *testing.T) { assert.EqualValues(t, updatedDetail, valResp.GetValidator().Description.Details) // Delegate coins - delegateMsg := stakingtypes.NewMsgDelegate(delegator, validatorAddress, chain.NewCoin(delegateAmount)) + delegateMsg := &stakingtypes.MsgDelegate{ + DelegatorAddress: delegator.String(), + ValidatorAddress: validatorAddress.String(), + Amount: chain.NewCoin(delegateAmount), + } delegateResult, err := client.BroadcastTx( ctx, chain.ClientContext.WithFromAddress(delegator), @@ -200,8 +204,7 @@ func TestStakingValidatorCRUDAndStaking(t *testing.T) { redelegateMsg, ) require.NoError(t, err) - // FIXME(v47-deterministic) uncomment after deterministic gas fix - // assert.Equal(t, int64(chain.GasLimitByMsgs(redelegateMsg)), redelegateResult.GasUsed) + assert.Equal(t, int64(chain.GasLimitByMsgs(redelegateMsg)), redelegateResult.GasUsed) t.Logf("Redelegation executed, txHash:%s", redelegateResult.TxHash) ddResp, err = stakingClient.DelegatorDelegations(ctx, &stakingtypes.QueryDelegatorDelegationsRequest{ @@ -222,7 +225,11 @@ func TestStakingValidatorCRUDAndStaking(t *testing.T) { setUnbondingTimeViaGovernance(ctx, t, chain, fastUnbondingTime) // Undelegate coins - undelegateMsg := stakingtypes.NewMsgUndelegate(delegator, validator2Address, chain.NewCoin(delegateAmount)) + undelegateMsg := &stakingtypes.MsgUndelegate{ + DelegatorAddress: delegator.String(), + ValidatorAddress: validator2Address.String(), + Amount: chain.NewCoin(delegateAmount), + } undelegateResult, err := client.BroadcastTx( ctx, chain.ClientContext.WithFromAddress(delegator), @@ -328,6 +335,95 @@ func TestValidatorUpdateWithLowMinSelfDelegation(t *testing.T) { assert.EqualValues(t, editValidatorMsg.Description.Details, valResp.GetValidator().Description.Details) } +// TestUnbondAndCancelUnbondingDelegation checks that it is possible to unbond and cancel unbonding delegation. +func TestUnbondAndCancelUnbondingDelegation(t *testing.T) { + ctx, chain := integrationtests.NewCoreumTestingContext(t) + + stakingClient := stakingtypes.NewQueryClient(chain.ClientContext) + customParamsClient := customparamstypes.NewQueryClient(chain.ClientContext) + + delegator := chain.GenAccount() + delegateAmount := sdkmath.NewInt(100) + chain.FundAccountWithOptions(ctx, t, delegator, integration.BalancesOptions{ + Messages: []sdk.Msg{ + &stakingtypes.MsgDelegate{}, + &stakingtypes.MsgUndelegate{}, + &stakingtypes.MsgCancelUnbondingDelegation{}, + }, + Amount: delegateAmount, + }) + + customStakingParams, err := customParamsClient.StakingParams(ctx, &customparamstypes.QueryStakingParamsRequest{}) + require.NoError(t, err) + // we stake the minimum possible staking amount + validatorStakingAmount := customStakingParams.Params.MinSelfDelegation.Mul(sdkmath.NewInt(2)) // we multiply not to conflict with the tests which increases the min amount + + // setup validator + _, validatorAddress, deactivateValidator, err := chain.CreateValidator(ctx, t, validatorStakingAmount, validatorStakingAmount) + require.NoError(t, err) + defer deactivateValidator() + + // delegate coins + delegateMsg := &stakingtypes.MsgDelegate{ + DelegatorAddress: delegator.String(), + ValidatorAddress: validatorAddress.String(), + Amount: chain.NewCoin(delegateAmount), + } + _, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(delegator), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(delegateMsg)), + delegateMsg, + ) + require.NoError(t, err) + + // undelegate coins + undelegateMsg := &stakingtypes.MsgUndelegate{ + DelegatorAddress: delegator.String(), + ValidatorAddress: validatorAddress.String(), + Amount: chain.NewCoin(delegateAmount), + } + _, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(delegator), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(undelegateMsg)), + undelegateMsg, + ) + require.NoError(t, err) + + // check unbonding delegation + unbondingDelegationRes, err := stakingClient.UnbondingDelegation(ctx, &stakingtypes.QueryUnbondingDelegationRequest{ + DelegatorAddr: delegator.String(), + ValidatorAddr: validatorAddress.String(), + }) + require.NoError(t, err) + require.Len(t, unbondingDelegationRes.Unbond.Entries, 1) + require.Equal(t, unbondingDelegationRes.Unbond.Entries[0].Balance.String(), delegateAmount.String()) + + // cancel undelegation + cancelUnbondingDelegationMsg := &stakingtypes.MsgCancelUnbondingDelegation{ + DelegatorAddress: delegator.String(), + ValidatorAddress: validatorAddress.String(), + Amount: chain.NewCoin(delegateAmount), + CreationHeight: unbondingDelegationRes.Unbond.Entries[0].CreationHeight, + } + txRes, err := client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(delegator), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(cancelUnbondingDelegationMsg)), + cancelUnbondingDelegationMsg, + ) + require.NoError(t, err) + require.Equal(t, chain.GasLimitByMsgs(cancelUnbondingDelegationMsg), uint64(txRes.GasUsed)) + + // check unbonding delegation one more time + _, err = stakingClient.UnbondingDelegation(ctx, &stakingtypes.QueryUnbondingDelegationRequest{ + DelegatorAddr: delegator.String(), + ValidatorAddr: validatorAddress.String(), + }) + require.ErrorContains(t, err, cosmoserrors.ErrNotFound.Error()) +} + func changeMinSelfDelegationCustomParam( ctx context.Context, t *testing.T, diff --git a/integration-tests/modules/vesting_test.go b/integration-tests/modules/vesting_test.go index c79c8dc9e..5e0a55e51 100644 --- a/integration-tests/modules/vesting_test.go +++ b/integration-tests/modules/vesting_test.go @@ -22,8 +22,8 @@ import ( customparamstypes "github.com/CoreumFoundation/coreum/v3/x/customparams/types" ) -// TestVestingAccountCreationAndBankSend tests vesting account can be created, and it's send limits are applied. -func TestVestingAccountCreationAndBankSend(t *testing.T) { +// TestContinuousAndDelayedVestingAccountCreationAndBankSend tests continuous and delayed vesting account can be created, and its send limit is applied. +func TestContinuousAndDelayedVestingAccountCreationAndBankSend(t *testing.T) { t.Parallel() ctx, chain := integrationtests.NewCoreumTestingContext(t) @@ -95,7 +95,7 @@ func TestVestingAccountCreationAndBankSend(t *testing.T) { chain.TxFactory().WithGas(chain.GasLimitByMsgs(msgSend)), msgSend, ) - requireT.True(cosmoserrors.ErrInsufficientFunds.Is(err)) + requireT.ErrorIs(err, cosmoserrors.ErrInsufficientFunds) // await vesting time to unlock the vesting coins select { @@ -119,6 +119,181 @@ func TestVestingAccountCreationAndBankSend(t *testing.T) { requireT.NoError(err) } +// TestPeriodicVestingAccountCreationAndBankSend tests periodic vesting account can be created, and its send limit is applied. +func TestPeriodicVestingAccountCreationAndBankSend(t *testing.T) { + t.Parallel() + + ctx, chain := integrationtests.NewCoreumTestingContext(t) + + creator := chain.GenAccount() + vestingAcc := chain.GenAccount() + recipient := chain.GenAccount() + + requireT := require.New(t) + authClient := authtypes.NewQueryClient(chain.ClientContext) + bankClient := banktypes.NewQueryClient(chain.ClientContext) + + vestingCoinPeriod1 := chain.NewCoin(sdkmath.NewInt(50)) + vestingCoinPeriod2 := chain.NewCoin(sdkmath.NewInt(60)) + amountToVest := vestingCoinPeriod1.Add(vestingCoinPeriod2) + chain.FundAccountWithOptions(ctx, t, creator, integration.BalancesOptions{ + Messages: []sdk.Msg{&vestingtypes.MsgCreatePeriodicVestingAccount{}}, + Amount: amountToVest.Amount, + }) + + createAccMsg := &vestingtypes.MsgCreatePeriodicVestingAccount{ + FromAddress: creator.String(), + ToAddress: vestingAcc.String(), + StartTime: time.Now().Unix() - 1, + VestingPeriods: vestingtypes.Periods{ + { + Length: 1, // activate it immediately + Amount: sdk.NewCoins(vestingCoinPeriod1), + }, + { + Length: 360, // +360 sec from start + Amount: sdk.NewCoins(vestingCoinPeriod2), + }, + }, + } + + txRes, err := client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(creator), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(createAccMsg)), + createAccMsg, + ) + requireT.NoError(err) + requireT.Equal(uint64(txRes.GasUsed), chain.GasLimitByMsgs(createAccMsg)) + + // check account is created and it's vesting + accountRes, err := authClient.Account(ctx, &authtypes.QueryAccountRequest{ + Address: vestingAcc.String(), + }) + requireT.NoError(err) + requireT.Equal("/cosmos.vesting.v1beta1.PeriodicVestingAccount", accountRes.Account.TypeUrl) + // check the balance is full + balanceRes, err := bankClient.Balance(ctx, &banktypes.QueryBalanceRequest{ + Address: vestingAcc.String(), + Denom: amountToVest.Denom, + }) + requireT.NoError(err) + requireT.Equal(amountToVest.String(), balanceRes.Balance.String()) + + // fund the vesting account to pay fees + chain.FundAccountWithOptions(ctx, t, vestingAcc, integration.BalancesOptions{ + Messages: []sdk.Msg{ + &banktypes.MsgSend{}, + }, + }) + + msgSend := &banktypes.MsgSend{ + FromAddress: vestingAcc.String(), + ToAddress: recipient.String(), + Amount: sdk.NewCoins(amountToVest), + } + + // try to send full amount from vesting account before delay is ended + _, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(vestingAcc), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(msgSend)), + msgSend, + ) + requireT.ErrorIs(err, cosmoserrors.ErrInsufficientFunds) + + // fund the vesting account to pay fees one more time + chain.FundAccountWithOptions(ctx, t, vestingAcc, integration.BalancesOptions{ + Messages: []sdk.Msg{&banktypes.MsgSend{}}, + }) + + msgSend = &banktypes.MsgSend{ + FromAddress: vestingAcc.String(), + ToAddress: recipient.String(), + Amount: sdk.NewCoins(vestingCoinPeriod1), + } + // try to send one more time, the coins should be unlocked at that time since we use first period only + _, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(vestingAcc), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(msgSend)), + msgSend, + ) + requireT.NoError(err) +} + +// TestPermanentLockedAccountCreationAndBankSend tests permanent locked account can be created, and its send limit is applied. +func TestPermanentLockedAccountCreationAndBankSend(t *testing.T) { + t.Parallel() + + ctx, chain := integrationtests.NewCoreumTestingContext(t) + + creator := chain.GenAccount() + vestingAcc := chain.GenAccount() + recipient := chain.GenAccount() + + requireT := require.New(t) + authClient := authtypes.NewQueryClient(chain.ClientContext) + bankClient := banktypes.NewQueryClient(chain.ClientContext) + + amountToVest := chain.NewCoin(sdkmath.NewInt(45)) + chain.FundAccountWithOptions(ctx, t, creator, integration.BalancesOptions{ + Messages: []sdk.Msg{&vestingtypes.MsgCreatePermanentLockedAccount{}}, + Amount: amountToVest.Amount, + }) + + createAccMsg := &vestingtypes.MsgCreatePermanentLockedAccount{ + FromAddress: creator.String(), + ToAddress: vestingAcc.String(), + Amount: sdk.NewCoins(amountToVest), + } + + txRes, err := client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(creator), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(createAccMsg)), + createAccMsg, + ) + requireT.NoError(err) + requireT.Equal(uint64(txRes.GasUsed), chain.GasLimitByMsgs(createAccMsg)) + + // check account is created and it's vesting + accountRes, err := authClient.Account(ctx, &authtypes.QueryAccountRequest{ + Address: vestingAcc.String(), + }) + requireT.NoError(err) + requireT.Equal("/cosmos.vesting.v1beta1.PermanentLockedAccount", accountRes.Account.TypeUrl) + // check the balance is full + balanceRes, err := bankClient.Balance(ctx, &banktypes.QueryBalanceRequest{ + Address: vestingAcc.String(), + Denom: amountToVest.Denom, + }) + requireT.NoError(err) + requireT.Equal(amountToVest.String(), balanceRes.Balance.String()) + + // fund the vesting account to pay fees + chain.FundAccountWithOptions(ctx, t, vestingAcc, integration.BalancesOptions{ + Messages: []sdk.Msg{ + &banktypes.MsgSend{}, + }, + }) + + msgSend := &banktypes.MsgSend{ + FromAddress: vestingAcc.String(), + ToAddress: recipient.String(), + Amount: sdk.NewCoins(amountToVest), + } + + // try to send full amount from vesting account before delay is ended + _, err = client.BroadcastTx( + ctx, + chain.ClientContext.WithFromAddress(vestingAcc), + chain.TxFactory().WithGas(chain.GasLimitByMsgs(msgSend)), + msgSend, + ) + requireT.ErrorIs(err, cosmoserrors.ErrInsufficientFunds) +} + // TestVestingAccountStaking tests the vesting account can delegate coins. func TestVestingAccountStaking(t *testing.T) { t.Parallel() @@ -333,7 +508,7 @@ func TestVestingAccountWithFTInteraction(t *testing.T) { chain.TxFactory().WithGas(chain.GasLimitByMsgs(burnMsg)), burnMsg, ) - requireT.True(cosmoserrors.ErrInsufficientFunds.Is(err)) + requireT.ErrorIs(err, cosmoserrors.ErrInsufficientFunds) // try to send vesting locker coins msgSend := &banktypes.MsgSend{ @@ -347,7 +522,7 @@ func TestVestingAccountWithFTInteraction(t *testing.T) { chain.TxFactory().WithGas(chain.GasLimitByMsgs(msgSend)), msgSend, ) - requireT.True(cosmoserrors.ErrInsufficientFunds.Is(err)) + requireT.ErrorIs(err, cosmoserrors.ErrInsufficientFunds) // freeze coins, it should work even for the vested coins freezeMsg := &assetfttypes.MsgFreeze{ @@ -400,7 +575,7 @@ func TestVestingAccountWithFTInteraction(t *testing.T) { chain.TxFactory().WithGas(chain.GasLimitByMsgs(msgSend)), msgSend, ) - requireT.True(cosmoserrors.ErrInsufficientFunds.Is(err)) + requireT.ErrorIs(err, cosmoserrors.ErrInsufficientFunds) // unfreeze coins, to let prev vesting account tx pass unfreezeMsg := &assetfttypes.MsgUnfreeze{ diff --git a/x/asset/nft/types/expected_keepers.go b/x/asset/nft/types/expected_keepers.go index 89f857e4f..7674335f4 100644 --- a/x/asset/nft/types/expected_keepers.go +++ b/x/asset/nft/types/expected_keepers.go @@ -20,7 +20,7 @@ type NFTKeeper interface { Burn(ctx sdk.Context, classID, nftID string) error Update(ctx sdk.Context, n nft.NFT) error GetOwner(ctx sdk.Context, classID, nftID string) sdk.AccAddress - Transfer(ctx sdk.Context, classID string, nftID string, receiver sdk.AccAddress) error + Transfer(ctx sdk.Context, classID, nftID string, receiver sdk.AccAddress) error } // BankKeeper defines the expected bank interface. diff --git a/x/deterministicgas/config.go b/x/deterministicgas/config.go index 58dfa3846..1ec46fc28 100644 --- a/x/deterministicgas/config.go +++ b/x/deterministicgas/config.go @@ -141,14 +141,17 @@ func DefaultConfig() Config { MsgToMsgURL(&slashingtypes.MsgUnjail{}): constantGasFunc(25000), // staking - MsgToMsgURL(&stakingtypes.MsgDelegate{}): constantGasFunc(83000), - MsgToMsgURL(&stakingtypes.MsgUndelegate{}): constantGasFunc(112000), - MsgToMsgURL(&stakingtypes.MsgBeginRedelegate{}): constantGasFunc(157000), - MsgToMsgURL(&stakingtypes.MsgCreateValidator{}): constantGasFunc(117000), - MsgToMsgURL(&stakingtypes.MsgEditValidator{}): constantGasFunc(13000), + MsgToMsgURL(&stakingtypes.MsgDelegate{}): constantGasFunc(83000), + MsgToMsgURL(&stakingtypes.MsgUndelegate{}): constantGasFunc(112000), + MsgToMsgURL(&stakingtypes.MsgBeginRedelegate{}): constantGasFunc(157000), + MsgToMsgURL(&stakingtypes.MsgCreateValidator{}): constantGasFunc(117000), + MsgToMsgURL(&stakingtypes.MsgEditValidator{}): constantGasFunc(13000), + MsgToMsgURL(&stakingtypes.MsgCancelUnbondingDelegation{}): constantGasFunc(75000), // vesting - MsgToMsgURL(&vestingtypes.MsgCreateVestingAccount{}): constantGasFunc(30000), + MsgToMsgURL(&vestingtypes.MsgCreateVestingAccount{}): constantGasFunc(30000), + MsgToMsgURL(&vestingtypes.MsgCreatePeriodicVestingAccount{}): constantGasFunc(32000), + MsgToMsgURL(&vestingtypes.MsgCreatePermanentLockedAccount{}): constantGasFunc(30000), // wasm MsgToMsgURL(&wasmtypes.MsgUpdateAdmin{}): constantGasFunc(8000), @@ -204,8 +207,6 @@ func DefaultConfig() Config { // staking &stakingtypes.MsgUpdateParams{}, // This is non-deterministic because all the gov proposals are non-deterministic anyway - // FIXME(v47-deterministic): add message to deterministic (we have separate task for it) - &stakingtypes.MsgCancelUnbondingDelegation{}, // slashing &slashingtypes.MsgUpdateParams{}, // This is non-deterministic because all the gov proposals are non-deterministic anyway @@ -217,12 +218,6 @@ func DefaultConfig() Config { &upgradetypes.MsgCancelUpgrade{}, // This is non-deterministic because all the gov proposals are non-deterministic anyway &upgradetypes.MsgSoftwareUpgrade{}, // This is non-deterministic because all the gov proposals are non-deterministic anyway - // vesting - // FIXME(v47-deterministic): add message to deterministic (we have separate task for it) - &vestingtypes.MsgCreatePeriodicVestingAccount{}, - // FIXME(v47-deterministic): add message to deterministic (we have separate task for it) - &vestingtypes.MsgCreatePermanentLockedAccount{}, - // wasm &wasmtypes.MsgStoreCode{}, &wasmtypes.MsgInstantiateContract{}, diff --git a/x/deterministicgas/config_test.go b/x/deterministicgas/config_test.go index 56be3f761..a33b53f02 100644 --- a/x/deterministicgas/config_test.go +++ b/x/deterministicgas/config_test.go @@ -96,7 +96,6 @@ func TestDeterministicGas_DeterministicMessages(t *testing.T) { // staking "/cosmos.staking.v1beta1.MsgUpdateParams", - "/cosmos.staking.v1beta1.MsgCancelUnbondingDelegation", // slashing "/cosmos.slashing.v1beta1.MsgUpdateParams", @@ -105,10 +104,6 @@ func TestDeterministicGas_DeterministicMessages(t *testing.T) { "/cosmos.upgrade.v1beta1.MsgCancelUpgrade", "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade", - // vesting - "/cosmos.vesting.v1beta1.MsgCreatePeriodicVestingAccount", - "/cosmos.vesting.v1beta1.MsgCreatePermanentLockedAccount", - // wasm "/cosmwasm.wasm.v1.MsgStoreCode", "/cosmwasm.wasm.v1.MsgInstantiateContract", @@ -190,8 +185,8 @@ func TestDeterministicGas_DeterministicMessages(t *testing.T) { // To make sure we do not increase/decrease deterministic types accidentally // we assert length to be equal to exact number, so each change requires // explicit adjustment of tests. - assert.Equal(t, 60, len(nondeterministicMsgs)) - assert.Equal(t, 50, len(deterministicMsgs)) + assert.Equal(t, 57, len(nondeterministicMsgs)) + assert.Equal(t, 53, len(deterministicMsgs)) for _, sdkMsg := range deterministicMsgs { sdkMsg := sdkMsg diff --git a/x/deterministicgas/spec/README.md b/x/deterministicgas/spec/README.md index 8f1a1ee8a..656dcd616 100644 --- a/x/deterministicgas/spec/README.md +++ b/x/deterministicgas/spec/README.md @@ -110,10 +110,13 @@ TotalGas = 65000 + 2 * 70000 + 2 * 1000 + max(0, 2050-2048) * 10 | `/cosmos.nft.v1beta1.MsgSend` | 25000 | | `/cosmos.slashing.v1beta1.MsgUnjail` | 25000 | | `/cosmos.staking.v1beta1.MsgBeginRedelegate` | 157000 | +| `/cosmos.staking.v1beta1.MsgCancelUnbondingDelegation` | 75000 | | `/cosmos.staking.v1beta1.MsgCreateValidator` | 117000 | | `/cosmos.staking.v1beta1.MsgDelegate` | 83000 | | `/cosmos.staking.v1beta1.MsgEditValidator` | 13000 | | `/cosmos.staking.v1beta1.MsgUndelegate` | 112000 | +| `/cosmos.vesting.v1beta1.MsgCreatePeriodicVestingAccount` | 32000 | +| `/cosmos.vesting.v1beta1.MsgCreatePermanentLockedAccount` | 30000 | | `/cosmos.vesting.v1beta1.MsgCreateVestingAccount` | 30000 | | `/cosmwasm.wasm.v1.MsgClearAdmin` | 6500 | | `/cosmwasm.wasm.v1.MsgUpdateAdmin` | 8000 | @@ -161,12 +164,9 @@ Real examples of special case tests could be found [here](https://github.com/Cor | `/cosmos.gov.v1beta1.MsgSubmitProposal` | | `/cosmos.mint.v1beta1.MsgUpdateParams` | | `/cosmos.slashing.v1beta1.MsgUpdateParams` | -| `/cosmos.staking.v1beta1.MsgCancelUnbondingDelegation` | | `/cosmos.staking.v1beta1.MsgUpdateParams` | | `/cosmos.upgrade.v1beta1.MsgCancelUpgrade` | | `/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade` | -| `/cosmos.vesting.v1beta1.MsgCreatePeriodicVestingAccount` | -| `/cosmos.vesting.v1beta1.MsgCreatePermanentLockedAccount` | | `/cosmwasm.wasm.v1.MsgExecuteContract` | | `/cosmwasm.wasm.v1.MsgIBCCloseChannel` | | `/cosmwasm.wasm.v1.MsgIBCSend` | diff --git a/x/wnft/types/exptected_keepers.go b/x/wnft/types/exptected_keepers.go index f2de79d3f..304acd96a 100644 --- a/x/wnft/types/exptected_keepers.go +++ b/x/wnft/types/exptected_keepers.go @@ -4,5 +4,5 @@ import sdk "github.com/cosmos/cosmos-sdk/types" // NonFungibleTokenProvider defines the interface to intercept within nft method calls. type NonFungibleTokenProvider interface { - Transfer(ctx sdk.Context, classID string, nftID string, receiver sdk.AccAddress) error + Transfer(ctx sdk.Context, classID, nftID string, receiver sdk.AccAddress) error }