From 08a4586300d1cd5588dcf31ce56097c13e41c278 Mon Sep 17 00:00:00 2001 From: Jayden Lee <41176085+tkxkd0159@users.noreply.github.com> Date: Mon, 16 Oct 2023 14:30:18 +0900 Subject: [PATCH] test(collection): refactor overall unittests of `x/collection` (#1139) * modify MsgOperatorBurnFT * clarify events * remove deterministic flag, always test for non-deterministic * add CHANGELOG * chore: refactor * chore: encoding unittest --- CHANGELOG.md | 1 + testutil/encoding.go | 19 + testutil/encoding_test.go | 33 + x/collection/keeper/keeper_test.go | 42 +- x/collection/keeper/msg_server_test.go | 899 +++++++++++++++---------- 5 files changed, 616 insertions(+), 378 deletions(-) create mode 100644 testutil/encoding.go create mode 100644 testutil/encoding_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index ceb4002f8b..5d8bc7f573 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/collection) [\#1131](https://github.com/Finschia/finschia-sdk/pull/1131) add additional unittest of x/collection(`MsgIssueFT`, `MsgMintFT`, `MsgBurnFT`) * (x/collection) [\#1133](https://github.com/Finschia/finschia-sdk/pull/1133) Refactor unittest for `SendFT`, `OperatorSendFT`, `AuthorizeOperator`, and `RevokeOperator` to check more states * (x/token) [\#1137](https://github.com/Finschia/finschia-sdk/pull/1137) Add test for event compatibility +* (x/collection) [\#1139](https://github.com/Finschia/finschia-sdk/pull/1139) refactor overall unittests of `x/collection` ### Bug Fixes * (ledger) [\#1040](https://github.com/Finschia/finschia-sdk/pull/1040) Fix a bug(unable to connect nano S plus ledger on ubuntu) diff --git a/testutil/encoding.go b/testutil/encoding.go new file mode 100644 index 0000000000..02b0e1e533 --- /dev/null +++ b/testutil/encoding.go @@ -0,0 +1,19 @@ +package testutil + +import ( + "encoding/json" + "fmt" +) + +func MustJSONMarshal(v any) []byte { + b, err := json.Marshal(v) + if err != nil { + panic(err) + } + + return b +} + +func W(input string) []byte { + return []byte(fmt.Sprintf("\"%s\"", input)) +} diff --git a/testutil/encoding_test.go b/testutil/encoding_test.go new file mode 100644 index 0000000000..d07ef1b6b4 --- /dev/null +++ b/testutil/encoding_test.go @@ -0,0 +1,33 @@ +package testutil_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/Finschia/finschia-sdk/testutil" +) + +func TestMustJSONMarshal(t *testing.T) { + type tc struct { + Name string `json:"myName"` + Order string `json:"myOrder"` + } + + a := tc{ + Name: "test", + Order: "first", + } + b := new(tc) + + marshaled := testutil.MustJSONMarshal(a) + err := json.Unmarshal(marshaled, b) + require.NoError(t, err) + require.Equal(t, a, *b) + require.Panics(t, func() { testutil.MustJSONMarshal(make(chan int)) }) +} + +func TestW(t *testing.T) { + require.Equal(t, []byte(`"test"`), testutil.W("test")) +} diff --git a/x/collection/keeper/keeper_test.go b/x/collection/keeper/keeper_test.go index e7a42c92ed..65b1305e82 100644 --- a/x/collection/keeper/keeper_test.go +++ b/x/collection/keeper/keeper_test.go @@ -2,7 +2,6 @@ package keeper_test import ( "context" - "fmt" "testing" "github.com/stretchr/testify/suite" @@ -18,8 +17,6 @@ import ( type KeeperTestSuite struct { suite.Suite - deterministic bool - ctx sdk.Context goCtx context.Context keeper keeper.Keeper @@ -44,29 +41,21 @@ type KeeperTestSuite struct { } func (s *KeeperTestSuite) createRandomAccounts(accNum int) []sdk.AccAddress { - if s.deterministic { - addresses := make([]sdk.AccAddress, accNum) - for i := range addresses { - addresses[i] = sdk.AccAddress(fmt.Sprintf("address%d", i)) - } - return addresses - } else { - seenAddresses := make(map[string]bool, accNum) - addresses := make([]sdk.AccAddress, accNum) - for i := range addresses { - var address sdk.AccAddress - for { - pk := secp256k1.GenPrivKey().PubKey() - address = sdk.AccAddress(pk.Address()) - if !seenAddresses[address.String()] { - seenAddresses[address.String()] = true - break - } + seenAddresses := make(map[string]bool, accNum) + addresses := make([]sdk.AccAddress, accNum) + for i := range addresses { + var address sdk.AccAddress + for { + pk := secp256k1.GenPrivKey().PubKey() + address = sdk.AccAddress(pk.Address()) + if !seenAddresses[address.String()] { + seenAddresses[address.String()] = true + break } - addresses[i] = address } - return addresses + addresses[i] = address } + return addresses } func (s *KeeperTestSuite) SetupTest() { @@ -188,10 +177,5 @@ func (s *KeeperTestSuite) SetupTest() { } func TestKeeperTestSuite(t *testing.T) { - for _, deterministic := range []bool{ - false, - true, - } { - suite.Run(t, &KeeperTestSuite{deterministic: deterministic}) - } + suite.Run(t, new(KeeperTestSuite)) } diff --git a/x/collection/keeper/msg_server_test.go b/x/collection/keeper/msg_server_test.go index 7be0619d07..e1ce0c2b61 100644 --- a/x/collection/keeper/msg_server_test.go +++ b/x/collection/keeper/msg_server_test.go @@ -1,15 +1,11 @@ package keeper_test import ( - "encoding/json" - "fmt" - "strings" - "testing" - - "github.com/stretchr/testify/assert" abci "github.com/tendermint/tendermint/abci/types" + "github.com/Finschia/finschia-sdk/testutil" sdk "github.com/Finschia/finschia-sdk/types" + "github.com/Finschia/finschia-sdk/types/query" "github.com/Finschia/finschia-sdk/x/collection" "github.com/Finschia/finschia-sdk/x/token/class" ) @@ -31,8 +27,16 @@ func (s *KeeperTestSuite) TestMsgSendFT() { }, ftID: collection.NewFTID(s.ftClassID), expectedEvents: sdk.Events{ - helperBuildEventSent(s.contractID, s.vendor, s.customer, s.vendor, collection.NewCoins(collection.NewFTCoin(s.ftClassID, s.balance))), - }, + sdk.Event{ + Type: "lbm.collection.v1.EventSent", + Attributes: []abci.EventAttribute{ + {Key: []byte("amount"), Value: testutil.MustJSONMarshal(collection.NewCoins(collection.NewFTCoin(s.ftClassID, s.balance))), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.customer.String()), Index: false}, + }, + }}, }, "contract not found": { isNegativeCase: true, @@ -108,7 +112,16 @@ func (s *KeeperTestSuite) TestMsgOperatorSendFT() { }, ftID: collection.NewFTID(s.ftClassID), expectedEvents: sdk.Events{ - helperBuildEventSent(s.contractID, s.customer, s.vendor, s.operator, collection.NewCoins(collection.NewFTCoin(s.ftClassID, s.balance))), + sdk.Event{ + Type: "lbm.collection.v1.EventSent", + Attributes: []abci.EventAttribute{ + {Key: []byte("amount"), Value: testutil.MustJSONMarshal(collection.NewCoins(collection.NewFTCoin(s.ftClassID, s.balance))), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.operator.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.vendor.String()), Index: false}, + }, + }, }, }, "contract not found": { @@ -183,59 +196,10 @@ func (s *KeeperTestSuite) TestMsgOperatorSendFT() { } } -func helperBuildEventSent(contractID string, from, to, operator sdk.AccAddress, amount collection.Coins) sdk.Event { - return sdk.Event{ - Type: "lbm.collection.v1.EventSent", - Attributes: []abci.EventAttribute{ - {Key: []byte("amount"), Value: []byte(asJsonStr(amount)), Index: false}, - {Key: []byte("contract_id"), Value: []byte(wrapQuot(contractID)), Index: false}, - {Key: []byte("from"), Value: []byte(wrapQuot(from.String())), Index: false}, - {Key: []byte("operator"), Value: []byte(wrapQuot(operator.String())), Index: false}, - {Key: []byte("to"), Value: []byte(wrapQuot(to.String())), Index: false}, - }, - } -} - -func TestHelperBuildEventSent(t *testing.T) { - testCases := map[string]struct { - expectedEvent sdk.Event - contractID string - from string - to string - operator string - amount collection.Coins - }{ - "helper function should keep event compatibility": { - expectedEvent: sdk.Event{Type: "lbm.collection.v1.EventSent", Attributes: []abci.EventAttribute{ - {Key: []byte("amount"), Value: []byte(`[{"token_id":"0000000100000000","amount":"1000000"}]`), Index: false}, - {Key: []byte("contract_id"), Value: []byte(`"9be17165"`), Index: false}, - {Key: []byte("from"), Value: []byte(`"link1v9jxgun9wdenqa2xzfx"`), Index: false}, - {Key: []byte("operator"), Value: []byte(`"link1v9jxgun9wdenqa2xzfx"`), Index: false}, - {Key: []byte("to"), Value: []byte(`"link1v9jxgun9wdenyjqyyxu"`), Index: false}, - }}, - contractID: "9be17165", - from: "link1v9jxgun9wdenqa2xzfx", - to: "link1v9jxgun9wdenyjqyyxu", - operator: "link1v9jxgun9wdenqa2xzfx", - amount: collection.NewCoins(collection.NewFTCoin("00000001", sdk.NewInt(1000000))), - }, - } - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - // Act - from, err := sdk.AccAddressFromBech32(tc.from) - assert.NoError(t, err) - to, err := sdk.AccAddressFromBech32(tc.to) - assert.NoError(t, err) - event := helperBuildEventSent(tc.contractID, from, to, from, tc.amount) - - // Assert - assert.Equal(t, tc.expectedEvent, event) - }) - } -} - func (s *KeeperTestSuite) TestMsgSendNFT() { + rootNFTID := collection.NewNFTID(s.nftClassID, 1) + issuedTokenIDs := s.extractChainedNFTIDs(rootNFTID) + testCases := map[string]struct { contractID string tokenID string @@ -244,8 +208,46 @@ func (s *KeeperTestSuite) TestMsgSendNFT() { }{ "valid request": { contractID: s.contractID, - tokenID: collection.NewNFTID(s.nftClassID, 1), - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventOwnerChanged", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventOwnerChanged", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventOwnerChanged", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventSent", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x5b, 0x7b, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x7d, 0x5d}, Index: false}, {Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}}}}, + tokenID: rootNFTID, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventOwnerChanged", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("token_id"), Value: testutil.W(issuedTokenIDs[1]), Index: false}, + }, + }, + sdk.Event{ + Type: "lbm.collection.v1.EventOwnerChanged", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("token_id"), Value: testutil.W(issuedTokenIDs[2]), Index: false}, + }, + }, + sdk.Event{ + Type: "lbm.collection.v1.EventOwnerChanged", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("token_id"), Value: testutil.W(issuedTokenIDs[3]), Index: false}, + }, + }, + sdk.Event{ + Type: "lbm.collection.v1.EventSent", + Attributes: []abci.EventAttribute{ + {Key: []byte("amount"), Value: testutil.MustJSONMarshal(collection.NewCoins(collection.Coin{TokenId: issuedTokenIDs[0], Amount: sdk.OneInt()})), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.vendor.String()), Index: false}, + }, + }, + }, }, "contract not found": { contractID: "deadbeef", @@ -286,16 +288,15 @@ func (s *KeeperTestSuite) TestMsgSendNFT() { } s.Require().NotNil(res) - - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } + s.Require().Equal(tc.events, ctx.EventManager().Events()) }) } } func (s *KeeperTestSuite) TestMsgOperatorSendNFT() { - tokenID := collection.NewNFTID(s.nftClassID, 1) + rootNFTID := collection.NewNFTID(s.nftClassID, 1) + issuedTokenIDs := s.extractChainedNFTIDs(rootNFTID) + testCases := map[string]struct { contractID string operator sdk.AccAddress @@ -308,21 +309,58 @@ func (s *KeeperTestSuite) TestMsgOperatorSendNFT() { contractID: s.contractID, operator: s.operator, from: s.customer, - tokenID: tokenID, - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventOwnerChanged", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventOwnerChanged", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventOwnerChanged", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventSent", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x5b, 0x7b, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x7d, 0x5d}, Index: false}, {Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x77, 0x30, 0x38, 0x70, 0x36, 0x74, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}}}}, - }, + tokenID: rootNFTID, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventOwnerChanged", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("token_id"), Value: testutil.W(issuedTokenIDs[1]), Index: false}, + }, + }, + sdk.Event{ + Type: "lbm.collection.v1.EventOwnerChanged", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("token_id"), Value: testutil.W(issuedTokenIDs[2]), Index: false}, + }, + }, + sdk.Event{ + Type: "lbm.collection.v1.EventOwnerChanged", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("token_id"), Value: testutil.W(issuedTokenIDs[3]), Index: false}, + }, + }, + sdk.Event{ + Type: "lbm.collection.v1.EventSent", + Attributes: []abci.EventAttribute{ + {Key: []byte("amount"), Value: testutil.MustJSONMarshal(collection.NewCoins(collection.Coin{TokenId: issuedTokenIDs[0], Amount: sdk.OneInt()})), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.operator.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.vendor.String()), Index: false}, + }, + }, + }}, "contract not found": { contractID: "deadbeef", operator: s.operator, from: s.customer, - tokenID: tokenID, + tokenID: rootNFTID, err: class.ErrContractNotExist, }, "not approved": { contractID: s.contractID, operator: s.vendor, from: s.customer, - tokenID: tokenID, + tokenID: rootNFTID, err: collection.ErrCollectionNotApproved, }, "not found": { @@ -366,20 +404,16 @@ func (s *KeeperTestSuite) TestMsgOperatorSendNFT() { } s.Require().NotNil(res) - - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } + s.Require().Equal(tc.events, ctx.EventManager().Events()) }) } } func (s *KeeperTestSuite) TestMsgAuthorizeOperator() { - const authorizedOperatorEventType = "lbm.collection.v1.EventAuthorizedOperator" testCases := map[string]struct { isNegativeCase bool req *collection.MsgAuthorizeOperator - expectedEvents sdk.Events + events sdk.Events expectedError error }{ "valid request": { @@ -388,9 +422,14 @@ func (s *KeeperTestSuite) TestMsgAuthorizeOperator() { Holder: s.customer.String(), Operator: s.vendor.String(), }, - expectedEvents: sdk.Events{ - helperBuildEventAuthRelated(authorizedOperatorEventType, s.contractID, s.customer, s.vendor), - }, + events: sdk.Events{sdk.Event{ + Type: "lbm.collection.v1.EventAuthorizedOperator", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("holder"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, + }, + }}, }, "contract not found": { isNegativeCase: true, @@ -431,10 +470,7 @@ func (s *KeeperTestSuite) TestMsgAuthorizeOperator() { } s.Require().NoError(err) s.Require().NotNil(res) - - // Assert - events := ctx.EventManager().Events() - s.Require().Equal(tc.expectedEvents, events) + s.Require().Equal(tc.events, ctx.EventManager().Events()) curAuth, err := s.keeper.GetAuthorization(ctx, tc.req.ContractId, holder, operator) s.Require().NoError(err) s.Require().Nil(prevAuth) @@ -445,11 +481,10 @@ func (s *KeeperTestSuite) TestMsgAuthorizeOperator() { } func (s *KeeperTestSuite) TestMsgRevokeOperator() { - const revokedOperatorEventType = "lbm.collection.v1.EventRevokedOperator" testCases := map[string]struct { isNegativeCase bool req *collection.MsgRevokeOperator - expectedEvents sdk.Events + events sdk.Events expectedError error }{ "valid request": { @@ -458,9 +493,14 @@ func (s *KeeperTestSuite) TestMsgRevokeOperator() { Holder: s.customer.String(), Operator: s.operator.String(), }, - expectedEvents: sdk.Events{ - helperBuildEventAuthRelated(revokedOperatorEventType, s.contractID, s.customer, s.operator), - }, + events: sdk.Events{sdk.Event{ + Type: "lbm.collection.v1.EventRevokedOperator", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("holder"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.operator.String()), Index: false}, + }, + }}, }, "contract not found": { isNegativeCase: true, @@ -502,9 +542,7 @@ func (s *KeeperTestSuite) TestMsgRevokeOperator() { s.Require().NoError(err) s.Require().NotNil(res) - // Assert - events := ctx.EventManager().Events() - s.Require().Equal(tc.expectedEvents, events) + s.Require().Equal(tc.events, ctx.EventManager().Events()) s.Require().NotNil(prevAuth) s.Require().Equal(tc.req.Holder, prevAuth.Holder) s.Require().Equal(tc.req.Operator, prevAuth.Operator) @@ -515,70 +553,59 @@ func (s *KeeperTestSuite) TestMsgRevokeOperator() { } } -func helperBuildEventAuthRelated(evtType, contractID string, holder, operator sdk.AccAddress) sdk.Event { - return sdk.Event{ - Type: evtType, - Attributes: []abci.EventAttribute{ - {Key: []byte("contract_id"), Value: []byte(wrapQuot(contractID)), Index: false}, - {Key: []byte("holder"), Value: []byte(wrapQuot(holder.String())), Index: false}, - {Key: []byte("operator"), Value: []byte(wrapQuot(operator.String())), Index: false}, - }, - } -} - -func TestHelperBuildAuthRelatedEvent(t *testing.T) { - testCases := map[string]struct { - expectedEvent sdk.Event - contractID string - holder string - operator string - }{ - "helper function should keep event compatibility for approve": { - expectedEvent: sdk.Event{Type: "lbm.collection.v1.EventSent", Attributes: []abci.EventAttribute{ - {Key: []byte("contract_id"), Value: []byte(`"9be17165"`), Index: false}, - {Key: []byte("holder"), Value: []byte(`"link1v9jxgun9wdenyjqyyxu"`), Index: false}, - {Key: []byte("operator"), Value: []byte(`"link1v9jxgun9wdenqa2xzfx"`), Index: false}, - }}, - contractID: "9be17165", - holder: "link1v9jxgun9wdenyjqyyxu", - operator: "link1v9jxgun9wdenqa2xzfx", - }, - "helper function should keep event compatibility for revoke": { - expectedEvent: sdk.Event{Type: "lbm.collection.v1.EventSent", Attributes: []abci.EventAttribute{ - {Key: []byte("contract_id"), Value: []byte(`"9be17165"`), Index: false}, - {Key: []byte("holder"), Value: []byte(`"link1v9jxgun9wdenyjqyyxu"`), Index: false}, - {Key: []byte("operator"), Value: []byte(`"link1v9jxgun9wdenzw08p6t"`), Index: false}, - }}, - contractID: "9be17165", - holder: "link1v9jxgun9wdenyjqyyxu", - operator: "link1v9jxgun9wdenzw08p6t", - }, - } - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - // Act - holder, err := sdk.AccAddressFromBech32(tc.holder) - assert.NoError(t, err) - operator, err := sdk.AccAddressFromBech32(tc.operator) - assert.NoError(t, err) - event := helperBuildEventAuthRelated(tc.expectedEvent.Type, tc.contractID, holder, operator) - - // Assert - assert.Equal(t, tc.expectedEvent, event) - }) - } -} - func (s *KeeperTestSuite) TestMsgCreateContract() { + expectedNewContractID := "3336b76f" testCases := map[string]struct { owner sdk.AccAddress err error events sdk.Events }{ "valid request": { - owner: s.vendor, - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventCreatedContract", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x33, 0x33, 0x33, 0x36, 0x62, 0x37, 0x36, 0x66, 0x22}, Index: false}, {Key: []uint8{0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x6d, 0x65, 0x74, 0x61}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x6e, 0x61, 0x6d, 0x65}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x75, 0x72, 0x69}, Value: []uint8{0x22, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventGranted", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x33, 0x33, 0x33, 0x36, 0x62, 0x37, 0x36, 0x66, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x72}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e}, Value: []uint8{0x22, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventGranted", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x33, 0x33, 0x33, 0x36, 0x62, 0x37, 0x36, 0x66, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x72}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e}, Value: []uint8{0x22, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x59, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventGranted", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x33, 0x33, 0x33, 0x36, 0x62, 0x37, 0x36, 0x66, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x72}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e}, Value: []uint8{0x22, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x49, 0x4e, 0x54, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventGranted", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x33, 0x33, 0x33, 0x36, 0x62, 0x37, 0x36, 0x66, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x72}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e}, Value: []uint8{0x22, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x52, 0x4e, 0x22}, Index: false}}}}, - }, + owner: s.vendor, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventCreatedContract", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(expectedNewContractID), Index: false}, + {Key: []byte("creator"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("meta"), Value: testutil.W(""), Index: false}, + {Key: []byte("name"), Value: testutil.W(""), Index: false}, + {Key: []byte("uri"), Value: testutil.W(""), Index: false}, + }, + }, + sdk.Event{ + Type: "lbm.collection.v1.EventGranted", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(expectedNewContractID), Index: false}, + {Key: []byte("grantee"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("granter"), Value: testutil.W(""), Index: false}, + {Key: []byte("permission"), Value: testutil.W(collection.Permission(collection.LegacyPermissionIssue).String()), Index: false}, + }}, + sdk.Event{ + Type: "lbm.collection.v1.EventGranted", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(expectedNewContractID), Index: false}, + {Key: []byte("grantee"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("granter"), Value: testutil.W(""), Index: false}, + {Key: []byte("permission"), Value: testutil.W(collection.Permission(collection.LegacyPermissionModify).String()), Index: false}, + }}, + sdk.Event{ + Type: "lbm.collection.v1.EventGranted", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(expectedNewContractID), Index: false}, + {Key: []byte("grantee"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("granter"), Value: testutil.W(""), Index: false}, + {Key: []byte("permission"), Value: testutil.W(collection.Permission(collection.LegacyPermissionMint).String()), Index: false}, + }}, + sdk.Event{ + Type: "lbm.collection.v1.EventGranted", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(expectedNewContractID), Index: false}, + {Key: []byte("grantee"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("granter"), Value: testutil.W(""), Index: false}, + {Key: []byte("permission"), Value: testutil.W(collection.Permission(collection.LegacyPermissionBurn).String()), Index: false}, + }}, + }}, } for name, tc := range testCases { @@ -589,21 +616,23 @@ func (s *KeeperTestSuite) TestMsgCreateContract() { Owner: tc.owner.String(), } res, err := s.msgServer.CreateContract(sdk.WrapSDKContext(ctx), req) + s.Require().Equal(expectedNewContractID, res.ContractId) s.Require().ErrorIs(err, tc.err) if tc.err != nil { return } s.Require().NotNil(res) + s.Require().Equal(tc.events, ctx.EventManager().Events()) - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } }) } } func (s *KeeperTestSuite) TestMsgIssueFT() { + expectedClassID := "00000002" + expectedTokenID := collection.NewFTID(expectedClassID) + testCases := map[string]struct { contractID string owner sdk.AccAddress @@ -619,13 +648,13 @@ func (s *KeeperTestSuite) TestMsgIssueFT() { sdk.Event{ Type: "lbm.collection.v1.EventCreatedFTClass", Attributes: []abci.EventAttribute{ - {Key: []uint8("contract_id"), Value: []uint8("\"9be17165\""), Index: false}, - {Key: []uint8("decimals"), Value: []uint8("0"), Index: false}, - {Key: []uint8("meta"), Value: []uint8("\"\""), Index: false}, - {Key: []uint8("mintable"), Value: []uint8("false"), Index: false}, - {Key: []uint8("name"), Value: []uint8("\"\""), Index: false}, - {Key: []uint8("operator"), Value: []uint8(fmt.Sprintf("\"%s\"", s.vendor)), Index: false}, - {Key: []uint8("token_id"), Value: []uint8("\"0000000200000000\""), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("decimals"), Value: []byte("0"), Index: false}, + {Key: []byte("meta"), Value: testutil.W(""), Index: false}, + {Key: []byte("mintable"), Value: []byte("false"), Index: false}, + {Key: []byte("name"), Value: testutil.W(""), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("token_id"), Value: testutil.W(expectedTokenID), Index: false}, }, }, }, @@ -638,22 +667,22 @@ func (s *KeeperTestSuite) TestMsgIssueFT() { sdk.Event{ Type: "lbm.collection.v1.EventCreatedFTClass", Attributes: []abci.EventAttribute{ - {Key: []uint8("contract_id"), Value: []uint8("\"9be17165\""), Index: false}, - {Key: []uint8("decimals"), Value: []uint8("0"), Index: false}, - {Key: []uint8("meta"), Value: []uint8("\"\""), Index: false}, - {Key: []uint8("mintable"), Value: []uint8("false"), Index: false}, - {Key: []uint8("name"), Value: []uint8("\"\""), Index: false}, - {Key: []uint8("operator"), Value: []uint8(fmt.Sprintf("\"%s\"", s.vendor)), Index: false}, - {Key: []uint8("token_id"), Value: []uint8("\"0000000200000000\""), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("decimals"), Value: []byte("0"), Index: false}, + {Key: []byte("meta"), Value: testutil.W(""), Index: false}, + {Key: []byte("mintable"), Value: []byte("false"), Index: false}, + {Key: []byte("name"), Value: testutil.W(""), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("token_id"), Value: testutil.W(expectedTokenID), Index: false}, }, }, sdk.Event{ Type: "lbm.collection.v1.EventMintedFT", Attributes: []abci.EventAttribute{ - {Key: []uint8("amount"), Value: []uint8("[{\"token_id\":\"0000000200000000\",\"amount\":\"1\"}]"), Index: false}, - {Key: []uint8("contract_id"), Value: []uint8("\"9be17165\""), Index: false}, - {Key: []uint8("operator"), Value: []uint8(fmt.Sprintf("\"%s\"", s.vendor)), Index: false}, - {Key: []uint8("to"), Value: []uint8(fmt.Sprintf("\"%s\"", s.customer)), Index: false}, + {Key: []byte("amount"), Value: testutil.MustJSONMarshal(collection.NewCoins(collection.Coin{TokenId: expectedTokenID, Amount: sdk.OneInt()})), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.customer.String()), Index: false}, }, }, }, @@ -709,6 +738,8 @@ func (s *KeeperTestSuite) TestMsgIssueFT() { } func (s *KeeperTestSuite) TestMsgIssueNFT() { + expectedTokenType := "10000002" + testCases := map[string]struct { contractID string owner sdk.AccAddress @@ -718,7 +749,33 @@ func (s *KeeperTestSuite) TestMsgIssueNFT() { "valid request": { contractID: s.contractID, owner: s.vendor, - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventCreatedNFTClass", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x6d, 0x65, 0x74, 0x61}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x6e, 0x61, 0x6d, 0x65}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventGranted", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x72}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e}, Value: []uint8{0x22, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x49, 0x4e, 0x54, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventGranted", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x72}, Value: []uint8{0x22, 0x22}, Index: false}, {Key: []uint8{0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e}, Value: []uint8{0x22, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x52, 0x4e, 0x22}, Index: false}}}}, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventCreatedNFTClass", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("meta"), Value: testutil.W(""), Index: false}, + {Key: []byte("name"), Value: testutil.W(""), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("token_type"), Value: testutil.W(expectedTokenType), Index: false}, + }}, + sdk.Event{ + Type: "lbm.collection.v1.EventGranted", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("grantee"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("granter"), Value: testutil.W(""), Index: false}, + {Key: []byte("permission"), Value: testutil.W(collection.Permission(collection.LegacyPermissionMint).String()), Index: false}, + }}, + sdk.Event{ + Type: "lbm.collection.v1.EventGranted", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("grantee"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("granter"), Value: testutil.W(""), Index: false}, + {Key: []byte("permission"), Value: testutil.W(collection.Permission(collection.LegacyPermissionBurn).String()), Index: false}, + }}, + }, }, "contract not found": { contractID: "deadbeef", @@ -747,10 +804,8 @@ func (s *KeeperTestSuite) TestMsgIssueNFT() { } s.Require().NotNil(res) + s.Require().Equal(tc.events, ctx.EventManager().Events()) - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } }) } } @@ -774,6 +829,10 @@ func (s *KeeperTestSuite) TestMsgMintFT() { amount := collection.NewCoins( collection.NewFTCoin(s.ftClassID, sdk.NewInt(100000)), ) + amounts := collection.NewCoins( + collection.NewFTCoin(s.ftClassID, sdk.NewInt(100000)), + collection.NewFTCoin(*mintableFTClassID, sdk.NewInt(200000)), + ) testCases := map[string]struct { contractID string @@ -782,7 +841,7 @@ func (s *KeeperTestSuite) TestMsgMintFT() { err error events sdk.Events }{ - "valid request": { + "valid request - single token": { contractID: s.contractID, from: s.vendor, amount: amount, @@ -790,10 +849,41 @@ func (s *KeeperTestSuite) TestMsgMintFT() { sdk.Event{ Type: "lbm.collection.v1.EventMintedFT", Attributes: []abci.EventAttribute{ - {Key: []uint8("amount"), Value: []uint8("[{\"token_id\":\"0000000100000000\",\"amount\":\"100000\"}]"), Index: false}, - {Key: []uint8("contract_id"), Value: []uint8("\"9be17165\""), Index: false}, - {Key: []uint8("operator"), Value: []uint8(fmt.Sprintf("\"%s\"", s.vendor)), Index: false}, - {Key: []uint8("to"), Value: []uint8(fmt.Sprintf("\"%s\"", s.customer)), Index: false}, + {Key: []byte("amount"), Value: testutil.MustJSONMarshal(amount), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.customer.String()), Index: false}, + }, + }, + }, + }, + "valid request - multi tokens": { + contractID: s.contractID, + from: s.vendor, + amount: amounts, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventMintedFT", + Attributes: []abci.EventAttribute{ + {Key: []byte("amount"), Value: testutil.MustJSONMarshal(amounts), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.customer.String()), Index: false}, + }, + }, + }, + }, + "valid request - empty amount": { + contractID: s.contractID, + from: s.vendor, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventMintedFT", + Attributes: []abci.EventAttribute{ + {Key: []byte("amount"), Value: []byte("[]"), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.customer.String()), Index: false}, }, }, }, @@ -818,21 +908,6 @@ func (s *KeeperTestSuite) TestMsgMintFT() { ), err: collection.ErrTokenNotExist, }, - "valid request - empty amount": { - contractID: s.contractID, - from: s.vendor, - events: sdk.Events{ - sdk.Event{ - Type: "lbm.collection.v1.EventMintedFT", - Attributes: []abci.EventAttribute{ - {Key: []uint8("amount"), Value: []uint8("[]"), Index: false}, - {Key: []uint8("contract_id"), Value: []uint8("\"9be17165\""), Index: false}, - {Key: []uint8("operator"), Value: []uint8(fmt.Sprintf("\"%s\"", s.vendor)), Index: false}, - {Key: []uint8("to"), Value: []uint8(fmt.Sprintf("\"%s\"", s.customer)), Index: false}, - }, - }, - }, - }, "include invalid tokenId among 2 tokens": { contractID: s.contractID, from: s.vendor, @@ -857,25 +932,6 @@ func (s *KeeperTestSuite) TestMsgMintFT() { ), err: collection.ErrTokenNotMintable, }, - "valid request - multi tokens": { - contractID: s.contractID, - from: s.vendor, - amount: collection.NewCoins( - collection.NewFTCoin(s.ftClassID, sdk.NewInt(100000)), - collection.NewFTCoin(*mintableFTClassID, sdk.NewInt(200000)), - ), - events: sdk.Events{ - sdk.Event{ - Type: "lbm.collection.v1.EventMintedFT", - Attributes: []abci.EventAttribute{ - {Key: []uint8("amount"), Value: []uint8("[{\"token_id\":\"0000000100000000\",\"amount\":\"100000\"},{\"token_id\":\"0000000200000000\",\"amount\":\"200000\"}]"), Index: false}, - {Key: []uint8("contract_id"), Value: []uint8("\"9be17165\""), Index: false}, - {Key: []uint8("operator"), Value: []uint8(fmt.Sprintf("\"%s\"", s.vendor)), Index: false}, - {Key: []uint8("to"), Value: []uint8(fmt.Sprintf("\"%s\"", s.customer)), Index: false}, - }, - }, - }, - }, } // query the values to be effected by MintFT @@ -956,7 +1012,17 @@ func (s *KeeperTestSuite) TestMsgMintFT() { func (s *KeeperTestSuite) TestMsgMintNFT() { params := []collection.MintNFTParam{{ TokenType: s.nftClassID, + Name: "tester", + Meta: "Mint NFT", }} + expectedTokens := []collection.NFT{ + { + TokenId: "1000000100000016", + Name: params[0].Name, + Meta: params[0].Meta, + }, + } + testCases := map[string]struct { contractID string from sdk.AccAddress @@ -968,8 +1034,17 @@ func (s *KeeperTestSuite) TestMsgMintNFT() { contractID: s.contractID, from: s.vendor, params: params, - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventMintedNFT", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73}, Value: []uint8{0x5b, 0x7b, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x36, 0x22, 0x2c, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x7d, 0x5d}, Index: false}}}}, - }, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventMintedNFT", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("to"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("tokens"), Value: testutil.MustJSONMarshal(expectedTokens), Index: false}, + }, + }, + }}, "contract not found": { contractID: "deadbeef", from: s.vendor, @@ -1009,18 +1084,15 @@ func (s *KeeperTestSuite) TestMsgMintNFT() { } s.Require().NotNil(res) - - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } + s.Require().Equal(tc.events, ctx.EventManager().Events()) }) } } func (s *KeeperTestSuite) TestMsgBurnFT() { // prepare mutli token burn test - amount := collection.NewCoins( - collection.NewFTCoin(s.ftClassID, s.balance), + singleAmount := collection.NewCoins( + collection.NewFTCoin(s.ftClassID, sdk.NewInt(50000)), ) // create a fungible token class @@ -1029,6 +1101,11 @@ func (s *KeeperTestSuite) TestMsgBurnFT() { Mintable: true, }) s.Require().NoError(err) + multiAmounts := collection.NewCoins( + collection.NewFTCoin(s.ftClassID, sdk.NewInt(50000)), + collection.NewFTCoin(*mintableFTClassID, sdk.NewInt(60000)), + ) + // mintft mintedCoin := collection.NewFTCoin(*mintableFTClassID, sdk.NewInt(1000000)) err = s.keeper.MintFT(s.ctx, s.contractID, s.vendor, []collection.Coin{mintedCoin}) @@ -1044,75 +1121,72 @@ func (s *KeeperTestSuite) TestMsgBurnFT() { "valid request": { contractID: s.contractID, from: s.vendor, - amount: collection.NewCoins( - collection.NewFTCoin(s.ftClassID, sdk.NewInt(50000)), - ), + amount: singleAmount, events: sdk.Events{ sdk.Event{ Type: "lbm.collection.v1.EventBurned", Attributes: []abci.EventAttribute{ - {Key: []uint8("amount"), Value: []uint8("[{\"token_id\":\"0000000100000000\",\"amount\":\"50000\"}]"), Index: false}, - {Key: []uint8("contract_id"), Value: []uint8("\"9be17165\""), Index: false}, - {Key: []uint8("from"), Value: []uint8(fmt.Sprintf("\"%s\"", s.vendor)), Index: false}, - {Key: []uint8("operator"), Value: []uint8(fmt.Sprintf("\"%s\"", s.vendor)), Index: false}, + {Key: []byte("amount"), Value: testutil.MustJSONMarshal(collection.NewCoins( + collection.NewFTCoin(s.ftClassID, sdk.NewInt(50000)), + )), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, }, }, }, }, - "contract not found": { - contractID: "deadbeef", - from: s.vendor, - amount: amount, - err: class.ErrContractNotExist, - }, - "no permission": { - contractID: s.contractID, - from: s.customer, - amount: amount, - err: collection.ErrTokenNoPermission, - }, - "insufficient funds": { - contractID: s.contractID, - from: s.vendor, - amount: collection.NewCoins( - collection.NewFTCoin("00bab10c", sdk.OneInt()), - ), - err: collection.ErrInsufficientToken, - }, - "no amount - valid": { + "valid multi amount burn": { contractID: s.contractID, from: s.vendor, + amount: multiAmounts, events: sdk.Events{ sdk.Event{ Type: "lbm.collection.v1.EventBurned", Attributes: []abci.EventAttribute{ - {Key: []uint8("amount"), Value: []uint8("[]"), Index: false}, - {Key: []uint8("contract_id"), Value: []uint8("\"9be17165\""), Index: false}, - {Key: []uint8("from"), Value: []uint8(fmt.Sprintf("\"%s\"", s.vendor)), Index: false}, - {Key: []uint8("operator"), Value: []uint8(fmt.Sprintf("\"%s\"", s.vendor)), Index: false}, + {Key: []byte("amount"), Value: testutil.MustJSONMarshal(multiAmounts), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, }, }, }, }, - "valid multi amount burn": { + "no amount - valid": { contractID: s.contractID, from: s.vendor, - amount: collection.NewCoins( - collection.NewFTCoin(s.ftClassID, sdk.NewInt(50000)), - collection.NewFTCoin(*mintableFTClassID, sdk.NewInt(60000)), - ), events: sdk.Events{ sdk.Event{ Type: "lbm.collection.v1.EventBurned", Attributes: []abci.EventAttribute{ - {Key: []uint8("amount"), Value: []uint8("[{\"token_id\":\"0000000100000000\",\"amount\":\"50000\"},{\"token_id\":\"0000000200000000\",\"amount\":\"60000\"}]"), Index: false}, - {Key: []uint8("contract_id"), Value: []uint8("\"9be17165\""), Index: false}, - {Key: []uint8("from"), Value: []uint8(fmt.Sprintf("\"%s\"", s.vendor)), Index: false}, - {Key: []uint8("operator"), Value: []uint8(fmt.Sprintf("\"%s\"", s.vendor)), Index: false}, + {Key: []byte("amount"), Value: []byte("[]"), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, }, }, }, }, + "contract not found": { + contractID: "deadbeef", + from: s.vendor, + amount: singleAmount, + err: class.ErrContractNotExist, + }, + "no permission": { + contractID: s.contractID, + from: s.customer, + amount: singleAmount, + err: collection.ErrTokenNoPermission, + }, + "insufficient funds": { + contractID: s.contractID, + from: s.vendor, + amount: collection.NewCoins( + collection.NewFTCoin("00bab10c", sdk.OneInt()), + ), + err: collection.ErrInsufficientToken, + }, "include insufficient funds amount 2 amounts": { contractID: s.contractID, from: s.vendor, @@ -1196,9 +1270,10 @@ func (s *KeeperTestSuite) TestMsgBurnFT() { } func (s *KeeperTestSuite) TestMsgOperatorBurnFT() { - amount := collection.NewCoins( + singleAmount := collection.NewCoins( collection.NewFTCoin(s.ftClassID, s.balance), ) + testCases := map[string]struct { contractID string operator sdk.AccAddress @@ -1211,31 +1286,48 @@ func (s *KeeperTestSuite) TestMsgOperatorBurnFT() { contractID: s.contractID, operator: s.operator, from: s.customer, - amount: amount, - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventBurned", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x5b, 0x7b, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x7d, 0x5d}, Index: false}, {Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x77, 0x30, 0x38, 0x70, 0x36, 0x74, 0x22}, Index: false}}}}, + amount: singleAmount, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventBurned", + Attributes: []abci.EventAttribute{ + {Key: []byte("amount"), Value: testutil.MustJSONMarshal(singleAmount), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.operator.String()), Index: false}, + }}}, }, "contract not found": { contractID: "deadbeef", operator: s.operator, from: s.customer, - amount: amount, + amount: singleAmount, err: class.ErrContractNotExist, }, "no authorization": { contractID: s.contractID, operator: s.vendor, from: s.customer, - amount: amount, + amount: singleAmount, err: collection.ErrCollectionNotApproved, }, "no permission": { contractID: s.contractID, operator: s.stranger, from: s.customer, - amount: amount, + amount: singleAmount, err: collection.ErrTokenNoPermission, }, - "insufficient funds": { + "insufficient funds - exist token": { + contractID: s.contractID, + operator: s.operator, + from: s.customer, + amount: collection.NewCoins( + collection.NewFTCoin(s.ftClassID, s.balance.Add(sdk.OneInt())), + ), + err: collection.ErrInsufficientToken, + }, + "insufficient funds - non-exist token": { contractID: s.contractID, operator: s.operator, from: s.customer, @@ -1263,18 +1355,19 @@ func (s *KeeperTestSuite) TestMsgOperatorBurnFT() { } s.Require().NotNil(res) - - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } + s.Require().Equal(tc.events, ctx.EventManager().Events()) }) } } func (s *KeeperTestSuite) TestMsgBurnNFT() { - tokenIDs := []string{ - collection.NewNFTID(s.nftClassID, s.numNFTs*2+1), + rootNFTID := collection.NewNFTID(s.nftClassID, s.numNFTs*2+1) + issuedTokenIDs := s.extractChainedNFTIDs(rootNFTID) + coins := make([]collection.Coin, 0) + for _, id := range issuedTokenIDs { + coins = append(coins, collection.NewCoin(id, sdk.NewInt(1))) } + testCases := map[string]struct { contractID string from sdk.AccAddress @@ -1285,19 +1378,27 @@ func (s *KeeperTestSuite) TestMsgBurnNFT() { "valid request": { contractID: s.contractID, from: s.vendor, - tokenIDs: tokenIDs, - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventBurned", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x5b, 0x7b, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x66, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x32, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x7d, 0x5d}, Index: false}, {Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}}}}, + tokenIDs: []string{rootNFTID}, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventBurned", + Attributes: []abci.EventAttribute{ + {Key: []byte("amount"), Value: testutil.MustJSONMarshal(coins), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, + }}}, }, "contract not found": { contractID: "deadbeef", from: s.vendor, - tokenIDs: tokenIDs, + tokenIDs: []string{rootNFTID}, err: class.ErrContractNotExist, }, "no permission": { contractID: s.contractID, from: s.customer, - tokenIDs: tokenIDs, + tokenIDs: []string{rootNFTID}, err: collection.ErrTokenNoPermission, }, "not found": { @@ -1342,18 +1443,19 @@ func (s *KeeperTestSuite) TestMsgBurnNFT() { } s.Require().NotNil(res) - - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } + s.Require().Equal(tc.events, ctx.EventManager().Events()) }) } } func (s *KeeperTestSuite) TestMsgOperatorBurnNFT() { - tokenIDs := []string{ - collection.NewNFTID(s.nftClassID, 1), + rootNFTID := collection.NewNFTID(s.nftClassID, 1) + issuedTokenIDs := s.extractChainedNFTIDs(rootNFTID) + coins := make([]collection.Coin, 0) + for _, id := range issuedTokenIDs { + coins = append(coins, collection.NewCoin(id, sdk.NewInt(1))) } + testCases := map[string]struct { contractID string operator sdk.AccAddress @@ -1366,28 +1468,36 @@ func (s *KeeperTestSuite) TestMsgOperatorBurnNFT() { contractID: s.contractID, operator: s.operator, from: s.customer, - tokenIDs: tokenIDs, - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventBurned", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74}, Value: []uint8{0x5b, 0x7b, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x22, 0x2c, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x7d, 0x5d}, Index: false}, {Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x77, 0x30, 0x38, 0x70, 0x36, 0x74, 0x22}, Index: false}}}}, + tokenIDs: []string{rootNFTID}, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventBurned", + Attributes: []abci.EventAttribute{ + {Key: []byte("amount"), Value: testutil.MustJSONMarshal(coins), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.operator.String()), Index: false}, + }}}, }, "contract not found": { contractID: "deadbeef", operator: s.operator, from: s.customer, - tokenIDs: tokenIDs, + tokenIDs: []string{rootNFTID}, err: class.ErrContractNotExist, }, "no authorization": { contractID: s.contractID, operator: s.vendor, from: s.customer, - tokenIDs: tokenIDs, + tokenIDs: []string{rootNFTID}, err: collection.ErrCollectionNotApproved, }, "no permission": { contractID: s.contractID, operator: s.stranger, from: s.customer, - tokenIDs: tokenIDs, + tokenIDs: []string{rootNFTID}, err: collection.ErrTokenNoPermission, }, "not found": { @@ -1436,16 +1546,19 @@ func (s *KeeperTestSuite) TestMsgOperatorBurnNFT() { } s.Require().NotNil(res) + s.Require().Equal(tc.events, ctx.EventManager().Events()) - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } }) } } func (s *KeeperTestSuite) TestMsgModify() { - tokenIndex := collection.NewNFTID(s.nftClassID, 1)[8:] + expectedTokenIndex := collection.NewNFTID(s.nftClassID, 1)[8:] + changes := []collection.Attribute{{ + Key: collection.AttributeKeyName.String(), + Value: "test", + }} + testCases := map[string]struct { contractID string operator sdk.AccAddress @@ -1457,8 +1570,14 @@ func (s *KeeperTestSuite) TestMsgModify() { "valid request": { contractID: s.contractID, operator: s.vendor, - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventModifiedContract", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73}, Value: []uint8{0x5b, 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x22, 0x3a, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2c, 0x22, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3a, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x7d, 0x5d}, Index: false}, {Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}}}}, - }, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventModifiedContract", + Attributes: []abci.EventAttribute{ + {Key: []byte("changes"), Value: testutil.MustJSONMarshal(changes), Index: false}, + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.vendor.String()), Index: false}, + }}}}, "contract not found": { contractID: "deadbeef", operator: s.vendor, @@ -1468,7 +1587,7 @@ func (s *KeeperTestSuite) TestMsgModify() { contractID: s.contractID, operator: s.customer, tokenType: s.nftClassID, - tokenIndex: tokenIndex, + tokenIndex: expectedTokenIndex, err: collection.ErrTokenNoPermission, }, "nft not found": { @@ -1496,11 +1615,6 @@ func (s *KeeperTestSuite) TestMsgModify() { for name, tc := range testCases { s.Run(name, func() { ctx, _ := s.ctx.CacheContext() - - changes := []collection.Attribute{{ - Key: collection.AttributeKeyName.String(), - Value: "test", - }} req := &collection.MsgModify{ ContractId: tc.contractID, Owner: tc.operator.String(), @@ -1515,10 +1629,7 @@ func (s *KeeperTestSuite) TestMsgModify() { } s.Require().NotNil(res) - - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } + s.Require().Equal(tc.events, ctx.EventManager().Events()) }) } } @@ -1537,7 +1648,16 @@ func (s *KeeperTestSuite) TestMsgGrantPermission() { granter: s.vendor, grantee: s.operator, permission: collection.LegacyPermissionModify.String(), - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventGranted", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x77, 0x30, 0x38, 0x70, 0x36, 0x74, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x71, 0x61, 0x32, 0x78, 0x7a, 0x66, 0x78, 0x22}, Index: false}, {Key: []uint8{0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e}, Value: []uint8{0x22, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x59, 0x22}, Index: false}}}}, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventGranted", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("grantee"), Value: testutil.W(s.operator.String()), Index: false}, + {Key: []byte("granter"), Value: testutil.W(s.vendor.String()), Index: false}, + {Key: []byte("permission"), Value: testutil.W(collection.Permission(collection.LegacyPermissionModify).String()), Index: false}, + }}, + }, }, "contract not found": { contractID: "deadbeef", @@ -1572,10 +1692,7 @@ func (s *KeeperTestSuite) TestMsgGrantPermission() { } s.Require().NotNil(res) - - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } + s.Require().Equal(tc.events, ctx.EventManager().Events()) }) } } @@ -1592,7 +1709,15 @@ func (s *KeeperTestSuite) TestMsgRevokePermission() { contractID: s.contractID, from: s.operator, permission: collection.LegacyPermissionMint.String(), - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventRenounced", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x77, 0x30, 0x38, 0x70, 0x36, 0x74, 0x22}, Index: false}, {Key: []uint8{0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e}, Value: []uint8{0x22, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x49, 0x4e, 0x54, 0x22}, Index: false}}}}, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventRenounced", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("grantee"), Value: testutil.W(s.operator.String()), Index: false}, + {Key: []byte("permission"), Value: testutil.W(collection.Permission(collection.LegacyPermissionMint).String()), Index: false}, + }}, + }, }, "contract not found": { contractID: "deadbeef", @@ -1624,10 +1749,7 @@ func (s *KeeperTestSuite) TestMsgRevokePermission() { } s.Require().NotNil(res) - - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } + s.Require().Equal(tc.events, ctx.EventManager().Events()) }) } } @@ -1644,7 +1766,17 @@ func (s *KeeperTestSuite) TestMsgAttach() { contractID: s.contractID, subjectID: collection.NewNFTID(s.nftClassID, s.depthLimit+1), targetID: collection.NewNFTID(s.nftClassID, 1), - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventAttached", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x35, 0x22}, Index: false}, {Key: []uint8{0x74, 0x61, 0x72, 0x67, 0x65, 0x74}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x22}, Index: false}}}}, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventAttached", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("holder"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("subject"), Value: testutil.W(collection.NewNFTID(s.nftClassID, s.depthLimit+1)), Index: false}, + {Key: []byte("target"), Value: testutil.W(collection.NewNFTID(s.nftClassID, 1)), Index: false}, + }}, + }, }, "contract not found": { contractID: "deadbeef", @@ -1677,15 +1809,17 @@ func (s *KeeperTestSuite) TestMsgAttach() { } s.Require().NotNil(res) - - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } + s.Require().Equal(tc.events, ctx.EventManager().Events()) }) } } func (s *KeeperTestSuite) TestMsgDetach() { + issuedNfts := make([]string, s.depthLimit) + for i := 1; i <= s.depthLimit; i++ { + issuedNfts[i-1] = collection.NewNFTID(s.nftClassID, i) + } + testCases := map[string]struct { contractID string subjectID string @@ -1694,8 +1828,34 @@ func (s *KeeperTestSuite) TestMsgDetach() { }{ "valid request": { contractID: s.contractID, - subjectID: collection.NewNFTID(s.nftClassID, 2), - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventDetached", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x22}, Index: false}, {Key: []uint8{0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventRootChanged", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventRootChanged", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x22}, Index: false}}}}, + subjectID: issuedNfts[1], + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventDetached", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("holder"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("previous_parent"), Value: testutil.W(issuedNfts[0]), Index: false}, + {Key: []byte("subject"), Value: testutil.W(issuedNfts[1]), Index: false}, + }}, + sdk.Event{ + Type: "lbm.collection.v1.EventRootChanged", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(issuedNfts[0]), Index: false}, + {Key: []byte("to"), Value: testutil.W(issuedNfts[1]), Index: false}, + {Key: []byte("token_id"), Value: testutil.W(issuedNfts[2]), Index: false}, + }}, + sdk.Event{ + Type: "lbm.collection.v1.EventRootChanged", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(issuedNfts[0]), Index: false}, + {Key: []byte("to"), Value: testutil.W(issuedNfts[1]), Index: false}, + {Key: []byte("token_id"), Value: testutil.W(issuedNfts[3]), Index: false}, + }}, + }, }, "contract not found": { contractID: "deadbeef", @@ -1730,10 +1890,8 @@ func (s *KeeperTestSuite) TestMsgDetach() { } s.Require().NotNil(res) + s.Require().Equal(tc.events, ctx.EventManager().Events()) - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } }) } } @@ -1752,8 +1910,17 @@ func (s *KeeperTestSuite) TestMsgOperatorAttach() { operator: s.operator, subjectID: collection.NewNFTID(s.nftClassID, s.depthLimit+1), targetID: collection.NewNFTID(s.nftClassID, 1), - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventAttached", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x77, 0x30, 0x38, 0x70, 0x36, 0x74, 0x22}, Index: false}, {Key: []uint8{0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x35, 0x22}, Index: false}, {Key: []uint8{0x74, 0x61, 0x72, 0x67, 0x65, 0x74}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x22}, Index: false}}}}, - }, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventAttached", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("holder"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.operator.String()), Index: false}, + {Key: []byte("subject"), Value: testutil.W(collection.NewNFTID(s.nftClassID, s.depthLimit+1)), Index: false}, + {Key: []byte("target"), Value: testutil.W(collection.NewNFTID(s.nftClassID, 1)), Index: false}, + }}, + }}, "contract not found": { contractID: "deadbeef", operator: s.operator, @@ -1795,15 +1962,17 @@ func (s *KeeperTestSuite) TestMsgOperatorAttach() { } s.Require().NotNil(res) - - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } + s.Require().Equal(tc.events, ctx.EventManager().Events()) }) } } func (s *KeeperTestSuite) TestMsgOperatorDetach() { + nfts := make([]string, s.depthLimit) + for i := 1; i <= s.depthLimit; i++ { + nfts[i-1] = collection.NewNFTID(s.nftClassID, i) + } + testCases := map[string]struct { contractID string operator sdk.AccAddress @@ -1815,8 +1984,33 @@ func (s *KeeperTestSuite) TestMsgOperatorDetach() { contractID: s.contractID, operator: s.operator, subjectID: collection.NewNFTID(s.nftClassID, 2), - events: sdk.Events{sdk.Event{Type: "lbm.collection.v1.EventDetached", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x79, 0x6a, 0x71, 0x79, 0x79, 0x78, 0x75, 0x22}, Index: false}, {Key: []uint8{0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72}, Value: []uint8{0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x39, 0x6a, 0x78, 0x67, 0x75, 0x6e, 0x39, 0x77, 0x64, 0x65, 0x6e, 0x7a, 0x77, 0x30, 0x38, 0x70, 0x36, 0x74, 0x22}, Index: false}, {Key: []uint8{0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x22}, Index: false}, {Key: []uint8{0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventRootChanged", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x22}, Index: false}}}, sdk.Event{Type: "lbm.collection.v1.EventRootChanged", Attributes: []abci.EventAttribute{{Key: []uint8{0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x39, 0x62, 0x65, 0x31, 0x37, 0x31, 0x36, 0x35, 0x22}, Index: false}, {Key: []uint8{0x66, 0x72, 0x6f, 0x6d}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x22}, Index: false}, {Key: []uint8{0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64}, Value: []uint8{0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x22}, Index: false}}}}, - }, + events: sdk.Events{ + sdk.Event{ + Type: "lbm.collection.v1.EventDetached", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("holder"), Value: testutil.W(s.customer.String()), Index: false}, + {Key: []byte("operator"), Value: testutil.W(s.operator.String()), Index: false}, + {Key: []byte("previous_parent"), Value: testutil.W(nfts[0]), Index: false}, + {Key: []byte("subject"), Value: testutil.W(nfts[1]), Index: false}, + }}, + sdk.Event{ + Type: "lbm.collection.v1.EventRootChanged", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(nfts[0]), Index: false}, + {Key: []byte("to"), Value: testutil.W(nfts[1]), Index: false}, + {Key: []byte("token_id"), Value: testutil.W(nfts[2]), Index: false}, + }}, + sdk.Event{ + Type: "lbm.collection.v1.EventRootChanged", + Attributes: []abci.EventAttribute{ + {Key: []byte("contract_id"), Value: testutil.W(s.contractID), Index: false}, + {Key: []byte("from"), Value: testutil.W(nfts[0]), Index: false}, + {Key: []byte("to"), Value: testutil.W(nfts[1]), Index: false}, + {Key: []byte("token_id"), Value: testutil.W(nfts[3]), Index: false}, + }}, + }}, "contract not found": { contractID: "deadbeef", operator: s.operator, @@ -1854,22 +2048,29 @@ func (s *KeeperTestSuite) TestMsgOperatorDetach() { } s.Require().NotNil(res) + s.Require().Equal(tc.events, ctx.EventManager().Events()) - if s.deterministic { - s.Require().Equal(tc.events, ctx.EventManager().Events()) - } }) } } -func asJsonStr(attrs collection.Coins) string { - var buf strings.Builder - enc := json.NewEncoder(&buf) - enc.Encode(attrs) - return strings.TrimSpace(buf.String()) -} - -// wrapQuot ("text") -> `"text"` -func wrapQuot(s string) string { - return `"` + strings.TrimSpace(s) + `"` +func (s *KeeperTestSuite) extractChainedNFTIDs(root string) []string { + allTokenIDs := make([]string, 0) + allTokenIDs = append(allTokenIDs, root) + cursor := allTokenIDs[0] + for { + ctx, _ := s.ctx.CacheContext() + res, err := s.queryServer.Children(sdk.WrapSDKContext(ctx), &collection.QueryChildrenRequest{ + ContractId: s.contractID, + TokenId: cursor, + Pagination: &query.PageRequest{}, + }) + s.Require().NoError(err) + if res.Children == nil { + break + } + allTokenIDs = append(allTokenIDs, res.Children[0].TokenId) + cursor = allTokenIDs[len(allTokenIDs)-1] + } + return allTokenIDs }