diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..884d976 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +.idea/ \ No newline at end of file diff --git a/types/codec.go b/types/codec.go index 061de29..87a3359 100644 --- a/types/codec.go +++ b/types/codec.go @@ -56,7 +56,7 @@ func MustProtoMarshalJSON(msg proto.Message) []byte { // ProtoMarshalJSON provides an auxiliary function to return Proto3 JSON encoded // bytes of a message. func ProtoMarshalJSON(msg proto.Message, resolver jsonpb.AnyResolver) ([]byte, error) { - jm := &jsonpb.Marshaler{OrigName: false, EmitDefaults: true, AnyResolver: resolver} + jm := &jsonpb.Marshaler{OrigName: false, EmitDefaults: false, AnyResolver: resolver} err := codectypes.UnpackInterfaces(msg, codectypes.ProtoJSONPacker{JSONPBMarshaler: jm}) if err != nil { return nil, err diff --git a/types/packet.go b/types/packet.go index b814916..27370aa 100644 --- a/types/packet.go +++ b/types/packet.go @@ -80,6 +80,17 @@ func (nftpd NonFungibleTokenPacketData) ValidateBasic() error { // GetBytes is a helper for serializing func (nftpd NonFungibleTokenPacketData) GetBytes() []byte { + // Format will reshape tokenUris and tokenData in NonFungibleTokenPacketData: + // 1. if tokenUris/tokenData is ["","",""] or [], then set it to nil. + // 2. if tokenUris/tokenData is ["a","b","c"] or ["a", "", "c"], then keep it. + // NOTE: Only use this before sending pkg. + if requireShape(nftpd.TokenUris) { + nftpd.TokenUris = nil + } + + if requireShape(nftpd.TokenData) { + nftpd.TokenData = nil + } return sdk.MustSortJSON(MustProtoMarshalJSON(&nftpd)) } @@ -89,3 +100,28 @@ func GetIfExist(i int, data []string) string { } return data[i] } + +// requireShape checks if TokenUris/TokenData needs to be set as nil +func requireShape(contents []string) bool { + if contents == nil { + return false + } + + // empty slice of string + if len(contents) == 0 { + return true + } + + emptyStringCount := 0 + for _, v := range contents { + if len(v) == 0 { + emptyStringCount++ + } + } + // slice of string with only empty string. + if emptyStringCount == len(contents) { + return true + } + + return false +} diff --git a/types/packet_test.go b/types/packet_test.go index 1dd810c..b29886a 100644 --- a/types/packet_test.go +++ b/types/packet_test.go @@ -1,6 +1,7 @@ package types import ( + "bytes" "testing" ) @@ -31,11 +32,21 @@ func TestNonFungibleTokenPacketData_ValidateBasic(t *testing.T) { packet: NonFungibleTokenPacketData{"cryptoCat", "uri", "", []string{"kitty"}, []string{}, tokenData, sender, receiver, "memo"}, wantErr: false, }, + { + name: "valid packet with nil tokenUris", + packet: NonFungibleTokenPacketData{"cryptoCat", "uri", "", []string{"kitty"}, nil, tokenData, sender, receiver, "memo"}, + wantErr: false, + }, { name: "valid packet with tokenUris", packet: NonFungibleTokenPacketData{"cryptoCat", "uri", "", []string{"kitty"}, []string{"1"}, tokenData, sender, receiver, "memo"}, wantErr: false, }, + { + name: "valid packet with tokenUris of empty string entry", + packet: NonFungibleTokenPacketData{"cryptoCat", "uri", "", []string{"kitty", "mary"}, []string{"1", ""}, tokenData, sender, receiver, "memo"}, + wantErr: false, + }, { name: "invalid packet with unmatched tokenUris number", packet: NonFungibleTokenPacketData{"cryptoCat", "uri", "", []string{"kitty"}, []string{"1", "2"}, tokenData, sender, receiver, "memo"}, @@ -46,11 +57,21 @@ func TestNonFungibleTokenPacketData_ValidateBasic(t *testing.T) { packet: NonFungibleTokenPacketData{"cryptoCat", "uri", "", []string{"kitty"}, []string{}, []string{}, sender, receiver, "memo"}, wantErr: false, }, + { + name: "valid packet with nil tokenData", + packet: NonFungibleTokenPacketData{"cryptoCat", "uri", "", []string{"kitty"}, []string{}, nil, sender, receiver, "memo"}, + wantErr: false, + }, { name: "valid packet with tokenData", packet: NonFungibleTokenPacketData{"cryptoCat", "uri", "", []string{"kitty"}, []string{}, []string{"1"}, sender, receiver, "memo"}, wantErr: false, }, + { + name: "valid packet with tokenData of empty string entry", + packet: NonFungibleTokenPacketData{"cryptoCat", "uri", "", []string{"kitty", "mary"}, []string{}, []string{"1", ""}, sender, receiver, "memo"}, + wantErr: false, + }, { name: "invalid packet with unmatched tokenData number", packet: NonFungibleTokenPacketData{"cryptoCat", "uri", "", []string{"kitty"}, []string{}, []string{"1", "2"}, sender, receiver, "memo"}, @@ -75,3 +96,77 @@ func TestNonFungibleTokenPacketData_ValidateBasic(t *testing.T) { }) } } + +func TestNonFungibleTokenPacketData_GetBytes(t *testing.T) { + type fields struct { + ClassId string + ClassUri string + ClassData string + TokenIds []string + TokenUris []string + TokenData []string + Sender string + Receiver string + Memo string + } + tests := []struct { + name string + fields fields + want []byte + }{ + { + "success", + fields{"classId", "classUri", "classData", []string{"id1", "id2"}, []string{"uri1", "uri2"}, []string{"data1"}, sender, receiver, "memo"}, + []byte(`{"classData":"classData","classId":"classId","classUri":"classUri","memo":"memo","receiver":"cosmos15mn87gny58ptfpzq0du6t398gle50xphkw2pkt","sender":"cosmos1eshqg3adwvnuqng0eqfr6ppj35j9hh6zyd9qss","tokenData":["data1"],"tokenIds":["id1","id2"],"tokenUris":["uri1","uri2"]}`), + }, + { + "success with missing classUri", + fields{"classId", "", "classData", []string{"id1", "id2"}, []string{"uri1", "uri2"}, []string{"data1"}, sender, receiver, "memo"}, + []byte(`{"classData":"classData","classId":"classId","memo":"memo","receiver":"cosmos15mn87gny58ptfpzq0du6t398gle50xphkw2pkt","sender":"cosmos1eshqg3adwvnuqng0eqfr6ppj35j9hh6zyd9qss","tokenData":["data1"],"tokenIds":["id1","id2"],"tokenUris":["uri1","uri2"]}`), + }, + { + "success with missing classData", + fields{"classId", "classUri", "", []string{"id1", "id2"}, []string{"uri1", "uri2"}, []string{"data1"}, sender, receiver, "memo"}, + []byte(`{"classId":"classId","classUri":"classUri","memo":"memo","receiver":"cosmos15mn87gny58ptfpzq0du6t398gle50xphkw2pkt","sender":"cosmos1eshqg3adwvnuqng0eqfr6ppj35j9hh6zyd9qss","tokenData":["data1"],"tokenIds":["id1","id2"],"tokenUris":["uri1","uri2"]}`), + }, + { + "success with empty tokenUris", + fields{"classId", "classUri", "classData", []string{"id1", "id2"}, []string{"", ""}, []string{"data1"}, sender, receiver, "memo"}, + []byte(`{"classData":"classData","classId":"classId","classUri":"classUri","memo":"memo","receiver":"cosmos15mn87gny58ptfpzq0du6t398gle50xphkw2pkt","sender":"cosmos1eshqg3adwvnuqng0eqfr6ppj35j9hh6zyd9qss","tokenData":["data1"],"tokenIds":["id1","id2"`), + }, + { + "success with nil tokenUris", + fields{"classId", "classUri", "classData", []string{"id1", "id2"}, nil, []string{"data1"}, sender, receiver, "memo"}, + []byte(`{"classData":"classData","classId":"classId","classUri":"classUri","memo":"memo","receiver":"cosmos15mn87gny58ptfpzq0du6t398gle50xphkw2pkt","sender":"cosmos1eshqg3adwvnuqng0eqfr6ppj35j9hh6zyd9qss","tokenData":["data1"],"tokenIds":["id1","id2"`), + }, + { + "success with empty tokenData", + fields{"classId", "classUri", "classData", []string{"id1", "id2"}, []string{"uri1", "uri2"}, []string{"", ""}, sender, receiver, "memo"}, + []byte(`{"classData":"classData","classId":"classId","classUri":"classUri","memo":"memo","receiver":"cosmos15mn87gny58ptfpzq0du6t398gle50xphkw2pkt","sender":"cosmos1eshqg3adwvnuqng0eqfr6ppj35j9hh6zyd9qss","tokenData":["data1"],"tokenIds":["id1","id2"`), + }, + { + "success with nil tokenData", + fields{"classId", "classUri", "classData", []string{"id1", "id2"}, []string{"uri1", "uri2"}, nil, sender, receiver, "memo"}, + []byte(`{"classData":"classData","classId":"classId","classUri":"classUri","memo":"memo","receiver":"cosmos15mn87gny58ptfpzq0du6t398gle50xphkw2pkt","sender":"cosmos1eshqg3adwvnuqng0eqfr6ppj35j9hh6zyd9qss","tokenData":["data1"],"tokenIds":["id1","id2"`), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + nftpd := NonFungibleTokenPacketData{ + ClassId: tt.fields.ClassId, + ClassUri: tt.fields.ClassUri, + ClassData: tt.fields.ClassData, + TokenIds: tt.fields.TokenIds, + TokenUris: tt.fields.TokenUris, + TokenData: tt.fields.TokenData, + Sender: tt.fields.Sender, + Receiver: tt.fields.Receiver, + Memo: tt.fields.Memo, + } + t.Logf("%s\n", nftpd.GetBytes()) + if got := nftpd.GetBytes(); bytes.Equal(got, tt.want) { + t.Errorf("NonFungibleTokenPacketData.GetBytes() = %v, want %v", got, tt.want) + } + }) + } +}