From 065f8082a659af03b6562e3c21f0c6f445ef4581 Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Fri, 27 May 2022 13:33:57 +0800 Subject: [PATCH 01/14] add proto&generate ptoto file --- modules/apps/nft-transfer/types/packet.pb.go | 597 ++++++++++++ modules/apps/nft-transfer/types/tx.pb.go | 850 ++++++++++++++++++ .../applications/nft_transfer/v1/packet.proto | 23 + .../ibc/applications/nft_transfer/v1/tx.proto | 45 + 4 files changed, 1515 insertions(+) create mode 100644 modules/apps/nft-transfer/types/packet.pb.go create mode 100644 modules/apps/nft-transfer/types/tx.pb.go create mode 100644 proto/ibc/applications/nft_transfer/v1/packet.proto create mode 100644 proto/ibc/applications/nft_transfer/v1/tx.proto diff --git a/modules/apps/nft-transfer/types/packet.pb.go b/modules/apps/nft-transfer/types/packet.pb.go new file mode 100644 index 00000000000..9662ca5cea9 --- /dev/null +++ b/modules/apps/nft-transfer/types/packet.pb.go @@ -0,0 +1,597 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/applications/nft_transfer/v1/packet.proto + +package types + +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// NonFungibleTokenPacketData defines a struct for the packet payload +// See NonFungibleTokenPacketData spec: +// https://github.com/cosmos/ibc/tree/master/spec/app/ics-721-nft-transfer#data-structures +type NonFungibleTokenPacketData struct { + // the class_id of tokens to be transferred + ClassId string `protobuf:"bytes,1,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` + // the class_uri of tokens to be transferred + ClassUri string `protobuf:"bytes,2,opt,name=class_uri,json=classUri,proto3" json:"class_uri,omitempty"` + // the non fungible tokens to be transferred + TokenIds []string `protobuf:"bytes,3,rep,name=token_ids,json=tokenIds,proto3" json:"token_ids,omitempty"` + // the non fungible tokens's uri to be transferred + TokenUris []string `protobuf:"bytes,4,rep,name=token_uris,json=tokenUris,proto3" json:"token_uris,omitempty"` + // the sender address + Sender string `protobuf:"bytes,5,opt,name=sender,proto3" json:"sender,omitempty"` + // the recipient address on the destination chain + Receiver string `protobuf:"bytes,6,opt,name=receiver,proto3" json:"receiver,omitempty"` +} + +func (m *NonFungibleTokenPacketData) Reset() { *m = NonFungibleTokenPacketData{} } +func (m *NonFungibleTokenPacketData) String() string { return proto.CompactTextString(m) } +func (*NonFungibleTokenPacketData) ProtoMessage() {} +func (*NonFungibleTokenPacketData) Descriptor() ([]byte, []int) { + return fileDescriptor_f82fdc932b824013, []int{0} +} +func (m *NonFungibleTokenPacketData) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NonFungibleTokenPacketData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NonFungibleTokenPacketData.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NonFungibleTokenPacketData) XXX_Merge(src proto.Message) { + xxx_messageInfo_NonFungibleTokenPacketData.Merge(m, src) +} +func (m *NonFungibleTokenPacketData) XXX_Size() int { + return m.Size() +} +func (m *NonFungibleTokenPacketData) XXX_DiscardUnknown() { + xxx_messageInfo_NonFungibleTokenPacketData.DiscardUnknown(m) +} + +var xxx_messageInfo_NonFungibleTokenPacketData proto.InternalMessageInfo + +func (m *NonFungibleTokenPacketData) GetClassId() string { + if m != nil { + return m.ClassId + } + return "" +} + +func (m *NonFungibleTokenPacketData) GetClassUri() string { + if m != nil { + return m.ClassUri + } + return "" +} + +func (m *NonFungibleTokenPacketData) GetTokenIds() []string { + if m != nil { + return m.TokenIds + } + return nil +} + +func (m *NonFungibleTokenPacketData) GetTokenUris() []string { + if m != nil { + return m.TokenUris + } + return nil +} + +func (m *NonFungibleTokenPacketData) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *NonFungibleTokenPacketData) GetReceiver() string { + if m != nil { + return m.Receiver + } + return "" +} + +func init() { + proto.RegisterType((*NonFungibleTokenPacketData)(nil), "ibc.applications.nft_transfer.v1.NonFungibleTokenPacketData") +} + +func init() { + proto.RegisterFile("ibc/applications/nft_transfer/v1/packet.proto", fileDescriptor_f82fdc932b824013) +} + +var fileDescriptor_f82fdc932b824013 = []byte{ + // 293 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0xbd, 0x4a, 0x03, 0x41, + 0x14, 0x85, 0xb3, 0x46, 0x63, 0x32, 0xe5, 0x14, 0x32, 0x46, 0x1c, 0x82, 0x95, 0x4d, 0x76, 0x08, + 0x29, 0xed, 0x44, 0x84, 0x34, 0x22, 0x62, 0x1a, 0x9b, 0x30, 0x7f, 0x89, 0x97, 0x6c, 0x66, 0x96, + 0xb9, 0xb3, 0x0b, 0xbe, 0x85, 0x0f, 0x65, 0x61, 0x99, 0xd2, 0x52, 0x92, 0x17, 0x91, 0x9d, 0x55, + 0x49, 0x79, 0xee, 0x77, 0x38, 0x17, 0x3e, 0x32, 0x06, 0xa5, 0x85, 0x2c, 0xcb, 0x02, 0xb4, 0x8c, + 0xe0, 0x1d, 0x0a, 0xb7, 0x8c, 0x8b, 0x18, 0xa4, 0xc3, 0xa5, 0x0d, 0xa2, 0x9e, 0x88, 0x52, 0xea, + 0xb5, 0x8d, 0x79, 0x19, 0x7c, 0xf4, 0x74, 0x04, 0x4a, 0xe7, 0x87, 0xf5, 0xfc, 0xb0, 0x9e, 0xd7, + 0x93, 0xab, 0x8f, 0x8c, 0x0c, 0x1f, 0xbc, 0xbb, 0xaf, 0xdc, 0x0a, 0x54, 0x61, 0x9f, 0xfd, 0xda, + 0xba, 0xc7, 0x34, 0x71, 0x27, 0xa3, 0xa4, 0xe7, 0xa4, 0xaf, 0x0b, 0x89, 0xb8, 0x00, 0xc3, 0xb2, + 0x51, 0x76, 0x3d, 0x78, 0x3a, 0x4d, 0x79, 0x66, 0xe8, 0x05, 0x19, 0xb4, 0xa8, 0x0a, 0xc0, 0x8e, + 0x12, 0x6b, 0xbb, 0xf3, 0x00, 0x0d, 0x8c, 0xcd, 0xd4, 0x02, 0x0c, 0xb2, 0xee, 0xa8, 0xdb, 0xc0, + 0x74, 0x98, 0x19, 0xa4, 0x97, 0x84, 0xb4, 0xb0, 0x0a, 0x80, 0xec, 0x38, 0xd1, 0xb6, 0x3e, 0x0f, + 0x80, 0xf4, 0x8c, 0xf4, 0xd0, 0x3a, 0x63, 0x03, 0x3b, 0x49, 0xab, 0xbf, 0x89, 0x0e, 0x49, 0x3f, + 0x58, 0x6d, 0xa1, 0xb6, 0x81, 0xf5, 0xda, 0x7f, 0x7f, 0xf9, 0x76, 0xfe, 0xb9, 0xe3, 0xd9, 0x76, + 0xc7, 0xb3, 0xef, 0x1d, 0xcf, 0xde, 0xf7, 0xbc, 0xb3, 0xdd, 0xf3, 0xce, 0xd7, 0x9e, 0x77, 0x5e, + 0x6e, 0x56, 0x10, 0x5f, 0x2b, 0x95, 0x6b, 0xbf, 0x11, 0xda, 0xe3, 0xc6, 0xa3, 0x00, 0xa5, 0xc7, + 0x2b, 0x2f, 0xea, 0xa9, 0xd8, 0x78, 0x53, 0x15, 0x16, 0x1b, 0xa3, 0xc9, 0xe4, 0xf8, 0xdf, 0x64, + 0x7c, 0x2b, 0x2d, 0xaa, 0x5e, 0xd2, 0x38, 0xfd, 0x09, 0x00, 0x00, 0xff, 0xff, 0x2f, 0x79, 0x46, + 0x74, 0x77, 0x01, 0x00, 0x00, +} + +func (m *NonFungibleTokenPacketData) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NonFungibleTokenPacketData) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NonFungibleTokenPacketData) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Receiver) > 0 { + i -= len(m.Receiver) + copy(dAtA[i:], m.Receiver) + i = encodeVarintPacket(dAtA, i, uint64(len(m.Receiver))) + i-- + dAtA[i] = 0x32 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintPacket(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x2a + } + if len(m.TokenUris) > 0 { + for iNdEx := len(m.TokenUris) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.TokenUris[iNdEx]) + copy(dAtA[i:], m.TokenUris[iNdEx]) + i = encodeVarintPacket(dAtA, i, uint64(len(m.TokenUris[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if len(m.TokenIds) > 0 { + for iNdEx := len(m.TokenIds) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.TokenIds[iNdEx]) + copy(dAtA[i:], m.TokenIds[iNdEx]) + i = encodeVarintPacket(dAtA, i, uint64(len(m.TokenIds[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if len(m.ClassUri) > 0 { + i -= len(m.ClassUri) + copy(dAtA[i:], m.ClassUri) + i = encodeVarintPacket(dAtA, i, uint64(len(m.ClassUri))) + i-- + dAtA[i] = 0x12 + } + if len(m.ClassId) > 0 { + i -= len(m.ClassId) + copy(dAtA[i:], m.ClassId) + i = encodeVarintPacket(dAtA, i, uint64(len(m.ClassId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintPacket(dAtA []byte, offset int, v uint64) int { + offset -= sovPacket(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *NonFungibleTokenPacketData) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClassId) + if l > 0 { + n += 1 + l + sovPacket(uint64(l)) + } + l = len(m.ClassUri) + if l > 0 { + n += 1 + l + sovPacket(uint64(l)) + } + if len(m.TokenIds) > 0 { + for _, s := range m.TokenIds { + l = len(s) + n += 1 + l + sovPacket(uint64(l)) + } + } + if len(m.TokenUris) > 0 { + for _, s := range m.TokenUris { + l = len(s) + n += 1 + l + sovPacket(uint64(l)) + } + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovPacket(uint64(l)) + } + l = len(m.Receiver) + if l > 0 { + n += 1 + l + sovPacket(uint64(l)) + } + return n +} + +func sovPacket(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozPacket(x uint64) (n int) { + return sovPacket(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *NonFungibleTokenPacketData) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NonFungibleTokenPacketData: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NonFungibleTokenPacketData: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthPacket + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPacket + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassUri", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthPacket + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPacket + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassUri = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TokenIds", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthPacket + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPacket + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TokenIds = append(m.TokenIds, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TokenUris", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthPacket + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPacket + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TokenUris = append(m.TokenUris, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthPacket + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPacket + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPacket + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthPacket + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPacket + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Receiver = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPacket(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPacket + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipPacket(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPacket + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPacket + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPacket + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthPacket + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupPacket + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthPacket + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthPacket = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowPacket = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupPacket = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/apps/nft-transfer/types/tx.pb.go b/modules/apps/nft-transfer/types/tx.pb.go new file mode 100644 index 00000000000..49e52737aed --- /dev/null +++ b/modules/apps/nft-transfer/types/tx.pb.go @@ -0,0 +1,850 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/applications/nft_transfer/v1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + types "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgTransfer defines a msg to transfer non fungible tokens between +// ICS721 enabled chains. See ICS Spec here: +// https://github.com/cosmos/ibc/tree/master/spec/app/ics-721-nft-transfer#data-structures +type MsgTransfer struct { + // the port on which the packet will be sent + SourcePort string `protobuf:"bytes,1,opt,name=source_port,json=sourcePort,proto3" json:"source_port,omitempty" yaml:"source_port"` + // the channel by which the packet will be sent + SourceChannel string `protobuf:"bytes,2,opt,name=source_channel,json=sourceChannel,proto3" json:"source_channel,omitempty" yaml:"source_channel"` + // the class_id of tokens to be transferred + ClassId string `protobuf:"bytes,3,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"` + // the non fungible tokens to be transferred + TokenIds []string `protobuf:"bytes,4,rep,name=token_ids,json=tokenIds,proto3" json:"token_ids,omitempty"` + // the sender address + Sender string `protobuf:"bytes,5,opt,name=sender,proto3" json:"sender,omitempty"` + // the recipient address on the destination chain + Receiver string `protobuf:"bytes,6,opt,name=receiver,proto3" json:"receiver,omitempty"` + // Timeout height relative to the current block height. + // The timeout is disabled when set to 0. + TimeoutHeight types.Height `protobuf:"bytes,7,opt,name=timeout_height,json=timeoutHeight,proto3" json:"timeout_height" yaml:"timeout_height"` + // Timeout timestamp in absolute nanoseconds since unix epoch. + // The timeout is disabled when set to 0. + TimeoutTimestamp uint64 `protobuf:"varint,8,opt,name=timeout_timestamp,json=timeoutTimestamp,proto3" json:"timeout_timestamp,omitempty" yaml:"timeout_timestamp"` +} + +func (m *MsgTransfer) Reset() { *m = MsgTransfer{} } +func (m *MsgTransfer) String() string { return proto.CompactTextString(m) } +func (*MsgTransfer) ProtoMessage() {} +func (*MsgTransfer) Descriptor() ([]byte, []int) { + return fileDescriptor_d1cb5d976a414ada, []int{0} +} +func (m *MsgTransfer) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgTransfer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgTransfer.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgTransfer) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgTransfer.Merge(m, src) +} +func (m *MsgTransfer) XXX_Size() int { + return m.Size() +} +func (m *MsgTransfer) XXX_DiscardUnknown() { + xxx_messageInfo_MsgTransfer.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgTransfer proto.InternalMessageInfo + +// MsgTransferResponse defines the Msg/Transfer response type. +type MsgTransferResponse struct { +} + +func (m *MsgTransferResponse) Reset() { *m = MsgTransferResponse{} } +func (m *MsgTransferResponse) String() string { return proto.CompactTextString(m) } +func (*MsgTransferResponse) ProtoMessage() {} +func (*MsgTransferResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_d1cb5d976a414ada, []int{1} +} +func (m *MsgTransferResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgTransferResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgTransferResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgTransferResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgTransferResponse.Merge(m, src) +} +func (m *MsgTransferResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgTransferResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgTransferResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgTransferResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgTransfer)(nil), "ibc.applications.nft_transfer.v1.MsgTransfer") + proto.RegisterType((*MsgTransferResponse)(nil), "ibc.applications.nft_transfer.v1.MsgTransferResponse") +} + +func init() { + proto.RegisterFile("ibc/applications/nft_transfer/v1/tx.proto", fileDescriptor_d1cb5d976a414ada) +} + +var fileDescriptor_d1cb5d976a414ada = []byte{ + // 491 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0x3f, 0x6f, 0xd3, 0x40, + 0x18, 0xc6, 0x6d, 0x52, 0x52, 0xe7, 0xa2, 0x56, 0x70, 0xd0, 0xca, 0x0d, 0x60, 0x5b, 0x9e, 0xc2, + 0x90, 0x3b, 0xa5, 0x15, 0x42, 0x2a, 0x0b, 0x0a, 0x0b, 0x19, 0x2a, 0x21, 0xab, 0x2c, 0x2c, 0xc6, + 0x3e, 0x5f, 0x9d, 0x13, 0xb6, 0xcf, 0xba, 0xbb, 0x18, 0xfa, 0x0d, 0x18, 0xf9, 0x08, 0xdd, 0xf9, + 0x22, 0x1d, 0x3b, 0x32, 0x45, 0x28, 0x59, 0x98, 0xf3, 0x09, 0x90, 0xff, 0x24, 0x38, 0x13, 0xea, + 0xe4, 0x7b, 0x9f, 0xf7, 0xf7, 0xbc, 0x27, 0xbf, 0xf7, 0x80, 0x97, 0x2c, 0x24, 0x38, 0xc8, 0xf3, + 0x84, 0x91, 0x40, 0x31, 0x9e, 0x49, 0x9c, 0x5d, 0x29, 0x5f, 0x89, 0x20, 0x93, 0x57, 0x54, 0xe0, + 0x62, 0x8c, 0xd5, 0x37, 0x94, 0x0b, 0xae, 0x38, 0x74, 0x58, 0x48, 0x50, 0x1b, 0x45, 0x6d, 0x14, + 0x15, 0xe3, 0xc1, 0xd3, 0x98, 0xc7, 0xbc, 0x82, 0x71, 0x79, 0xaa, 0x7d, 0x03, 0xbb, 0xbc, 0x82, + 0x70, 0x41, 0x31, 0x49, 0x18, 0xcd, 0x54, 0x39, 0xb4, 0x3e, 0xd5, 0x80, 0xfb, 0xb3, 0x03, 0xfa, + 0x17, 0x32, 0xbe, 0x6c, 0x26, 0xc1, 0xd7, 0xa0, 0x2f, 0xf9, 0x5c, 0x10, 0xea, 0xe7, 0x5c, 0x28, + 0x53, 0x77, 0xf4, 0x61, 0x6f, 0x72, 0xbc, 0x5e, 0xd8, 0xf0, 0x3a, 0x48, 0x93, 0x73, 0xb7, 0xd5, + 0x74, 0x3d, 0x50, 0x57, 0x1f, 0xb8, 0x50, 0xf0, 0x2d, 0x38, 0x6c, 0x7a, 0x64, 0x16, 0x64, 0x19, + 0x4d, 0xcc, 0x07, 0x95, 0xf7, 0x64, 0xbd, 0xb0, 0x8f, 0x76, 0xbc, 0x4d, 0xdf, 0xf5, 0x0e, 0x6a, + 0xe1, 0x5d, 0x5d, 0xc3, 0x13, 0x60, 0x90, 0x24, 0x90, 0xd2, 0x67, 0x91, 0xd9, 0x29, 0xbd, 0xde, + 0x7e, 0x55, 0x4f, 0x23, 0xf8, 0x0c, 0xf4, 0x14, 0xff, 0x42, 0x33, 0x9f, 0x45, 0xd2, 0xdc, 0x73, + 0x3a, 0xc3, 0x9e, 0x67, 0x54, 0xc2, 0x34, 0x92, 0xf0, 0x18, 0x74, 0x25, 0xcd, 0x22, 0x2a, 0xcc, + 0x87, 0x95, 0xab, 0xa9, 0xe0, 0x00, 0x18, 0x82, 0x12, 0xca, 0x0a, 0x2a, 0xcc, 0x6e, 0xd5, 0xd9, + 0xd6, 0xf0, 0x33, 0x38, 0x54, 0x2c, 0xa5, 0x7c, 0xae, 0xfc, 0x19, 0x65, 0xf1, 0x4c, 0x99, 0xfb, + 0x8e, 0x3e, 0xec, 0x9f, 0x0e, 0x50, 0xb9, 0xe8, 0x72, 0x61, 0xa8, 0x59, 0x53, 0x31, 0x46, 0xef, + 0x2b, 0x62, 0xf2, 0xe2, 0x76, 0x61, 0x6b, 0xff, 0xfe, 0x66, 0xd7, 0xef, 0x7a, 0x07, 0x8d, 0x50, + 0xd3, 0x70, 0x0a, 0x1e, 0x6f, 0x88, 0xf2, 0x2b, 0x55, 0x90, 0xe6, 0xa6, 0xe1, 0xe8, 0xc3, 0xbd, + 0xc9, 0xf3, 0xf5, 0xc2, 0x36, 0x77, 0x87, 0x6c, 0x11, 0xd7, 0x7b, 0xd4, 0x68, 0x97, 0x1b, 0xe9, + 0xdc, 0xf8, 0x7e, 0x63, 0x6b, 0x7f, 0x6e, 0x6c, 0xcd, 0x3d, 0x02, 0x4f, 0x5a, 0x8f, 0xe5, 0x51, + 0x99, 0xf3, 0x4c, 0xd2, 0xd3, 0xaf, 0xa0, 0x73, 0x21, 0x63, 0x98, 0x03, 0x63, 0xfb, 0x8e, 0x23, + 0xf4, 0xbf, 0xc4, 0xa0, 0xd6, 0xa4, 0xc1, 0xab, 0x7b, 0xe1, 0x9b, 0x8b, 0x27, 0x1f, 0x6f, 0x97, + 0x96, 0x7e, 0xb7, 0xb4, 0xf4, 0xdf, 0x4b, 0x4b, 0xff, 0xb1, 0xb2, 0xb4, 0xbb, 0x95, 0xa5, 0xfd, + 0x5a, 0x59, 0xda, 0xa7, 0x37, 0x31, 0x53, 0xb3, 0x79, 0x88, 0x08, 0x4f, 0x31, 0xe1, 0x32, 0xe5, + 0x12, 0xb3, 0x90, 0x8c, 0x62, 0x8e, 0x8b, 0x33, 0x9c, 0xf2, 0x68, 0x9e, 0x50, 0x59, 0x66, 0xbf, + 0xca, 0xfc, 0x68, 0x9b, 0x79, 0x75, 0x9d, 0x53, 0x19, 0x76, 0xab, 0x6c, 0x9e, 0xfd, 0x0d, 0x00, + 0x00, 0xff, 0xff, 0xab, 0x50, 0x1c, 0xc8, 0x21, 0x03, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // Transfer defines a rpc handler method for MsgTransfer. + Transfer(ctx context.Context, in *MsgTransfer, opts ...grpc.CallOption) (*MsgTransferResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) Transfer(ctx context.Context, in *MsgTransfer, opts ...grpc.CallOption) (*MsgTransferResponse, error) { + out := new(MsgTransferResponse) + err := c.cc.Invoke(ctx, "/ibc.applications.nft_transfer.v1.Msg/Transfer", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // Transfer defines a rpc handler method for MsgTransfer. + Transfer(context.Context, *MsgTransfer) (*MsgTransferResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) Transfer(ctx context.Context, req *MsgTransfer) (*MsgTransferResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Transfer not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_Transfer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgTransfer) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).Transfer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ibc.applications.nft_transfer.v1.Msg/Transfer", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).Transfer(ctx, req.(*MsgTransfer)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "ibc.applications.nft_transfer.v1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Transfer", + Handler: _Msg_Transfer_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "ibc/applications/nft_transfer/v1/tx.proto", +} + +func (m *MsgTransfer) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgTransfer) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgTransfer) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TimeoutTimestamp != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.TimeoutTimestamp)) + i-- + dAtA[i] = 0x40 + } + { + size, err := m.TimeoutHeight.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + if len(m.Receiver) > 0 { + i -= len(m.Receiver) + copy(dAtA[i:], m.Receiver) + i = encodeVarintTx(dAtA, i, uint64(len(m.Receiver))) + i-- + dAtA[i] = 0x32 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x2a + } + if len(m.TokenIds) > 0 { + for iNdEx := len(m.TokenIds) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.TokenIds[iNdEx]) + copy(dAtA[i:], m.TokenIds[iNdEx]) + i = encodeVarintTx(dAtA, i, uint64(len(m.TokenIds[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if len(m.ClassId) > 0 { + i -= len(m.ClassId) + copy(dAtA[i:], m.ClassId) + i = encodeVarintTx(dAtA, i, uint64(len(m.ClassId))) + i-- + dAtA[i] = 0x1a + } + if len(m.SourceChannel) > 0 { + i -= len(m.SourceChannel) + copy(dAtA[i:], m.SourceChannel) + i = encodeVarintTx(dAtA, i, uint64(len(m.SourceChannel))) + i-- + dAtA[i] = 0x12 + } + if len(m.SourcePort) > 0 { + i -= len(m.SourcePort) + copy(dAtA[i:], m.SourcePort) + i = encodeVarintTx(dAtA, i, uint64(len(m.SourcePort))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgTransferResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgTransferResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgTransferResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgTransfer) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.SourcePort) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.SourceChannel) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ClassId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.TokenIds) > 0 { + for _, s := range m.TokenIds { + l = len(s) + n += 1 + l + sovTx(uint64(l)) + } + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Receiver) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.TimeoutHeight.Size() + n += 1 + l + sovTx(uint64(l)) + if m.TimeoutTimestamp != 0 { + n += 1 + sovTx(uint64(m.TimeoutTimestamp)) + } + return n +} + +func (m *MsgTransferResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgTransfer) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgTransfer: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgTransfer: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SourcePort", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SourcePort = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SourceChannel", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SourceChannel = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TokenIds", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TokenIds = append(m.TokenIds, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Receiver = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeoutHeight", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.TimeoutHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeoutTimestamp", wireType) + } + m.TimeoutTimestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TimeoutTimestamp |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgTransferResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgTransferResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgTransferResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/ibc/applications/nft_transfer/v1/packet.proto b/proto/ibc/applications/nft_transfer/v1/packet.proto new file mode 100644 index 00000000000..6eef4d90460 --- /dev/null +++ b/proto/ibc/applications/nft_transfer/v1/packet.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; + +package ibc.applications.nft_transfer.v1; + +option go_package = "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types"; + +// NonFungibleTokenPacketData defines a struct for the packet payload +// See NonFungibleTokenPacketData spec: +// https://github.com/cosmos/ibc/tree/master/spec/app/ics-721-nft-transfer#data-structures +message NonFungibleTokenPacketData { + // the class_id of tokens to be transferred + string class_id = 1; + // the class_uri of tokens to be transferred + string class_uri = 2; + // the non fungible tokens to be transferred + repeated string token_ids = 3; + // the non fungible tokens's uri to be transferred + repeated string token_uris = 4; + // the sender address + string sender = 5; + // the recipient address on the destination chain + string receiver = 6; +} diff --git a/proto/ibc/applications/nft_transfer/v1/tx.proto b/proto/ibc/applications/nft_transfer/v1/tx.proto new file mode 100644 index 00000000000..85be211b2b1 --- /dev/null +++ b/proto/ibc/applications/nft_transfer/v1/tx.proto @@ -0,0 +1,45 @@ +syntax = "proto3"; + +package ibc.applications.nft_transfer.v1; + +option go_package = "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types"; + +import "gogoproto/gogo.proto"; +import "ibc/core/client/v1/client.proto"; + +// Msg defines the ibc/nft-transfer Msg service. +service Msg { + // Transfer defines a rpc handler method for MsgTransfer. + rpc Transfer(MsgTransfer) returns (MsgTransferResponse); +} + +// MsgTransfer defines a msg to transfer non fungible tokens between +// ICS721 enabled chains. See ICS Spec here: +// https://github.com/cosmos/ibc/tree/master/spec/app/ics-721-nft-transfer#data-structures +message MsgTransfer { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // the port on which the packet will be sent + string source_port = 1 [(gogoproto.moretags) = "yaml:\"source_port\""]; + // the channel by which the packet will be sent + string source_channel = 2 [(gogoproto.moretags) = "yaml:\"source_channel\""]; + // the class_id of tokens to be transferred + string class_id = 3; + // the non fungible tokens to be transferred + repeated string token_ids = 4; + // the sender address + string sender = 5; + // the recipient address on the destination chain + string receiver = 6; + // Timeout height relative to the current block height. + // The timeout is disabled when set to 0. + ibc.core.client.v1.Height timeout_height = 7 + [(gogoproto.moretags) = "yaml:\"timeout_height\"", (gogoproto.nullable) = false]; + // Timeout timestamp in absolute nanoseconds since unix epoch. + // The timeout is disabled when set to 0. + uint64 timeout_timestamp = 8 [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""]; +} + +// MsgTransferResponse defines the Msg/Transfer response type. +message MsgTransferResponse {} From a4d000f75ebe6feadbeea42c34880fda35a521e5 Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Fri, 27 May 2022 15:16:15 +0800 Subject: [PATCH 02/14] add some basic types --- modules/apps/nft-transfer/ibc_module.go | 288 ++++++++++++++++++ modules/apps/nft-transfer/keeper/keeper.go | 22 ++ modules/apps/nft-transfer/module.go | 1 + modules/apps/nft-transfer/types/codec.go | 26 ++ .../nft-transfer/types/expected_keeper.go | 16 + 5 files changed, 353 insertions(+) create mode 100644 modules/apps/nft-transfer/ibc_module.go create mode 100644 modules/apps/nft-transfer/keeper/keeper.go create mode 100644 modules/apps/nft-transfer/module.go create mode 100644 modules/apps/nft-transfer/types/codec.go create mode 100644 modules/apps/nft-transfer/types/expected_keeper.go diff --git a/modules/apps/nft-transfer/ibc_module.go b/modules/apps/nft-transfer/ibc_module.go new file mode 100644 index 00000000000..fd9738f22d8 --- /dev/null +++ b/modules/apps/nft-transfer/ibc_module.go @@ -0,0 +1,288 @@ +package nt + +import ( + "fmt" + "math" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/keeper" + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" + channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types" + host "github.com/cosmos/ibc-go/v3/modules/core/24-host" + ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" +) + +// IBCModule implements the ICS26 interface for transfer given the transfer keeper. +type IBCModule struct { + keeper keeper.Keeper +} + +// NewIBCModule creates a new IBCModule given the keeper +func NewIBCModule(k keeper.Keeper) IBCModule { + return IBCModule{ + keeper: k, + } +} + +// ValidateTransferChannelParams does validation of a newly created transfer channel. A transfer +// channel must be UNORDERED, use the correct port (by default 'transfer'), and use the current +// supported version. Only 2^32 channels are allowed to be created. +func ValidateTransferChannelParams( + ctx sdk.Context, + keeper keeper.Keeper, + order channeltypes.Order, + portID string, + channelID string, +) error { + // NOTE: for escrow address security only 2^32 channels are allowed to be created + // Issue: https://github.com/cosmos/cosmos-sdk/issues/7737 + channelSequence, err := channeltypes.ParseChannelSequence(channelID) + if err != nil { + return err + } + if channelSequence > uint64(math.MaxUint32) { + return sdkerrors.Wrapf(types.ErrMaxTransferChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, uint64(math.MaxUint32)) + } + if order != channeltypes.UNORDERED { + return sdkerrors.Wrapf(channeltypes.ErrInvalidChannelOrdering, "expected %s channel, got %s ", channeltypes.UNORDERED, order) + } + + // Require portID is the portID transfer module is bound to + boundPort := keeper.GetPort(ctx) + if boundPort != portID { + return sdkerrors.Wrapf(porttypes.ErrInvalidPort, "invalid port: %s, expected %s", portID, boundPort) + } + + return nil +} + +// OnChanOpenInit implements the IBCModule interface +func (im IBCModule) OnChanOpenInit( + ctx sdk.Context, + order channeltypes.Order, + connectionHops []string, + portID string, + channelID string, + chanCap *capabilitytypes.Capability, + counterparty channeltypes.Counterparty, + version string, +) (string, error) { + if err := ValidateTransferChannelParams(ctx, im.keeper, order, portID, channelID); err != nil { + return "", err + } + + if strings.TrimSpace(version) == "" { + version = types.Version + } + + if version != types.Version { + return "", sdkerrors.Wrapf(types.ErrInvalidVersion, "got %s, expected %s", version, types.Version) + } + + // Claim channel capability passed back by IBC module + if err := im.keeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { + return "", err + } + + return version, nil +} + +// OnChanOpenTry implements the IBCModule interface. +func (im IBCModule) OnChanOpenTry( + ctx sdk.Context, + order channeltypes.Order, + connectionHops []string, + portID, + channelID string, + chanCap *capabilitytypes.Capability, + counterparty channeltypes.Counterparty, + counterpartyVersion string, +) (string, error) { + if err := ValidateTransferChannelParams(ctx, im.keeper, order, portID, channelID); err != nil { + return "", err + } + + if counterpartyVersion != types.Version { + return "", sdkerrors.Wrapf(types.ErrInvalidVersion, "invalid counterparty version: got: %s, expected %s", counterpartyVersion, types.Version) + } + + // Module may have already claimed capability in OnChanOpenInit in the case of crossing hellos + // (ie chainA and chainB both call ChanOpenInit before one of them calls ChanOpenTry) + // If module can already authenticate the capability then module already owns it so we don't need to claim + // Otherwise, module does not have channel capability and we must claim it from IBC + if !im.keeper.AuthenticateCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)) { + // Only claim channel capability passed back by IBC module if we do not already own it + if err := im.keeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { + return "", err + } + } + + return types.Version, nil +} + +// OnChanOpenAck implements the IBCModule interface +func (im IBCModule) OnChanOpenAck( + ctx sdk.Context, + portID, + channelID string, + _ string, + counterpartyVersion string, +) error { + if counterpartyVersion != types.Version { + return sdkerrors.Wrapf(types.ErrInvalidVersion, "invalid counterparty version: %s, expected %s", counterpartyVersion, types.Version) + } + return nil +} + +// OnChanOpenConfirm implements the IBCModule interface +func (im IBCModule) OnChanOpenConfirm( + ctx sdk.Context, + portID, + channelID string, +) error { + return nil +} + +// OnChanCloseInit implements the IBCModule interface +func (im IBCModule) OnChanCloseInit( + ctx sdk.Context, + portID, + channelID string, +) error { + // Disallow user-initiated channel closing for transfer channels + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "user cannot close channel") +} + +// OnChanCloseConfirm implements the IBCModule interface +func (im IBCModule) OnChanCloseConfirm( + ctx sdk.Context, + portID, + channelID string, +) error { + return nil +} + +// OnRecvPacket implements the IBCModule interface. A successful acknowledgement +// is returned if the packet data is successfully decoded and the receive application +// logic returns without error. +func (im IBCModule) OnRecvPacket( + ctx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, +) ibcexported.Acknowledgement { + ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) + + var data types.NonFungibleTokenPacketData + if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { + ack = channeltypes.NewErrorAcknowledgement("cannot unmarshal ICS-20 transfer packet data") + } + + // only attempt the application logic if the packet data + // was successfully decoded + if ack.Success() { + err := im.keeper.OnRecvPacket(ctx, packet, data) + if err != nil { + ack = types.NewErrorAcknowledgement(err) + } + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypePacket, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + sdk.NewAttribute(sdk.AttributeKeySender, data.Sender), + sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), + sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), + sdk.NewAttribute(types.AttributeKeyAmount, data.Amount), + sdk.NewAttribute(types.AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success())), + ), + ) + + // NOTE: acknowledgement will be written synchronously during IBC handler execution. + return ack +} + +// OnAcknowledgementPacket implements the IBCModule interface +func (im IBCModule) OnAcknowledgementPacket( + ctx sdk.Context, + packet channeltypes.Packet, + acknowledgement []byte, + relayer sdk.AccAddress, +) error { + var ack channeltypes.Acknowledgement + if err := types.ModuleCdc.UnmarshalJSON(acknowledgement, &ack); err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet acknowledgement: %v", err) + } + var data types.FungibleTokenPacketData + if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data: %s", err.Error()) + } + + if err := im.keeper.OnAcknowledgementPacket(ctx, packet, data, ack); err != nil { + return err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypePacket, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + sdk.NewAttribute(sdk.AttributeKeySender, data.Sender), + sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), + sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), + sdk.NewAttribute(types.AttributeKeyAmount, data.Amount), + sdk.NewAttribute(types.AttributeKeyAck, ack.String()), + ), + ) + + switch resp := ack.Response.(type) { + case *channeltypes.Acknowledgement_Result: + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypePacket, + sdk.NewAttribute(types.AttributeKeyAckSuccess, string(resp.Result)), + ), + ) + case *channeltypes.Acknowledgement_Error: + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypePacket, + sdk.NewAttribute(types.AttributeKeyAckError, resp.Error), + ), + ) + } + + return nil +} + +// OnTimeoutPacket implements the IBCModule interface +func (im IBCModule) OnTimeoutPacket( + ctx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, +) error { + var data types.NonFungibleTokenPacketData + if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data: %s", err.Error()) + } + // refund tokens + if err := im.keeper.OnTimeoutPacket(ctx, packet, data); err != nil { + return err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeTimeout, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + sdk.NewAttribute(types.AttributeKeyRefundReceiver, data.Sender), + sdk.NewAttribute(types.AttributeKeyRefundDenom, data.Denom), + sdk.NewAttribute(types.AttributeKeyRefundAmount, data.Amount), + ), + ) + + return nil +} diff --git a/modules/apps/nft-transfer/keeper/keeper.go b/modules/apps/nft-transfer/keeper/keeper.go new file mode 100644 index 00000000000..1603145a034 --- /dev/null +++ b/modules/apps/nft-transfer/keeper/keeper.go @@ -0,0 +1,22 @@ +package keeper + +import ( + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" + + "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" +) + +// Keeper defines the IBC fungible transfer keeper +type Keeper struct { + storeKey sdk.StoreKey + cdc codec.BinaryCodec + + ics4Wrapper types.ICS4Wrapper + channelKeeper types.ChannelKeeper + portKeeper types.PortKeeper + authKeeper types.AccountKeeper + bankKeeper types.BankKeeper + scopedKeeper capabilitykeeper.ScopedKeeper +} diff --git a/modules/apps/nft-transfer/module.go b/modules/apps/nft-transfer/module.go new file mode 100644 index 00000000000..ba8c8e338f2 --- /dev/null +++ b/modules/apps/nft-transfer/module.go @@ -0,0 +1 @@ +package nt diff --git a/modules/apps/nft-transfer/types/codec.go b/modules/apps/nft-transfer/types/codec.go new file mode 100644 index 00000000000..4615d4a228c --- /dev/null +++ b/modules/apps/nft-transfer/types/codec.go @@ -0,0 +1,26 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +// RegisterInterfaces register the ibc transfer module interfaces to protobuf +// Any. +func RegisterInterfaces(registry codectypes.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), &MsgTransfer{}) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} + +var ( + + // ModuleCdc references the global x/ibc-transfer module codec. Note, the codec + // should ONLY be used in certain instances of tests and for JSON encoding. + // + // The actual codec used for serialization should be provided to x/ibc transfer and + // defined at the application level. + ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) +) diff --git a/modules/apps/nft-transfer/types/expected_keeper.go b/modules/apps/nft-transfer/types/expected_keeper.go new file mode 100644 index 00000000000..2f0861fec6d --- /dev/null +++ b/modules/apps/nft-transfer/types/expected_keeper.go @@ -0,0 +1,16 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// NFTKeeper defines the expected nft keeper +type NFTKeeper interface { + SaveClass(ctx sdk.Context, classID, classURI string) error + Mint(ctx sdk.Context, classID, tokenID, tokenURI, receiver string) + Transfer(ctx sdk.Context, classID, tokenID, receiver string) + Burn(ctx sdk.Context, classID, tokenID string) + + GetOwner(ctx sdk.Context, classID string, nftID string) sdk.AccAddress + HasClass(ctx sdk.Context, classID string) bool +} From 29f29ac63fbcf0ce86eab131901f634173b8fd0a Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Mon, 30 May 2022 09:53:03 +0800 Subject: [PATCH 03/14] implement SendTransfer --- modules/apps/nft-transfer/ibc_module.go | 120 ++++----- modules/apps/nft-transfer/keeper/keeper.go | 31 ++- modules/apps/nft-transfer/keeper/relay.go | 234 ++++++++++++++++++ modules/apps/nft-transfer/types/ack.go | 27 ++ modules/apps/nft-transfer/types/errors.go | 15 ++ .../nft-transfer/types/expected_keeper.go | 34 ++- modules/apps/nft-transfer/types/keys.go | 50 ++++ modules/apps/nft-transfer/types/packet.go | 69 ++++++ 8 files changed, 513 insertions(+), 67 deletions(-) create mode 100644 modules/apps/nft-transfer/keeper/relay.go create mode 100644 modules/apps/nft-transfer/types/ack.go create mode 100644 modules/apps/nft-transfer/types/errors.go create mode 100644 modules/apps/nft-transfer/types/keys.go create mode 100644 modules/apps/nft-transfer/types/packet.go diff --git a/modules/apps/nft-transfer/ibc_module.go b/modules/apps/nft-transfer/ibc_module.go index fd9738f22d8..afa5ce450c0 100644 --- a/modules/apps/nft-transfer/ibc_module.go +++ b/modules/apps/nft-transfer/ibc_module.go @@ -1,7 +1,6 @@ package nt import ( - "fmt" "math" "strings" @@ -17,6 +16,10 @@ import ( ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" ) +var ( + _ porttypes.IBCModule = IBCModule{} +) + // IBCModule implements the ICS26 interface for transfer given the transfer keeper. type IBCModule struct { keeper keeper.Keeper @@ -29,8 +32,8 @@ func NewIBCModule(k keeper.Keeper) IBCModule { } } -// ValidateTransferChannelParams does validation of a newly created transfer channel. A transfer -// channel must be UNORDERED, use the correct port (by default 'transfer'), and use the current +// ValidateTransferChannelParams does validation of a newly created nft-transfer channel. A nft-transfer +// channel must be UNORDERED, use the correct port (by default 'nft-transfer'), and use the current // supported version. Only 2^32 channels are allowed to be created. func ValidateTransferChannelParams( ctx sdk.Context, @@ -46,7 +49,7 @@ func ValidateTransferChannelParams( return err } if channelSequence > uint64(math.MaxUint32) { - return sdkerrors.Wrapf(types.ErrMaxTransferChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, uint64(math.MaxUint32)) + return sdkerrors.Wrapf(types.ErrMaxTransferChannels, "channel sequence %d is greater than max allowed nft-transfer channels %d", channelSequence, uint64(math.MaxUint32)) } if order != channeltypes.UNORDERED { return sdkerrors.Wrapf(channeltypes.ErrInvalidChannelOrdering, "expected %s channel, got %s ", channeltypes.UNORDERED, order) @@ -179,29 +182,28 @@ func (im IBCModule) OnRecvPacket( var data types.NonFungibleTokenPacketData if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { - ack = channeltypes.NewErrorAcknowledgement("cannot unmarshal ICS-20 transfer packet data") + ack = channeltypes.NewErrorAcknowledgement("cannot unmarshal ICS-721 nft-transfer packet data") } // only attempt the application logic if the packet data // was successfully decoded if ack.Success() { - err := im.keeper.OnRecvPacket(ctx, packet, data) - if err != nil { + if err := im.keeper.OnRecvPacket(ctx, packet, data); err != nil { ack = types.NewErrorAcknowledgement(err) } } - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypePacket, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - sdk.NewAttribute(sdk.AttributeKeySender, data.Sender), - sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), - sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), - sdk.NewAttribute(types.AttributeKeyAmount, data.Amount), - sdk.NewAttribute(types.AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success())), - ), - ) + // ctx.EventManager().EmitEvent( + // sdk.NewEvent( + // types.EventTypePacket, + // sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + // sdk.NewAttribute(sdk.AttributeKeySender, data.Sender), + // sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), + // sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), + // sdk.NewAttribute(types.AttributeKeyAmount, data.Amount), + // sdk.NewAttribute(types.AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success())), + // ), + // ) // NOTE: acknowledgement will be written synchronously during IBC handler execution. return ack @@ -216,45 +218,45 @@ func (im IBCModule) OnAcknowledgementPacket( ) error { var ack channeltypes.Acknowledgement if err := types.ModuleCdc.UnmarshalJSON(acknowledgement, &ack); err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet acknowledgement: %v", err) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-721 transfer packet acknowledgement: %v", err) } - var data types.FungibleTokenPacketData + var data types.NonFungibleTokenPacketData if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data: %s", err.Error()) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-721 transfer packet data: %s", err.Error()) } if err := im.keeper.OnAcknowledgementPacket(ctx, packet, data, ack); err != nil { return err } - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypePacket, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - sdk.NewAttribute(sdk.AttributeKeySender, data.Sender), - sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), - sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), - sdk.NewAttribute(types.AttributeKeyAmount, data.Amount), - sdk.NewAttribute(types.AttributeKeyAck, ack.String()), - ), - ) - - switch resp := ack.Response.(type) { - case *channeltypes.Acknowledgement_Result: - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypePacket, - sdk.NewAttribute(types.AttributeKeyAckSuccess, string(resp.Result)), - ), - ) - case *channeltypes.Acknowledgement_Error: - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypePacket, - sdk.NewAttribute(types.AttributeKeyAckError, resp.Error), - ), - ) - } + // ctx.EventManager().EmitEvent( + // sdk.NewEvent( + // types.EventTypePacket, + // sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + // sdk.NewAttribute(sdk.AttributeKeySender, data.Sender), + // sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), + // sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), + // sdk.NewAttribute(types.AttributeKeyAmount, data.Amount), + // sdk.NewAttribute(types.AttributeKeyAck, ack.String()), + // ), + // ) + + // switch resp := ack.Response.(type) { + // case *channeltypes.Acknowledgement_Result: + // ctx.EventManager().EmitEvent( + // sdk.NewEvent( + // types.EventTypePacket, + // sdk.NewAttribute(types.AttributeKeyAckSuccess, string(resp.Result)), + // ), + // ) + // case *channeltypes.Acknowledgement_Error: + // ctx.EventManager().EmitEvent( + // sdk.NewEvent( + // types.EventTypePacket, + // sdk.NewAttribute(types.AttributeKeyAckError, resp.Error), + // ), + // ) + // } return nil } @@ -267,22 +269,22 @@ func (im IBCModule) OnTimeoutPacket( ) error { var data types.NonFungibleTokenPacketData if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data: %s", err.Error()) + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-721 transfer packet data: %s", err.Error()) } // refund tokens if err := im.keeper.OnTimeoutPacket(ctx, packet, data); err != nil { return err } - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeTimeout, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - sdk.NewAttribute(types.AttributeKeyRefundReceiver, data.Sender), - sdk.NewAttribute(types.AttributeKeyRefundDenom, data.Denom), - sdk.NewAttribute(types.AttributeKeyRefundAmount, data.Amount), - ), - ) + // ctx.EventManager().EmitEvent( + // sdk.NewEvent( + // types.EventTypeTimeout, + // sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + // sdk.NewAttribute(types.AttributeKeyRefundReceiver, data.Sender), + // sdk.NewAttribute(types.AttributeKeyRefundDenom, data.Denom), + // sdk.NewAttribute(types.AttributeKeyRefundAmount, data.Amount), + // ), + // ) return nil } diff --git a/modules/apps/nft-transfer/keeper/keeper.go b/modules/apps/nft-transfer/keeper/keeper.go index 1603145a034..2c99832bbae 100644 --- a/modules/apps/nft-transfer/keeper/keeper.go +++ b/modules/apps/nft-transfer/keeper/keeper.go @@ -4,19 +4,38 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" ) -// Keeper defines the IBC fungible transfer keeper +// Keeper defines the IBC non fungible transfer keeper type Keeper struct { storeKey sdk.StoreKey cdc codec.BinaryCodec ics4Wrapper types.ICS4Wrapper channelKeeper types.ChannelKeeper - portKeeper types.PortKeeper - authKeeper types.AccountKeeper - bankKeeper types.BankKeeper - scopedKeeper capabilitykeeper.ScopedKeeper + nftKeeper types.NFTKeeper + // portKeeper types.PortKeeper + // authKeeper types.AccountKeeper + // bankKeeper types.BankKeeper + scopedKeeper capabilitykeeper.ScopedKeeper +} + +// GetPort returns the portID for the transfer module. +func (k Keeper) GetPort(ctx sdk.Context) string { + store := ctx.KVStore(k.storeKey) + return string(store.Get(types.PortKey)) +} + +// AuthenticateCapability wraps the scopedKeeper's AuthenticateCapability function +func (k Keeper) AuthenticateCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) bool { + return k.scopedKeeper.AuthenticateCapability(ctx, cap, name) +} + +// ClaimCapability allows the nft-transfer module that can claim a capability that IBC module +// passes to it +func (k Keeper) ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) error { + return k.scopedKeeper.ClaimCapability(ctx, cap, name) } diff --git a/modules/apps/nft-transfer/keeper/relay.go b/modules/apps/nft-transfer/keeper/relay.go new file mode 100644 index 00000000000..1ca1e790a1d --- /dev/null +++ b/modules/apps/nft-transfer/keeper/relay.go @@ -0,0 +1,234 @@ +package keeper + +import ( + "fmt" + + "github.com/armon/go-metrics" + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" + clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/v3/modules/core/24-host" + coretypes "github.com/cosmos/ibc-go/v3/modules/core/types" +) + +// SendTransfer handles nft-transfer sending logic. +// A sending chain may be acting as a source or sink zone. +// +// when a chain is sending tokens across a port and channel which are +// not equal to the last prefixed port and channel pair, it is acting as a source zone. +// when tokens are sent from a source zone, the destination port and +// channel will be prefixed onto the classId (once the tokens are received) +// adding another hop to the tokens record. +// +// when a chain is sending tokens across a port and channel which are +// equal to the last prefixed port and channel pair, it is acting as a sink zone. +// when tokens are sent from a sink zone, the last prefixed port and channel +// pair on the classId is removed (once the tokens are received), undoing the last hop in the tokens record. +// +// For example, assume these steps of transfer occur: +// A -> B -> C -> A -> C -> B -> A +// +//| sender chain | receiver chain | +//| :-----: | -------------------------: | :------------: | :------------: | -------------------------: | :-----: | +//| chain | classID | (port,channel) | (port,channel) | classID | chain | +//| A | nftClass | (p1,c1) | (p2,c2) | p2/c2/nftClass | B | +//| B | p2/c2/nftClass | (p3,c3) | (p4,c4) | p4/c4/p2/c2/nftClass | C | +//| C | p4/c4/p2/c2/nftClass | (p5,c5) | (p6,c6) | p6/c6/p4/c4/p2/c2/nftClass | A | +//| A | p6/c6/p4/c4/p2/c2/nftClass | (p6,c6) | (p5,c5) | p4/c4/p2/c2/nftClass | C | +//| C | p4/c4/p2/c2/nftClass | (p4,c4) | (p3,c3) | p2/c2/nftClass | B | +//| B | p2/c2/nftClass | (p2,c2) | (p1,c1) | nftClass | A | +// +func (k Keeper) SendTransfer( + ctx sdk.Context, + sourcePort, + sourceChannel, + classID string, + tokenIDs []string, + sender sdk.AccAddress, + receiver string, + timeoutHeight clienttypes.Height, + timeoutTimestamp uint64, +) error { + sourceChannelEnd, found := k.channelKeeper.GetChannel(ctx, sourcePort, sourceChannel) + if !found { + return sdkerrors.Wrapf(channeltypes.ErrChannelNotFound, "port ID (%s) channel ID (%s)", sourcePort, sourceChannel) + } + + destinationPort := sourceChannelEnd.GetCounterparty().GetPortID() + destinationChannel := sourceChannelEnd.GetCounterparty().GetChannelID() + + // get the next sequence + sequence, found := k.channelKeeper.GetNextSequenceSend(ctx, sourcePort, sourceChannel) + if !found { + return sdkerrors.Wrapf( + channeltypes.ErrSequenceSendNotFound, + "source port: %s, source channel: %s", sourcePort, sourceChannel, + ) + } + + // See spec for this logic: https://github.com/cosmos/ibc/blob/master/spec/app/ics-721-nft-transfer/README.md#packet-relay + channelCap, ok := k.scopedKeeper.GetCapability(ctx, host.ChannelCapabilityPath(sourcePort, sourceChannel)) + if !ok { + return sdkerrors.Wrap(channeltypes.ErrChannelCapabilityNotFound, "module does not own channel capability") + } + + class, exist := k.nftKeeper.GetClass(ctx, classID) + if !exist { + return sdkerrors.Wrap(types.ErrInvalidClassID, "classId not exist") + } + + var tokenURIs []string + for _, tokenID := range tokenIDs { + tokenURI, err := k.handleToken(ctx, + sourcePort, + sourceChannel, + classID, + tokenID, + sender, + ) + if err != nil { + return err + } + tokenURIs = append(tokenURIs, tokenURI) + } + + labels := []metrics.Label{ + telemetry.NewLabel(coretypes.LabelDestinationPort, destinationPort), + telemetry.NewLabel(coretypes.LabelDestinationChannel, destinationChannel), + } + + packetData := types.NewNonFungibleTokenPacketData( + classID, class.GetUri(), tokenIDs, tokenURIs, sender.String(), receiver, + ) + + packet := channeltypes.NewPacket( + packetData.GetBytes(), + sequence, + sourcePort, + sourceChannel, + destinationPort, + destinationChannel, + timeoutHeight, + timeoutTimestamp, + ) + + if err := k.ics4Wrapper.SendPacket(ctx, channelCap, packet); err != nil { + return err + } + + defer func() { + telemetry.SetGaugeWithLabels( + []string{"tx", "msg", "ibc", "nft-transfer"}, + float32(len(tokenIDs)), + []metrics.Label{telemetry.NewLabel("class_id", class.GetUri())}, + ) + + telemetry.IncrCounterWithLabels( + []string{"ibc", types.ModuleName, "send"}, + 1, + labels, + ) + }() + + return nil +} + +// OnRecvPacket processes a cross chain fungible token transfer. If the +// sender chain is the source of minted tokens then vouchers will be minted +// and sent to the receiving address. Otherwise if the sender chain is sending +// back tokens this chain originally transferred to it, the tokens are +// unescrowed and sent to the receiving address. +func (k Keeper) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet, data types.NonFungibleTokenPacketData) error { + + // defer func() { + // if transferAmount.IsInt64() { + // telemetry.SetGaugeWithLabels( + // []string{"ibc", types.ModuleName, "packet", "receive"}, + // float32(transferAmount.Int64()), + // []metrics.Label{telemetry.NewLabel(coretypes.LabelDenom, data.Denom)}, + // ) + // } + + // telemetry.IncrCounterWithLabels( + // []string{"ibc", types.ModuleName, "receive"}, + // 1, + // append( + // labels, telemetry.NewLabel(coretypes.LabelSource, "false"), + // ), + // ) + // }() + + return nil +} + +// OnAcknowledgementPacket responds to the the success or failure of a packet +// acknowledgement written on the receiving chain. If the acknowledgement +// was a success then nothing occurs. If the acknowledgement failed, then +// the sender is refunded their tokens using the refundPacketToken function. +func (k Keeper) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Packet, data types.NonFungibleTokenPacketData, ack channeltypes.Acknowledgement) error { + switch ack.Response.(type) { + case *channeltypes.Acknowledgement_Error: + return k.refundPacketToken(ctx, packet, data) + default: + // the acknowledgement succeeded on the receiving chain so nothing + // needs to be executed and no error needs to be returned + return nil + } +} + +// OnTimeoutPacket refunds the sender since the original packet sent was +// never received and has been timed out. +func (k Keeper) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet, data types.NonFungibleTokenPacketData) error { + return k.refundPacketToken(ctx, packet, data) +} + +// refundPacketToken will unescrow and send back the tokens back to sender +// if the sending chain was the source chain. Otherwise, the sent tokens +// were burnt in the original send so new tokens are minted and sent to +// the sending address. +func (k Keeper) refundPacketToken(ctx sdk.Context, packet channeltypes.Packet, data types.NonFungibleTokenPacketData) error { + return nil +} + +// handleToken will escrow the tokens to escrow account +// if the token was away from origin chain . Otherwise, the sent tokens +// were burnt in the sending chain and will unescrow the token to receiver +// in the destination chain +func (k Keeper) handleToken(ctx sdk.Context, + sourcePort, + sourceChannel, + classID, + tokenID string, + sender sdk.AccAddress, +) (string, error) { + nft, exist := k.nftKeeper.GetNFT(ctx, classID, tokenID) + if !exist { + return "", sdkerrors.Wrap(types.ErrInvalidTokenID, "tokenId not exist") + } + + owner := k.nftKeeper.GetOwner(ctx, classID, tokenID) + if !sender.Equals(owner) { + return "", sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "not token owner") + } + + isAwayFromOrigin := k.isAwayFromOrigin(sourcePort, sourceChannel, classID) + if !isAwayFromOrigin { + return nft.GetUri(), k.nftKeeper.Burn(ctx, classID, tokenID) + } + + // create the escrow address for the tokens + escrowAddress := types.GetEscrowAddress(sourcePort, sourceChannel) + if err := k.nftKeeper.Transfer(ctx, classID, tokenID, escrowAddress.String()); err != nil { + return "", err + } + return nft.GetUri(), nil +} + +func (k Keeper) isAwayFromOrigin(sourcePort, sourceChannel, classID string) bool { + prefixClassID := fmt.Sprintf("%s/%s", sourcePort, sourceChannel) + return classID[:len(prefixClassID)] != prefixClassID +} diff --git a/modules/apps/nft-transfer/types/ack.go b/modules/apps/nft-transfer/types/ack.go new file mode 100644 index 00000000000..6512f2e8371 --- /dev/null +++ b/modules/apps/nft-transfer/types/ack.go @@ -0,0 +1,27 @@ +package types + +import ( + "fmt" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" +) + +const ( + // ackErrorString defines a string constant included in error acknowledgements + // NOTE: Changing this const is state machine breaking as acknowledgements are written into state + ackErrorString = "error handling packet on destination chain: see events for details" +) + +// NewErrorAcknowledgement returns a deterministic error string which may be used in +// the packet acknowledgement. +func NewErrorAcknowledgement(err error) channeltypes.Acknowledgement { + // the ABCI code is included in the abcitypes.ResponseDeliverTx hash + // constructed in Tendermint and is therefore deterministic + _, code, _ := sdkerrors.ABCIInfo(err, false) // discard non-determinstic codespace and log values + + errorString := fmt.Sprintf("ABCI code: %d: %s", code, ackErrorString) + + return channeltypes.NewErrorAcknowledgement(errorString) +} diff --git a/modules/apps/nft-transfer/types/errors.go b/modules/apps/nft-transfer/types/errors.go new file mode 100644 index 00000000000..6873d0ad5c1 --- /dev/null +++ b/modules/apps/nft-transfer/types/errors.go @@ -0,0 +1,15 @@ +package types + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// IBC transfer sentinel errors +var ( + ErrInvalidPacketTimeout = sdkerrors.Register(ModuleName, 2, "invalid packet timeout") + ErrInvalidVersion = sdkerrors.Register(ModuleName, 3, "invalid ICS721 version") + ErrMaxTransferChannels = sdkerrors.Register(ModuleName, 4, "max nft-transfer channels") + ErrInvalidClassID = sdkerrors.Register(ModuleName, 5, "invalid class id") + ErrInvalidTokenID = sdkerrors.Register(ModuleName, 5, "invalid token id") + ErrInvalidPacket = sdkerrors.Register(ModuleName, 5, "invalid non-fungible token packet") +) diff --git a/modules/apps/nft-transfer/types/expected_keeper.go b/modules/apps/nft-transfer/types/expected_keeper.go index 2f0861fec6d..0ab80ecefd2 100644 --- a/modules/apps/nft-transfer/types/expected_keeper.go +++ b/modules/apps/nft-transfer/types/expected_keeper.go @@ -2,15 +2,45 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + + channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" ) +// Class defines the expected nft class +type Class interface { + GetId() string + GetUri() string +} + +// NFT defines the expected nft +type NFT interface { + GetId() string + GetUri() string +} + // NFTKeeper defines the expected nft keeper +// TODO type NFTKeeper interface { SaveClass(ctx sdk.Context, classID, classURI string) error Mint(ctx sdk.Context, classID, tokenID, tokenURI, receiver string) - Transfer(ctx sdk.Context, classID, tokenID, receiver string) - Burn(ctx sdk.Context, classID, tokenID string) + Transfer(ctx sdk.Context, classID, tokenID, receiver string) error + Burn(ctx sdk.Context, classID, tokenID string) error GetOwner(ctx sdk.Context, classID string, nftID string) sdk.AccAddress HasClass(ctx sdk.Context, classID string) bool + GetClass(ctx sdk.Context, classID string) (Class, bool) + GetNFT(ctx sdk.Context, classID, tokenID string) (NFT, bool) +} + +// ICS4Wrapper defines the expected ICS4Wrapper for middleware +type ICS4Wrapper interface { + SendPacket(ctx sdk.Context, channelCap *capabilitytypes.Capability, packet ibcexported.PacketI) error +} + +// ChannelKeeper defines the expected IBC channel keeper +type ChannelKeeper interface { + GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) + GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) } diff --git a/modules/apps/nft-transfer/types/keys.go b/modules/apps/nft-transfer/types/keys.go new file mode 100644 index 00000000000..241cba99e8f --- /dev/null +++ b/modules/apps/nft-transfer/types/keys.go @@ -0,0 +1,50 @@ +package types + +import ( + "crypto/sha256" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // ModuleName defines the IBC nft-transfer name + ModuleName = "nft-transfer" + + // Version defines the current version the IBC nft-tranfer + // module supports + Version = "ics721-1" + + // PortID is the default port id that nft-tranfer module binds to + PortID = "nft-tranfer" + + // StoreKey is the store key string for IBC nft-tranfer + StoreKey = ModuleName + + // RouterKey is the message route for IBC nft-tranfer + RouterKey = ModuleName + + // QuerierRoute is the querier route for IBC nft-tranfer + QuerierRoute = ModuleName +) + +var ( + // PortKey defines the key to store the port ID in store + PortKey = []byte{0x01} +) + +// GetEscrowAddress returns the escrow address for the specified channel. +// The escrow address follows the format as outlined in ADR 028: +// https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md +func GetEscrowAddress(portID, channelID string) sdk.AccAddress { + // a slash is used to create domain separation between port and channel identifiers to + // prevent address collisions between escrow addresses created for different channels + contents := fmt.Sprintf("%s/%s", portID, channelID) + + // ADR 028 AddressHash construction + preImage := []byte(Version) + preImage = append(preImage, 0) + preImage = append(preImage, contents...) + hash := sha256.Sum256(preImage) + return hash[:20] +} diff --git a/modules/apps/nft-transfer/types/packet.go b/modules/apps/nft-transfer/types/packet.go new file mode 100644 index 00000000000..961e5417ed6 --- /dev/null +++ b/modules/apps/nft-transfer/types/packet.go @@ -0,0 +1,69 @@ +package types + +import ( + "strings" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var ( + // DefaultRelativePacketTimeoutHeight is the default packet timeout height (in blocks) relative + // to the current block height of the counterparty chain provided by the client state. The + // timeout is disabled when set to 0. + DefaultRelativePacketTimeoutHeight = "0-1000" + + // DefaultRelativePacketTimeoutTimestamp is the default packet timeout timestamp (in nanoseconds) + // relative to the current block timestamp of the counterparty chain provided by the client + // state. The timeout is disabled when set to 0. The default is currently set to a 10 minute + // timeout. + DefaultRelativePacketTimeoutTimestamp = uint64((time.Duration(10) * time.Minute).Nanoseconds()) +) + +// NewNonFungibleTokenPacketData contructs a new NonFungibleTokenPacketData instance +func NewNonFungibleTokenPacketData( + classID, classURI string, + tokenIDs, tokenURI []string, + sender, receiver string, +) NonFungibleTokenPacketData { + return NonFungibleTokenPacketData{ + ClassId: classID, + ClassUri: classURI, + TokenIds: tokenIDs, + TokenUris: tokenURI, + Sender: sender, + Receiver: receiver, + } +} + +// ValidateBasic is used for validating the nft transfer. +// NOTE: The addresses formats are not validated as the sender and recipient can have different +// formats defined by their corresponding chains that are not known to IBC. +func (nftpd NonFungibleTokenPacketData) ValidateBasic() error { + if strings.TrimSpace(nftpd.ClassId) == "" { + return sdkerrors.Wrap(ErrInvalidClassID, "classId cannot be blank") + } + + if len(nftpd.TokenIds) == 0 { + return sdkerrors.Wrap(ErrInvalidTokenID, "tokenId cannot be blank") + } + + if len(nftpd.TokenIds) != len(nftpd.TokenUris) { + return sdkerrors.Wrap(ErrInvalidPacket, "tokenIds and tokenUris lengths do not match") + } + + if strings.TrimSpace(nftpd.Sender) == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be blank") + } + + if strings.TrimSpace(nftpd.Receiver) == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "receiver address cannot be blank") + } + return nil +} + +// GetBytes is a helper for serialising +func (nftpd NonFungibleTokenPacketData) GetBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&nftpd)) +} From fc47dcb504867d48340bbd89e6dbd8a901ed7881 Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Mon, 30 May 2022 10:18:56 +0800 Subject: [PATCH 04/14] add classTrace --- docs/ibc/proto-docs.md | 178 ++++++++ go.mod | 95 +---- modules/apps/nft-transfer/types/genesis.pb.go | 387 ++++++++++++++++++ .../apps/nft-transfer/types/transfer.pb.go | 376 +++++++++++++++++ .../nft_transfer/v1/genesis.proto | 14 + .../nft_transfer/v1/transfer.proto | 15 + 6 files changed, 971 insertions(+), 94 deletions(-) create mode 100644 modules/apps/nft-transfer/types/genesis.pb.go create mode 100644 modules/apps/nft-transfer/types/transfer.pb.go create mode 100644 proto/ibc/applications/nft_transfer/v1/genesis.proto create mode 100644 proto/ibc/applications/nft_transfer/v1/transfer.proto diff --git a/docs/ibc/proto-docs.md b/docs/ibc/proto-docs.md index db7c27316c4..4e27769c9f4 100644 --- a/docs/ibc/proto-docs.md +++ b/docs/ibc/proto-docs.md @@ -112,6 +112,21 @@ - [Type](#ibc.applications.interchain_accounts.v1.Type) +- [ibc/applications/nft_transfer/v1/transfer.proto](#ibc/applications/nft_transfer/v1/transfer.proto) + - [ClassTrace](#ibc.applications.nft_transfer.v1.ClassTrace) + +- [ibc/applications/nft_transfer/v1/genesis.proto](#ibc/applications/nft_transfer/v1/genesis.proto) + - [GenesisState](#ibc.applications.nft_transfer.v1.GenesisState) + +- [ibc/applications/nft_transfer/v1/packet.proto](#ibc/applications/nft_transfer/v1/packet.proto) + - [NonFungibleTokenPacketData](#ibc.applications.nft_transfer.v1.NonFungibleTokenPacketData) + +- [ibc/applications/nft_transfer/v1/tx.proto](#ibc/applications/nft_transfer/v1/tx.proto) + - [MsgTransfer](#ibc.applications.nft_transfer.v1.MsgTransfer) + - [MsgTransferResponse](#ibc.applications.nft_transfer.v1.MsgTransferResponse) + + - [Msg](#ibc.applications.nft_transfer.v1.Msg) + - [ibc/applications/transfer/v1/transfer.proto](#ibc/applications/transfer/v1/transfer.proto) - [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) - [Params](#ibc.applications.transfer.v1.Params) @@ -1731,6 +1746,169 @@ host + +

Top

+ +## ibc/applications/nft_transfer/v1/transfer.proto + + + + + +### ClassTrace +ClassTrace contains the base classID for ICS721 non-fungible tokens and the +source tracing information path. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `path` | [string](#string) | | path defines the chain of port/channel identifiers used for tracing the source of the non-fungible token. | +| `base_class_id` | [string](#string) | | base classID of the relayed non-fungible token. | + + + + + + + + + + + + + + + + +

Top

+ +## ibc/applications/nft_transfer/v1/genesis.proto + + + + + +### GenesisState +GenesisState defines the ibc-nft-transfer genesis state + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | | +| `traces` | [ClassTrace](#ibc.applications.nft_transfer.v1.ClassTrace) | repeated | | + + + + + + + + + + + + + + + + +

Top

+ +## ibc/applications/nft_transfer/v1/packet.proto + + + + + +### NonFungibleTokenPacketData +NonFungibleTokenPacketData defines a struct for the packet payload +See NonFungibleTokenPacketData spec: +https://github.com/cosmos/ibc/tree/master/spec/app/ics-721-nft-transfer#data-structures + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `class_id` | [string](#string) | | the class_id of tokens to be transferred | +| `class_uri` | [string](#string) | | the class_uri of tokens to be transferred | +| `token_ids` | [string](#string) | repeated | the non fungible tokens to be transferred | +| `token_uris` | [string](#string) | repeated | the non fungible tokens's uri to be transferred | +| `sender` | [string](#string) | | the sender address | +| `receiver` | [string](#string) | | the recipient address on the destination chain | + + + + + + + + + + + + + + + + +

Top

+ +## ibc/applications/nft_transfer/v1/tx.proto + + + + + +### MsgTransfer +MsgTransfer defines a msg to transfer non fungible tokens between +ICS721 enabled chains. See ICS Spec here: +https://github.com/cosmos/ibc/tree/master/spec/app/ics-721-nft-transfer#data-structures + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `source_port` | [string](#string) | | the port on which the packet will be sent | +| `source_channel` | [string](#string) | | the channel by which the packet will be sent | +| `class_id` | [string](#string) | | the class_id of tokens to be transferred | +| `token_ids` | [string](#string) | repeated | the non fungible tokens to be transferred | +| `sender` | [string](#string) | | the sender address | +| `receiver` | [string](#string) | | the recipient address on the destination chain | +| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Timeout height relative to the current block height. The timeout is disabled when set to 0. | +| `timeout_timestamp` | [uint64](#uint64) | | Timeout timestamp in absolute nanoseconds since unix epoch. The timeout is disabled when set to 0. | + + + + + + + + +### MsgTransferResponse +MsgTransferResponse defines the Msg/Transfer response type. + + + + + + + + + + + + + + +### Msg +Msg defines the ibc/nft-transfer Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Transfer` | [MsgTransfer](#ibc.applications.nft_transfer.v1.MsgTransfer) | [MsgTransferResponse](#ibc.applications.nft_transfer.v1.MsgTransferResponse) | Transfer defines a rpc handler method for MsgTransfer. | | + + + + +

Top

diff --git a/go.mod b/go.mod index e595ea97f26..fc1b62d06ea 100644 --- a/go.mod +++ b/go.mod @@ -26,97 +26,4 @@ require ( gopkg.in/yaml.v2 v2.4.0 ) -require ( - filippo.io/edwards25519 v1.0.0-beta.2 // indirect - github.com/99designs/keyring v1.1.6 // indirect - github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect - github.com/DataDog/zstd v1.4.5 // indirect - github.com/Workiva/go-datastructures v1.0.53 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/bgentry/speakeasy v0.1.0 // indirect - github.com/btcsuite/btcd v0.22.0-beta // indirect - github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/coinbase/rosetta-sdk-go v0.7.0 // indirect - github.com/cosmos/btcutil v1.0.4 // indirect - github.com/cosmos/go-bip39 v1.0.0 // indirect - github.com/cosmos/iavl v0.17.3 // indirect - github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect - github.com/cosmos/ledger-go v0.9.2 // indirect - github.com/danieljoos/wincred v1.0.2 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect - github.com/dgraph-io/badger/v2 v2.2007.2 // indirect - github.com/dgraph-io/ristretto v0.0.3 // indirect - github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect - github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect - github.com/felixge/httpsnoop v1.0.1 // indirect - github.com/fsnotify/fsnotify v1.5.1 // indirect - github.com/gin-gonic/gin v1.7.0 // indirect - github.com/go-kit/kit v0.12.0 // indirect - github.com/go-kit/log v0.2.0 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect - github.com/gogo/gateway v1.1.0 // indirect - github.com/golang/snappy v0.0.3 // indirect - github.com/google/btree v1.0.0 // indirect - github.com/google/orderedcode v0.0.1 // indirect - github.com/gorilla/handlers v1.5.1 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect - github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect - github.com/gtank/merlin v0.1.1 // indirect - github.com/gtank/ristretto255 v0.1.2 // indirect - github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect - github.com/improbable-eng/grpc-web v0.14.1 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/jmhodges/levigo v1.0.0 // indirect - github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect - github.com/klauspost/compress v1.13.6 // indirect - github.com/lib/pq v1.10.4 // indirect - github.com/libp2p/go-buffer-pool v0.0.2 // indirect - github.com/magiconair/properties v1.8.6 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect - github.com/minio/highwayhash v1.0.2 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.4.3 // indirect - github.com/mtibben/percent v0.2.1 // indirect - github.com/pelletier/go-toml v1.9.4 // indirect - github.com/pelletier/go-toml/v2 v2.0.0-beta.8 // indirect - github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.12.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect - github.com/rs/cors v1.8.2 // indirect - github.com/rs/zerolog v1.23.0 // indirect - github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect - github.com/spf13/afero v1.8.2 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/subosito/gotenv v1.2.0 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect - github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect - github.com/tendermint/btcd v0.1.1 // indirect - github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect - github.com/tendermint/go-amino v0.16.0 // indirect - github.com/zondax/hid v0.9.0 // indirect - go.etcd.io/bbolt v1.3.6 // indirect - golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect - golang.org/x/net v0.0.0-20220412020605-290c469a71a5 // indirect - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/text v0.3.7 // indirect - gopkg.in/ini.v1 v1.66.4 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - nhooyr.io/websocket v1.8.6 // indirect -) +require github.com/gin-gonic/gin v1.7.0 // indirect diff --git a/modules/apps/nft-transfer/types/genesis.pb.go b/modules/apps/nft-transfer/types/genesis.pb.go new file mode 100644 index 00000000000..3b51593f3d3 --- /dev/null +++ b/modules/apps/nft-transfer/types/genesis.pb.go @@ -0,0 +1,387 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/applications/nft_transfer/v1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState defines the ibc-nft-transfer genesis state +type GenesisState struct { + PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` + Traces []ClassTrace `protobuf:"bytes,2,rep,name=traces,proto3" json:"traces"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_1971f5a454018ffc, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetPortId() string { + if m != nil { + return m.PortId + } + return "" +} + +func (m *GenesisState) GetTraces() []ClassTrace { + if m != nil { + return m.Traces + } + return nil +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "ibc.applications.nft_transfer.v1.GenesisState") +} + +func init() { + proto.RegisterFile("ibc/applications/nft_transfer/v1/genesis.proto", fileDescriptor_1971f5a454018ffc) +} + +var fileDescriptor_1971f5a454018ffc = []byte{ + // 261 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x8f, 0xb1, 0x4e, 0xc3, 0x30, + 0x10, 0x86, 0x13, 0x40, 0x41, 0x04, 0xa6, 0x08, 0x89, 0xaa, 0x83, 0x89, 0x98, 0x3a, 0x50, 0x5b, + 0xa5, 0x23, 0x5b, 0x19, 0x10, 0x8c, 0x05, 0x16, 0x96, 0xca, 0x71, 0xdc, 0x60, 0x29, 0xc9, 0x59, + 0xbe, 0x6b, 0x24, 0xde, 0x82, 0xc7, 0xea, 0xd8, 0x91, 0x09, 0xa1, 0xe4, 0x45, 0x90, 0x53, 0x54, + 0x75, 0xeb, 0xf6, 0xdb, 0xfa, 0xef, 0xbb, 0xfb, 0x62, 0x6e, 0x32, 0x25, 0xa4, 0xb5, 0xa5, 0x51, + 0x92, 0x0c, 0xd4, 0x28, 0xea, 0x25, 0x2d, 0xc8, 0xc9, 0x1a, 0x97, 0xda, 0x89, 0x66, 0x22, 0x0a, + 0x5d, 0x6b, 0x34, 0xc8, 0xad, 0x03, 0x82, 0x24, 0x35, 0x99, 0xe2, 0xfb, 0x7d, 0xbe, 0xdf, 0xe7, + 0xcd, 0x64, 0x28, 0x0e, 0x12, 0x77, 0xed, 0x1e, 0x39, 0xbc, 0x2c, 0xa0, 0x80, 0x3e, 0x0a, 0x9f, + 0xb6, 0xbf, 0x37, 0x18, 0x5f, 0x3c, 0x6e, 0x37, 0xbf, 0x90, 0x24, 0x9d, 0x5c, 0xc5, 0xa7, 0x16, + 0x1c, 0x2d, 0x4c, 0x3e, 0x08, 0xd3, 0x70, 0x74, 0x36, 0x8f, 0xfc, 0xf3, 0x29, 0x4f, 0x9e, 0xe3, + 0x88, 0x9c, 0x54, 0x1a, 0x07, 0x47, 0xe9, 0xf1, 0xe8, 0xfc, 0xee, 0x96, 0x1f, 0x3a, 0x91, 0x3f, + 0x94, 0x12, 0xf1, 0xd5, 0x0f, 0xcd, 0x4e, 0xd6, 0x3f, 0xd7, 0xc1, 0xfc, 0x9f, 0x30, 0x7b, 0x5b, + 0xb7, 0x2c, 0xdc, 0xb4, 0x2c, 0xfc, 0x6d, 0x59, 0xf8, 0xd5, 0xb1, 0x60, 0xd3, 0xb1, 0xe0, 0xbb, + 0x63, 0xc1, 0xfb, 0x7d, 0x61, 0xe8, 0x63, 0x95, 0x71, 0x05, 0x95, 0x50, 0x80, 0x15, 0xa0, 0xf7, + 0x1c, 0x17, 0x20, 0x9a, 0xa9, 0xa8, 0x20, 0x5f, 0x95, 0x1a, 0xbd, 0x75, 0x6f, 0x3b, 0xde, 0xd9, + 0xd2, 0xa7, 0xd5, 0x98, 0x45, 0xbd, 0xd2, 0xf4, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x13, 0x89, 0x34, + 0xae, 0x6d, 0x01, 0x00, 0x00, +} + +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Traces) > 0 { + for iNdEx := len(m.Traces) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Traces[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.PortId) > 0 { + i -= len(m.PortId) + copy(dAtA[i:], m.PortId) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.PortId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.PortId) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if len(m.Traces) > 0 { + for _, e := range m.Traces { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PortId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PortId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Traces", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Traces = append(m.Traces, ClassTrace{}) + if err := m.Traces[len(m.Traces)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/apps/nft-transfer/types/transfer.pb.go b/modules/apps/nft-transfer/types/transfer.pb.go new file mode 100644 index 00000000000..9c6e10f7492 --- /dev/null +++ b/modules/apps/nft-transfer/types/transfer.pb.go @@ -0,0 +1,376 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/applications/nft_transfer/v1/transfer.proto + +package types + +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// ClassTrace contains the base classID for ICS721 non-fungible tokens and the +// source tracing information path. +type ClassTrace struct { + // path defines the chain of port/channel identifiers used for tracing the + // source of the non-fungible token. + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + // base classID of the relayed non-fungible token. + BaseClassId string `protobuf:"bytes,2,opt,name=base_class_id,json=baseClassId,proto3" json:"base_class_id,omitempty"` +} + +func (m *ClassTrace) Reset() { *m = ClassTrace{} } +func (m *ClassTrace) String() string { return proto.CompactTextString(m) } +func (*ClassTrace) ProtoMessage() {} +func (*ClassTrace) Descriptor() ([]byte, []int) { + return fileDescriptor_fbbec0a5a50746a6, []int{0} +} +func (m *ClassTrace) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ClassTrace) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ClassTrace.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ClassTrace) XXX_Merge(src proto.Message) { + xxx_messageInfo_ClassTrace.Merge(m, src) +} +func (m *ClassTrace) XXX_Size() int { + return m.Size() +} +func (m *ClassTrace) XXX_DiscardUnknown() { + xxx_messageInfo_ClassTrace.DiscardUnknown(m) +} + +var xxx_messageInfo_ClassTrace proto.InternalMessageInfo + +func (m *ClassTrace) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +func (m *ClassTrace) GetBaseClassId() string { + if m != nil { + return m.BaseClassId + } + return "" +} + +func init() { + proto.RegisterType((*ClassTrace)(nil), "ibc.applications.nft_transfer.v1.ClassTrace") +} + +func init() { + proto.RegisterFile("ibc/applications/nft_transfer/v1/transfer.proto", fileDescriptor_fbbec0a5a50746a6) +} + +var fileDescriptor_fbbec0a5a50746a6 = []byte{ + // 218 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0xcf, 0x4c, 0x4a, 0xd6, + 0x4f, 0x2c, 0x28, 0xc8, 0xc9, 0x4c, 0x4e, 0x2c, 0xc9, 0xcc, 0xcf, 0x2b, 0xd6, 0xcf, 0x4b, 0x2b, + 0x89, 0x2f, 0x29, 0x4a, 0xcc, 0x2b, 0x4e, 0x4b, 0x2d, 0xd2, 0x2f, 0x33, 0xd4, 0x87, 0xb1, 0xf5, + 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, 0x85, 0x14, 0x32, 0x93, 0x92, 0xf5, 0x90, 0x35, 0xe8, 0x21, 0x6b, + 0xd0, 0x2b, 0x33, 0x54, 0x72, 0xe1, 0xe2, 0x72, 0xce, 0x49, 0x2c, 0x2e, 0x0e, 0x29, 0x4a, 0x4c, + 0x4e, 0x15, 0x12, 0xe2, 0x62, 0x29, 0x48, 0x2c, 0xc9, 0x90, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, + 0x02, 0xb3, 0x85, 0x94, 0xb8, 0x78, 0x93, 0x12, 0x8b, 0x53, 0xe3, 0x93, 0x41, 0xca, 0xe2, 0x33, + 0x53, 0x24, 0x98, 0xc0, 0x92, 0xdc, 0x20, 0x41, 0xb0, 0x56, 0xcf, 0x14, 0xa7, 0xd0, 0x13, 0x8f, + 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, + 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xb2, 0x4e, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, + 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0xce, 0xcd, 0x2f, 0x06, 0x79, 0x42, 0x37, 0x3d, 0x5f, + 0xbf, 0xcc, 0x58, 0x3f, 0x37, 0x3f, 0xa5, 0x34, 0x27, 0xb5, 0x18, 0xe4, 0x25, 0xb0, 0x57, 0x74, + 0xe1, 0x5e, 0x29, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0xfb, 0xc2, 0x18, 0x10, 0x00, 0x00, + 0xff, 0xff, 0xcd, 0x50, 0x0d, 0x5a, 0xf8, 0x00, 0x00, 0x00, +} + +func (m *ClassTrace) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ClassTrace) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ClassTrace) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.BaseClassId) > 0 { + i -= len(m.BaseClassId) + copy(dAtA[i:], m.BaseClassId) + i = encodeVarintTransfer(dAtA, i, uint64(len(m.BaseClassId))) + i-- + dAtA[i] = 0x12 + } + if len(m.Path) > 0 { + i -= len(m.Path) + copy(dAtA[i:], m.Path) + i = encodeVarintTransfer(dAtA, i, uint64(len(m.Path))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintTransfer(dAtA []byte, offset int, v uint64) int { + offset -= sovTransfer(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ClassTrace) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Path) + if l > 0 { + n += 1 + l + sovTransfer(uint64(l)) + } + l = len(m.BaseClassId) + if l > 0 { + n += 1 + l + sovTransfer(uint64(l)) + } + return n +} + +func sovTransfer(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTransfer(x uint64) (n int) { + return sovTransfer(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ClassTrace) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ClassTrace: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ClassTrace: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTransfer + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTransfer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Path = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseClassId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTransfer + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTransfer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BaseClassId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTransfer(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTransfer + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTransfer(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTransfer + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTransfer + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTransfer + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTransfer + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTransfer + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTransfer + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTransfer = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTransfer = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTransfer = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/ibc/applications/nft_transfer/v1/genesis.proto b/proto/ibc/applications/nft_transfer/v1/genesis.proto new file mode 100644 index 00000000000..e2de20e3fbb --- /dev/null +++ b/proto/ibc/applications/nft_transfer/v1/genesis.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +package ibc.applications.nft_transfer.v1; + +option go_package = "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types"; + +import "ibc/applications/nft_transfer/v1/transfer.proto"; +import "gogoproto/gogo.proto"; + +// GenesisState defines the ibc-nft-transfer genesis state +message GenesisState { + string port_id = 1; + repeated ClassTrace traces = 2 [(gogoproto.nullable) = false]; +} \ No newline at end of file diff --git a/proto/ibc/applications/nft_transfer/v1/transfer.proto b/proto/ibc/applications/nft_transfer/v1/transfer.proto new file mode 100644 index 00000000000..521c753311c --- /dev/null +++ b/proto/ibc/applications/nft_transfer/v1/transfer.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +package ibc.applications.nft_transfer.v1; + +option go_package = "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types"; + +// ClassTrace contains the base classID for ICS721 non-fungible tokens and the +// source tracing information path. +message ClassTrace { + // path defines the chain of port/channel identifiers used for tracing the + // source of the non-fungible token. + string path = 1; + // base classID of the relayed non-fungible token. + string base_class_id = 2; +} From 8a9e2bfd6aa3ac9cf880a4a31dccef5af4e7930a Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Mon, 30 May 2022 10:51:40 +0800 Subject: [PATCH 05/14] refactor code --- go.mod | 95 ++++++++++++++++- modules/apps/nft-transfer/keeper/relay.go | 120 ++++++++++++---------- 2 files changed, 159 insertions(+), 56 deletions(-) diff --git a/go.mod b/go.mod index fc1b62d06ea..e595ea97f26 100644 --- a/go.mod +++ b/go.mod @@ -26,4 +26,97 @@ require ( gopkg.in/yaml.v2 v2.4.0 ) -require github.com/gin-gonic/gin v1.7.0 // indirect +require ( + filippo.io/edwards25519 v1.0.0-beta.2 // indirect + github.com/99designs/keyring v1.1.6 // indirect + github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/DataDog/zstd v1.4.5 // indirect + github.com/Workiva/go-datastructures v1.0.53 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/btcsuite/btcd v0.22.0-beta // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/coinbase/rosetta-sdk-go v0.7.0 // indirect + github.com/cosmos/btcutil v1.0.4 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/iavl v0.17.3 // indirect + github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect + github.com/cosmos/ledger-go v0.9.2 // indirect + github.com/danieljoos/wincred v1.0.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect + github.com/dgraph-io/badger/v2 v2.2007.2 // indirect + github.com/dgraph-io/ristretto v0.0.3 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect + github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/fsnotify/fsnotify v1.5.1 // indirect + github.com/gin-gonic/gin v1.7.0 // indirect + github.com/go-kit/kit v0.12.0 // indirect + github.com/go-kit/log v0.2.0 // indirect + github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gogo/gateway v1.1.0 // indirect + github.com/golang/snappy v0.0.3 // indirect + github.com/google/btree v1.0.0 // indirect + github.com/google/orderedcode v0.0.1 // indirect + github.com/gorilla/handlers v1.5.1 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/gtank/merlin v0.1.1 // indirect + github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect + github.com/improbable-eng/grpc-web v0.14.1 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect + github.com/klauspost/compress v1.13.6 // indirect + github.com/lib/pq v1.10.4 // indirect + github.com/libp2p/go-buffer-pool v0.0.2 // indirect + github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect + github.com/minio/highwayhash v1.0.2 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/pelletier/go-toml v1.9.4 // indirect + github.com/pelletier/go-toml/v2 v2.0.0-beta.8 // indirect + github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.12.1 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect + github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect + github.com/rs/cors v1.8.2 // indirect + github.com/rs/zerolog v1.23.0 // indirect + github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect + github.com/spf13/afero v1.8.2 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.2.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect + github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect + github.com/tendermint/btcd v0.1.1 // indirect + github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/zondax/hid v0.9.0 // indirect + go.etcd.io/bbolt v1.3.6 // indirect + golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect + golang.org/x/net v0.0.0-20220412020605-290c469a71a5 // indirect + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/text v0.3.7 // indirect + gopkg.in/ini.v1 v1.66.4 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + nhooyr.io/websocket v1.8.6 // indirect +) diff --git a/modules/apps/nft-transfer/keeper/relay.go b/modules/apps/nft-transfer/keeper/relay.go index 1ca1e790a1d..58c417e85d3 100644 --- a/modules/apps/nft-transfer/keeper/relay.go +++ b/modules/apps/nft-transfer/keeper/relay.go @@ -70,61 +70,43 @@ func (k Keeper) SendTransfer( ) } - // See spec for this logic: https://github.com/cosmos/ibc/blob/master/spec/app/ics-721-nft-transfer/README.md#packet-relay channelCap, ok := k.scopedKeeper.GetCapability(ctx, host.ChannelCapabilityPath(sourcePort, sourceChannel)) if !ok { return sdkerrors.Wrap(channeltypes.ErrChannelCapabilityNotFound, "module does not own channel capability") } - class, exist := k.nftKeeper.GetClass(ctx, classID) - if !exist { - return sdkerrors.Wrap(types.ErrInvalidClassID, "classId not exist") - } - - var tokenURIs []string - for _, tokenID := range tokenIDs { - tokenURI, err := k.handleToken(ctx, - sourcePort, - sourceChannel, - classID, - tokenID, - sender, - ) - if err != nil { - return err - } - tokenURIs = append(tokenURIs, tokenURI) - } - - labels := []metrics.Label{ - telemetry.NewLabel(coretypes.LabelDestinationPort, destinationPort), - telemetry.NewLabel(coretypes.LabelDestinationChannel, destinationChannel), - } - - packetData := types.NewNonFungibleTokenPacketData( - classID, class.GetUri(), tokenIDs, tokenURIs, sender.String(), receiver, - ) - - packet := channeltypes.NewPacket( - packetData.GetBytes(), - sequence, + // See spec for this logic: https://github.com/cosmos/ibc/blob/master/spec/app/ics-721-nft-transfer/README.md#packet-relay + packet, err := k.createOutgoingPacket(ctx, sourcePort, sourceChannel, destinationPort, destinationChannel, + classID, + tokenIDs, + sender, + receiver, + sequence, timeoutHeight, timeoutTimestamp, ) + if err != nil { + return err + } if err := k.ics4Wrapper.SendPacket(ctx, channelCap, packet); err != nil { return err } defer func() { + labels := []metrics.Label{ + telemetry.NewLabel(coretypes.LabelDestinationPort, destinationPort), + telemetry.NewLabel(coretypes.LabelDestinationChannel, destinationChannel), + } + telemetry.SetGaugeWithLabels( []string{"tx", "msg", "ibc", "nft-transfer"}, float32(len(tokenIDs)), - []metrics.Label{telemetry.NewLabel("class_id", class.GetUri())}, + []metrics.Label{telemetry.NewLabel("class_id", classID)}, ) telemetry.IncrCounterWithLabels( @@ -133,7 +115,6 @@ func (k Keeper) SendTransfer( labels, ) }() - return nil } @@ -194,38 +175,67 @@ func (k Keeper) refundPacketToken(ctx sdk.Context, packet channeltypes.Packet, d return nil } -// handleToken will escrow the tokens to escrow account +// createOutgoingPacket will escrow the tokens to escrow account // if the token was away from origin chain . Otherwise, the sent tokens // were burnt in the sending chain and will unescrow the token to receiver // in the destination chain -func (k Keeper) handleToken(ctx sdk.Context, +func (k Keeper) createOutgoingPacket(ctx sdk.Context, sourcePort, sourceChannel, - classID, - tokenID string, + destinationPort, + destinationChannel, + classID string, + tokenIDs []string, sender sdk.AccAddress, -) (string, error) { - nft, exist := k.nftKeeper.GetNFT(ctx, classID, tokenID) + receiver string, + sequence uint64, + timeoutHeight clienttypes.Height, + timeoutTimestamp uint64, +) (channeltypes.Packet, error) { + class, exist := k.nftKeeper.GetClass(ctx, classID) if !exist { - return "", sdkerrors.Wrap(types.ErrInvalidTokenID, "tokenId not exist") + return channeltypes.Packet{}, sdkerrors.Wrap(types.ErrInvalidClassID, "classId not exist") } - owner := k.nftKeeper.GetOwner(ctx, classID, tokenID) - if !sender.Equals(owner) { - return "", sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "not token owner") - } + var tokenURIs []string + for _, tokenID := range tokenIDs { + nft, exist := k.nftKeeper.GetNFT(ctx, classID, tokenID) + if !exist { + return channeltypes.Packet{}, sdkerrors.Wrap(types.ErrInvalidTokenID, "tokenId not exist") + } - isAwayFromOrigin := k.isAwayFromOrigin(sourcePort, sourceChannel, classID) - if !isAwayFromOrigin { - return nft.GetUri(), k.nftKeeper.Burn(ctx, classID, tokenID) - } + owner := k.nftKeeper.GetOwner(ctx, classID, tokenID) + if !sender.Equals(owner) { + return channeltypes.Packet{}, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "not token owner") + } - // create the escrow address for the tokens - escrowAddress := types.GetEscrowAddress(sourcePort, sourceChannel) - if err := k.nftKeeper.Transfer(ctx, classID, tokenID, escrowAddress.String()); err != nil { - return "", err + isAwayFromOrigin := k.isAwayFromOrigin(sourcePort, sourceChannel, classID) + if !isAwayFromOrigin { + return channeltypes.Packet{}, k.nftKeeper.Burn(ctx, classID, tokenID) + } + + // create the escrow address for the tokens + escrowAddress := types.GetEscrowAddress(sourcePort, sourceChannel) + if err := k.nftKeeper.Transfer(ctx, classID, tokenID, escrowAddress.String()); err != nil { + return channeltypes.Packet{}, err + } + tokenURIs = append(tokenURIs, nft.GetUri()) } - return nft.GetUri(), nil + + packetData := types.NewNonFungibleTokenPacketData( + classID, class.GetUri(), tokenIDs, tokenURIs, sender.String(), receiver, + ) + + return channeltypes.NewPacket( + packetData.GetBytes(), + sequence, + sourcePort, + sourceChannel, + destinationPort, + destinationChannel, + timeoutHeight, + timeoutTimestamp, + ), nil } func (k Keeper) isAwayFromOrigin(sourcePort, sourceChannel, classID string) bool { From 698de37ad929eaac5556351b7e8074c1488af0d9 Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Mon, 30 May 2022 10:56:45 +0800 Subject: [PATCH 06/14] bump up gin-gonic/gin --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b2f2e409401..f85c5c9a323 100644 --- a/go.mod +++ b/go.mod @@ -53,7 +53,7 @@ require ( github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect github.com/felixge/httpsnoop v1.0.1 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect - github.com/gin-gonic/gin v1.7.0 // indirect + github.com/gin-gonic/gin v1.7.7 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.0 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect diff --git a/go.sum b/go.sum index 6d985a7ab23..75806955892 100644 --- a/go.sum +++ b/go.sum @@ -338,8 +338,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/gin-gonic/gin v1.7.0 h1:jGB9xAJQ12AIGNB4HguylppmDK1Am9ppF7XnGXXJuoU= -github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= +github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= +github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= From 78fd6edad7f1f767047f70deee4038e818ee2c82 Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Mon, 30 May 2022 15:36:41 +0800 Subject: [PATCH 07/14] finish createOutgoingPacket --- modules/apps/nft-transfer/ibc_module.go | 2 + modules/apps/nft-transfer/keeper/keeper.go | 21 +++++++++- modules/apps/nft-transfer/keeper/relay.go | 31 +++++++++++--- modules/apps/nft-transfer/keeper/trace.go | 40 +++++++++++++++++++ modules/apps/nft-transfer/types/errors.go | 5 ++- .../nft-transfer/types/expected_keeper.go | 9 +++++ modules/apps/nft-transfer/types/keys.go | 6 +++ modules/apps/nft-transfer/types/trace.go | 37 +++++++++++++++++ 8 files changed, 142 insertions(+), 9 deletions(-) create mode 100644 modules/apps/nft-transfer/keeper/trace.go create mode 100644 modules/apps/nft-transfer/types/trace.go diff --git a/modules/apps/nft-transfer/ibc_module.go b/modules/apps/nft-transfer/ibc_module.go index afa5ce450c0..23c986483c3 100644 --- a/modules/apps/nft-transfer/ibc_module.go +++ b/modules/apps/nft-transfer/ibc_module.go @@ -139,6 +139,7 @@ func (im IBCModule) OnChanOpenAck( if counterpartyVersion != types.Version { return sdkerrors.Wrapf(types.ErrInvalidVersion, "invalid counterparty version: %s, expected %s", counterpartyVersion, types.Version) } + im.keeper.SetEscrowAddress(ctx, portID, channelID) return nil } @@ -148,6 +149,7 @@ func (im IBCModule) OnChanOpenConfirm( portID, channelID string, ) error { + im.keeper.SetEscrowAddress(ctx, portID, channelID) return nil } diff --git a/modules/apps/nft-transfer/keeper/keeper.go b/modules/apps/nft-transfer/keeper/keeper.go index 2c99832bbae..b3ad067122f 100644 --- a/modules/apps/nft-transfer/keeper/keeper.go +++ b/modules/apps/nft-transfer/keeper/keeper.go @@ -17,8 +17,7 @@ type Keeper struct { ics4Wrapper types.ICS4Wrapper channelKeeper types.ChannelKeeper nftKeeper types.NFTKeeper - // portKeeper types.PortKeeper - // authKeeper types.AccountKeeper + authkeeper types.AccountKeeper // bankKeeper types.BankKeeper scopedKeeper capabilitykeeper.ScopedKeeper } @@ -39,3 +38,21 @@ func (k Keeper) AuthenticateCapability(ctx sdk.Context, cap *capabilitytypes.Cap func (k Keeper) ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) error { return k.scopedKeeper.ClaimCapability(ctx, cap, name) } + +// MustUnmarshalClassTrace attempts to decode and return an ClassTrace object from +// raw encoded bytes. It panics on error. +func (k Keeper) MustUnmarshalClassTrace(bz []byte) types.ClassTrace { + var classTrace types.ClassTrace + k.cdc.MustUnmarshal(bz, &classTrace) + return classTrace +} + +// SetEscrowAddress attempts to save a account to auth module +func (k Keeper) SetEscrowAddress(ctx sdk.Context, portID, channelID string) { + // create the escrow address for the tokens + escrowAddress := types.GetEscrowAddress(portID, channelID) + if !k.authkeeper.HasAccount(ctx, escrowAddress) { + acc := k.authkeeper.NewAccountWithAddress(ctx, escrowAddress) + k.authkeeper.SetAccount(ctx, acc) + } +} diff --git a/modules/apps/nft-transfer/keeper/relay.go b/modules/apps/nft-transfer/keeper/relay.go index 58c417e85d3..3297af5f6b0 100644 --- a/modules/apps/nft-transfer/keeper/relay.go +++ b/modules/apps/nft-transfer/keeper/relay.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + "strings" "github.com/armon/go-metrics" "github.com/cosmos/cosmos-sdk/telemetry" @@ -197,21 +198,42 @@ func (k Keeper) createOutgoingPacket(ctx sdk.Context, return channeltypes.Packet{}, sdkerrors.Wrap(types.ErrInvalidClassID, "classId not exist") } - var tokenURIs []string + var ( + // NOTE: class and hex hash correctness checked during msg.ValidateBasic + fullClassPath = classID + err error + tokenURIs []string + ) + + // deconstruct the token denomination into the denomination trace info + // to determine if the sender is the source chain + if strings.HasPrefix(classID, "ibc/") { + fullClassPath, err = k.ClassPathFromHash(ctx, classID) + if err != nil { + return channeltypes.Packet{}, err + } + } + + isAwayFromOrigin := k.isAwayFromOrigin(sourcePort, + sourceChannel, fullClassPath) + for _, tokenID := range tokenIDs { nft, exist := k.nftKeeper.GetNFT(ctx, classID, tokenID) if !exist { return channeltypes.Packet{}, sdkerrors.Wrap(types.ErrInvalidTokenID, "tokenId not exist") } + tokenURIs = append(tokenURIs, nft.GetUri()) owner := k.nftKeeper.GetOwner(ctx, classID, tokenID) if !sender.Equals(owner) { return channeltypes.Packet{}, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "not token owner") } - isAwayFromOrigin := k.isAwayFromOrigin(sourcePort, sourceChannel, classID) if !isAwayFromOrigin { - return channeltypes.Packet{}, k.nftKeeper.Burn(ctx, classID, tokenID) + if err := k.nftKeeper.Burn(ctx, classID, tokenID); err != nil { + return channeltypes.Packet{}, err + } + continue } // create the escrow address for the tokens @@ -219,11 +241,10 @@ func (k Keeper) createOutgoingPacket(ctx sdk.Context, if err := k.nftKeeper.Transfer(ctx, classID, tokenID, escrowAddress.String()); err != nil { return channeltypes.Packet{}, err } - tokenURIs = append(tokenURIs, nft.GetUri()) } packetData := types.NewNonFungibleTokenPacketData( - classID, class.GetUri(), tokenIDs, tokenURIs, sender.String(), receiver, + fullClassPath, class.GetUri(), tokenIDs, tokenURIs, sender.String(), receiver, ) return channeltypes.NewPacket( diff --git a/modules/apps/nft-transfer/keeper/trace.go b/modules/apps/nft-transfer/keeper/trace.go new file mode 100644 index 00000000000..5e5dcf498ff --- /dev/null +++ b/modules/apps/nft-transfer/keeper/trace.go @@ -0,0 +1,40 @@ +package keeper + +import ( + tmbytes "github.com/tendermint/tendermint/libs/bytes" + + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" +) + +// GetClassTrace retreives the full identifiers trace and base classId from the store. +func (k Keeper) GetClassTrace(ctx sdk.Context, denomTraceHash tmbytes.HexBytes) (types.ClassTrace, bool) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ClassTraceKey) + bz := store.Get(denomTraceHash) + if bz == nil { + return types.ClassTrace{}, false + } + + denomTrace := k.MustUnmarshalClassTrace(bz) + return denomTrace, true +} + +// ClassPathFromHash returns the full class path prefix from an ibc classId with a hash +// component. +func (k Keeper) ClassPathFromHash(ctx sdk.Context, classID string) (string, error) { + // trim the class prefix, by default "ibc/" + hexHash := classID[len(types.ClassPrefix+"/"):] + + hash, err := types.ParseHexHash(hexHash) + if err != nil { + return "", sdkerrors.Wrap(types.ErrInvalidClassID, err.Error()) + } + + classTrace, found := k.GetClassTrace(ctx, hash) + if !found { + return "", sdkerrors.Wrap(types.ErrTraceNotFound, hexHash) + } + return classTrace.GetFullClassPath(), nil +} diff --git a/modules/apps/nft-transfer/types/errors.go b/modules/apps/nft-transfer/types/errors.go index 6873d0ad5c1..107a888d631 100644 --- a/modules/apps/nft-transfer/types/errors.go +++ b/modules/apps/nft-transfer/types/errors.go @@ -10,6 +10,7 @@ var ( ErrInvalidVersion = sdkerrors.Register(ModuleName, 3, "invalid ICS721 version") ErrMaxTransferChannels = sdkerrors.Register(ModuleName, 4, "max nft-transfer channels") ErrInvalidClassID = sdkerrors.Register(ModuleName, 5, "invalid class id") - ErrInvalidTokenID = sdkerrors.Register(ModuleName, 5, "invalid token id") - ErrInvalidPacket = sdkerrors.Register(ModuleName, 5, "invalid non-fungible token packet") + ErrInvalidTokenID = sdkerrors.Register(ModuleName, 6, "invalid token id") + ErrInvalidPacket = sdkerrors.Register(ModuleName, 7, "invalid non-fungible token packet") + ErrTraceNotFound = sdkerrors.Register(ModuleName, 8, "classTrace trace not found") ) diff --git a/modules/apps/nft-transfer/types/expected_keeper.go b/modules/apps/nft-transfer/types/expected_keeper.go index 0ab80ecefd2..a298a337a5c 100644 --- a/modules/apps/nft-transfer/types/expected_keeper.go +++ b/modules/apps/nft-transfer/types/expected_keeper.go @@ -4,6 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + "github.com/cosmos/cosmos-sdk/x/auth/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" ) @@ -44,3 +45,11 @@ type ChannelKeeper interface { GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) } + +// AccountKeeper defines the contract required for account APIs. +type AccountKeeper interface { + NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) types.AccountI + // Set an account in the store. + SetAccount(sdk.Context, types.AccountI) + HasAccount(ctx sdk.Context, addr sdk.AccAddress) bool +} diff --git a/modules/apps/nft-transfer/types/keys.go b/modules/apps/nft-transfer/types/keys.go index 241cba99e8f..1f947c647c1 100644 --- a/modules/apps/nft-transfer/types/keys.go +++ b/modules/apps/nft-transfer/types/keys.go @@ -26,11 +26,17 @@ const ( // QuerierRoute is the querier route for IBC nft-tranfer QuerierRoute = ModuleName + + // ClassPrefix is the prefix used for internal SDK non-fungible token representation. + ClassPrefix = "ibc" ) var ( // PortKey defines the key to store the port ID in store PortKey = []byte{0x01} + + // ClassTraceKey defines the key to store the class trace info in store + ClassTraceKey = []byte{0x02} ) // GetEscrowAddress returns the escrow address for the specified channel. diff --git a/modules/apps/nft-transfer/types/trace.go b/modules/apps/nft-transfer/types/trace.go new file mode 100644 index 00000000000..c2edfad7a88 --- /dev/null +++ b/modules/apps/nft-transfer/types/trace.go @@ -0,0 +1,37 @@ +package types + +import ( + "encoding/hex" + + tmbytes "github.com/tendermint/tendermint/libs/bytes" + tmtypes "github.com/tendermint/tendermint/types" +) + +// ParseHexHash parses a hex hash in string format to bytes and validates its correctness. +func ParseHexHash(hexHash string) (tmbytes.HexBytes, error) { + hash, err := hex.DecodeString(hexHash) + if err != nil { + return nil, err + } + + if err := tmtypes.ValidateHash(hash); err != nil { + return nil, err + } + + return hash, nil +} + +// GetFullClassPath returns the full classId according to the ICS721 specification: +// tracePath + "/" + BaseClassId +// If there exists no trace then the base BaseClassId is returned. +func (ct ClassTrace) GetFullClassPath() string { + if ct.Path == "" { + return ct.BaseClassId + } + return ct.GetPrefix() + ct.BaseClassId +} + +// GetPrefix returns the receiving classId prefix composed by the trace info and a separator. +func (ct ClassTrace) GetPrefix() string { + return ct.Path + "/" +} From bdd80ff8c62f0be6386d9072e2e4fc98a66f3d82 Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Tue, 31 May 2022 08:14:56 +0800 Subject: [PATCH 08/14] implement OnRecvPacket --- modules/apps/nft-transfer/keeper/keeper.go | 6 ++ modules/apps/nft-transfer/keeper/relay.go | 83 +++++++++++++------ modules/apps/nft-transfer/keeper/trace.go | 13 +++ .../nft-transfer/types/expected_keeper.go | 2 +- modules/apps/nft-transfer/types/trace.go | 60 ++++++++++++++ 5 files changed, 137 insertions(+), 27 deletions(-) diff --git a/modules/apps/nft-transfer/keeper/keeper.go b/modules/apps/nft-transfer/keeper/keeper.go index b3ad067122f..150f8e85082 100644 --- a/modules/apps/nft-transfer/keeper/keeper.go +++ b/modules/apps/nft-transfer/keeper/keeper.go @@ -47,6 +47,12 @@ func (k Keeper) MustUnmarshalClassTrace(bz []byte) types.ClassTrace { return classTrace } +// MustMarshalClassTrace attempts to decode and return an ClassTrace object from +// raw encoded bytes. It panics on error. +func (k Keeper) MustMarshalClassTrace(classTrace types.ClassTrace) []byte { + return k.cdc.MustMarshal(&classTrace) +} + // SetEscrowAddress attempts to save a account to auth module func (k Keeper) SetEscrowAddress(ctx sdk.Context, portID, channelID string) { // create the escrow address for the tokens diff --git a/modules/apps/nft-transfer/keeper/relay.go b/modules/apps/nft-transfer/keeper/relay.go index 3297af5f6b0..82cc8c44d44 100644 --- a/modules/apps/nft-transfer/keeper/relay.go +++ b/modules/apps/nft-transfer/keeper/relay.go @@ -1,7 +1,6 @@ package keeper import ( - "fmt" "strings" "github.com/armon/go-metrics" @@ -124,26 +123,63 @@ func (k Keeper) SendTransfer( // and sent to the receiving address. Otherwise if the sender chain is sending // back tokens this chain originally transferred to it, the tokens are // unescrowed and sent to the receiving address. -func (k Keeper) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet, data types.NonFungibleTokenPacketData) error { - - // defer func() { - // if transferAmount.IsInt64() { - // telemetry.SetGaugeWithLabels( - // []string{"ibc", types.ModuleName, "packet", "receive"}, - // float32(transferAmount.Int64()), - // []metrics.Label{telemetry.NewLabel(coretypes.LabelDenom, data.Denom)}, - // ) - // } - - // telemetry.IncrCounterWithLabels( - // []string{"ibc", types.ModuleName, "receive"}, - // 1, - // append( - // labels, telemetry.NewLabel(coretypes.LabelSource, "false"), - // ), - // ) - // }() +func (k Keeper) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet, + data types.NonFungibleTokenPacketData) error { + // validate packet data upon receiving + if err := data.ValidateBasic(); err != nil { + return err + } + + // decode the receiver address + _, err := sdk.AccAddressFromBech32(data.Receiver) + if err != nil { + return err + } + + isAwayFromOrigin := types.IsAwayFromOrigin(packet.GetSourcePort(), + packet.GetSourceChannel(), data.ClassId) + if !isAwayFromOrigin { + classPrefix := types.GetClassPrefix(packet.GetSourcePort(), packet.GetSourceChannel()) + unprefixedClassID := data.ClassId[len(classPrefix):] + + // The denomination used to send the coins is either the native denom or the hash of the path + // if the denomination is not native. + classTrace := types.ParseClassTrace(unprefixedClassID) + + voucherClassID := classTrace.IBCClassID() + for _, tokenID := range data.TokenIds { + if err := k.nftKeeper.Transfer(ctx, + voucherClassID, tokenID, data.Receiver); err != nil { + return err + } + } + return nil + } + + // since SendPacket did not prefix the denomination, we must prefix denomination here + classPrefix := types.GetClassPrefix(packet.GetDestPort(), packet.GetDestChannel()) + // NOTE: sourcePrefix contains the trailing "/" + prefixedClassID := classPrefix + data.ClassId + + // construct the denomination trace from the full raw denomination + classTrace := types.ParseClassTrace(prefixedClassID) + if !k.HasClassTrace(ctx, classTrace.Hash()) { + k.SetClassTrace(ctx, classTrace) + } + + voucherClassID := classTrace.IBCClassID() + if !k.nftKeeper.HasClass(ctx, voucherClassID) { + if err := k.nftKeeper.SaveClass(ctx, voucherClassID, data.ClassUri); err != nil { + return err + } + } + for i, tokenID := range data.TokenIds { + if err := k.nftKeeper.Mint(ctx, + voucherClassID, tokenID, data.TokenUris[i], data.Receiver); err != nil { + return err + } + } return nil } @@ -214,7 +250,7 @@ func (k Keeper) createOutgoingPacket(ctx sdk.Context, } } - isAwayFromOrigin := k.isAwayFromOrigin(sourcePort, + isAwayFromOrigin := types.IsAwayFromOrigin(sourcePort, sourceChannel, fullClassPath) for _, tokenID := range tokenIDs { @@ -258,8 +294,3 @@ func (k Keeper) createOutgoingPacket(ctx sdk.Context, timeoutTimestamp, ), nil } - -func (k Keeper) isAwayFromOrigin(sourcePort, sourceChannel, classID string) bool { - prefixClassID := fmt.Sprintf("%s/%s", sourcePort, sourceChannel) - return classID[:len(prefixClassID)] != prefixClassID -} diff --git a/modules/apps/nft-transfer/keeper/trace.go b/modules/apps/nft-transfer/keeper/trace.go index 5e5dcf498ff..659a3e48172 100644 --- a/modules/apps/nft-transfer/keeper/trace.go +++ b/modules/apps/nft-transfer/keeper/trace.go @@ -38,3 +38,16 @@ func (k Keeper) ClassPathFromHash(ctx sdk.Context, classID string) (string, erro } return classTrace.GetFullClassPath(), nil } + +// HasClassTrace checks if a the key with the given denomination trace hash exists on the store. +func (k Keeper) HasClassTrace(ctx sdk.Context, denomTraceHash tmbytes.HexBytes) bool { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ClassTraceKey) + return store.Has(denomTraceHash) +} + +// SetClassTrace sets a new {trace hash -> class trace} pair to the store. +func (k Keeper) SetClassTrace(ctx sdk.Context, denomTrace types.ClassTrace) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ClassTraceKey) + bz := k.MustMarshalClassTrace(denomTrace) + store.Set(denomTrace.Hash(), bz) +} diff --git a/modules/apps/nft-transfer/types/expected_keeper.go b/modules/apps/nft-transfer/types/expected_keeper.go index a298a337a5c..f0f47d29f76 100644 --- a/modules/apps/nft-transfer/types/expected_keeper.go +++ b/modules/apps/nft-transfer/types/expected_keeper.go @@ -25,7 +25,7 @@ type NFT interface { // TODO type NFTKeeper interface { SaveClass(ctx sdk.Context, classID, classURI string) error - Mint(ctx sdk.Context, classID, tokenID, tokenURI, receiver string) + Mint(ctx sdk.Context, classID, tokenID, tokenURI, receiver string) error Transfer(ctx sdk.Context, classID, tokenID, receiver string) error Burn(ctx sdk.Context, classID, tokenID string) error diff --git a/modules/apps/nft-transfer/types/trace.go b/modules/apps/nft-transfer/types/trace.go index c2edfad7a88..00f134c4cd6 100644 --- a/modules/apps/nft-transfer/types/trace.go +++ b/modules/apps/nft-transfer/types/trace.go @@ -1,7 +1,10 @@ package types import ( + "crypto/sha256" "encoding/hex" + "fmt" + "strings" tmbytes "github.com/tendermint/tendermint/libs/bytes" tmtypes "github.com/tendermint/tendermint/types" @@ -21,6 +24,46 @@ func ParseHexHash(hexHash string) (tmbytes.HexBytes, error) { return hash, nil } +// GetClassPrefix returns the receiving denomination prefix +func GetClassPrefix(portID, channelID string) string { + return fmt.Sprintf("%s/%s/", portID, channelID) +} + +// IsAwayFromOrigin determine if non-fungible token is moving away from +// the origin chain (the chain issued by the native nft). +// Note that fullClassPath refers to the full path of the unencoded classID. +// The longer the fullClassPath, the farther it is from the origin chain +func IsAwayFromOrigin(sourcePort, sourceChannel, fullClassPath string) bool { + prefixClassID := GetClassPrefix(sourcePort, sourceChannel) + if !strings.HasPrefix(fullClassPath, prefixClassID) { + return true + } + return fullClassPath[:len(prefixClassID)] != prefixClassID +} + +// ParseClassTrace parses a string with the ibc prefix (denom trace) and the base denomination +// into a DenomTrace type. +// +// Examples: +// +// - "portidone/channelidone/uatom" => DenomTrace{Path: "portidone/channelidone", BaseDenom: "uatom"} +// - "uatom" => DenomTrace{Path: "", BaseDenom: "uatom"} +func ParseClassTrace(rawClassID string) ClassTrace { + classSplit := strings.Split(rawClassID, "/") + + if classSplit[0] == rawClassID { + return ClassTrace{ + Path: "", + BaseClassId: rawClassID, + } + } + + return ClassTrace{ + Path: strings.Join(classSplit[:len(classSplit)-1], "/"), + BaseClassId: classSplit[len(classSplit)-1], + } +} + // GetFullClassPath returns the full classId according to the ICS721 specification: // tracePath + "/" + BaseClassId // If there exists no trace then the base BaseClassId is returned. @@ -35,3 +78,20 @@ func (ct ClassTrace) GetFullClassPath() string { func (ct ClassTrace) GetPrefix() string { return ct.Path + "/" } + +// Hash returns the hex bytes of the SHA256 hash of the ClassTrace fields using the following formula: +// +// hash = sha256(tracePath + "/" + baseClassId) +func (ct ClassTrace) Hash() tmbytes.HexBytes { + hash := sha256.Sum256([]byte(ct.GetFullClassPath())) + return hash[:] +} + +// IBCClassID a coin denomination for an ICS20 fungible token in the format +// 'ibc/{hash(tracePath + baseDenom)}'. If the trace is empty, it will return the base denomination. +func (ct ClassTrace) IBCClassID() string { + if ct.Path != "" { + return fmt.Sprintf("%s/%s", ClassPrefix, ct.Hash()) + } + return ct.BaseClassId +} From eeee9e3112e025e0ce0c35125db12b2c59aa15c5 Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Tue, 31 May 2022 14:25:56 +0800 Subject: [PATCH 09/14] implement OnRecvPacket --- modules/apps/nft-transfer/keeper/relay.go | 120 +++++++++++++--------- modules/apps/nft-transfer/types/packet.go | 10 ++ modules/apps/nft-transfer/types/trace.go | 22 ++-- 3 files changed, 95 insertions(+), 57 deletions(-) diff --git a/modules/apps/nft-transfer/keeper/relay.go b/modules/apps/nft-transfer/keeper/relay.go index 82cc8c44d44..95340a33de7 100644 --- a/modules/apps/nft-transfer/keeper/relay.go +++ b/modules/apps/nft-transfer/keeper/relay.go @@ -131,56 +131,8 @@ func (k Keeper) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet, return err } - // decode the receiver address - _, err := sdk.AccAddressFromBech32(data.Receiver) - if err != nil { - return err - } - - isAwayFromOrigin := types.IsAwayFromOrigin(packet.GetSourcePort(), - packet.GetSourceChannel(), data.ClassId) - if !isAwayFromOrigin { - classPrefix := types.GetClassPrefix(packet.GetSourcePort(), packet.GetSourceChannel()) - unprefixedClassID := data.ClassId[len(classPrefix):] - - // The denomination used to send the coins is either the native denom or the hash of the path - // if the denomination is not native. - classTrace := types.ParseClassTrace(unprefixedClassID) - - voucherClassID := classTrace.IBCClassID() - for _, tokenID := range data.TokenIds { - if err := k.nftKeeper.Transfer(ctx, - voucherClassID, tokenID, data.Receiver); err != nil { - return err - } - } - return nil - } - - // since SendPacket did not prefix the denomination, we must prefix denomination here - classPrefix := types.GetClassPrefix(packet.GetDestPort(), packet.GetDestChannel()) - // NOTE: sourcePrefix contains the trailing "/" - prefixedClassID := classPrefix + data.ClassId - - // construct the denomination trace from the full raw denomination - classTrace := types.ParseClassTrace(prefixedClassID) - if !k.HasClassTrace(ctx, classTrace.Hash()) { - k.SetClassTrace(ctx, classTrace) - } - - voucherClassID := classTrace.IBCClassID() - if !k.nftKeeper.HasClass(ctx, voucherClassID) { - if err := k.nftKeeper.SaveClass(ctx, voucherClassID, data.ClassUri); err != nil { - return err - } - } - for i, tokenID := range data.TokenIds { - if err := k.nftKeeper.Mint(ctx, - voucherClassID, tokenID, data.TokenUris[i], data.Receiver); err != nil { - return err - } - } - return nil + // See spec for this logic: https://github.com/cosmos/ibc/blob/master/spec/app/ics-721-nft-transfer/README.md#packet-relay + return k.processReceivedPacket(ctx, packet, data) } // OnAcknowledgementPacket responds to the the success or failure of a packet @@ -209,6 +161,24 @@ func (k Keeper) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet, dat // were burnt in the original send so new tokens are minted and sent to // the sending address. func (k Keeper) refundPacketToken(ctx sdk.Context, packet channeltypes.Packet, data types.NonFungibleTokenPacketData) error { + if types.IsAwayFromOrigin(packet.GetSourcePort(), + packet.GetSourceChannel(), data.ClassId) { + for _, tokenID := range data.TokenIds { + if err := k.nftKeeper.Transfer(ctx, data.ClassId, tokenID, data.Sender); err != nil { + return err + } + } + return nil + } + + classTrace := types.ParseClassTrace(data.ClassId) + voucherClassID := classTrace.IBCClassID() + for i, tokenID := range data.TokenIds { + if err := k.nftKeeper.Mint(ctx, + voucherClassID, tokenID, data.TokenUris[i], data.Sender); err != nil { + return err + } + } return nil } @@ -294,3 +264,53 @@ func (k Keeper) createOutgoingPacket(ctx sdk.Context, timeoutTimestamp, ), nil } + +// processReceivedPacket will mint the tokens to receiver account +// if the token was away from origin chain . Otherwise, the sent tokens +// were burnt in the sending chain and will unescrow the token to receiver +// in the destination chain +func (k Keeper) processReceivedPacket(ctx sdk.Context, packet channeltypes.Packet, + data types.NonFungibleTokenPacketData) error { + if types.IsAwayFromOrigin(packet.GetSourcePort(), packet.GetSourceChannel(), data.ClassId) { + // since SendPacket did not prefix the classID, we must prefix classID here + classPrefix := types.GetClassPrefix(packet.GetDestPort(), packet.GetDestChannel()) + // NOTE: sourcePrefix contains the trailing "/" + prefixedClassID := classPrefix + data.ClassId + + // construct the class trace from the full raw classID + classTrace := types.ParseClassTrace(prefixedClassID) + if !k.HasClassTrace(ctx, classTrace.Hash()) { + k.SetClassTrace(ctx, classTrace) + } + + voucherClassID := classTrace.IBCClassID() + if !k.nftKeeper.HasClass(ctx, voucherClassID) { + if err := k.nftKeeper.SaveClass(ctx, voucherClassID, data.ClassUri); err != nil { + return err + } + } + for i, tokenID := range data.TokenIds { + if err := k.nftKeeper.Mint(ctx, + voucherClassID, tokenID, data.TokenUris[i], data.Receiver); err != nil { + return err + } + } + return nil + } + + // If the token moves in the direction of back to origin, + // we need to unescrow the token and transfer it to the receiver + + // we should remove the prefix. For example: + // p6/c6/p4/c4/p2/c2/nftClas -> p4/c4/p2/c2/nftClass + unprefixedClassID := types.RemoveClassPrefix(packet.GetSourcePort(), + packet.GetSourceChannel(), data.ClassId) + voucherClassID := types.ParseClassTrace(unprefixedClassID).IBCClassID() + for _, tokenID := range data.TokenIds { + if err := k.nftKeeper.Transfer(ctx, + voucherClassID, tokenID, data.Receiver); err != nil { + return err + } + } + return nil +} diff --git a/modules/apps/nft-transfer/types/packet.go b/modules/apps/nft-transfer/types/packet.go index 961e5417ed6..c833b894d34 100644 --- a/modules/apps/nft-transfer/types/packet.go +++ b/modules/apps/nft-transfer/types/packet.go @@ -57,9 +57,19 @@ func (nftpd NonFungibleTokenPacketData) ValidateBasic() error { return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be blank") } + // decode the sender address + if _, err := sdk.AccAddressFromBech32(nftpd.Sender); err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, " invalid sender address") + } + if strings.TrimSpace(nftpd.Receiver) == "" { return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "receiver address cannot be blank") } + + // decode the receiver address + if _, err := sdk.AccAddressFromBech32(nftpd.Receiver); err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, " invalid receiver address") + } return nil } diff --git a/modules/apps/nft-transfer/types/trace.go b/modules/apps/nft-transfer/types/trace.go index 00f134c4cd6..00c3daa0444 100644 --- a/modules/apps/nft-transfer/types/trace.go +++ b/modules/apps/nft-transfer/types/trace.go @@ -24,11 +24,19 @@ func ParseHexHash(hexHash string) (tmbytes.HexBytes, error) { return hash, nil } -// GetClassPrefix returns the receiving denomination prefix +// GetClassPrefix returns the receiving class prefix func GetClassPrefix(portID, channelID string) string { return fmt.Sprintf("%s/%s/", portID, channelID) } +// RemoveClassPrefix returns the unprefixed classID +func RemoveClassPrefix(portID, channelID, classID string) string { + // since SendPacket did not prefix the classID, we must prefix classID here + classPrefix := GetClassPrefix(portID, channelID) + // NOTE: sourcePrefix contains the trailing "/" + return classID[len(classPrefix):] +} + // IsAwayFromOrigin determine if non-fungible token is moving away from // the origin chain (the chain issued by the native nft). // Note that fullClassPath refers to the full path of the unencoded classID. @@ -41,13 +49,13 @@ func IsAwayFromOrigin(sourcePort, sourceChannel, fullClassPath string) bool { return fullClassPath[:len(prefixClassID)] != prefixClassID } -// ParseClassTrace parses a string with the ibc prefix (denom trace) and the base denomination -// into a DenomTrace type. +// ParseClassTrace parses a string with the ibc prefix (class trace) and the base classID +// into a ClassTrace type. // // Examples: // -// - "portidone/channelidone/uatom" => DenomTrace{Path: "portidone/channelidone", BaseDenom: "uatom"} -// - "uatom" => DenomTrace{Path: "", BaseDenom: "uatom"} +// - "port-1/channel-1/class-1" => ClassTrace{Path: "port-1/channel-1", BaseClassId: "class-1"} +// - "class-1" => ClassTrace{Path: "", BaseClassId: "class-1"} func ParseClassTrace(rawClassID string) ClassTrace { classSplit := strings.Split(rawClassID, "/") @@ -87,8 +95,8 @@ func (ct ClassTrace) Hash() tmbytes.HexBytes { return hash[:] } -// IBCClassID a coin denomination for an ICS20 fungible token in the format -// 'ibc/{hash(tracePath + baseDenom)}'. If the trace is empty, it will return the base denomination. +// IBCClassID a classID for an ICS721 non-fungible token in the format +// 'ibc/{hash(tracePath + BaseClassId)}'. If the trace is empty, it will return the base classID. func (ct ClassTrace) IBCClassID() string { if ct.Path != "" { return fmt.Sprintf("%s/%s", ClassPrefix, ct.Hash()) From 2179d46ffc7250a0604af0c6f7b09270817e3d1b Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Tue, 31 May 2022 18:36:43 +0800 Subject: [PATCH 10/14] implement grpc_query --- docs/ibc/proto-docs.md | 183 +- modules/apps/29-fee/types/query.pb.go | 160 +- modules/apps/29-fee/types/query.pb.gw.go | 248 +-- modules/apps/nft-transfer/ibc_module.go | 23 +- .../apps/nft-transfer/keeper/grpc_query.go | 113 + modules/apps/nft-transfer/keeper/keeper.go | 19 + .../apps/nft-transfer/keeper/msg_server.go | 50 + modules/apps/nft-transfer/types/events.go | 15 + modules/apps/nft-transfer/types/genesis.pb.go | 42 +- modules/apps/nft-transfer/types/query.pb.go | 1906 +++++++++++++++++ .../apps/nft-transfer/types/query.pb.gw.go | 482 +++++ modules/apps/nft-transfer/types/trace.go | 74 + proto/ibc/applications/fee/v1/query.proto | 3 +- .../nft_transfer/v1/genesis.proto | 2 +- .../applications/nft_transfer/v1/query.proto | 91 + 15 files changed, 3166 insertions(+), 245 deletions(-) create mode 100644 modules/apps/nft-transfer/keeper/grpc_query.go create mode 100644 modules/apps/nft-transfer/keeper/msg_server.go create mode 100644 modules/apps/nft-transfer/types/events.go create mode 100644 modules/apps/nft-transfer/types/query.pb.go create mode 100644 modules/apps/nft-transfer/types/query.pb.gw.go create mode 100644 proto/ibc/applications/nft_transfer/v1/query.proto diff --git a/docs/ibc/proto-docs.md b/docs/ibc/proto-docs.md index ff9a2d5b0dc..f5e83f037d5 100644 --- a/docs/ibc/proto-docs.md +++ b/docs/ibc/proto-docs.md @@ -121,6 +121,18 @@ - [ibc/applications/nft_transfer/v1/packet.proto](#ibc/applications/nft_transfer/v1/packet.proto) - [NonFungibleTokenPacketData](#ibc.applications.nft_transfer.v1.NonFungibleTokenPacketData) +- [ibc/applications/nft_transfer/v1/query.proto](#ibc/applications/nft_transfer/v1/query.proto) + - [QueryClassHashRequest](#ibc.applications.nft_transfer.v1.QueryClassHashRequest) + - [QueryClassHashResponse](#ibc.applications.nft_transfer.v1.QueryClassHashResponse) + - [QueryClassTraceRequest](#ibc.applications.nft_transfer.v1.QueryClassTraceRequest) + - [QueryClassTraceResponse](#ibc.applications.nft_transfer.v1.QueryClassTraceResponse) + - [QueryClassTracesRequest](#ibc.applications.nft_transfer.v1.QueryClassTracesRequest) + - [QueryClassTracesResponse](#ibc.applications.nft_transfer.v1.QueryClassTracesResponse) + - [QueryEscrowAddressRequest](#ibc.applications.nft_transfer.v1.QueryEscrowAddressRequest) + - [QueryEscrowAddressResponse](#ibc.applications.nft_transfer.v1.QueryEscrowAddressResponse) + + - [Query](#ibc.applications.nft_transfer.v1.Query) + - [ibc/applications/nft_transfer/v1/tx.proto](#ibc/applications/nft_transfer/v1/tx.proto) - [MsgTransfer](#ibc.applications.nft_transfer.v1.MsgTransfer) - [MsgTransferResponse](#ibc.applications.nft_transfer.v1.MsgTransferResponse) @@ -1222,14 +1234,14 @@ Query defines the ICS29 gRPC querier service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | | `IncentivizedPackets` | [QueryIncentivizedPacketsRequest](#ibc.applications.fee.v1.QueryIncentivizedPacketsRequest) | [QueryIncentivizedPacketsResponse](#ibc.applications.fee.v1.QueryIncentivizedPacketsResponse) | IncentivizedPackets returns all incentivized packets and their associated fees | GET|/ibc/apps/fee/v1/incentivized_packets| -| `IncentivizedPacket` | [QueryIncentivizedPacketRequest](#ibc.applications.fee.v1.QueryIncentivizedPacketRequest) | [QueryIncentivizedPacketResponse](#ibc.applications.fee.v1.QueryIncentivizedPacketResponse) | IncentivizedPacket returns all packet fees for a packet given its identifier | GET|/ibc/apps/fee/v1/incentivized_packet/port/{packet_id.port_id}/channel/{packet_id.channel_id}/sequence/{packet_id.sequence}| -| `IncentivizedPacketsForChannel` | [QueryIncentivizedPacketsForChannelRequest](#ibc.applications.fee.v1.QueryIncentivizedPacketsForChannelRequest) | [QueryIncentivizedPacketsForChannelResponse](#ibc.applications.fee.v1.QueryIncentivizedPacketsForChannelResponse) | Gets all incentivized packets for a specific channel | GET|/ibc/apps/fee/v1/incentivized_packets/port/{port_id}/channel/{channel_id}| -| `TotalRecvFees` | [QueryTotalRecvFeesRequest](#ibc.applications.fee.v1.QueryTotalRecvFeesRequest) | [QueryTotalRecvFeesResponse](#ibc.applications.fee.v1.QueryTotalRecvFeesResponse) | TotalRecvFees returns the total receive fees for a packet given its identifier | GET|/ibc/apps/fee/v1/total_recv_fees/port/{packet_id.port_id}/channel/{packet_id.channel_id}/sequence/{packet_id.sequence}| -| `TotalAckFees` | [QueryTotalAckFeesRequest](#ibc.applications.fee.v1.QueryTotalAckFeesRequest) | [QueryTotalAckFeesResponse](#ibc.applications.fee.v1.QueryTotalAckFeesResponse) | TotalAckFees returns the total acknowledgement fees for a packet given its identifier | GET|/ibc/apps/fee/v1/total_ack_fees/port/{packet_id.port_id}/channel/{packet_id.channel_id}/sequence/{packet_id.sequence}| -| `TotalTimeoutFees` | [QueryTotalTimeoutFeesRequest](#ibc.applications.fee.v1.QueryTotalTimeoutFeesRequest) | [QueryTotalTimeoutFeesResponse](#ibc.applications.fee.v1.QueryTotalTimeoutFeesResponse) | TotalTimeoutFees returns the total timeout fees for a packet given its identifier | GET|/ibc/apps/fee/v1/total_timeout_fees/port/{packet_id.port_id}/channel/{packet_id.channel_id}/sequence/{packet_id.sequence}| -| `CounterpartyAddress` | [QueryCounterpartyAddressRequest](#ibc.applications.fee.v1.QueryCounterpartyAddressRequest) | [QueryCounterpartyAddressResponse](#ibc.applications.fee.v1.QueryCounterpartyAddressResponse) | CounterpartyAddress returns the registered counterparty address for forward relaying | GET|/ibc/apps/fee/v1/counterparty_address/{relayer_address}/channel/{channel_id}| +| `IncentivizedPacket` | [QueryIncentivizedPacketRequest](#ibc.applications.fee.v1.QueryIncentivizedPacketRequest) | [QueryIncentivizedPacketResponse](#ibc.applications.fee.v1.QueryIncentivizedPacketResponse) | IncentivizedPacket returns all packet fees for a packet given its identifier | GET|/ibc/apps/fee/v1/channels/{packet_id.channel_id}/ports/{packet_id.port_id}/sequences/{packet_id.sequence}/incentivized_packet| +| `IncentivizedPacketsForChannel` | [QueryIncentivizedPacketsForChannelRequest](#ibc.applications.fee.v1.QueryIncentivizedPacketsForChannelRequest) | [QueryIncentivizedPacketsForChannelResponse](#ibc.applications.fee.v1.QueryIncentivizedPacketsForChannelResponse) | Gets all incentivized packets for a specific channel | GET|/ibc/apps/fee/v1/channels/{channel_id}/ports/{port_id}/incentivized_packets| +| `TotalRecvFees` | [QueryTotalRecvFeesRequest](#ibc.applications.fee.v1.QueryTotalRecvFeesRequest) | [QueryTotalRecvFeesResponse](#ibc.applications.fee.v1.QueryTotalRecvFeesResponse) | TotalRecvFees returns the total receive fees for a packet given its identifier | GET|/ibc/apps/fee/v1/channels/{packet_id.channel_id}/ports/{packet_id.port_id}/sequences/{packet_id.sequence}/total_recv_fees| +| `TotalAckFees` | [QueryTotalAckFeesRequest](#ibc.applications.fee.v1.QueryTotalAckFeesRequest) | [QueryTotalAckFeesResponse](#ibc.applications.fee.v1.QueryTotalAckFeesResponse) | TotalAckFees returns the total acknowledgement fees for a packet given its identifier | GET|/ibc/apps/fee/v1/channels/{packet_id.channel_id}/ports/{packet_id.port_id}/sequences/{packet_id.sequence}/total_ack_fees| +| `TotalTimeoutFees` | [QueryTotalTimeoutFeesRequest](#ibc.applications.fee.v1.QueryTotalTimeoutFeesRequest) | [QueryTotalTimeoutFeesResponse](#ibc.applications.fee.v1.QueryTotalTimeoutFeesResponse) | TotalTimeoutFees returns the total timeout fees for a packet given its identifier | GET|/ibc/apps/fee/v1/channels/{packet_id.channel_id}/ports/{packet_id.port_id}/sequences/{packet_id.sequence}/total_timeout_fees| +| `CounterpartyAddress` | [QueryCounterpartyAddressRequest](#ibc.applications.fee.v1.QueryCounterpartyAddressRequest) | [QueryCounterpartyAddressResponse](#ibc.applications.fee.v1.QueryCounterpartyAddressResponse) | CounterpartyAddress returns the registered counterparty address for forward relaying | GET|/ibc/apps/fee/v1/channels/{channel_id}/relayers/{relayer_address}/counterparty_address| | `FeeEnabledChannels` | [QueryFeeEnabledChannelsRequest](#ibc.applications.fee.v1.QueryFeeEnabledChannelsRequest) | [QueryFeeEnabledChannelsResponse](#ibc.applications.fee.v1.QueryFeeEnabledChannelsResponse) | FeeEnabledChannels returns a list of all fee enabled channels | GET|/ibc/apps/fee/v1/fee_enabled| -| `FeeEnabledChannel` | [QueryFeeEnabledChannelRequest](#ibc.applications.fee.v1.QueryFeeEnabledChannelRequest) | [QueryFeeEnabledChannelResponse](#ibc.applications.fee.v1.QueryFeeEnabledChannelResponse) | FeeEnabledChannel returns true if the provided port and channel identifiers belong to a fee enabled channel | GET|/ibc/apps/fee/v1/fee_enabled/port/{port_id}/channel/{channel_id}| +| `FeeEnabledChannel` | [QueryFeeEnabledChannelRequest](#ibc.applications.fee.v1.QueryFeeEnabledChannelRequest) | [QueryFeeEnabledChannelResponse](#ibc.applications.fee.v1.QueryFeeEnabledChannelResponse) | FeeEnabledChannel returns true if the provided port and channel identifiers belong to a fee enabled channel | GET|/ibc/apps/fee/v1/channels/{channel_id}/ports/{port_id}/fee_enabled| @@ -1851,6 +1863,163 @@ https://github.com/cosmos/ibc/tree/master/spec/app/ics-721-nft-transfer#data-str + +

Top

+ +## ibc/applications/nft_transfer/v1/query.proto + + + + + +### QueryClassHashRequest +QueryClassHashRequest is the request type for the Query/ClassHash RPC +method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `trace` | [string](#string) | | The class trace ([port_id]/[channel_id])+/[denom] | + + + + + + + + +### QueryClassHashResponse +QueryClassHashResponse is the response type for the Query/ClassHash RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `hash` | [string](#string) | | hash (in hex format) of the denomination trace information. | + + + + + + + + +### QueryClassTraceRequest +QueryClassTraceRequest is the request type for the Query/ClassDenom RPC +method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `hash` | [string](#string) | | hash (in hex format) or classID (full classID with ibc prefix) of the denomination trace information. | + + + + + + + + +### QueryClassTraceResponse +QueryClassTraceResponse is the response type for the Query/ClassDenom RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `class_trace` | [ClassTrace](#ibc.applications.nft_transfer.v1.ClassTrace) | | class_trace returns the requested class trace information. | + + + + + + + + +### QueryClassTracesRequest +QueryConnectionsRequest is the request type for the Query/ClassTraces RPC +method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryClassTracesResponse +QueryClassTracesResponse is the response type for the Query/ClassTraces RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `class_traces` | [ClassTrace](#ibc.applications.nft_transfer.v1.ClassTrace) | repeated | class_traces returns all class trace information. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + + + +### QueryEscrowAddressRequest +QueryEscrowAddressRequest is the request type for the EscrowAddress RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | unique port identifier | +| `channel_id` | [string](#string) | | unique channel identifier | + + + + + + + + +### QueryEscrowAddressResponse +QueryEscrowAddressResponse is the response type of the EscrowAddress RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `escrow_address` | [string](#string) | | the escrow account address | + + + + + + + + + + + + + + +### Query +Query provides defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `ClassTrace` | [QueryClassTraceRequest](#ibc.applications.nft_transfer.v1.QueryClassTraceRequest) | [QueryClassTraceResponse](#ibc.applications.nft_transfer.v1.QueryClassTraceResponse) | ClassTrace queries a class trace information. | GET|/ibc/apps/nft_transfer/v1/class_traces/{hash}| +| `ClassTraces` | [QueryClassTracesRequest](#ibc.applications.nft_transfer.v1.QueryClassTracesRequest) | [QueryClassTracesResponse](#ibc.applications.nft_transfer.v1.QueryClassTracesResponse) | ClassTraces queries all class traces. | GET|/ibc/apps/nft_transfer/v1/class_traces| +| `ClassHash` | [QueryClassHashRequest](#ibc.applications.nft_transfer.v1.QueryClassHashRequest) | [QueryClassHashResponse](#ibc.applications.nft_transfer.v1.QueryClassHashResponse) | ClassHash queries a class hash information. | GET|/ibc/apps/nft_transfer/v1/class_hashes/{trace}| +| `EscrowAddress` | [QueryEscrowAddressRequest](#ibc.applications.nft_transfer.v1.QueryEscrowAddressRequest) | [QueryEscrowAddressResponse](#ibc.applications.nft_transfer.v1.QueryEscrowAddressResponse) | EscrowAddress returns the escrow address for a particular port and channel id. | GET|/ibc/apps/nft_transfer/v1/channels/{channel_id}/ports/{port_id}/escrow_address| + + + + +

Top

diff --git a/modules/apps/29-fee/types/query.pb.go b/modules/apps/29-fee/types/query.pb.go index 32677378fe3..1a9eba1927f 100644 --- a/modules/apps/29-fee/types/query.pb.go +++ b/modules/apps/29-fee/types/query.pb.go @@ -966,88 +966,88 @@ func init() { } var fileDescriptor_0638a8a78ca2503c = []byte{ - // 1281 bytes of a gzipped FileDescriptorProto + // 1285 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0x4f, 0x6f, 0x1b, 0x45, 0x1c, 0xcd, 0xa4, 0xa1, 0x4d, 0x26, 0xa1, 0x4d, 0xc7, 0xa1, 0x4d, 0x4d, 0x62, 0xa7, 0x53, 0x0a, - 0x21, 0x28, 0xbb, 0x8a, 0x43, 0x9b, 0x96, 0x53, 0x6b, 0x43, 0x68, 0x04, 0x82, 0x76, 0x95, 0x0b, - 0x08, 0xe4, 0xae, 0x77, 0xc7, 0xce, 0x2a, 0xce, 0xce, 0x76, 0x77, 0x6d, 0x70, 0xd3, 0x20, 0x35, - 0x52, 0x84, 0x04, 0x15, 0x42, 0x42, 0xe2, 0x80, 0xb8, 0x22, 0x24, 0x24, 0xb8, 0xf3, 0x0d, 0x7a, - 0xaa, 0x2a, 0x71, 0xe1, 0x64, 0xaa, 0x84, 0x4f, 0x60, 0x71, 0x40, 0xe2, 0x82, 0x76, 0x66, 0x76, - 0xbd, 0xee, 0xee, 0x26, 0xde, 0x92, 0x88, 0x53, 0xec, 0xf9, 0xfd, 0x99, 0xf7, 0xde, 0xfc, 0x3c, - 0xf3, 0x14, 0x78, 0xc1, 0xa8, 0x68, 0xb2, 0x6a, 0x59, 0x75, 0x43, 0x53, 0x5d, 0x83, 0x9a, 0x8e, - 0x5c, 0x25, 0x44, 0x6e, 0x2e, 0xc8, 0x77, 0x1a, 0xc4, 0x6e, 0x49, 0x96, 0x4d, 0x5d, 0x8a, 0xce, - 0x1a, 0x15, 0x4d, 0x0a, 0x27, 0x49, 0x55, 0x42, 0xa4, 0xe6, 0x42, 0x76, 0xa2, 0x46, 0x6b, 0x94, - 0xe5, 0xc8, 0xde, 0x27, 0x9e, 0x9e, 0x9d, 0xaa, 0x51, 0x5a, 0xab, 0x13, 0x59, 0xb5, 0x0c, 0x59, - 0x35, 0x4d, 0xea, 0x8a, 0x22, 0x1e, 0xcd, 0x69, 0xd4, 0xd9, 0xa0, 0x8e, 0x5c, 0x51, 0x1d, 0x6f, - 0xa3, 0x0a, 0x71, 0xd5, 0x05, 0x59, 0xa3, 0x86, 0x29, 0xe2, 0x73, 0xe1, 0x38, 0x43, 0x11, 0x64, - 0x59, 0x6a, 0xcd, 0x30, 0x59, 0x33, 0x91, 0x7b, 0x3e, 0x09, 0xbd, 0x87, 0x8f, 0xa7, 0x5c, 0x4c, - 0x4a, 0xa9, 0x11, 0x93, 0x38, 0x86, 0x13, 0xee, 0xa4, 0x51, 0x9b, 0xc8, 0xda, 0x9a, 0x6a, 0x9a, - 0xa4, 0xee, 0xa5, 0x88, 0x8f, 0x3c, 0x05, 0x3f, 0x00, 0x30, 0x7f, 0xcb, 0xc3, 0xb3, 0x62, 0x6a, - 0xc4, 0x74, 0x8d, 0xa6, 0x71, 0x97, 0xe8, 0x37, 0x55, 0x6d, 0x9d, 0xb8, 0x8e, 0x42, 0xee, 0x34, - 0x88, 0xe3, 0xa2, 0x65, 0x08, 0xbb, 0x20, 0x27, 0xc1, 0x0c, 0x98, 0x1d, 0x2d, 0xbc, 0x2c, 0x71, - 0x46, 0x92, 0xc7, 0x48, 0xe2, 0xba, 0x0a, 0x46, 0xd2, 0x4d, 0xb5, 0x46, 0x44, 0xad, 0x12, 0xaa, - 0x44, 0xe7, 0xe1, 0x18, 0x4b, 0x2c, 0xaf, 0x11, 0xa3, 0xb6, 0xe6, 0x4e, 0x0e, 0xce, 0x80, 0xd9, - 0x21, 0x65, 0x94, 0xad, 0xdd, 0x60, 0x4b, 0xf8, 0x0b, 0x00, 0x67, 0x92, 0xe1, 0x38, 0x16, 0x35, - 0x1d, 0x82, 0xaa, 0x70, 0xc2, 0x08, 0x85, 0xcb, 0x16, 0x8f, 0x4f, 0x82, 0x99, 0x63, 0xb3, 0xa3, - 0x85, 0x79, 0x29, 0xe1, 0x60, 0xa5, 0x15, 0xdd, 0xab, 0xa9, 0x1a, 0x7e, 0xc7, 0x65, 0x42, 0x9c, - 0xe2, 0xd0, 0xc3, 0x76, 0x7e, 0x40, 0xc9, 0x18, 0xd1, 0xfd, 0xf0, 0x0e, 0x80, 0xb9, 0x04, 0x30, - 0xbe, 0x34, 0xd7, 0xe0, 0x08, 0xdf, 0xbd, 0x6c, 0xe8, 0x42, 0x99, 0x69, 0xb6, 0xbf, 0xa7, 0xba, - 0xe4, 0x4b, 0xdd, 0xf4, 0x34, 0xf1, 0xb2, 0x56, 0x74, 0xb1, 0xdf, 0xb0, 0x25, 0xbe, 0xf7, 0x23, - 0xca, 0xe7, 0xc9, 0x67, 0x14, 0x68, 0xa2, 0xc3, 0x4c, 0x8c, 0x26, 0x02, 0xd2, 0x33, 0x49, 0x82, - 0xa2, 0x92, 0xe0, 0x47, 0x00, 0xbe, 0x9a, 0x74, 0x3c, 0xcb, 0xd4, 0x2e, 0x71, 0xbe, 0x87, 0x3d, - 0x37, 0x67, 0xe1, 0x09, 0x8b, 0xda, 0x4c, 0x62, 0x4f, 0x9d, 0x11, 0xe5, 0xb8, 0xf7, 0x75, 0x45, - 0x47, 0xd3, 0x10, 0x0a, 0x89, 0xbd, 0xd8, 0x31, 0x16, 0x1b, 0x11, 0x2b, 0x31, 0xd2, 0x0e, 0x45, - 0xa5, 0xfd, 0x0a, 0xc0, 0xb9, 0x7e, 0x08, 0x09, 0x95, 0x6f, 0x1f, 0xe2, 0xe4, 0xc5, 0xcf, 0xdc, - 0xc7, 0xf0, 0x1c, 0xc3, 0xb3, 0x4a, 0x5d, 0xb5, 0xae, 0x10, 0xad, 0xc9, 0x52, 0x0f, 0x6b, 0xda, - 0xf0, 0x77, 0x00, 0x66, 0xe3, 0xfa, 0x0b, 0x7e, 0xf7, 0xe0, 0x88, 0x4d, 0xb4, 0x66, 0xb9, 0x4a, - 0x88, 0x4f, 0xea, 0x5c, 0xcf, 0x81, 0xf9, 0x47, 0x55, 0xa2, 0x86, 0x59, 0x7c, 0xd3, 0x6b, 0xde, - 0x69, 0xe7, 0xc7, 0x5b, 0xea, 0x46, 0xfd, 0x0d, 0x1c, 0x54, 0xe2, 0x9f, 0xfe, 0xc8, 0xcf, 0xd6, - 0x0c, 0x77, 0xad, 0x51, 0x91, 0x34, 0xba, 0x21, 0x8b, 0xbb, 0x8f, 0xff, 0x99, 0x77, 0xf4, 0x75, - 0xd9, 0x6d, 0x59, 0xc4, 0x61, 0x4d, 0x1c, 0x65, 0xd8, 0x16, 0x28, 0xf0, 0x47, 0x70, 0xb2, 0x8b, - 0xed, 0xba, 0xb6, 0x7e, 0xb8, 0xd4, 0xbf, 0x05, 0x61, 0x69, 0x83, 0xf6, 0x82, 0x79, 0x0b, 0x0e, - 0xab, 0xda, 0x7a, 0x9f, 0xc4, 0x4b, 0x82, 0xf8, 0x29, 0x4e, 0xdc, 0x2f, 0x4c, 0xc7, 0xfb, 0x84, - 0xca, 0x21, 0xe0, 0xdb, 0x70, 0xaa, 0x8b, 0x6b, 0xd5, 0xd8, 0x20, 0xb4, 0xe1, 0x1e, 0x2e, 0xf5, - 0x1f, 0x01, 0x9c, 0x4e, 0xd8, 0x42, 0xd0, 0xdf, 0x01, 0x70, 0xcc, 0xe5, 0xeb, 0x7d, 0x6a, 0xf0, - 0xb6, 0xd0, 0x20, 0xc3, 0x35, 0x08, 0x17, 0xa7, 0xd3, 0x61, 0xd4, 0xed, 0xe2, 0xc1, 0xdf, 0xfb, - 0x57, 0x5d, 0x89, 0x36, 0x4c, 0x97, 0xd8, 0x96, 0x6a, 0xbb, 0xad, 0xeb, 0xba, 0x6e, 0x13, 0x27, - 0xd0, 0xe3, 0xf5, 0x9e, 0x5f, 0xbd, 0x27, 0xc8, 0x48, 0xf1, 0x85, 0x4e, 0x3b, 0x7f, 0x9a, 0x23, - 0xe9, 0xc6, 0x70, 0xf8, 0x32, 0x28, 0xc1, 0x53, 0x36, 0xa9, 0xab, 0x2d, 0x62, 0x97, 0x55, 0xde, - 0x8f, 0x5f, 0x26, 0xc5, 0x6c, 0xa7, 0x9d, 0x3f, 0xe3, 0x4f, 0x70, 0x4f, 0x02, 0x56, 0x4e, 0x8a, - 0x15, 0x81, 0x00, 0x37, 0xc5, 0xeb, 0x14, 0x8b, 0x4e, 0x48, 0xa9, 0xc0, 0x09, 0x2d, 0x14, 0x0e, - 0x76, 0xe3, 0x40, 0xf3, 0x9d, 0x76, 0xfe, 0x45, 0x01, 0x34, 0x26, 0x0b, 0x2b, 0x19, 0x2d, 0xda, - 0x1b, 0x7f, 0xe9, 0xbf, 0x44, 0xcb, 0x84, 0xbc, 0x65, 0xaa, 0x95, 0x3a, 0xd1, 0xc5, 0xd5, 0xf4, - 0x7f, 0x3c, 0xd2, 0x3f, 0xf8, 0x87, 0x14, 0x87, 0x46, 0xa8, 0x70, 0x1f, 0xc0, 0x89, 0x2a, 0x21, - 0x65, 0xc2, 0xe3, 0x65, 0x71, 0x10, 0xfe, 0x60, 0xcd, 0x25, 0x5e, 0x95, 0x91, 0x9e, 0xc5, 0x0b, - 0x62, 0xd2, 0x84, 0x6c, 0x71, 0x5d, 0xb1, 0x82, 0xaa, 0x11, 0x2c, 0x78, 0xdb, 0x1f, 0xfb, 0x48, - 0x4f, 0x5f, 0xb4, 0xd7, 0xba, 0x2f, 0x0b, 0x3f, 0x1e, 0xd4, 0x69, 0xe7, 0x4f, 0xf2, 0x7d, 0x44, - 0x00, 0x07, 0xaf, 0x4d, 0xef, 0xdc, 0x0d, 0xf6, 0x37, 0x77, 0xf8, 0x83, 0xa4, 0x93, 0x0b, 0xa4, - 0x5a, 0x82, 0xa3, 0x21, 0x4e, 0x0c, 0xc8, 0x70, 0xf1, 0x4c, 0xa7, 0x9d, 0x47, 0x11, 0xc2, 0x58, - 0x81, 0x5d, 0x9e, 0x85, 0x5f, 0xc6, 0xe1, 0x73, 0xac, 0x37, 0xfa, 0x15, 0xc0, 0x4c, 0xcc, 0x0b, - 0x86, 0xae, 0x24, 0xca, 0x7c, 0x80, 0xe7, 0xcb, 0x5e, 0x7d, 0x86, 0x4a, 0xce, 0x07, 0xcf, 0x6f, - 0xff, 0xf6, 0xe7, 0x37, 0x83, 0xaf, 0xa0, 0x8b, 0xb2, 0x70, 0xa9, 0x81, 0x3b, 0x8d, 0x7b, 0x3b, - 0xd1, 0x83, 0x41, 0x88, 0xa2, 0xed, 0xd0, 0x52, 0x5a, 0x00, 0x3e, 0xf2, 0x2b, 0xe9, 0x0b, 0x05, - 0xf0, 0x6d, 0xc0, 0x90, 0xdf, 0x43, 0x77, 0xfb, 0x41, 0x2e, 0x7b, 0x63, 0x21, 0x6f, 0x06, 0x57, - 0xb3, 0x24, 0x06, 0x66, 0x2b, 0x30, 0xdb, 0xa1, 0x58, 0x77, 0x38, 0xb6, 0x64, 0xc7, 0x03, 0x6a, - 0x6a, 0x24, 0x1c, 0xf7, 0xd7, 0xb6, 0xd0, 0x3f, 0x00, 0x4e, 0xef, 0x6b, 0x46, 0x50, 0x31, 0xf5, - 0xd1, 0x44, 0xac, 0x59, 0xb6, 0xf4, 0x9f, 0x7a, 0x08, 0xbd, 0x6e, 0x31, 0xb9, 0xde, 0x41, 0x2b, - 0x7d, 0x1d, 0xb4, 0xaf, 0x57, 0x44, 0xa5, 0x90, 0x36, 0xe8, 0x6f, 0x00, 0x9f, 0xef, 0xb1, 0x26, - 0xa8, 0xb0, 0x3f, 0xd2, 0x38, 0x9f, 0x94, 0x5d, 0x4c, 0x55, 0x23, 0xd8, 0x7c, 0xc6, 0xd8, 0x7c, - 0x8a, 0x9a, 0x11, 0x36, 0xae, 0x97, 0x5f, 0x0e, 0xec, 0xcd, 0x11, 0x1d, 0xfc, 0x5f, 0x00, 0x8e, - 0x85, 0xad, 0x09, 0x5a, 0xe8, 0x83, 0x45, 0xaf, 0x4b, 0xca, 0x16, 0xd2, 0x94, 0x08, 0xde, 0x5b, - 0x8c, 0xf7, 0x27, 0xa8, 0x91, 0xc0, 0xdb, 0x77, 0x37, 0x47, 0x44, 0x7b, 0x67, 0x10, 0x8e, 0x3f, - 0x6d, 0x4b, 0xd0, 0xa5, 0x3e, 0x78, 0x44, 0x9d, 0x52, 0xf6, 0x72, 0xda, 0x32, 0x21, 0xc1, 0x7d, - 0xfe, 0xc3, 0xdf, 0x44, 0xad, 0x04, 0x0d, 0xc2, 0xee, 0xe6, 0x88, 0x74, 0x78, 0x02, 0x60, 0x26, - 0xc6, 0x56, 0x1c, 0x74, 0x85, 0x27, 0xfb, 0xa4, 0x83, 0xae, 0xf0, 0x7d, 0x3c, 0x0c, 0x5e, 0x65, - 0x7a, 0xbc, 0x87, 0xde, 0x8d, 0xe8, 0x11, 0x67, 0x5a, 0xe4, 0xcd, 0xa7, 0x8c, 0x53, 0xc2, 0x8f, - 0xfb, 0x67, 0x00, 0x51, 0xd4, 0x32, 0x1c, 0x74, 0xd3, 0x27, 0x5a, 0x9e, 0x83, 0x6e, 0xfa, 0x64, - 0x77, 0x82, 0x5f, 0x62, 0xfc, 0x72, 0x68, 0x2a, 0xc2, 0x2f, 0xf4, 0xd8, 0xa2, 0x47, 0x00, 0x9e, - 0x8e, 0x34, 0x41, 0x97, 0x53, 0xee, 0xea, 0xa3, 0x5d, 0x4a, 0x5d, 0x27, 0xc0, 0xde, 0x60, 0x60, - 0x8b, 0xe8, 0xda, 0x7e, 0x60, 0xfb, 0xb9, 0x5d, 0x8b, 0xef, 0x3f, 0xdc, 0xcd, 0x81, 0xc7, 0xbb, - 0x39, 0xf0, 0x64, 0x37, 0x07, 0xbe, 0xde, 0xcb, 0x0d, 0x3c, 0xde, 0xcb, 0x0d, 0xfc, 0xbe, 0x97, - 0x1b, 0xf8, 0xf0, 0x52, 0xd4, 0xae, 0x1b, 0x15, 0x6d, 0xbe, 0x46, 0xe5, 0xe6, 0xa2, 0xbc, 0x41, - 0xf5, 0x46, 0x9d, 0x38, 0x7c, 0xeb, 0xc2, 0xd5, 0x79, 0x6f, 0x77, 0xe6, 0xe0, 0x2b, 0xc7, 0xd9, - 0x3f, 0x91, 0x16, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x61, 0x8e, 0x05, 0x2f, 0x71, 0x13, 0x00, - 0x00, + 0x21, 0x28, 0xbb, 0x8a, 0x43, 0x9b, 0x96, 0x13, 0xb5, 0x4b, 0x20, 0x20, 0x44, 0x59, 0x2a, 0x04, + 0x08, 0x70, 0xd7, 0xbb, 0x63, 0x67, 0x15, 0x67, 0x67, 0xbb, 0xbb, 0xb6, 0x70, 0xd3, 0x00, 0xad, + 0x88, 0x40, 0x80, 0x00, 0x09, 0x89, 0x03, 0xe2, 0x8a, 0x90, 0x90, 0xf8, 0x00, 0x7c, 0x83, 0x8a, + 0x03, 0x8a, 0xc4, 0x85, 0x93, 0x41, 0x09, 0x27, 0x8e, 0x3e, 0x71, 0x00, 0x09, 0xed, 0xcc, 0xec, + 0x7a, 0xdd, 0xdd, 0x4d, 0xec, 0x60, 0x85, 0x53, 0xec, 0xf9, 0xfd, 0x99, 0xf7, 0xde, 0xfc, 0x3c, + 0xf3, 0x14, 0x78, 0xce, 0x28, 0x69, 0xb2, 0x6a, 0x59, 0x55, 0x43, 0x53, 0x5d, 0x83, 0x9a, 0x8e, + 0x5c, 0x26, 0x44, 0xae, 0x2f, 0xc8, 0x37, 0x6b, 0xc4, 0x6e, 0x48, 0x96, 0x4d, 0x5d, 0x8a, 0x4e, + 0x1b, 0x25, 0x4d, 0x0a, 0x27, 0x49, 0x65, 0x42, 0xa4, 0xfa, 0x42, 0x7a, 0xa2, 0x42, 0x2b, 0x94, + 0xe5, 0xc8, 0xde, 0x27, 0x9e, 0x9e, 0x9e, 0xaa, 0x50, 0x5a, 0xa9, 0x12, 0x59, 0xb5, 0x0c, 0x59, + 0x35, 0x4d, 0xea, 0x8a, 0x22, 0x1e, 0xcd, 0x68, 0xd4, 0x59, 0xa7, 0x8e, 0x5c, 0x52, 0x1d, 0x6f, + 0xa3, 0x12, 0x71, 0xd5, 0x05, 0x59, 0xa3, 0x86, 0x29, 0xe2, 0x73, 0xe1, 0x38, 0x43, 0x11, 0x64, + 0x59, 0x6a, 0xc5, 0x30, 0x59, 0x33, 0x91, 0x7b, 0x36, 0x09, 0xbd, 0x87, 0x8f, 0xa7, 0x9c, 0x4f, + 0x4a, 0xa9, 0x10, 0x93, 0x38, 0x86, 0x13, 0xee, 0xa4, 0x51, 0x9b, 0xc8, 0xda, 0xaa, 0x6a, 0x9a, + 0xa4, 0xea, 0xa5, 0x88, 0x8f, 0x3c, 0x05, 0x7f, 0x0a, 0x60, 0xf6, 0x65, 0x0f, 0xcf, 0x8a, 0xa9, + 0x11, 0xd3, 0x35, 0xea, 0xc6, 0x2d, 0xa2, 0x5f, 0x53, 0xb5, 0x35, 0xe2, 0x3a, 0x0a, 0xb9, 0x59, + 0x23, 0x8e, 0x8b, 0x96, 0x21, 0x6c, 0x83, 0x9c, 0x04, 0x33, 0x60, 0x76, 0x34, 0xf7, 0xa8, 0xc4, + 0x19, 0x49, 0x1e, 0x23, 0x89, 0xeb, 0x2a, 0x18, 0x49, 0xd7, 0xd4, 0x0a, 0x11, 0xb5, 0x4a, 0xa8, + 0x12, 0x9d, 0x85, 0x63, 0x2c, 0xb1, 0xb8, 0x4a, 0x8c, 0xca, 0xaa, 0x3b, 0x39, 0x38, 0x03, 0x66, + 0x87, 0x94, 0x51, 0xb6, 0xf6, 0x1c, 0x5b, 0xc2, 0x1f, 0x03, 0x38, 0x93, 0x0c, 0xc7, 0xb1, 0xa8, + 0xe9, 0x10, 0x54, 0x86, 0x13, 0x46, 0x28, 0x5c, 0xb4, 0x78, 0x7c, 0x12, 0xcc, 0x1c, 0x99, 0x1d, + 0xcd, 0xcd, 0x4b, 0x09, 0x07, 0x2b, 0xad, 0xe8, 0x5e, 0x4d, 0xd9, 0xf0, 0x3b, 0x2e, 0x13, 0xe2, + 0xe4, 0x87, 0xee, 0x35, 0xb3, 0x03, 0x4a, 0xca, 0x88, 0xee, 0x87, 0xb7, 0x00, 0xcc, 0x24, 0x80, + 0xf1, 0xa5, 0x79, 0x1a, 0x8e, 0xf0, 0xdd, 0x8b, 0x86, 0x2e, 0x94, 0x99, 0x66, 0xfb, 0x7b, 0xaa, + 0x4b, 0xbe, 0xd4, 0x75, 0x4f, 0x13, 0x2f, 0x6b, 0x45, 0x17, 0xfb, 0x0d, 0x5b, 0xe2, 0x7b, 0x37, + 0xa2, 0x7c, 0x98, 0x7c, 0x46, 0x81, 0x26, 0x3a, 0x4c, 0xc5, 0x68, 0x22, 0x20, 0x1d, 0x48, 0x12, + 0x14, 0x95, 0x04, 0xff, 0x0c, 0xe0, 0xe3, 0x49, 0xc7, 0xb3, 0x4c, 0xed, 0x02, 0xe7, 0xdb, 0xef, + 0xb9, 0x39, 0x0d, 0x8f, 0x59, 0xd4, 0x66, 0x12, 0x7b, 0xea, 0x8c, 0x28, 0x47, 0xbd, 0xaf, 0x2b, + 0x3a, 0x9a, 0x86, 0x50, 0x48, 0xec, 0xc5, 0x8e, 0xb0, 0xd8, 0x88, 0x58, 0x89, 0x91, 0x76, 0x28, + 0x2a, 0xed, 0x67, 0x00, 0xce, 0x75, 0x43, 0x48, 0xa8, 0x7c, 0xa3, 0x8f, 0x93, 0x17, 0x3f, 0x73, + 0x6f, 0xc1, 0x33, 0x0c, 0xcf, 0x75, 0xea, 0xaa, 0x55, 0x85, 0x68, 0x75, 0x96, 0xda, 0xaf, 0x69, + 0xc3, 0x5f, 0x03, 0x98, 0x8e, 0xeb, 0x2f, 0xf8, 0xdd, 0x86, 0x23, 0x36, 0xd1, 0xea, 0xc5, 0x32, + 0x21, 0x3e, 0xa9, 0x33, 0x1d, 0x07, 0xe6, 0x1f, 0x55, 0x81, 0x1a, 0x66, 0xfe, 0xaa, 0xd7, 0xbc, + 0xd5, 0xcc, 0x8e, 0x37, 0xd4, 0xf5, 0xea, 0x53, 0x38, 0xa8, 0xc4, 0xdf, 0xff, 0x96, 0x9d, 0xad, + 0x18, 0xee, 0x6a, 0xad, 0x24, 0x69, 0x74, 0x5d, 0x16, 0x77, 0x1f, 0xff, 0x33, 0xef, 0xe8, 0x6b, + 0xb2, 0xdb, 0xb0, 0x88, 0xc3, 0x9a, 0x38, 0xca, 0xb0, 0x2d, 0x50, 0xe0, 0x37, 0xe1, 0x64, 0x1b, + 0xdb, 0x15, 0x6d, 0xad, 0xbf, 0xd4, 0xbf, 0x02, 0x61, 0x69, 0x83, 0xf6, 0x82, 0x79, 0x03, 0x0e, + 0xab, 0xda, 0x5a, 0x97, 0xc4, 0x0b, 0x82, 0xf8, 0x09, 0x4e, 0xdc, 0x2f, 0xec, 0x8d, 0xf7, 0x31, + 0x95, 0x43, 0xc0, 0x37, 0xe0, 0x54, 0x1b, 0xd7, 0x75, 0x63, 0x9d, 0xd0, 0x9a, 0xdb, 0x5f, 0xea, + 0xdf, 0x01, 0x38, 0x9d, 0xb0, 0x85, 0xa0, 0xbf, 0x05, 0xe0, 0x98, 0xcb, 0xd7, 0xbb, 0xd4, 0xe0, + 0x59, 0xa1, 0x41, 0x8a, 0x6b, 0x10, 0x2e, 0xee, 0x4d, 0x87, 0x51, 0xb7, 0x8d, 0x07, 0x7f, 0xe3, + 0x5f, 0x75, 0x05, 0x5a, 0x33, 0x5d, 0x62, 0x5b, 0xaa, 0xed, 0x36, 0xae, 0xe8, 0xba, 0x4d, 0x9c, + 0x40, 0x8f, 0x27, 0x3b, 0x7e, 0xf5, 0x9e, 0x20, 0x23, 0xf9, 0x87, 0x5a, 0xcd, 0xec, 0x49, 0x8e, + 0xa4, 0x1d, 0xc3, 0xe1, 0xcb, 0xa0, 0x00, 0x4f, 0xd8, 0xa4, 0xaa, 0x36, 0x88, 0x5d, 0x54, 0x79, + 0x3f, 0x7e, 0x99, 0xe4, 0xd3, 0xad, 0x66, 0xf6, 0x94, 0x3f, 0xc1, 0x1d, 0x09, 0x58, 0x39, 0x2e, + 0x56, 0x04, 0x02, 0x5c, 0x17, 0xaf, 0x53, 0x2c, 0x3a, 0x21, 0xa5, 0x02, 0x27, 0xb4, 0x50, 0x38, + 0xd8, 0x8d, 0x03, 0xcd, 0xb6, 0x9a, 0xd9, 0x87, 0x05, 0xd0, 0x98, 0x2c, 0xac, 0xa4, 0xb4, 0x68, + 0x6f, 0xfc, 0x89, 0xff, 0x12, 0x2d, 0x13, 0xf2, 0x8c, 0xa9, 0x96, 0xaa, 0x44, 0x17, 0x57, 0xd3, + 0xff, 0xf1, 0x48, 0x7f, 0xeb, 0x1f, 0x52, 0x1c, 0x1a, 0xa1, 0xc2, 0x1d, 0x00, 0x27, 0xca, 0x84, + 0x14, 0x09, 0x8f, 0x17, 0xc5, 0x41, 0xf8, 0x83, 0x35, 0x97, 0x78, 0x55, 0x46, 0x7a, 0xe6, 0xcf, + 0x89, 0x49, 0x13, 0xb2, 0xc5, 0x75, 0xc5, 0x0a, 0x2a, 0x47, 0xb0, 0xe0, 0xbb, 0xfe, 0xd8, 0x47, + 0x7a, 0xfa, 0xa2, 0x3d, 0xd1, 0x7e, 0x59, 0xf8, 0xf1, 0xa0, 0x56, 0x33, 0x7b, 0x9c, 0xef, 0x23, + 0x02, 0x38, 0x78, 0x6d, 0x3a, 0xe7, 0x6e, 0xb0, 0xbb, 0xb9, 0xc3, 0xaf, 0x27, 0x9d, 0x5c, 0x20, + 0xd5, 0x12, 0x1c, 0x0d, 0x71, 0x62, 0x40, 0x86, 0xf3, 0xa7, 0x5a, 0xcd, 0x2c, 0x8a, 0x10, 0xc6, + 0x0a, 0x6c, 0xf3, 0xcc, 0xfd, 0x34, 0x0e, 0x1f, 0x60, 0xbd, 0xd1, 0x8f, 0x00, 0xa6, 0x62, 0x5e, + 0x30, 0x74, 0x29, 0x51, 0xe6, 0x7d, 0x3c, 0x5f, 0xfa, 0xf2, 0x01, 0x2a, 0x39, 0x1f, 0x3c, 0x7f, + 0xf7, 0x97, 0x3f, 0xbe, 0x1c, 0x7c, 0x0c, 0x9d, 0x97, 0x85, 0x4b, 0x0d, 0xdc, 0x69, 0xdc, 0xdb, + 0x89, 0x3e, 0x1f, 0x84, 0x28, 0xda, 0x0e, 0x2d, 0xf5, 0x0a, 0xc0, 0x47, 0x7e, 0xa9, 0xf7, 0x42, + 0x01, 0x7c, 0x0b, 0x30, 0xe4, 0xef, 0xa1, 0xcd, 0x08, 0x72, 0x7f, 0xd0, 0xe4, 0x8d, 0xe0, 0x2a, + 0x96, 0xda, 0x07, 0xbe, 0x29, 0x7b, 0x23, 0xd2, 0x11, 0x14, 0xd3, 0xb3, 0x29, 0x3b, 0x1e, 0x2c, + 0x53, 0x23, 0x1d, 0x51, 0x7f, 0x71, 0x33, 0x4e, 0x12, 0xf4, 0x0f, 0x80, 0xd3, 0x7b, 0xfa, 0x11, + 0x94, 0xef, 0xf9, 0x74, 0x22, 0xee, 0x2c, 0x5d, 0xf8, 0x4f, 0x3d, 0x84, 0x64, 0xaf, 0x30, 0xc5, + 0x5e, 0x44, 0x2f, 0xec, 0xa1, 0x58, 0x9c, 0x4e, 0xbe, 0x3a, 0xb1, 0x13, 0xf1, 0x37, 0x80, 0x0f, + 0x76, 0xf8, 0x13, 0x94, 0xdb, 0x1b, 0x6b, 0x9c, 0x59, 0x4a, 0x2f, 0xf6, 0x54, 0x23, 0xf8, 0xdc, + 0xe1, 0x23, 0xb0, 0x81, 0x1a, 0x87, 0x37, 0x02, 0xae, 0x87, 0xa4, 0x18, 0xb8, 0x27, 0xf4, 0x17, + 0x80, 0x63, 0x61, 0x8f, 0x82, 0x16, 0xba, 0x60, 0xd2, 0x69, 0x97, 0xd2, 0xb9, 0x5e, 0x4a, 0x04, + 0xf7, 0xf7, 0x39, 0xf7, 0x5b, 0xe8, 0x9d, 0xc3, 0xe6, 0xee, 0x1b, 0x28, 0xf4, 0xd1, 0x20, 0x1c, + 0xbf, 0xdf, 0xa3, 0xa0, 0x0b, 0x5d, 0x70, 0x89, 0xda, 0xa6, 0xf4, 0xc5, 0x5e, 0xcb, 0x84, 0x0c, + 0x1f, 0x70, 0x19, 0xde, 0x45, 0xb7, 0x0f, 0x5b, 0x86, 0xb0, 0x87, 0x42, 0x7f, 0x02, 0x98, 0x8a, + 0xb1, 0x19, 0xfb, 0x5d, 0xe9, 0xc9, 0xbe, 0x69, 0xbf, 0x2b, 0x7d, 0x0f, 0x4f, 0x83, 0xdf, 0x66, + 0x92, 0xbc, 0x86, 0x5e, 0xed, 0xf2, 0x67, 0x2e, 0x6c, 0x93, 0x23, 0x6f, 0xdc, 0x67, 0xa9, 0x36, + 0xe5, 0x38, 0xd7, 0x83, 0x7e, 0x00, 0x10, 0x45, 0xcd, 0xc4, 0x7e, 0x6f, 0x40, 0xa2, 0x19, 0xda, + 0xef, 0x0d, 0x48, 0xf6, 0x2d, 0xf8, 0x11, 0xc6, 0x34, 0x83, 0xa6, 0x22, 0x4c, 0x43, 0xcf, 0x30, + 0xda, 0x06, 0xf0, 0x64, 0xa4, 0x09, 0xba, 0xd8, 0xe3, 0xae, 0x3e, 0xda, 0xa5, 0x9e, 0xeb, 0x04, + 0xd8, 0xe7, 0x19, 0xd8, 0xab, 0x28, 0x7f, 0xc0, 0xdb, 0x37, 0x44, 0x29, 0xff, 0xd2, 0xbd, 0x9d, + 0x0c, 0xd8, 0xde, 0xc9, 0x80, 0xdf, 0x77, 0x32, 0xe0, 0x8b, 0xdd, 0xcc, 0xc0, 0xf6, 0x6e, 0x66, + 0xe0, 0xd7, 0xdd, 0xcc, 0xc0, 0x1b, 0x17, 0xa2, 0x56, 0xde, 0x28, 0x69, 0xf3, 0x15, 0x2a, 0xd7, + 0x17, 0xe5, 0x75, 0xaa, 0xd7, 0xaa, 0xc4, 0xe1, 0x9b, 0xe7, 0x2e, 0xcf, 0x7b, 0xfb, 0x33, 0x77, + 0x5f, 0x3a, 0xca, 0xfe, 0xc1, 0xb4, 0xf8, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x50, 0x32, 0x7d, + 0x07, 0x8d, 0x13, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/modules/apps/29-fee/types/query.pb.gw.go b/modules/apps/29-fee/types/query.pb.gw.go index 9b9e47c5939..712c7f32727 100644 --- a/modules/apps/29-fee/types/query.pb.gw.go +++ b/modules/apps/29-fee/types/query.pb.gw.go @@ -68,7 +68,7 @@ func local_request_Query_IncentivizedPackets_0(ctx context.Context, marshaler ru } var ( - filter_Query_IncentivizedPacket_0 = &utilities.DoubleArray{Encoding: map[string]int{"packet_id": 0, "port_id": 1, "channel_id": 2, "sequence": 3}, Base: []int{1, 1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 2, 2, 2, 3, 4, 5}} + filter_Query_IncentivizedPacket_0 = &utilities.DoubleArray{Encoding: map[string]int{"packet_id": 0, "channel_id": 1, "port_id": 2, "sequence": 3}, Base: []int{1, 1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 2, 2, 2, 3, 4, 5}} ) func request_Query_IncentivizedPacket_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { @@ -82,26 +82,26 @@ func request_Query_IncentivizedPacket_0(ctx context.Context, marshaler runtime.M _ = err ) - val, ok = pathParams["packet_id.port_id"] + val, ok = pathParams["packet_id.channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) } - val, ok = pathParams["packet_id.channel_id"] + val, ok = pathParams["packet_id.port_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) } val, ok = pathParams["packet_id.sequence"] @@ -138,26 +138,26 @@ func local_request_Query_IncentivizedPacket_0(ctx context.Context, marshaler run _ = err ) - val, ok = pathParams["packet_id.port_id"] + val, ok = pathParams["packet_id.channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) } - val, ok = pathParams["packet_id.channel_id"] + val, ok = pathParams["packet_id.port_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) } val, ok = pathParams["packet_id.sequence"] @@ -184,7 +184,7 @@ func local_request_Query_IncentivizedPacket_0(ctx context.Context, marshaler run } var ( - filter_Query_IncentivizedPacketsForChannel_0 = &utilities.DoubleArray{Encoding: map[string]int{"port_id": 0, "channel_id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} + filter_Query_IncentivizedPacketsForChannel_0 = &utilities.DoubleArray{Encoding: map[string]int{"channel_id": 0, "port_id": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} ) func request_Query_IncentivizedPacketsForChannel_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { @@ -198,26 +198,26 @@ func request_Query_IncentivizedPacketsForChannel_0(ctx context.Context, marshale _ = err ) - val, ok = pathParams["port_id"] + val, ok = pathParams["channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") } - protoReq.PortId, err = runtime.String(val) + protoReq.ChannelId, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) } - val, ok = pathParams["channel_id"] + val, ok = pathParams["port_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") } - protoReq.ChannelId, err = runtime.String(val) + protoReq.PortId, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } if err := req.ParseForm(); err != nil { @@ -243,26 +243,26 @@ func local_request_Query_IncentivizedPacketsForChannel_0(ctx context.Context, ma _ = err ) - val, ok = pathParams["port_id"] + val, ok = pathParams["channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") } - protoReq.PortId, err = runtime.String(val) + protoReq.ChannelId, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) } - val, ok = pathParams["channel_id"] + val, ok = pathParams["port_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") } - protoReq.ChannelId, err = runtime.String(val) + protoReq.PortId, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } if err := req.ParseForm(); err != nil { @@ -278,7 +278,7 @@ func local_request_Query_IncentivizedPacketsForChannel_0(ctx context.Context, ma } var ( - filter_Query_TotalRecvFees_0 = &utilities.DoubleArray{Encoding: map[string]int{"packet_id": 0, "port_id": 1, "channel_id": 2, "sequence": 3}, Base: []int{1, 1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 2, 2, 2, 3, 4, 5}} + filter_Query_TotalRecvFees_0 = &utilities.DoubleArray{Encoding: map[string]int{"packet_id": 0, "channel_id": 1, "port_id": 2, "sequence": 3}, Base: []int{1, 1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 2, 2, 2, 3, 4, 5}} ) func request_Query_TotalRecvFees_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { @@ -292,26 +292,26 @@ func request_Query_TotalRecvFees_0(ctx context.Context, marshaler runtime.Marsha _ = err ) - val, ok = pathParams["packet_id.port_id"] + val, ok = pathParams["packet_id.channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) } - val, ok = pathParams["packet_id.channel_id"] + val, ok = pathParams["packet_id.port_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) } val, ok = pathParams["packet_id.sequence"] @@ -348,26 +348,26 @@ func local_request_Query_TotalRecvFees_0(ctx context.Context, marshaler runtime. _ = err ) - val, ok = pathParams["packet_id.port_id"] + val, ok = pathParams["packet_id.channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) } - val, ok = pathParams["packet_id.channel_id"] + val, ok = pathParams["packet_id.port_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) } val, ok = pathParams["packet_id.sequence"] @@ -394,7 +394,7 @@ func local_request_Query_TotalRecvFees_0(ctx context.Context, marshaler runtime. } var ( - filter_Query_TotalAckFees_0 = &utilities.DoubleArray{Encoding: map[string]int{"packet_id": 0, "port_id": 1, "channel_id": 2, "sequence": 3}, Base: []int{1, 1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 2, 2, 2, 3, 4, 5}} + filter_Query_TotalAckFees_0 = &utilities.DoubleArray{Encoding: map[string]int{"packet_id": 0, "channel_id": 1, "port_id": 2, "sequence": 3}, Base: []int{1, 1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 2, 2, 2, 3, 4, 5}} ) func request_Query_TotalAckFees_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { @@ -408,26 +408,26 @@ func request_Query_TotalAckFees_0(ctx context.Context, marshaler runtime.Marshal _ = err ) - val, ok = pathParams["packet_id.port_id"] + val, ok = pathParams["packet_id.channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) } - val, ok = pathParams["packet_id.channel_id"] + val, ok = pathParams["packet_id.port_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) } val, ok = pathParams["packet_id.sequence"] @@ -464,26 +464,26 @@ func local_request_Query_TotalAckFees_0(ctx context.Context, marshaler runtime.M _ = err ) - val, ok = pathParams["packet_id.port_id"] + val, ok = pathParams["packet_id.channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) } - val, ok = pathParams["packet_id.channel_id"] + val, ok = pathParams["packet_id.port_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) } val, ok = pathParams["packet_id.sequence"] @@ -510,7 +510,7 @@ func local_request_Query_TotalAckFees_0(ctx context.Context, marshaler runtime.M } var ( - filter_Query_TotalTimeoutFees_0 = &utilities.DoubleArray{Encoding: map[string]int{"packet_id": 0, "port_id": 1, "channel_id": 2, "sequence": 3}, Base: []int{1, 1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 2, 2, 2, 3, 4, 5}} + filter_Query_TotalTimeoutFees_0 = &utilities.DoubleArray{Encoding: map[string]int{"packet_id": 0, "channel_id": 1, "port_id": 2, "sequence": 3}, Base: []int{1, 1, 1, 2, 3, 0, 0, 0}, Check: []int{0, 1, 2, 2, 2, 3, 4, 5}} ) func request_Query_TotalTimeoutFees_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { @@ -524,26 +524,26 @@ func request_Query_TotalTimeoutFees_0(ctx context.Context, marshaler runtime.Mar _ = err ) - val, ok = pathParams["packet_id.port_id"] + val, ok = pathParams["packet_id.channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) } - val, ok = pathParams["packet_id.channel_id"] + val, ok = pathParams["packet_id.port_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) } val, ok = pathParams["packet_id.sequence"] @@ -580,26 +580,26 @@ func local_request_Query_TotalTimeoutFees_0(ctx context.Context, marshaler runti _ = err ) - val, ok = pathParams["packet_id.port_id"] + val, ok = pathParams["packet_id.channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) } - val, ok = pathParams["packet_id.channel_id"] + val, ok = pathParams["packet_id.port_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "packet_id.port_id") } - err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.channel_id", val) + err = runtime.PopulateFieldFromPath(&protoReq, "packet_id.port_id", val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "packet_id.port_id", err) } val, ok = pathParams["packet_id.sequence"] @@ -636,26 +636,26 @@ func request_Query_CounterpartyAddress_0(ctx context.Context, marshaler runtime. _ = err ) - val, ok = pathParams["relayer_address"] + val, ok = pathParams["channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "relayer_address") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") } - protoReq.RelayerAddress, err = runtime.String(val) + protoReq.ChannelId, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "relayer_address", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) } - val, ok = pathParams["channel_id"] + val, ok = pathParams["relayer_address"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "relayer_address") } - protoReq.ChannelId, err = runtime.String(val) + protoReq.RelayerAddress, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "relayer_address", err) } msg, err := client.CounterpartyAddress(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) @@ -674,26 +674,26 @@ func local_request_Query_CounterpartyAddress_0(ctx context.Context, marshaler ru _ = err ) - val, ok = pathParams["relayer_address"] + val, ok = pathParams["channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "relayer_address") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") } - protoReq.RelayerAddress, err = runtime.String(val) + protoReq.ChannelId, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "relayer_address", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) } - val, ok = pathParams["channel_id"] + val, ok = pathParams["relayer_address"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "relayer_address") } - protoReq.ChannelId, err = runtime.String(val) + protoReq.RelayerAddress, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "relayer_address", err) } msg, err := server.CounterpartyAddress(ctx, &protoReq) @@ -748,26 +748,26 @@ func request_Query_FeeEnabledChannel_0(ctx context.Context, marshaler runtime.Ma _ = err ) - val, ok = pathParams["port_id"] + val, ok = pathParams["channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") } - protoReq.PortId, err = runtime.String(val) + protoReq.ChannelId, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) } - val, ok = pathParams["channel_id"] + val, ok = pathParams["port_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") } - protoReq.ChannelId, err = runtime.String(val) + protoReq.PortId, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } msg, err := client.FeeEnabledChannel(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) @@ -786,26 +786,26 @@ func local_request_Query_FeeEnabledChannel_0(ctx context.Context, marshaler runt _ = err ) - val, ok = pathParams["port_id"] + val, ok = pathParams["channel_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") } - protoReq.PortId, err = runtime.String(val) + protoReq.ChannelId, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) } - val, ok = pathParams["channel_id"] + val, ok = pathParams["port_id"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") } - protoReq.ChannelId, err = runtime.String(val) + protoReq.PortId, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) } msg, err := server.FeeEnabledChannel(ctx, &protoReq) @@ -1226,21 +1226,21 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie var ( pattern_Query_IncentivizedPackets_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "apps", "fee", "v1", "incentivized_packets"}, "", runtime.AssumeColonVerbOpt(true))) - pattern_Query_IncentivizedPacket_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5, 1, 0, 4, 1, 5, 6, 2, 7, 1, 0, 4, 1, 5, 8, 2, 9, 1, 0, 4, 1, 5, 10}, []string{"ibc", "apps", "fee", "v1", "incentivized_packet", "port", "packet_id.port_id", "channel", "packet_id.channel_id", "sequence", "packet_id.sequence"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_IncentivizedPacket_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9, 2, 10}, []string{"ibc", "apps", "fee", "v1", "channels", "packet_id.channel_id", "ports", "packet_id.port_id", "sequences", "packet_id.sequence", "incentivized_packet"}, "", runtime.AssumeColonVerbOpt(true))) - pattern_Query_IncentivizedPacketsForChannel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5, 1, 0, 4, 1, 5, 6, 2, 7, 1, 0, 4, 1, 5, 8}, []string{"ibc", "apps", "fee", "v1", "incentivized_packets", "port", "port_id", "channel", "channel_id"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_IncentivizedPacketsForChannel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "apps", "fee", "v1", "channels", "channel_id", "ports", "port_id", "incentivized_packets"}, "", runtime.AssumeColonVerbOpt(true))) - pattern_Query_TotalRecvFees_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5, 1, 0, 4, 1, 5, 6, 2, 7, 1, 0, 4, 1, 5, 8, 2, 9, 1, 0, 4, 1, 5, 10}, []string{"ibc", "apps", "fee", "v1", "total_recv_fees", "port", "packet_id.port_id", "channel", "packet_id.channel_id", "sequence", "packet_id.sequence"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_TotalRecvFees_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9, 2, 10}, []string{"ibc", "apps", "fee", "v1", "channels", "packet_id.channel_id", "ports", "packet_id.port_id", "sequences", "packet_id.sequence", "total_recv_fees"}, "", runtime.AssumeColonVerbOpt(true))) - pattern_Query_TotalAckFees_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5, 1, 0, 4, 1, 5, 6, 2, 7, 1, 0, 4, 1, 5, 8, 2, 9, 1, 0, 4, 1, 5, 10}, []string{"ibc", "apps", "fee", "v1", "total_ack_fees", "port", "packet_id.port_id", "channel", "packet_id.channel_id", "sequence", "packet_id.sequence"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_TotalAckFees_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9, 2, 10}, []string{"ibc", "apps", "fee", "v1", "channels", "packet_id.channel_id", "ports", "packet_id.port_id", "sequences", "packet_id.sequence", "total_ack_fees"}, "", runtime.AssumeColonVerbOpt(true))) - pattern_Query_TotalTimeoutFees_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5, 1, 0, 4, 1, 5, 6, 2, 7, 1, 0, 4, 1, 5, 8, 2, 9, 1, 0, 4, 1, 5, 10}, []string{"ibc", "apps", "fee", "v1", "total_timeout_fees", "port", "packet_id.port_id", "channel", "packet_id.channel_id", "sequence", "packet_id.sequence"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_TotalTimeoutFees_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9, 2, 10}, []string{"ibc", "apps", "fee", "v1", "channels", "packet_id.channel_id", "ports", "packet_id.port_id", "sequences", "packet_id.sequence", "total_timeout_fees"}, "", runtime.AssumeColonVerbOpt(true))) - pattern_Query_CounterpartyAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7}, []string{"ibc", "apps", "fee", "v1", "counterparty_address", "relayer_address", "channel", "channel_id"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_CounterpartyAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "apps", "fee", "v1", "channels", "channel_id", "relayers", "relayer_address", "counterparty_address"}, "", runtime.AssumeColonVerbOpt(true))) pattern_Query_FeeEnabledChannels_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "apps", "fee", "v1", "fee_enabled"}, "", runtime.AssumeColonVerbOpt(true))) - pattern_Query_FeeEnabledChannel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5, 1, 0, 4, 1, 5, 6, 2, 7, 1, 0, 4, 1, 5, 8}, []string{"ibc", "apps", "fee", "v1", "fee_enabled", "port", "port_id", "channel", "channel_id"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_FeeEnabledChannel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "apps", "fee", "v1", "channels", "channel_id", "ports", "port_id", "fee_enabled"}, "", runtime.AssumeColonVerbOpt(true))) ) var ( diff --git a/modules/apps/nft-transfer/ibc_module.go b/modules/apps/nft-transfer/ibc_module.go index 23c986483c3..6e2ab842d14 100644 --- a/modules/apps/nft-transfer/ibc_module.go +++ b/modules/apps/nft-transfer/ibc_module.go @@ -1,6 +1,7 @@ package nt import ( + "fmt" "math" "strings" @@ -195,17 +196,17 @@ func (im IBCModule) OnRecvPacket( } } - // ctx.EventManager().EmitEvent( - // sdk.NewEvent( - // types.EventTypePacket, - // sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - // sdk.NewAttribute(sdk.AttributeKeySender, data.Sender), - // sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), - // sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), - // sdk.NewAttribute(types.AttributeKeyAmount, data.Amount), - // sdk.NewAttribute(types.AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success())), - // ), - // ) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypePacket, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + sdk.NewAttribute(sdk.AttributeKeySender, data.Sender), + sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), + sdk.NewAttribute(types.AttributeKeyClassID, data.ClassId), + sdk.NewAttribute(types.AttributeKeyTokenIDs, strings.Join(data.TokenIds, ",")), + sdk.NewAttribute(types.AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success())), + ), + ) // NOTE: acknowledgement will be written synchronously during IBC handler execution. return ack diff --git a/modules/apps/nft-transfer/keeper/grpc_query.go b/modules/apps/nft-transfer/keeper/grpc_query.go new file mode 100644 index 00000000000..5c44c5499db --- /dev/null +++ b/modules/apps/nft-transfer/keeper/grpc_query.go @@ -0,0 +1,113 @@ +package keeper + +import ( + "context" + "fmt" + "strings" + + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" +) + +var _ types.QueryServer = Keeper{} + +// ClassTrace implements the Query/ClassTrace gRPC method +func (k Keeper) ClassTrace(c context.Context, req *types.QueryClassTraceRequest) (*types.QueryClassTraceResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + hash, err := types.ParseHexHash(strings.TrimPrefix(req.Hash, "ibc/")) + if err != nil { + return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid denom trace hash: %s, error: %s", hash.String(), err)) + } + + ctx := sdk.UnwrapSDKContext(c) + classTrace, found := k.GetClassTrace(ctx, hash) + if !found { + return nil, status.Error( + codes.NotFound, + sdkerrors.Wrap(types.ErrTraceNotFound, req.Hash).Error(), + ) + } + + return &types.QueryClassTraceResponse{ + ClassTrace: &classTrace, + }, nil +} + +// ClassTraces implements the Query/ClassTraces gRPC method +func (k Keeper) ClassTraces(c context.Context, req *types.QueryClassTracesRequest) (*types.QueryClassTracesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + + traces := types.Traces{} + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ClassTraceKey) + + pageRes, err := query.Paginate(store, req.Pagination, func(_, value []byte) error { + result, err := k.UnmarshalClassTrace(value) + if err != nil { + return err + } + + traces = append(traces, result) + return nil + }) + if err != nil { + return nil, err + } + + return &types.QueryClassTracesResponse{ + ClassTraces: traces.Sort(), + Pagination: pageRes, + }, nil +} + +// ClassHash implements the Query/ClassHash gRPC method +func (k Keeper) ClassHash(c context.Context, req *types.QueryClassHashRequest) (*types.QueryClassHashResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + // Convert given request trace path to ClassTrace struct to confirm the path in a valid class trace format + classTrace := types.ParseClassTrace(req.Trace) + if err := classTrace.Validate(); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + ctx := sdk.UnwrapSDKContext(c) + classHash := classTrace.Hash() + found := k.HasClassTrace(ctx, classHash) + if !found { + return nil, status.Error( + codes.NotFound, + sdkerrors.Wrap(types.ErrTraceNotFound, req.Trace).Error(), + ) + } + + return &types.QueryClassHashResponse{ + Hash: classHash.String(), + }, nil +} + +// EscrowAddress implements the EscrowAddress gRPC method +func (k Keeper) EscrowAddress(c context.Context, req *types.QueryEscrowAddressRequest) (*types.QueryEscrowAddressResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + addr := types.GetEscrowAddress(req.PortId, req.ChannelId) + + return &types.QueryEscrowAddressResponse{ + EscrowAddress: addr.String(), + }, nil +} diff --git a/modules/apps/nft-transfer/keeper/keeper.go b/modules/apps/nft-transfer/keeper/keeper.go index 150f8e85082..5523b8fe258 100644 --- a/modules/apps/nft-transfer/keeper/keeper.go +++ b/modules/apps/nft-transfer/keeper/keeper.go @@ -1,12 +1,15 @@ package keeper import ( + "github.com/tendermint/tendermint/libs/log" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" + host "github.com/cosmos/ibc-go/v3/modules/core/24-host" ) // Keeper defines the IBC non fungible transfer keeper @@ -22,6 +25,11 @@ type Keeper struct { scopedKeeper capabilitykeeper.ScopedKeeper } +// Logger returns a module-specific logger. +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", "x/"+host.ModuleName+"-"+types.ModuleName) +} + // GetPort returns the portID for the transfer module. func (k Keeper) GetPort(ctx sdk.Context) string { store := ctx.KVStore(k.storeKey) @@ -53,6 +61,17 @@ func (k Keeper) MustMarshalClassTrace(classTrace types.ClassTrace) []byte { return k.cdc.MustMarshal(&classTrace) } +// UnmarshalClassTrace attempts to decode and return an ClassTrace object from +// raw encoded bytes. +func (k Keeper) UnmarshalClassTrace(bz []byte) (types.ClassTrace, error) { + var classTrace types.ClassTrace + if err := k.cdc.Unmarshal(bz, &classTrace); err != nil { + return types.ClassTrace{}, err + } + + return classTrace, nil +} + // SetEscrowAddress attempts to save a account to auth module func (k Keeper) SetEscrowAddress(ctx sdk.Context, portID, channelID string) { // create the escrow address for the tokens diff --git a/modules/apps/nft-transfer/keeper/msg_server.go b/modules/apps/nft-transfer/keeper/msg_server.go new file mode 100644 index 00000000000..0c06cc8967e --- /dev/null +++ b/modules/apps/nft-transfer/keeper/msg_server.go @@ -0,0 +1,50 @@ +package keeper + +import ( + "context" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" +) + +var _ types.MsgServer = Keeper{} + +// See createOutgoingPacket in spec:https://github.com/cosmos/ibc/tree/master/spec/app/ics-721-nft-transfer#packet-relay + +// Transfer defines a rpc handler method for MsgTransfer. +func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } + if err := k.SendTransfer( + ctx, msg.SourcePort, msg.SourceChannel, msg.ClassId, msg.TokenIds, + sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp, + ); err != nil { + return nil, err + } + + k.Logger(ctx).Info("IBC non-fungible token transfer", + "classID", msg.ClassId, + "tokenIDs", strings.Join(msg.TokenIds, ","), + "sender", msg.Sender, + "receiver", msg.Receiver, + ) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.EventTypeTransfer, + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver), + ), + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + ), + }) + + return &types.MsgTransferResponse{}, nil +} diff --git a/modules/apps/nft-transfer/types/events.go b/modules/apps/nft-transfer/types/events.go new file mode 100644 index 00000000000..2a595a6399d --- /dev/null +++ b/modules/apps/nft-transfer/types/events.go @@ -0,0 +1,15 @@ +package types + +// IBC transfer events +const ( + EventTypeTimeout = "timeout" + EventTypePacket = "non_fungible_token_packet" + EventTypeTransfer = "ibc_nft_transfer" + EventTypeChannelClose = "channel_closed" + EventTypeDenomTrace = "denomination_trace" + + AttributeKeyReceiver = "receiver" + AttributeKeyClassID = "classID" + AttributeKeyTokenIDs = "tokenIDs" + AttributeKeyAckSuccess = "success" +) diff --git a/modules/apps/nft-transfer/types/genesis.pb.go b/modules/apps/nft-transfer/types/genesis.pb.go index 3b51593f3d3..679b1a8de10 100644 --- a/modules/apps/nft-transfer/types/genesis.pb.go +++ b/modules/apps/nft-transfer/types/genesis.pb.go @@ -25,8 +25,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // GenesisState defines the ibc-nft-transfer genesis state type GenesisState struct { - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - Traces []ClassTrace `protobuf:"bytes,2,rep,name=traces,proto3" json:"traces"` + PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` + Traces Traces `protobuf:"bytes,2,rep,name=traces,proto3,castrepeated=Traces" json:"traces"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -69,7 +69,7 @@ func (m *GenesisState) GetPortId() string { return "" } -func (m *GenesisState) GetTraces() []ClassTrace { +func (m *GenesisState) GetTraces() Traces { if m != nil { return m.Traces } @@ -85,24 +85,24 @@ func init() { } var fileDescriptor_1971f5a454018ffc = []byte{ - // 261 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x8f, 0xb1, 0x4e, 0xc3, 0x30, - 0x10, 0x86, 0x13, 0x40, 0x41, 0x04, 0xa6, 0x08, 0x89, 0xaa, 0x83, 0x89, 0x98, 0x3a, 0x50, 0x5b, - 0xa5, 0x23, 0x5b, 0x19, 0x10, 0x8c, 0x05, 0x16, 0x96, 0xca, 0x71, 0xdc, 0x60, 0x29, 0xc9, 0x59, - 0xbe, 0x6b, 0x24, 0xde, 0x82, 0xc7, 0xea, 0xd8, 0x91, 0x09, 0xa1, 0xe4, 0x45, 0x90, 0x53, 0x54, - 0x75, 0xeb, 0xf6, 0xdb, 0xfa, 0xef, 0xbb, 0xfb, 0x62, 0x6e, 0x32, 0x25, 0xa4, 0xb5, 0xa5, 0x51, - 0x92, 0x0c, 0xd4, 0x28, 0xea, 0x25, 0x2d, 0xc8, 0xc9, 0x1a, 0x97, 0xda, 0x89, 0x66, 0x22, 0x0a, - 0x5d, 0x6b, 0x34, 0xc8, 0xad, 0x03, 0x82, 0x24, 0x35, 0x99, 0xe2, 0xfb, 0x7d, 0xbe, 0xdf, 0xe7, - 0xcd, 0x64, 0x28, 0x0e, 0x12, 0x77, 0xed, 0x1e, 0x39, 0xbc, 0x2c, 0xa0, 0x80, 0x3e, 0x0a, 0x9f, - 0xb6, 0xbf, 0x37, 0x18, 0x5f, 0x3c, 0x6e, 0x37, 0xbf, 0x90, 0x24, 0x9d, 0x5c, 0xc5, 0xa7, 0x16, - 0x1c, 0x2d, 0x4c, 0x3e, 0x08, 0xd3, 0x70, 0x74, 0x36, 0x8f, 0xfc, 0xf3, 0x29, 0x4f, 0x9e, 0xe3, - 0x88, 0x9c, 0x54, 0x1a, 0x07, 0x47, 0xe9, 0xf1, 0xe8, 0xfc, 0xee, 0x96, 0x1f, 0x3a, 0x91, 0x3f, - 0x94, 0x12, 0xf1, 0xd5, 0x0f, 0xcd, 0x4e, 0xd6, 0x3f, 0xd7, 0xc1, 0xfc, 0x9f, 0x30, 0x7b, 0x5b, - 0xb7, 0x2c, 0xdc, 0xb4, 0x2c, 0xfc, 0x6d, 0x59, 0xf8, 0xd5, 0xb1, 0x60, 0xd3, 0xb1, 0xe0, 0xbb, - 0x63, 0xc1, 0xfb, 0x7d, 0x61, 0xe8, 0x63, 0x95, 0x71, 0x05, 0x95, 0x50, 0x80, 0x15, 0xa0, 0xf7, - 0x1c, 0x17, 0x20, 0x9a, 0xa9, 0xa8, 0x20, 0x5f, 0x95, 0x1a, 0xbd, 0x75, 0x6f, 0x3b, 0xde, 0xd9, - 0xd2, 0xa7, 0xd5, 0x98, 0x45, 0xbd, 0xd2, 0xf4, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x13, 0x89, 0x34, - 0xae, 0x6d, 0x01, 0x00, 0x00, + // 270 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0xcb, 0x4c, 0x4a, 0xd6, + 0x4f, 0x2c, 0x28, 0xc8, 0xc9, 0x4c, 0x4e, 0x2c, 0xc9, 0xcc, 0xcf, 0x2b, 0xd6, 0xcf, 0x4b, 0x2b, + 0x89, 0x2f, 0x29, 0x4a, 0xcc, 0x2b, 0x4e, 0x4b, 0x2d, 0xd2, 0x2f, 0x33, 0xd4, 0x4f, 0x4f, 0xcd, + 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0xc8, 0x4c, 0x4a, 0xd6, + 0x43, 0x56, 0xaf, 0x87, 0xac, 0x5e, 0xaf, 0xcc, 0x50, 0x4a, 0x9f, 0xa0, 0x89, 0x70, 0xd5, 0x60, + 0x23, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x4c, 0x7d, 0x10, 0x0b, 0x22, 0xaa, 0x54, 0xcb, + 0xc5, 0xe3, 0x0e, 0xb1, 0x39, 0xb8, 0x24, 0xb1, 0x24, 0x55, 0x48, 0x9c, 0x8b, 0xbd, 0x20, 0xbf, + 0xa8, 0x24, 0x3e, 0x33, 0x45, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, 0x88, 0x0d, 0xc4, 0xf5, 0x4c, + 0x11, 0x0a, 0xe1, 0x62, 0x2b, 0x29, 0x4a, 0x4c, 0x4e, 0x2d, 0x96, 0x60, 0x52, 0x60, 0xd6, 0xe0, + 0x36, 0xd2, 0xd1, 0x23, 0xe4, 0x44, 0x3d, 0xe7, 0x9c, 0xc4, 0xe2, 0xe2, 0x10, 0x90, 0x26, 0x27, + 0xbe, 0x13, 0xf7, 0xe4, 0x19, 0x56, 0xdd, 0x97, 0x67, 0x03, 0x73, 0x8b, 0x83, 0xa0, 0x66, 0x39, + 0x85, 0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, + 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x75, 0x7a, 0x66, 0x49, + 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x72, 0x7e, 0x71, 0x6e, 0x7e, 0x31, 0xc8, 0xc7, + 0xba, 0xe9, 0xf9, 0xfa, 0x65, 0xc6, 0xfa, 0xb9, 0xf9, 0x29, 0xa5, 0x39, 0xa9, 0xc5, 0x20, 0xff, + 0x83, 0xfd, 0xad, 0x0b, 0xf7, 0x77, 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0xd8, 0x73, 0xc6, + 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcf, 0x0c, 0xe7, 0x08, 0x77, 0x01, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { diff --git a/modules/apps/nft-transfer/types/query.pb.go b/modules/apps/nft-transfer/types/query.pb.go new file mode 100644 index 00000000000..5adf3bb1784 --- /dev/null +++ b/modules/apps/nft-transfer/types/query.pb.go @@ -0,0 +1,1906 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/applications/nft_transfer/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + query "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryClassTraceRequest is the request type for the Query/ClassDenom RPC +// method +type QueryClassTraceRequest struct { + // hash (in hex format) or classID (full classID with ibc prefix) of the denomination trace information. + Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` +} + +func (m *QueryClassTraceRequest) Reset() { *m = QueryClassTraceRequest{} } +func (m *QueryClassTraceRequest) String() string { return proto.CompactTextString(m) } +func (*QueryClassTraceRequest) ProtoMessage() {} +func (*QueryClassTraceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_5a14f935a5261724, []int{0} +} +func (m *QueryClassTraceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassTraceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassTraceRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassTraceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassTraceRequest.Merge(m, src) +} +func (m *QueryClassTraceRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryClassTraceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassTraceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassTraceRequest proto.InternalMessageInfo + +func (m *QueryClassTraceRequest) GetHash() string { + if m != nil { + return m.Hash + } + return "" +} + +// QueryClassTraceResponse is the response type for the Query/ClassDenom RPC +// method. +type QueryClassTraceResponse struct { + // class_trace returns the requested class trace information. + ClassTrace *ClassTrace `protobuf:"bytes,1,opt,name=class_trace,json=classTrace,proto3" json:"class_trace,omitempty"` +} + +func (m *QueryClassTraceResponse) Reset() { *m = QueryClassTraceResponse{} } +func (m *QueryClassTraceResponse) String() string { return proto.CompactTextString(m) } +func (*QueryClassTraceResponse) ProtoMessage() {} +func (*QueryClassTraceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_5a14f935a5261724, []int{1} +} +func (m *QueryClassTraceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassTraceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassTraceResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassTraceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassTraceResponse.Merge(m, src) +} +func (m *QueryClassTraceResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryClassTraceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassTraceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassTraceResponse proto.InternalMessageInfo + +func (m *QueryClassTraceResponse) GetClassTrace() *ClassTrace { + if m != nil { + return m.ClassTrace + } + return nil +} + +// QueryConnectionsRequest is the request type for the Query/ClassTraces RPC +// method +type QueryClassTracesRequest struct { + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryClassTracesRequest) Reset() { *m = QueryClassTracesRequest{} } +func (m *QueryClassTracesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryClassTracesRequest) ProtoMessage() {} +func (*QueryClassTracesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_5a14f935a5261724, []int{2} +} +func (m *QueryClassTracesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassTracesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassTracesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassTracesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassTracesRequest.Merge(m, src) +} +func (m *QueryClassTracesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryClassTracesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassTracesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassTracesRequest proto.InternalMessageInfo + +func (m *QueryClassTracesRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryClassTracesResponse is the response type for the Query/ClassTraces RPC +// method. +type QueryClassTracesResponse struct { + // class_traces returns all class trace information. + ClassTraces Traces `protobuf:"bytes,1,rep,name=class_traces,json=classTraces,proto3,castrepeated=Traces" json:"class_traces"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryClassTracesResponse) Reset() { *m = QueryClassTracesResponse{} } +func (m *QueryClassTracesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryClassTracesResponse) ProtoMessage() {} +func (*QueryClassTracesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_5a14f935a5261724, []int{3} +} +func (m *QueryClassTracesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassTracesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassTracesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassTracesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassTracesResponse.Merge(m, src) +} +func (m *QueryClassTracesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryClassTracesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassTracesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassTracesResponse proto.InternalMessageInfo + +func (m *QueryClassTracesResponse) GetClassTraces() Traces { + if m != nil { + return m.ClassTraces + } + return nil +} + +func (m *QueryClassTracesResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryClassHashRequest is the request type for the Query/ClassHash RPC +// method +type QueryClassHashRequest struct { + // The class trace ([port_id]/[channel_id])+/[denom] + Trace string `protobuf:"bytes,1,opt,name=trace,proto3" json:"trace,omitempty"` +} + +func (m *QueryClassHashRequest) Reset() { *m = QueryClassHashRequest{} } +func (m *QueryClassHashRequest) String() string { return proto.CompactTextString(m) } +func (*QueryClassHashRequest) ProtoMessage() {} +func (*QueryClassHashRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_5a14f935a5261724, []int{4} +} +func (m *QueryClassHashRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassHashRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassHashRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassHashRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassHashRequest.Merge(m, src) +} +func (m *QueryClassHashRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryClassHashRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassHashRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassHashRequest proto.InternalMessageInfo + +func (m *QueryClassHashRequest) GetTrace() string { + if m != nil { + return m.Trace + } + return "" +} + +// QueryClassHashResponse is the response type for the Query/ClassHash RPC +// method. +type QueryClassHashResponse struct { + // hash (in hex format) of the denomination trace information. + Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` +} + +func (m *QueryClassHashResponse) Reset() { *m = QueryClassHashResponse{} } +func (m *QueryClassHashResponse) String() string { return proto.CompactTextString(m) } +func (*QueryClassHashResponse) ProtoMessage() {} +func (*QueryClassHashResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_5a14f935a5261724, []int{5} +} +func (m *QueryClassHashResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassHashResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassHashResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassHashResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassHashResponse.Merge(m, src) +} +func (m *QueryClassHashResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryClassHashResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassHashResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassHashResponse proto.InternalMessageInfo + +func (m *QueryClassHashResponse) GetHash() string { + if m != nil { + return m.Hash + } + return "" +} + +// QueryEscrowAddressRequest is the request type for the EscrowAddress RPC method. +type QueryEscrowAddressRequest struct { + // unique port identifier + PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` + // unique channel identifier + ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` +} + +func (m *QueryEscrowAddressRequest) Reset() { *m = QueryEscrowAddressRequest{} } +func (m *QueryEscrowAddressRequest) String() string { return proto.CompactTextString(m) } +func (*QueryEscrowAddressRequest) ProtoMessage() {} +func (*QueryEscrowAddressRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_5a14f935a5261724, []int{6} +} +func (m *QueryEscrowAddressRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryEscrowAddressRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryEscrowAddressRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryEscrowAddressRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryEscrowAddressRequest.Merge(m, src) +} +func (m *QueryEscrowAddressRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryEscrowAddressRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryEscrowAddressRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryEscrowAddressRequest proto.InternalMessageInfo + +func (m *QueryEscrowAddressRequest) GetPortId() string { + if m != nil { + return m.PortId + } + return "" +} + +func (m *QueryEscrowAddressRequest) GetChannelId() string { + if m != nil { + return m.ChannelId + } + return "" +} + +// QueryEscrowAddressResponse is the response type of the EscrowAddress RPC method. +type QueryEscrowAddressResponse struct { + // the escrow account address + EscrowAddress string `protobuf:"bytes,1,opt,name=escrow_address,json=escrowAddress,proto3" json:"escrow_address,omitempty"` +} + +func (m *QueryEscrowAddressResponse) Reset() { *m = QueryEscrowAddressResponse{} } +func (m *QueryEscrowAddressResponse) String() string { return proto.CompactTextString(m) } +func (*QueryEscrowAddressResponse) ProtoMessage() {} +func (*QueryEscrowAddressResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_5a14f935a5261724, []int{7} +} +func (m *QueryEscrowAddressResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryEscrowAddressResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryEscrowAddressResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryEscrowAddressResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryEscrowAddressResponse.Merge(m, src) +} +func (m *QueryEscrowAddressResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryEscrowAddressResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryEscrowAddressResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryEscrowAddressResponse proto.InternalMessageInfo + +func (m *QueryEscrowAddressResponse) GetEscrowAddress() string { + if m != nil { + return m.EscrowAddress + } + return "" +} + +func init() { + proto.RegisterType((*QueryClassTraceRequest)(nil), "ibc.applications.nft_transfer.v1.QueryClassTraceRequest") + proto.RegisterType((*QueryClassTraceResponse)(nil), "ibc.applications.nft_transfer.v1.QueryClassTraceResponse") + proto.RegisterType((*QueryClassTracesRequest)(nil), "ibc.applications.nft_transfer.v1.QueryClassTracesRequest") + proto.RegisterType((*QueryClassTracesResponse)(nil), "ibc.applications.nft_transfer.v1.QueryClassTracesResponse") + proto.RegisterType((*QueryClassHashRequest)(nil), "ibc.applications.nft_transfer.v1.QueryClassHashRequest") + proto.RegisterType((*QueryClassHashResponse)(nil), "ibc.applications.nft_transfer.v1.QueryClassHashResponse") + proto.RegisterType((*QueryEscrowAddressRequest)(nil), "ibc.applications.nft_transfer.v1.QueryEscrowAddressRequest") + proto.RegisterType((*QueryEscrowAddressResponse)(nil), "ibc.applications.nft_transfer.v1.QueryEscrowAddressResponse") +} + +func init() { + proto.RegisterFile("ibc/applications/nft_transfer/v1/query.proto", fileDescriptor_5a14f935a5261724) +} + +var fileDescriptor_5a14f935a5261724 = []byte{ + // 661 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcd, 0x6e, 0xd3, 0x40, + 0x10, 0x8e, 0x0b, 0x0d, 0xca, 0x84, 0xf6, 0xb0, 0x2a, 0xb4, 0x58, 0x90, 0x56, 0x91, 0x28, 0x15, + 0x6a, 0x76, 0x49, 0x2b, 0xa0, 0x50, 0x2e, 0xb4, 0xe2, 0xa7, 0x07, 0x50, 0x09, 0x3f, 0x07, 0x2e, + 0xd1, 0x7a, 0xb3, 0xb5, 0x2d, 0xa5, 0x5e, 0xd7, 0xeb, 0x04, 0x55, 0x55, 0x2e, 0x3c, 0x01, 0x12, + 0x07, 0xde, 0x81, 0x33, 0x42, 0x3c, 0x00, 0x87, 0x1e, 0x2b, 0x71, 0xe1, 0x04, 0x28, 0xe5, 0x41, + 0x90, 0xd7, 0x1b, 0xdb, 0x51, 0x22, 0xd2, 0xe4, 0x66, 0x7b, 0xe6, 0x9b, 0xf9, 0xbe, 0x6f, 0x66, + 0x64, 0x58, 0x75, 0x2d, 0x46, 0xa8, 0xef, 0x37, 0x5d, 0x46, 0x43, 0x57, 0x78, 0x92, 0x78, 0x7b, + 0x61, 0x3d, 0x0c, 0xa8, 0x27, 0xf7, 0x78, 0x40, 0xda, 0x55, 0x72, 0xd0, 0xe2, 0xc1, 0x21, 0xf6, + 0x03, 0x11, 0x0a, 0xb4, 0xe4, 0x5a, 0x0c, 0x67, 0xb3, 0x71, 0x36, 0x1b, 0xb7, 0xab, 0xe6, 0x9c, + 0x2d, 0x6c, 0xa1, 0x92, 0x49, 0xf4, 0x14, 0xe3, 0xcc, 0x9b, 0x4c, 0xc8, 0x7d, 0x21, 0x89, 0x45, + 0x25, 0x8f, 0x0b, 0x92, 0x76, 0xd5, 0xe2, 0x21, 0xad, 0x12, 0x9f, 0xda, 0xae, 0xa7, 0x8a, 0xe9, + 0x5c, 0x32, 0x92, 0x51, 0xd2, 0x2f, 0x06, 0x5c, 0xb5, 0x85, 0xb0, 0x9b, 0x9c, 0x50, 0xdf, 0x25, + 0xd4, 0xf3, 0x44, 0xa8, 0xa9, 0xa9, 0x68, 0x79, 0x15, 0x2e, 0xbf, 0x88, 0x1a, 0x6e, 0x37, 0xa9, + 0x94, 0xaf, 0x02, 0xca, 0x78, 0x8d, 0x1f, 0xb4, 0xb8, 0x0c, 0x11, 0x82, 0xf3, 0x0e, 0x95, 0xce, + 0x82, 0xb1, 0x64, 0xac, 0x14, 0x6a, 0xea, 0xb9, 0xec, 0xc0, 0xfc, 0x40, 0xb6, 0xf4, 0x85, 0x27, + 0x39, 0x7a, 0x06, 0x45, 0x16, 0x7d, 0x8d, 0xa8, 0x30, 0xae, 0x50, 0xc5, 0xb5, 0x55, 0x3c, 0xca, + 0x11, 0x9c, 0x29, 0x05, 0x2c, 0x79, 0x2e, 0xd3, 0x81, 0x4e, 0xb2, 0x47, 0xec, 0x31, 0x40, 0xea, + 0x8a, 0x6e, 0xb4, 0x8c, 0x63, 0x0b, 0x71, 0x64, 0x21, 0x8e, 0x67, 0xa2, 0x2d, 0xc4, 0xbb, 0xd4, + 0xee, 0x89, 0xaa, 0x65, 0x90, 0xe5, 0xef, 0x06, 0x2c, 0x0c, 0xf6, 0xd0, 0x72, 0xea, 0x70, 0x31, + 0x23, 0x47, 0x2e, 0x18, 0x4b, 0xe7, 0xc6, 0xd5, 0xb3, 0x35, 0x7b, 0xfc, 0x6b, 0x31, 0xf7, 0xf9, + 0xf7, 0x62, 0x5e, 0xd7, 0x2e, 0xa6, 0xfa, 0x24, 0x7a, 0xd2, 0xa7, 0x62, 0x4a, 0xa9, 0xb8, 0x31, + 0x52, 0x45, 0xcc, 0xae, 0x4f, 0x46, 0x05, 0x2e, 0xa5, 0x2a, 0x9e, 0x52, 0xe9, 0xf4, 0x7c, 0x9a, + 0x83, 0xe9, 0x74, 0x16, 0x85, 0x5a, 0xfc, 0xd2, 0x3f, 0xf0, 0x38, 0x5d, 0x4b, 0x1e, 0x36, 0xf0, + 0x97, 0x70, 0x45, 0x65, 0x3f, 0x92, 0x2c, 0x10, 0xef, 0x1e, 0x36, 0x1a, 0x01, 0x97, 0xc9, 0x20, + 0xe6, 0xe1, 0x82, 0x2f, 0x82, 0xb0, 0xee, 0x36, 0x34, 0x26, 0x1f, 0xbd, 0xee, 0x34, 0xd0, 0x35, + 0x00, 0xe6, 0x50, 0xcf, 0xe3, 0xcd, 0x28, 0x36, 0xa5, 0x62, 0x05, 0xfd, 0x65, 0xa7, 0x51, 0xde, + 0x06, 0x73, 0x58, 0x51, 0x4d, 0xe3, 0x3a, 0xcc, 0x72, 0x15, 0xa8, 0xd3, 0x38, 0xa2, 0x8b, 0xcf, + 0xf0, 0x6c, 0xfa, 0xda, 0xa7, 0x3c, 0x4c, 0xab, 0x2a, 0xe8, 0x9b, 0x01, 0x90, 0xba, 0x8e, 0x36, + 0x46, 0xcf, 0x68, 0xf8, 0xc6, 0x9b, 0xf7, 0x26, 0x40, 0xc6, 0xa4, 0xcb, 0xb7, 0xdf, 0xff, 0xf8, + 0xfb, 0x71, 0x8a, 0xa0, 0x4a, 0xef, 0x3c, 0x07, 0xcf, 0x32, 0xbb, 0x4e, 0xe4, 0x28, 0x72, 0xb7, + 0x83, 0xbe, 0x18, 0x50, 0xcc, 0x6c, 0x1f, 0x1a, 0x9f, 0x41, 0x6f, 0x18, 0xe6, 0xfd, 0x49, 0xa0, + 0x9a, 0x3d, 0x56, 0xec, 0x57, 0xd0, 0xf2, 0xd9, 0xd8, 0xa3, 0xaf, 0x06, 0x14, 0x92, 0xfd, 0x41, + 0x77, 0xc7, 0xe9, 0x9c, 0x59, 0x50, 0x73, 0x63, 0x7c, 0xa0, 0x26, 0x7c, 0x47, 0x11, 0xbe, 0x85, + 0xf0, 0x28, 0xc2, 0x91, 0xcd, 0x91, 0xdd, 0x8a, 0x78, 0x07, 0x75, 0x0d, 0x98, 0xe9, 0xdb, 0x3a, + 0xb4, 0x79, 0x46, 0x0e, 0xc3, 0x0e, 0xc0, 0x7c, 0x30, 0x19, 0x58, 0x8b, 0x78, 0xa3, 0x44, 0xec, + 0xa2, 0xe7, 0xff, 0x11, 0x11, 0xdf, 0x8c, 0x24, 0x47, 0xe9, 0x3d, 0x75, 0x48, 0x74, 0x65, 0x92, + 0x1c, 0xe9, 0xdb, 0xeb, 0x90, 0xfe, 0x73, 0xd9, 0x7a, 0x7d, 0xdc, 0x2d, 0x19, 0x27, 0xdd, 0x92, + 0xf1, 0xa7, 0x5b, 0x32, 0x3e, 0x9c, 0x96, 0x72, 0x27, 0xa7, 0xa5, 0xdc, 0xcf, 0xd3, 0x52, 0xee, + 0xed, 0xa6, 0xed, 0x86, 0x4e, 0xcb, 0xc2, 0x4c, 0xec, 0x13, 0xfd, 0xcb, 0x71, 0x2d, 0x56, 0xb1, + 0x05, 0x69, 0xaf, 0x93, 0x7d, 0xd1, 0x68, 0x35, 0xb9, 0x4c, 0x88, 0x54, 0x12, 0x22, 0xe1, 0xa1, + 0xcf, 0xa5, 0x95, 0x57, 0x3f, 0x8c, 0xf5, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xed, 0xaf, 0x76, + 0xd0, 0x13, 0x07, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // ClassTrace queries a class trace information. + ClassTrace(ctx context.Context, in *QueryClassTraceRequest, opts ...grpc.CallOption) (*QueryClassTraceResponse, error) + // ClassTraces queries all class traces. + ClassTraces(ctx context.Context, in *QueryClassTracesRequest, opts ...grpc.CallOption) (*QueryClassTracesResponse, error) + // ClassHash queries a class hash information. + ClassHash(ctx context.Context, in *QueryClassHashRequest, opts ...grpc.CallOption) (*QueryClassHashResponse, error) + // EscrowAddress returns the escrow address for a particular port and channel id. + EscrowAddress(ctx context.Context, in *QueryEscrowAddressRequest, opts ...grpc.CallOption) (*QueryEscrowAddressResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) ClassTrace(ctx context.Context, in *QueryClassTraceRequest, opts ...grpc.CallOption) (*QueryClassTraceResponse, error) { + out := new(QueryClassTraceResponse) + err := c.cc.Invoke(ctx, "/ibc.applications.nft_transfer.v1.Query/ClassTrace", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) ClassTraces(ctx context.Context, in *QueryClassTracesRequest, opts ...grpc.CallOption) (*QueryClassTracesResponse, error) { + out := new(QueryClassTracesResponse) + err := c.cc.Invoke(ctx, "/ibc.applications.nft_transfer.v1.Query/ClassTraces", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) ClassHash(ctx context.Context, in *QueryClassHashRequest, opts ...grpc.CallOption) (*QueryClassHashResponse, error) { + out := new(QueryClassHashResponse) + err := c.cc.Invoke(ctx, "/ibc.applications.nft_transfer.v1.Query/ClassHash", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) EscrowAddress(ctx context.Context, in *QueryEscrowAddressRequest, opts ...grpc.CallOption) (*QueryEscrowAddressResponse, error) { + out := new(QueryEscrowAddressResponse) + err := c.cc.Invoke(ctx, "/ibc.applications.nft_transfer.v1.Query/EscrowAddress", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // ClassTrace queries a class trace information. + ClassTrace(context.Context, *QueryClassTraceRequest) (*QueryClassTraceResponse, error) + // ClassTraces queries all class traces. + ClassTraces(context.Context, *QueryClassTracesRequest) (*QueryClassTracesResponse, error) + // ClassHash queries a class hash information. + ClassHash(context.Context, *QueryClassHashRequest) (*QueryClassHashResponse, error) + // EscrowAddress returns the escrow address for a particular port and channel id. + EscrowAddress(context.Context, *QueryEscrowAddressRequest) (*QueryEscrowAddressResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) ClassTrace(ctx context.Context, req *QueryClassTraceRequest) (*QueryClassTraceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClassTrace not implemented") +} +func (*UnimplementedQueryServer) ClassTraces(ctx context.Context, req *QueryClassTracesRequest) (*QueryClassTracesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClassTraces not implemented") +} +func (*UnimplementedQueryServer) ClassHash(ctx context.Context, req *QueryClassHashRequest) (*QueryClassHashResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClassHash not implemented") +} +func (*UnimplementedQueryServer) EscrowAddress(ctx context.Context, req *QueryEscrowAddressRequest) (*QueryEscrowAddressResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method EscrowAddress not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_ClassTrace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryClassTraceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ClassTrace(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ibc.applications.nft_transfer.v1.Query/ClassTrace", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ClassTrace(ctx, req.(*QueryClassTraceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_ClassTraces_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryClassTracesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ClassTraces(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ibc.applications.nft_transfer.v1.Query/ClassTraces", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ClassTraces(ctx, req.(*QueryClassTracesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_ClassHash_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryClassHashRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ClassHash(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ibc.applications.nft_transfer.v1.Query/ClassHash", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ClassHash(ctx, req.(*QueryClassHashRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_EscrowAddress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryEscrowAddressRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).EscrowAddress(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ibc.applications.nft_transfer.v1.Query/EscrowAddress", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).EscrowAddress(ctx, req.(*QueryEscrowAddressRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "ibc.applications.nft_transfer.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ClassTrace", + Handler: _Query_ClassTrace_Handler, + }, + { + MethodName: "ClassTraces", + Handler: _Query_ClassTraces_Handler, + }, + { + MethodName: "ClassHash", + Handler: _Query_ClassHash_Handler, + }, + { + MethodName: "EscrowAddress", + Handler: _Query_EscrowAddress_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "ibc/applications/nft_transfer/v1/query.proto", +} + +func (m *QueryClassTraceRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClassTraceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClassTraceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryClassTraceResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClassTraceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClassTraceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ClassTrace != nil { + { + size, err := m.ClassTrace.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryClassTracesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClassTracesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClassTracesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryClassTracesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClassTracesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClassTracesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.ClassTraces) > 0 { + for iNdEx := len(m.ClassTraces) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ClassTraces[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryClassHashRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClassHashRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClassHashRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Trace) > 0 { + i -= len(m.Trace) + copy(dAtA[i:], m.Trace) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Trace))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryClassHashResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClassHashResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClassHashResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryEscrowAddressRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryEscrowAddressRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryEscrowAddressRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChannelId) > 0 { + i -= len(m.ChannelId) + copy(dAtA[i:], m.ChannelId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ChannelId))) + i-- + dAtA[i] = 0x12 + } + if len(m.PortId) > 0 { + i -= len(m.PortId) + copy(dAtA[i:], m.PortId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.PortId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryEscrowAddressResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryEscrowAddressResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryEscrowAddressResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.EscrowAddress) > 0 { + i -= len(m.EscrowAddress) + copy(dAtA[i:], m.EscrowAddress) + i = encodeVarintQuery(dAtA, i, uint64(len(m.EscrowAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryClassTraceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryClassTraceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ClassTrace != nil { + l = m.ClassTrace.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryClassTracesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryClassTracesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ClassTraces) > 0 { + for _, e := range m.ClassTraces { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryClassHashRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Trace) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryClassHashResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryEscrowAddressRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.PortId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.ChannelId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryEscrowAddressResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.EscrowAddress) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryClassTraceRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassTraceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassTraceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryClassTraceResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassTraceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassTraceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassTrace", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ClassTrace == nil { + m.ClassTrace = &ClassTrace{} + } + if err := m.ClassTrace.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryClassTracesRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassTracesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassTracesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryClassTracesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassTracesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassTracesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassTraces", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassTraces = append(m.ClassTraces, ClassTrace{}) + if err := m.ClassTraces[len(m.ClassTraces)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryClassHashRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassHashRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassHashRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Trace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Trace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryClassHashResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassHashResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassHashResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryEscrowAddressRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryEscrowAddressRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryEscrowAddressRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PortId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PortId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChannelId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryEscrowAddressResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryEscrowAddressResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryEscrowAddressResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EscrowAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.EscrowAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/apps/nft-transfer/types/query.pb.gw.go b/modules/apps/nft-transfer/types/query.pb.gw.go new file mode 100644 index 00000000000..d47072e3ce0 --- /dev/null +++ b/modules/apps/nft-transfer/types/query.pb.gw.go @@ -0,0 +1,482 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: ibc/applications/nft_transfer/v1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage + +func request_Query_ClassTrace_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassTraceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["hash"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash") + } + + protoReq.Hash, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err) + } + + msg, err := client.ClassTrace(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ClassTrace_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassTraceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["hash"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash") + } + + protoReq.Hash, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err) + } + + msg, err := server.ClassTrace(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_ClassTraces_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_ClassTraces_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassTracesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ClassTraces_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ClassTraces(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ClassTraces_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassTracesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ClassTraces_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ClassTraces(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_ClassHash_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassHashRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["trace"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "trace") + } + + protoReq.Trace, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "trace", err) + } + + msg, err := client.ClassHash(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ClassHash_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassHashRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["trace"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "trace") + } + + protoReq.Trace, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "trace", err) + } + + msg, err := server.ClassHash(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_EscrowAddress_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryEscrowAddressRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + msg, err := client.EscrowAddress(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_EscrowAddress_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryEscrowAddressRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["channel_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "channel_id") + } + + protoReq.ChannelId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "channel_id", err) + } + + val, ok = pathParams["port_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "port_id") + } + + protoReq.PortId, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "port_id", err) + } + + msg, err := server.EscrowAddress(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_ClassTrace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClassTrace_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassTrace_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ClassTraces_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClassTraces_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassTraces_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ClassHash_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClassHash_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassHash_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_EscrowAddress_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_EscrowAddress_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_EscrowAddress_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_ClassTrace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ClassTrace_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassTrace_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ClassTraces_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ClassTraces_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassTraces_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ClassHash_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ClassHash_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassHash_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_EscrowAddress_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_EscrowAddress_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_EscrowAddress_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_ClassTrace_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "apps", "nft_transfer", "v1", "class_traces", "hash"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_ClassTraces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "apps", "nft_transfer", "v1", "class_traces"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_ClassHash_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "apps", "nft_transfer", "v1", "class_hashes", "trace"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_EscrowAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "apps", "nft_transfer", "v1", "channels", "channel_id", "ports", "port_id", "escrow_address"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_ClassTrace_0 = runtime.ForwardResponseMessage + + forward_Query_ClassTraces_0 = runtime.ForwardResponseMessage + + forward_Query_ClassHash_0 = runtime.ForwardResponseMessage + + forward_Query_EscrowAddress_0 = runtime.ForwardResponseMessage +) diff --git a/modules/apps/nft-transfer/types/trace.go b/modules/apps/nft-transfer/types/trace.go index 00c3daa0444..8d47704c605 100644 --- a/modules/apps/nft-transfer/types/trace.go +++ b/modules/apps/nft-transfer/types/trace.go @@ -4,10 +4,14 @@ import ( "crypto/sha256" "encoding/hex" "fmt" + "sort" "strings" tmbytes "github.com/tendermint/tendermint/libs/bytes" tmtypes "github.com/tendermint/tendermint/types" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + host "github.com/cosmos/ibc-go/v3/modules/core/24-host" ) // ParseHexHash parses a hex hash in string format to bytes and validates its correctness. @@ -103,3 +107,73 @@ func (ct ClassTrace) IBCClassID() string { } return ct.BaseClassId } + +// Validate performs a basic validation of the ClassTrace fields. +func (ct ClassTrace) Validate() error { + // empty trace is accepted when token lives on the original chain + switch { + case ct.Path == "" && ct.BaseClassId != "": + return nil + case strings.TrimSpace(ct.BaseClassId) == "": + return fmt.Errorf("base class_id cannot be blank") + } + + // NOTE: no base class validation + + identifiers := strings.Split(ct.Path, "/") + return validateTraceIdentifiers(identifiers) +} + +func validateTraceIdentifiers(identifiers []string) error { + if len(identifiers) == 0 || len(identifiers)%2 != 0 { + return fmt.Errorf("trace info must come in pairs of port and channel identifiers '{portID}/{channelID}', got the identifiers: %s", identifiers) + } + + // validate correctness of port and channel identifiers + for i := 0; i < len(identifiers); i += 2 { + if err := host.PortIdentifierValidator(identifiers[i]); err != nil { + return sdkerrors.Wrapf(err, "invalid port ID at position %d", i) + } + if err := host.ChannelIdentifierValidator(identifiers[i+1]); err != nil { + return sdkerrors.Wrapf(err, "invalid channel ID at position %d", i) + } + } + return nil +} + +// Traces defines a wrapper type for a slice of DenomTrace. +type Traces []ClassTrace + +// Validate performs a basic validation of each denomination trace info. +func (t Traces) Validate() error { + seenTraces := make(map[string]bool) + for i, trace := range t { + hash := trace.Hash().String() + if seenTraces[hash] { + return fmt.Errorf("duplicated class trace with hash %s", trace.Hash()) + } + + if err := trace.Validate(); err != nil { + return sdkerrors.Wrapf(err, "failed class trace %d validation", i) + } + seenTraces[hash] = true + } + return nil +} + +var _ sort.Interface = Traces{} + +// Len implements sort.Interface for Traces +func (t Traces) Len() int { return len(t) } + +// Less implements sort.Interface for Traces +func (t Traces) Less(i, j int) bool { return t[i].GetFullClassPath() < t[j].GetFullClassPath() } + +// Swap implements sort.Interface for Traces +func (t Traces) Swap(i, j int) { t[i], t[j] = t[j], t[i] } + +// Sort is a helper function to sort the set of denomination traces in-place +func (t Traces) Sort() Traces { + sort.Sort(t) + return t +} diff --git a/proto/ibc/applications/fee/v1/query.proto b/proto/ibc/applications/fee/v1/query.proto index 0e1caa5d0f7..5f648107323 100644 --- a/proto/ibc/applications/fee/v1/query.proto +++ b/proto/ibc/applications/fee/v1/query.proto @@ -52,7 +52,8 @@ service Query { // CounterpartyAddress returns the registered counterparty address for forward relaying rpc CounterpartyAddress(QueryCounterpartyAddressRequest) returns (QueryCounterpartyAddressResponse) { - option (google.api.http).get = "/ibc/apps/fee/v1/channels/{channel_id}/relayers/{relayer_address}/counterparty_address"; + option (google.api.http).get = + "/ibc/apps/fee/v1/channels/{channel_id}/relayers/{relayer_address}/counterparty_address"; } // FeeEnabledChannels returns a list of all fee enabled channels diff --git a/proto/ibc/applications/nft_transfer/v1/genesis.proto b/proto/ibc/applications/nft_transfer/v1/genesis.proto index e2de20e3fbb..1449cb3b9ca 100644 --- a/proto/ibc/applications/nft_transfer/v1/genesis.proto +++ b/proto/ibc/applications/nft_transfer/v1/genesis.proto @@ -10,5 +10,5 @@ import "gogoproto/gogo.proto"; // GenesisState defines the ibc-nft-transfer genesis state message GenesisState { string port_id = 1; - repeated ClassTrace traces = 2 [(gogoproto.nullable) = false]; + repeated ClassTrace traces = 2 [(gogoproto.castrepeated) = "Traces", (gogoproto.nullable) = false]; } \ No newline at end of file diff --git a/proto/ibc/applications/nft_transfer/v1/query.proto b/proto/ibc/applications/nft_transfer/v1/query.proto new file mode 100644 index 00000000000..fdc1b81731c --- /dev/null +++ b/proto/ibc/applications/nft_transfer/v1/query.proto @@ -0,0 +1,91 @@ +syntax = "proto3"; + +package ibc.applications.nft_transfer.v1; + +import "gogoproto/gogo.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "ibc/applications/nft_transfer/v1/transfer.proto"; +import "google/api/annotations.proto"; + +option go_package = "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types"; + +// Query provides defines the gRPC querier service. +service Query { + // ClassTrace queries a class trace information. + rpc ClassTrace(QueryClassTraceRequest) returns (QueryClassTraceResponse) { + option (google.api.http).get = "/ibc/apps/nft_transfer/v1/class_traces/{hash}"; + } + + // ClassTraces queries all class traces. + rpc ClassTraces(QueryClassTracesRequest) returns (QueryClassTracesResponse) { + option (google.api.http).get = "/ibc/apps/nft_transfer/v1/class_traces"; + } + + // ClassHash queries a class hash information. + rpc ClassHash(QueryClassHashRequest) returns (QueryClassHashResponse) { + option (google.api.http).get = "/ibc/apps/nft_transfer/v1/class_hashes/{trace}"; + } + + // EscrowAddress returns the escrow address for a particular port and channel id. + rpc EscrowAddress(QueryEscrowAddressRequest) returns (QueryEscrowAddressResponse) { + option (google.api.http).get = "/ibc/apps/nft_transfer/v1/channels/{channel_id}/ports/{port_id}/escrow_address"; + } +} + +// QueryClassTraceRequest is the request type for the Query/ClassDenom RPC +// method +message QueryClassTraceRequest { + // hash (in hex format) or classID (full classID with ibc prefix) of the denomination trace information. + string hash = 1; +} + +// QueryClassTraceResponse is the response type for the Query/ClassDenom RPC +// method. +message QueryClassTraceResponse { + // class_trace returns the requested class trace information. + ClassTrace class_trace = 1; +} + +// QueryConnectionsRequest is the request type for the Query/ClassTraces RPC +// method +message QueryClassTracesRequest { + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} + +// QueryClassTracesResponse is the response type for the Query/ClassTraces RPC +// method. +message QueryClassTracesResponse { + // class_traces returns all class trace information. + repeated ClassTrace class_traces = 1 [(gogoproto.castrepeated) = "Traces", (gogoproto.nullable) = false]; + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryClassHashRequest is the request type for the Query/ClassHash RPC +// method +message QueryClassHashRequest { + // The class trace ([port_id]/[channel_id])+/[denom] + string trace = 1; +} + +// QueryClassHashResponse is the response type for the Query/ClassHash RPC +// method. +message QueryClassHashResponse { + // hash (in hex format) of the denomination trace information. + string hash = 1; +} + +// QueryEscrowAddressRequest is the request type for the EscrowAddress RPC method. +message QueryEscrowAddressRequest { + // unique port identifier + string port_id = 1; + // unique channel identifier + string channel_id = 2; +} + +// QueryEscrowAddressResponse is the response type of the EscrowAddress RPC method. +message QueryEscrowAddressResponse { + // the escrow account address + string escrow_address = 1; +} \ No newline at end of file From 7185f73c7ad1aab6e50370f74b005786aeed3fc0 Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Wed, 1 Jun 2022 11:43:52 +0800 Subject: [PATCH 11/14] format code --- .../apps/nft-transfer/keeper/grpc_query.go | 19 +++++++------ modules/apps/nft-transfer/keeper/keeper.go | 28 +------------------ modules/apps/nft-transfer/keeper/trace.go | 24 ++++++++++++++++ 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/modules/apps/nft-transfer/keeper/grpc_query.go b/modules/apps/nft-transfer/keeper/grpc_query.go index 5c44c5499db..55710e238f9 100644 --- a/modules/apps/nft-transfer/keeper/grpc_query.go +++ b/modules/apps/nft-transfer/keeper/grpc_query.go @@ -5,12 +5,13 @@ import ( "fmt" "strings" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/query" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" ) @@ -18,7 +19,8 @@ import ( var _ types.QueryServer = Keeper{} // ClassTrace implements the Query/ClassTrace gRPC method -func (k Keeper) ClassTrace(c context.Context, req *types.QueryClassTraceRequest) (*types.QueryClassTraceResponse, error) { +func (k Keeper) ClassTrace(c context.Context, + req *types.QueryClassTraceRequest) (*types.QueryClassTraceResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } @@ -43,16 +45,15 @@ func (k Keeper) ClassTrace(c context.Context, req *types.QueryClassTraceRequest) } // ClassTraces implements the Query/ClassTraces gRPC method -func (k Keeper) ClassTraces(c context.Context, req *types.QueryClassTracesRequest) (*types.QueryClassTracesResponse, error) { +func (k Keeper) ClassTraces(c context.Context, + req *types.QueryClassTracesRequest) (*types.QueryClassTracesResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } ctx := sdk.UnwrapSDKContext(c) - traces := types.Traces{} store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ClassTraceKey) - pageRes, err := query.Paginate(store, req.Pagination, func(_, value []byte) error { result, err := k.UnmarshalClassTrace(value) if err != nil { @@ -73,7 +74,8 @@ func (k Keeper) ClassTraces(c context.Context, req *types.QueryClassTracesReques } // ClassHash implements the Query/ClassHash gRPC method -func (k Keeper) ClassHash(c context.Context, req *types.QueryClassHashRequest) (*types.QueryClassHashResponse, error) { +func (k Keeper) ClassHash(c context.Context, + req *types.QueryClassHashRequest) (*types.QueryClassHashResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } @@ -100,7 +102,8 @@ func (k Keeper) ClassHash(c context.Context, req *types.QueryClassHashRequest) ( } // EscrowAddress implements the EscrowAddress gRPC method -func (k Keeper) EscrowAddress(c context.Context, req *types.QueryEscrowAddressRequest) (*types.QueryEscrowAddressResponse, error) { +func (k Keeper) EscrowAddress(c context.Context, + req *types.QueryEscrowAddressRequest) (*types.QueryEscrowAddressResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } diff --git a/modules/apps/nft-transfer/keeper/keeper.go b/modules/apps/nft-transfer/keeper/keeper.go index 5523b8fe258..6a56509a629 100644 --- a/modules/apps/nft-transfer/keeper/keeper.go +++ b/modules/apps/nft-transfer/keeper/keeper.go @@ -21,8 +21,7 @@ type Keeper struct { channelKeeper types.ChannelKeeper nftKeeper types.NFTKeeper authkeeper types.AccountKeeper - // bankKeeper types.BankKeeper - scopedKeeper capabilitykeeper.ScopedKeeper + scopedKeeper capabilitykeeper.ScopedKeeper } // Logger returns a module-specific logger. @@ -47,31 +46,6 @@ func (k Keeper) ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability return k.scopedKeeper.ClaimCapability(ctx, cap, name) } -// MustUnmarshalClassTrace attempts to decode and return an ClassTrace object from -// raw encoded bytes. It panics on error. -func (k Keeper) MustUnmarshalClassTrace(bz []byte) types.ClassTrace { - var classTrace types.ClassTrace - k.cdc.MustUnmarshal(bz, &classTrace) - return classTrace -} - -// MustMarshalClassTrace attempts to decode and return an ClassTrace object from -// raw encoded bytes. It panics on error. -func (k Keeper) MustMarshalClassTrace(classTrace types.ClassTrace) []byte { - return k.cdc.MustMarshal(&classTrace) -} - -// UnmarshalClassTrace attempts to decode and return an ClassTrace object from -// raw encoded bytes. -func (k Keeper) UnmarshalClassTrace(bz []byte) (types.ClassTrace, error) { - var classTrace types.ClassTrace - if err := k.cdc.Unmarshal(bz, &classTrace); err != nil { - return types.ClassTrace{}, err - } - - return classTrace, nil -} - // SetEscrowAddress attempts to save a account to auth module func (k Keeper) SetEscrowAddress(ctx sdk.Context, portID, channelID string) { // create the escrow address for the tokens diff --git a/modules/apps/nft-transfer/keeper/trace.go b/modules/apps/nft-transfer/keeper/trace.go index 659a3e48172..e15cfc8ee1f 100644 --- a/modules/apps/nft-transfer/keeper/trace.go +++ b/modules/apps/nft-transfer/keeper/trace.go @@ -51,3 +51,27 @@ func (k Keeper) SetClassTrace(ctx sdk.Context, denomTrace types.ClassTrace) { bz := k.MustMarshalClassTrace(denomTrace) store.Set(denomTrace.Hash(), bz) } + +// MustUnmarshalClassTrace attempts to decode and return an ClassTrace object from +// raw encoded bytes. It panics on error. +func (k Keeper) MustUnmarshalClassTrace(bz []byte) types.ClassTrace { + var classTrace types.ClassTrace + k.cdc.MustUnmarshal(bz, &classTrace) + return classTrace +} + +// MustMarshalClassTrace attempts to decode and return an ClassTrace object from +// raw encoded bytes. It panics on error. +func (k Keeper) MustMarshalClassTrace(classTrace types.ClassTrace) []byte { + return k.cdc.MustMarshal(&classTrace) +} + +// UnmarshalClassTrace attempts to decode and return an ClassTrace object from +// raw encoded bytes. +func (k Keeper) UnmarshalClassTrace(bz []byte) (types.ClassTrace, error) { + var classTrace types.ClassTrace + if err := k.cdc.Unmarshal(bz, &classTrace); err != nil { + return types.ClassTrace{}, err + } + return classTrace, nil +} From b9d0845eeec252fad5b18d55a7279682beb8589a Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Wed, 1 Jun 2022 14:14:28 +0800 Subject: [PATCH 12/14] add import/export genesis --- modules/apps/nft-transfer/keeper/genesis.go | 37 ++++ modules/apps/nft-transfer/keeper/keeper.go | 22 ++- .../apps/nft-transfer/keeper/msg_server.go | 2 - modules/apps/nft-transfer/keeper/trace.go | 26 +++ modules/apps/nft-transfer/module.go | 175 ++++++++++++++++++ .../nft-transfer/types/expected_keeper.go | 5 + modules/apps/nft-transfer/types/genesis.go | 30 +++ 7 files changed, 294 insertions(+), 3 deletions(-) create mode 100644 modules/apps/nft-transfer/keeper/genesis.go create mode 100644 modules/apps/nft-transfer/types/genesis.go diff --git a/modules/apps/nft-transfer/keeper/genesis.go b/modules/apps/nft-transfer/keeper/genesis.go new file mode 100644 index 00000000000..c10e3b2f85f --- /dev/null +++ b/modules/apps/nft-transfer/keeper/genesis.go @@ -0,0 +1,37 @@ +package keeper + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" +) + +// InitGenesis initializes the ibc nft-transfer state and binds to PortID. +func (k Keeper) InitGenesis(ctx sdk.Context, state types.GenesisState) { + k.SetPort(ctx, state.PortId) + + for _, trace := range state.Traces { + k.SetClassTrace(ctx, trace) + } + + // Only try to bind to port if it is not already bound, since we may already own + // port capability from capability InitGenesis + if !k.IsBound(ctx, state.PortId) { + // nft-transfer module binds to the nft-transfer port on InitChain + // and claims the returned capability + err := k.BindPort(ctx, state.PortId) + if err != nil { + panic(fmt.Sprintf("could not claim port capability: %v", err)) + } + } +} + +// ExportGenesis exports ibc nft-transfer module's portID and class trace info into its genesis state. +func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { + return &types.GenesisState{ + PortId: k.GetPort(ctx), + Traces: k.GetAllClassTraces(ctx), + } +} diff --git a/modules/apps/nft-transfer/keeper/keeper.go b/modules/apps/nft-transfer/keeper/keeper.go index 6a56509a629..b6531587064 100644 --- a/modules/apps/nft-transfer/keeper/keeper.go +++ b/modules/apps/nft-transfer/keeper/keeper.go @@ -19,6 +19,7 @@ type Keeper struct { ics4Wrapper types.ICS4Wrapper channelKeeper types.ChannelKeeper + portKeeper types.PortKeeper nftKeeper types.NFTKeeper authkeeper types.AccountKeeper scopedKeeper capabilitykeeper.ScopedKeeper @@ -29,12 +30,31 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", "x/"+host.ModuleName+"-"+types.ModuleName) } -// GetPort returns the portID for the transfer module. +// SetPort sets the portID for the nft-transfer module. Used in InitGenesis +func (k Keeper) SetPort(ctx sdk.Context, portID string) { + store := ctx.KVStore(k.storeKey) + store.Set(types.PortKey, []byte(portID)) +} + +// GetPort returns the portID for the nft-transfer module. func (k Keeper) GetPort(ctx sdk.Context) string { store := ctx.KVStore(k.storeKey) return string(store.Get(types.PortKey)) } +// IsBound checks if the transfer module is already bound to the desired port +func (k Keeper) IsBound(ctx sdk.Context, portID string) bool { + _, ok := k.scopedKeeper.GetCapability(ctx, host.PortPath(portID)) + return ok +} + +// BindPort defines a wrapper function for the ort Keeper's function in +// order to expose it to module's InitGenesis function +func (k Keeper) BindPort(ctx sdk.Context, portID string) error { + cap := k.portKeeper.BindPort(ctx, portID) + return k.ClaimCapability(ctx, cap, host.PortPath(portID)) +} + // AuthenticateCapability wraps the scopedKeeper's AuthenticateCapability function func (k Keeper) AuthenticateCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) bool { return k.scopedKeeper.AuthenticateCapability(ctx, cap, name) diff --git a/modules/apps/nft-transfer/keeper/msg_server.go b/modules/apps/nft-transfer/keeper/msg_server.go index 0c06cc8967e..3e7f3b668b4 100644 --- a/modules/apps/nft-transfer/keeper/msg_server.go +++ b/modules/apps/nft-transfer/keeper/msg_server.go @@ -10,8 +10,6 @@ import ( var _ types.MsgServer = Keeper{} -// See createOutgoingPacket in spec:https://github.com/cosmos/ibc/tree/master/spec/app/ics-721-nft-transfer#packet-relay - // Transfer defines a rpc handler method for MsgTransfer. func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) diff --git a/modules/apps/nft-transfer/keeper/trace.go b/modules/apps/nft-transfer/keeper/trace.go index e15cfc8ee1f..1c0341caa24 100644 --- a/modules/apps/nft-transfer/keeper/trace.go +++ b/modules/apps/nft-transfer/keeper/trace.go @@ -21,6 +21,32 @@ func (k Keeper) GetClassTrace(ctx sdk.Context, denomTraceHash tmbytes.HexBytes) return denomTrace, true } +// GetAllClassTraces returns the trace information for all the class. +func (k Keeper) GetAllClassTraces(ctx sdk.Context) types.Traces { + traces := types.Traces{} + k.IterateClassTraces(ctx, func(classTrace types.ClassTrace) bool { + traces = append(traces, classTrace) + return false + }) + + return traces.Sort() +} + +// IterateClassTraces iterates over the class traces in the store +// and performs a callback function. +func (k Keeper) IterateClassTraces(ctx sdk.Context, cb func(denomTrace types.ClassTrace) bool) { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, types.ClassTraceKey) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + classTrace := k.MustUnmarshalClassTrace(iterator.Value()) + if cb(classTrace) { + break + } + } +} + // ClassPathFromHash returns the full class path prefix from an ibc classId with a hash // component. func (k Keeper) ClassPathFromHash(ctx sdk.Context, classID string) (string, error) { diff --git a/modules/apps/nft-transfer/module.go b/modules/apps/nft-transfer/module.go index ba8c8e338f2..fa3b6ba6bc4 100644 --- a/modules/apps/nft-transfer/module.go +++ b/modules/apps/nft-transfer/module.go @@ -1 +1,176 @@ package nt + +import ( + "context" + "encoding/json" + "fmt" + "math/rand" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/keeper" + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" + porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} + _ porttypes.IBCModule = IBCModule{} +) + +// AppModuleBasic is the IBC nft-transfer AppModuleBasic +type AppModuleBasic struct{} + +// Name implements AppModuleBasic interface +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec implements AppModuleBasic interface +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {} + +// RegisterInterfaces registers module concrete types into protobuf Any. +func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// DefaultGenesis returns default genesis state as raw bytes for the ibc +// nft-transfer module. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesisState()) +} + +// ValidateGenesis performs genesis state validation for the ibc nft-transfer module. +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + var gs types.GenesisState + if err := cdc.UnmarshalJSON(bz, &gs); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + + return gs.Validate() +} + +// RegisterRESTRoutes implements AppModuleBasic interface +func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) {} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the ibc nft-transfer module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +// GetTxCmd implements AppModuleBasic interface +func (AppModuleBasic) GetTxCmd() *cobra.Command { + //return cli.NewTxCmd() + return nil +} + +// GetQueryCmd implements AppModuleBasic interface +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + //return cli.GetQueryCmd() + return nil +} + +// AppModule represents the AppModule for this module +type AppModule struct { + AppModuleBasic + keeper keeper.Keeper +} + +// NewAppModule creates a new nft-transfer module +func NewAppModule(k keeper.Keeper) AppModule { + return AppModule{ + keeper: k, + } +} + +// RegisterInvariants implements the AppModule interface +func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} + +// Route implements the AppModule interface +func (am AppModule) Route() sdk.Route { + return sdk.Route{} +} + +// QuerierRoute implements the AppModule interface +func (AppModule) QuerierRoute() string { + return types.QuerierRoute +} + +// LegacyQuerierHandler implements the AppModule interface +func (am AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier { + return nil +} + +// RegisterServices registers module services. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), am.keeper) + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) +} + +// InitGenesis performs genesis initialization for the ibc nft-transfer module. It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { + var genesisState types.GenesisState + cdc.MustUnmarshalJSON(data, &genesisState) + am.keeper.InitGenesis(ctx, genesisState) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the exported genesis state as raw bytes for the ibc nft-transfer +// module. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + gs := am.keeper.ExportGenesis(ctx) + return cdc.MustMarshalJSON(gs) +} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + +// BeginBlock implements the AppModule interface +func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { +} + +// EndBlock implements the AppModule interface +func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the nft-transfer module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + //simulation.RandomizedGenState(simState) +} + +// ProposalContents doesn't return any content functions for governance proposals. +func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +// RandomizedParams creates randomized ibc nft-transfer param changes for the simulator. +func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { + //return simulation.ParamChanges(r) + return nil +} + +// RegisterStoreDecoder registers a decoder for nft-transfer module's types +func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { + //sdr[types.StoreKey] = simulation.NewDecodeStore(am.keeper) +} + +// WeightedOperations returns the all the nft-transfer module operations with their respective weights. +func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { + return nil +} diff --git a/modules/apps/nft-transfer/types/expected_keeper.go b/modules/apps/nft-transfer/types/expected_keeper.go index f0f47d29f76..1e98ac07153 100644 --- a/modules/apps/nft-transfer/types/expected_keeper.go +++ b/modules/apps/nft-transfer/types/expected_keeper.go @@ -46,6 +46,11 @@ type ChannelKeeper interface { GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) } +// PortKeeper defines the expected IBC port keeper +type PortKeeper interface { + BindPort(ctx sdk.Context, portID string) *capabilitytypes.Capability +} + // AccountKeeper defines the contract required for account APIs. type AccountKeeper interface { NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) types.AccountI diff --git a/modules/apps/nft-transfer/types/genesis.go b/modules/apps/nft-transfer/types/genesis.go new file mode 100644 index 00000000000..e1826e1fa52 --- /dev/null +++ b/modules/apps/nft-transfer/types/genesis.go @@ -0,0 +1,30 @@ +package types + +import ( + host "github.com/cosmos/ibc-go/v3/modules/core/24-host" +) + +// NewGenesisState creates a new ibc nft-transfer GenesisState instance. +func NewGenesisState(portID string, traces Traces) *GenesisState { + return &GenesisState{ + PortId: portID, + Traces: traces, + } +} + +// DefaultGenesisState returns a GenesisState with "nft-transfer" as the default PortID. +func DefaultGenesisState() *GenesisState { + return &GenesisState{ + PortId: PortID, + Traces: Traces{}, + } +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + if err := host.PortIdentifierValidator(gs.PortId); err != nil { + return err + } + return gs.Traces.Validate() +} From b9b958edde4ce9943d3575f075cb0f9e974cebfe Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Wed, 1 Jun 2022 16:44:34 +0800 Subject: [PATCH 13/14] add command --- modules/apps/nft-transfer/client/cli/cli.go | 43 ++++++ modules/apps/nft-transfer/client/cli/query.go | 140 ++++++++++++++++++ modules/apps/nft-transfer/client/cli/tx.go | 121 +++++++++++++++ modules/apps/nft-transfer/module.go | 11 +- modules/apps/nft-transfer/types/codec.go | 15 ++ modules/apps/nft-transfer/types/msgs.go | 90 +++++++++++ 6 files changed, 415 insertions(+), 5 deletions(-) create mode 100644 modules/apps/nft-transfer/client/cli/cli.go create mode 100644 modules/apps/nft-transfer/client/cli/query.go create mode 100644 modules/apps/nft-transfer/client/cli/tx.go create mode 100644 modules/apps/nft-transfer/types/msgs.go diff --git a/modules/apps/nft-transfer/client/cli/cli.go b/modules/apps/nft-transfer/client/cli/cli.go new file mode 100644 index 00000000000..3ddd75804f6 --- /dev/null +++ b/modules/apps/nft-transfer/client/cli/cli.go @@ -0,0 +1,43 @@ +package cli + +import ( + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" +) + +// GetQueryCmd returns the query commands for IBC connections +func GetQueryCmd() *cobra.Command { + queryCmd := &cobra.Command{ + Use: "nft-transfer", + Short: "IBC non-fungible token transfer query subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + queryCmd.AddCommand( + GetCmdQueryClassTrace(), + GetCmdQueryClassTraces(), + GetCmdQueryEscrowAddress(), + GetCmdQueryClassHash(), + ) + + return queryCmd +} + +// NewTxCmd returns the transaction commands for IBC fungible token transfer +func NewTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: "nft-transfer", + Short: "IBC fungible token transfer transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + NewTransferTxCmd(), + ) + + return txCmd +} diff --git a/modules/apps/nft-transfer/client/cli/query.go b/modules/apps/nft-transfer/client/cli/query.go new file mode 100644 index 00000000000..e8c0afac52d --- /dev/null +++ b/modules/apps/nft-transfer/client/cli/query.go @@ -0,0 +1,140 @@ +package cli + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/version" + "github.com/spf13/cobra" + + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" +) + +// GetCmdQueryClassTrace defines the command to query a a class trace from a given trace hash or ibc class. +func GetCmdQueryClassTrace() *cobra.Command { + cmd := &cobra.Command{ + Use: "class-trace [hash/class]", + Short: "Query the class trace info from a given trace hash or ibc class", + Long: "Query the class trace info from a given trace hash or ibc class", + Example: fmt.Sprintf("%s query nft-transfer class-trace 27A6394C3F9FF9C9DCF5DFFADF9BB5FE9A37C7E92B006199894CF1824DF9AC7C", version.AppName), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + req := &types.QueryClassTraceRequest{ + Hash: args[0], + } + + res, err := queryClient.ClassTrace(cmd.Context(), req) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryClassTraces defines the command to query all the class trace infos +// that this chain mantains. +func GetCmdQueryClassTraces() *cobra.Command { + cmd := &cobra.Command{ + Use: "class-traces", + Short: "Query the trace info for all the class", + Long: "Query the trace info for all the class", + Example: fmt.Sprintf("%s query nft-transfer class-traces", version.AppName), + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + req := &types.QueryClassTracesRequest{ + Pagination: pageReq, + } + + res, err := queryClient.ClassTraces(cmd.Context(), req) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "class trace") + + return cmd +} + +// GetCmdQueryEscrowAddress returns the command handler for nft-transfer escrow-address querying. +func GetCmdQueryEscrowAddress() *cobra.Command { + cmd := &cobra.Command{ + Use: "escrow-address", + Short: "Get the escrow address for a channel", + Long: "Get the escrow address for a channel", + Args: cobra.ExactArgs(2), + Example: fmt.Sprintf("%s query nft-transfer escrow-address [port] [channel-id]", version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + port := args[0] + channel := args[1] + addr := types.GetEscrowAddress(port, channel) + return clientCtx.PrintString(fmt.Sprintf("%s\n", addr.String())) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdQueryClassHash defines the command to query a class hash from a given trace. +func GetCmdQueryClassHash() *cobra.Command { + cmd := &cobra.Command{ + Use: "class-hash [trace]", + Short: "Query the class hash info from a given class trace", + Long: "Query the class hash info from a given class trace", + Example: fmt.Sprintf("%s query nft-transfer class-hash transfer/channel-0/class-id", version.AppName), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + req := &types.QueryClassHashRequest{ + Trace: args[0], + } + + res, err := queryClient.ClassHash(cmd.Context(), req) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} diff --git a/modules/apps/nft-transfer/client/cli/tx.go b/modules/apps/nft-transfer/client/cli/tx.go new file mode 100644 index 00000000000..ac1c16148d9 --- /dev/null +++ b/modules/apps/nft-transfer/client/cli/tx.go @@ -0,0 +1,121 @@ +package cli + +import ( + "errors" + "fmt" + "strings" + "time" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/version" + "github.com/spf13/cobra" + + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" + clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" + channelutils "github.com/cosmos/ibc-go/v3/modules/core/04-channel/client/utils" +) + +const ( + flagPacketTimeoutHeight = "packet-timeout-height" + flagPacketTimeoutTimestamp = "packet-timeout-timestamp" + flagAbsoluteTimeouts = "absolute-timeouts" +) + +// NewTransferTxCmd returns the command to create a NewMsgTransfer transaction +func NewTransferTxCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "nft-transfer [src-port] [src-channel] [receiver] [classID] [tokenIDs]", + Short: "Transfer a non-fungible token through IBC", + Long: strings.TrimSpace(`Transfer a non-fungible token through IBC. Timeouts can be specified +as absolute or relative using the "absolute-timeouts" flag. Timeout height can be set by passing in the height string +in the form {revision}-{height} using the "packet-timeout-height" flag. Relative timeout height is added to the block +height queried from the latest consensus state corresponding to the counterparty channel. Relative timeout timestamp +is added to the greater value of the local clock time and the block timestamp queried from the latest consensus state +corresponding to the counterparty channel. Any timeout set to 0 is disabled.`), + Example: fmt.Sprintf("%s tx nft-transfer transfer [src-port] [src-channel] [classID] [tokenIDs]", version.AppName), + Args: cobra.ExactArgs(4), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + sender := clientCtx.GetFromAddress().String() + srcPort := args[0] + srcChannel := args[1] + receiver := args[2] + classID := args[3] + tokenIDs := strings.Split(args[4], ",") + + if len(tokenIDs) == 0 { + return errors.New("tokenIDs cannot be empty") + } + + timeoutHeightStr, err := cmd.Flags().GetString(flagPacketTimeoutHeight) + if err != nil { + return err + } + timeoutHeight, err := clienttypes.ParseHeight(timeoutHeightStr) + if err != nil { + return err + } + + timeoutTimestamp, err := cmd.Flags().GetUint64(flagPacketTimeoutTimestamp) + if err != nil { + return err + } + + absoluteTimeouts, err := cmd.Flags().GetBool(flagAbsoluteTimeouts) + if err != nil { + return err + } + + // if the timeouts are not absolute, retrieve latest block height and block timestamp + // for the consensus state connected to the destination port/channel + if !absoluteTimeouts { + consensusState, height, _, err := channelutils.QueryLatestConsensusState(clientCtx, srcPort, srcChannel) + if err != nil { + return err + } + + if !timeoutHeight.IsZero() { + absoluteHeight := height + absoluteHeight.RevisionNumber += timeoutHeight.RevisionNumber + absoluteHeight.RevisionHeight += timeoutHeight.RevisionHeight + timeoutHeight = absoluteHeight + } + + if timeoutTimestamp != 0 { + // use local clock time as reference time if it is later than the + // consensus state timestamp of the counter party chain, otherwise + // still use consensus state timestamp as reference + now := time.Now().UnixNano() + consensusStateTimestamp := consensusState.GetTimestamp() + if now > 0 { + now := uint64(now) + if now > consensusStateTimestamp { + timeoutTimestamp = now + timeoutTimestamp + } else { + timeoutTimestamp = consensusStateTimestamp + timeoutTimestamp + } + } else { + return errors.New("local clock time is not greater than Jan 1st, 1970 12:00 AM") + } + } + } + + msg := types.NewMsgTransfer( + srcPort, srcChannel, classID, tokenIDs, sender, receiver, timeoutHeight, timeoutTimestamp, + ) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(flagPacketTimeoutHeight, types.DefaultRelativePacketTimeoutHeight, "Packet timeout block height. The timeout is disabled when set to 0-0.") + cmd.Flags().Uint64(flagPacketTimeoutTimestamp, types.DefaultRelativePacketTimeoutTimestamp, "Packet timeout timestamp in nanoseconds from now. Default is 10 minutes. The timeout is disabled when set to 0.") + cmd.Flags().Bool(flagAbsoluteTimeouts, false, "Timeout flags are used as absolute timeouts.") + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/modules/apps/nft-transfer/module.go b/modules/apps/nft-transfer/module.go index fa3b6ba6bc4..7d9a4c41915 100644 --- a/modules/apps/nft-transfer/module.go +++ b/modules/apps/nft-transfer/module.go @@ -19,6 +19,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/client/cli" "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/keeper" "github.com/cosmos/ibc-go/v3/modules/apps/nft-transfer/types" porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types" @@ -39,7 +40,9 @@ func (AppModuleBasic) Name() string { } // RegisterLegacyAminoCodec implements AppModuleBasic interface -func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {} +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} // RegisterInterfaces registers module concrete types into protobuf Any. func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { @@ -72,14 +75,12 @@ func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *r // GetTxCmd implements AppModuleBasic interface func (AppModuleBasic) GetTxCmd() *cobra.Command { - //return cli.NewTxCmd() - return nil + return cli.NewTxCmd() } // GetQueryCmd implements AppModuleBasic interface func (AppModuleBasic) GetQueryCmd() *cobra.Command { - //return cli.GetQueryCmd() - return nil + return cli.GetQueryCmd() } // AppModule represents the AppModule for this module diff --git a/modules/apps/nft-transfer/types/codec.go b/modules/apps/nft-transfer/types/codec.go index 4615d4a228c..ae994780f42 100644 --- a/modules/apps/nft-transfer/types/codec.go +++ b/modules/apps/nft-transfer/types/codec.go @@ -7,6 +7,12 @@ import ( "github.com/cosmos/cosmos-sdk/types/msgservice" ) +// RegisterLegacyAminoCodec registers the necessary x/ibc transfer interfaces and concrete types +// on the provided LegacyAmino codec. These types are used for Amino JSON serialization. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgTransfer{}, "cosmos-sdk/MsgTransferNFT", nil) +} + // RegisterInterfaces register the ibc transfer module interfaces to protobuf // Any. func RegisterInterfaces(registry codectypes.InterfaceRegistry) { @@ -16,6 +22,7 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { } var ( + amino = codec.NewLegacyAmino() // ModuleCdc references the global x/ibc-transfer module codec. Note, the codec // should ONLY be used in certain instances of tests and for JSON encoding. @@ -23,4 +30,12 @@ var ( // The actual codec used for serialization should be provided to x/ibc transfer and // defined at the application level. ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) + + // AminoCdc is a amino codec created to support amino json compatible msgs. + AminoCdc = codec.NewAminoCodec(amino) ) + +func init() { + RegisterLegacyAminoCodec(amino) + amino.Seal() +} diff --git a/modules/apps/nft-transfer/types/msgs.go b/modules/apps/nft-transfer/types/msgs.go new file mode 100644 index 00000000000..90a00b430e1 --- /dev/null +++ b/modules/apps/nft-transfer/types/msgs.go @@ -0,0 +1,90 @@ +package types + +import ( + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" + host "github.com/cosmos/ibc-go/v3/modules/core/24-host" +) + +// msg types +const ( + TypeMsgTransfer = "nft-transfer" +) + +// NewMsgTransfer creates a new MsgTransfer instance +//nolint:interfacer +func NewMsgTransfer( + sourcePort, sourceChannel string, + classID string, tokenIds []string, sender, receiver string, + timeoutHeight clienttypes.Height, timeoutTimestamp uint64, +) *MsgTransfer { + return &MsgTransfer{ + SourcePort: sourcePort, + SourceChannel: sourceChannel, + ClassId: classID, + TokenIds: tokenIds, + Sender: sender, + Receiver: receiver, + TimeoutHeight: timeoutHeight, + TimeoutTimestamp: timeoutTimestamp, + } +} + +// Route implements sdk.Msg +func (MsgTransfer) Route() string { + return RouterKey +} + +// Type implements sdk.Msg +func (MsgTransfer) Type() string { + return TypeMsgTransfer +} + +// ValidateBasic performs a basic check of the MsgTransfer fields. +// NOTE: timeout height or timestamp values can be 0 to disable the timeout. +// NOTE: The recipient addresses format is not validated as the format defined by +// the chain is not known to IBC. +func (msg MsgTransfer) ValidateBasic() error { + if err := host.PortIdentifierValidator(msg.SourcePort); err != nil { + return sdkerrors.Wrap(err, "invalid source port ID") + } + if err := host.ChannelIdentifierValidator(msg.SourceChannel); err != nil { + return sdkerrors.Wrap(err, "invalid source channel ID") + } + + if strings.TrimSpace(msg.ClassId) == "" { + return sdkerrors.Wrap(ErrInvalidClassID, "classId cannot be blank") + } + + if len(msg.TokenIds) == 0 { + return sdkerrors.Wrap(ErrInvalidTokenID, "tokenId cannot be blank") + } + + // NOTE: sender format must be validated as it is required by the GetSigners function. + _, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) + } + if strings.TrimSpace(msg.Receiver) == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing recipient address") + } + return nil +} + +// GetSignBytes implements sdk.Msg. +func (msg MsgTransfer) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) +} + +// GetSigners implements sdk.Msg +func (msg MsgTransfer) GetSigners() []sdk.AccAddress { + signer, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + panic(err) + } + return []sdk.AccAddress{signer} +} From df7ce8b4dc308827aa2116cafd94ec791af40348 Mon Sep 17 00:00:00 2001 From: Dreamer <745124335@qq.com> Date: Thu, 2 Jun 2022 11:49:24 +0800 Subject: [PATCH 14/14] add uint test for types package --- modules/apps/nft-transfer/client/cli/cli.go | 4 +- modules/apps/nft-transfer/client/cli/tx.go | 2 +- modules/apps/nft-transfer/types/codec.go | 8 +- .../apps/nft-transfer/types/genesis_test.go | 40 ++++++++++ modules/apps/nft-transfer/types/msgs.go | 6 ++ modules/apps/nft-transfer/types/msgs_test.go | 37 +++++++++ .../apps/nft-transfer/types/packet_test.go | 49 ++++++++++++ modules/apps/nft-transfer/types/trace.go | 7 +- modules/apps/nft-transfer/types/trace_test.go | 76 +++++++++++++++++++ 9 files changed, 219 insertions(+), 10 deletions(-) create mode 100644 modules/apps/nft-transfer/types/genesis_test.go create mode 100644 modules/apps/nft-transfer/types/msgs_test.go create mode 100644 modules/apps/nft-transfer/types/packet_test.go create mode 100644 modules/apps/nft-transfer/types/trace_test.go diff --git a/modules/apps/nft-transfer/client/cli/cli.go b/modules/apps/nft-transfer/client/cli/cli.go index 3ddd75804f6..9a5d2f5f6dd 100644 --- a/modules/apps/nft-transfer/client/cli/cli.go +++ b/modules/apps/nft-transfer/client/cli/cli.go @@ -25,11 +25,11 @@ func GetQueryCmd() *cobra.Command { return queryCmd } -// NewTxCmd returns the transaction commands for IBC fungible token transfer +// NewTxCmd returns the transaction commands for IBC non-fungible token transfer func NewTxCmd() *cobra.Command { txCmd := &cobra.Command{ Use: "nft-transfer", - Short: "IBC fungible token transfer transaction subcommands", + Short: "IBC non-fungible token transfer transaction subcommands", DisableFlagParsing: true, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, diff --git a/modules/apps/nft-transfer/client/cli/tx.go b/modules/apps/nft-transfer/client/cli/tx.go index ac1c16148d9..03eba9b70e4 100644 --- a/modules/apps/nft-transfer/client/cli/tx.go +++ b/modules/apps/nft-transfer/client/cli/tx.go @@ -26,7 +26,7 @@ const ( // NewTransferTxCmd returns the command to create a NewMsgTransfer transaction func NewTransferTxCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "nft-transfer [src-port] [src-channel] [receiver] [classID] [tokenIDs]", + Use: "transfer [src-port] [src-channel] [receiver] [classID] [tokenIDs]", Short: "Transfer a non-fungible token through IBC", Long: strings.TrimSpace(`Transfer a non-fungible token through IBC. Timeouts can be specified as absolute or relative using the "absolute-timeouts" flag. Timeout height can be set by passing in the height string diff --git a/modules/apps/nft-transfer/types/codec.go b/modules/apps/nft-transfer/types/codec.go index ae994780f42..3312c300125 100644 --- a/modules/apps/nft-transfer/types/codec.go +++ b/modules/apps/nft-transfer/types/codec.go @@ -7,13 +7,13 @@ import ( "github.com/cosmos/cosmos-sdk/types/msgservice" ) -// RegisterLegacyAminoCodec registers the necessary x/ibc transfer interfaces and concrete types +// RegisterLegacyAminoCodec registers the necessary nft-transfer interfaces and concrete types // on the provided LegacyAmino codec. These types are used for Amino JSON serialization. func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgTransfer{}, "cosmos-sdk/MsgTransferNFT", nil) } -// RegisterInterfaces register the ibc transfer module interfaces to protobuf +// RegisterInterfaces register the ibc nft-transfer module interfaces to protobuf // Any. func RegisterInterfaces(registry codectypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgTransfer{}) @@ -24,10 +24,10 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { var ( amino = codec.NewLegacyAmino() - // ModuleCdc references the global x/ibc-transfer module codec. Note, the codec + // ModuleCdc references the global nft-transfer module codec. Note, the codec // should ONLY be used in certain instances of tests and for JSON encoding. // - // The actual codec used for serialization should be provided to x/ibc transfer and + // The actual codec used for serialization should be provided to nft-transfer and // defined at the application level. ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) diff --git a/modules/apps/nft-transfer/types/genesis_test.go b/modules/apps/nft-transfer/types/genesis_test.go new file mode 100644 index 00000000000..b702bd65abf --- /dev/null +++ b/modules/apps/nft-transfer/types/genesis_test.go @@ -0,0 +1,40 @@ +package types + +import ( + "testing" +) + +func TestGenesisState_Validate(t *testing.T) { + tests := []struct { + name string + genState *GenesisState + wantErr bool + }{ + { + name: "default", + genState: DefaultGenesisState(), + wantErr: false, + }, + { + "valid genesis", + &GenesisState{ + PortId: "portidone", + }, + false, + }, + { + "invalid client", + &GenesisState{ + PortId: "(INVALIDPORT)", + }, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := tt.genState.Validate(); (err != nil) != tt.wantErr { + t.Errorf("GenesisState.Validate() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/modules/apps/nft-transfer/types/msgs.go b/modules/apps/nft-transfer/types/msgs.go index 90a00b430e1..cdbdb8f2c8f 100644 --- a/modules/apps/nft-transfer/types/msgs.go +++ b/modules/apps/nft-transfer/types/msgs.go @@ -64,6 +64,12 @@ func (msg MsgTransfer) ValidateBasic() error { return sdkerrors.Wrap(ErrInvalidTokenID, "tokenId cannot be blank") } + for _, tokenID := range msg.TokenIds { + if strings.TrimSpace(tokenID) == "" { + return sdkerrors.Wrap(ErrInvalidTokenID, "tokenId cannot be blank") + } + } + // NOTE: sender format must be validated as it is required by the GetSigners function. _, err := sdk.AccAddressFromBech32(msg.Sender) if err != nil { diff --git a/modules/apps/nft-transfer/types/msgs_test.go b/modules/apps/nft-transfer/types/msgs_test.go new file mode 100644 index 00000000000..c724b03e5cf --- /dev/null +++ b/modules/apps/nft-transfer/types/msgs_test.go @@ -0,0 +1,37 @@ +package types + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" +) + +var ( + sender = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String() + receiver = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String() +) + +func TestMsgTransfer_ValidateBasic(t *testing.T) { + tests := []struct { + name string + msg *MsgTransfer + wantErr bool + }{ + {"valid msg", NewMsgTransfer("nft-transfer", "channel-1", "cryptoCat", []string{"kitty"}, sender, receiver, clienttypes.NewHeight(1, 1), 1), false}, + {"invalid msg with port", NewMsgTransfer("@nft-transfer", "channel-1", "cryptoCat", []string{"kitty"}, sender, receiver, clienttypes.NewHeight(1, 1), 1), true}, + {"invalid msg with channel", NewMsgTransfer("nft-transfer", "@channel-1", "cryptoCat", []string{"kitty"}, sender, receiver, clienttypes.NewHeight(1, 1), 1), true}, + {"invalid msg with class", NewMsgTransfer("nft-transfer", "channel-1", "", []string{"kitty"}, sender, receiver, clienttypes.NewHeight(1, 1), 1), true}, + {"invalid msg with token_id", NewMsgTransfer("nft-transfer", "channel-1", "cryptoCat", []string{""}, sender, receiver, clienttypes.NewHeight(1, 1), 1), true}, + {"invalid msg with sender", NewMsgTransfer("nft-transfer", "channel-1", "cryptoCat", []string{"kitty"}, "", receiver, clienttypes.NewHeight(1, 1), 1), true}, + {"invalid msg with receiver", NewMsgTransfer("nft-transfer", "channel-1", "cryptoCat", []string{"kitty"}, sender, "", clienttypes.NewHeight(1, 1), 1), true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := tt.msg.ValidateBasic(); (err != nil) != tt.wantErr { + t.Errorf("MsgTransfer.ValidateBasic() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/modules/apps/nft-transfer/types/packet_test.go b/modules/apps/nft-transfer/types/packet_test.go new file mode 100644 index 00000000000..16bae1bb8f3 --- /dev/null +++ b/modules/apps/nft-transfer/types/packet_test.go @@ -0,0 +1,49 @@ +package types + +import "testing" + +func TestNonFungibleTokenPacketData_ValidateBasic(t *testing.T) { + tests := []struct { + name string + packet NonFungibleTokenPacketData + wantErr bool + }{ + { + name: "valid packet", + packet: NonFungibleTokenPacketData{"cryptoCat", "uri", []string{"kitty"}, []string{"kitty_uri"}, sender, receiver}, + wantErr: false, + }, + { + name: "invalid packet with empty classID", + packet: NonFungibleTokenPacketData{"", "uri", []string{"kitty"}, []string{"kitty_uri"}, sender, receiver}, + wantErr: true, + }, + { + name: "invalid packet with empty tokenIds", + packet: NonFungibleTokenPacketData{"cryptoCat", "uri", []string{}, []string{"kitty_uri"}, sender, receiver}, + wantErr: true, + }, + { + name: "invalid packet with empty tokenUris", + packet: NonFungibleTokenPacketData{"cryptoCat", "uri", []string{"kitty"}, []string{}, sender, receiver}, + wantErr: true, + }, + { + name: "invalid packet with empty sender", + packet: NonFungibleTokenPacketData{"cryptoCat", "uri", []string{"kitty"}, []string{}, "", receiver}, + wantErr: true, + }, + { + name: "invalid packet with empty receiver", + packet: NonFungibleTokenPacketData{"cryptoCat", "uri", []string{"kitty"}, []string{}, sender, receiver}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := tt.packet.ValidateBasic(); (err != nil) != tt.wantErr { + t.Errorf("NonFungibleTokenPacketData.ValidateBasic() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/modules/apps/nft-transfer/types/trace.go b/modules/apps/nft-transfer/types/trace.go index 8d47704c605..42898e3b91f 100644 --- a/modules/apps/nft-transfer/types/trace.go +++ b/modules/apps/nft-transfer/types/trace.go @@ -33,11 +33,12 @@ func GetClassPrefix(portID, channelID string) string { return fmt.Sprintf("%s/%s/", portID, channelID) } -// RemoveClassPrefix returns the unprefixed classID +// RemoveClassPrefix returns the unprefixed classID. +// After the receiving chain receives the packet,if isAwayFromOrigin=false, it means that nft is moving +// in the direction of the original chain, and the portID/channelID prefix of the sending chain +// in trace.path needs to be removed func RemoveClassPrefix(portID, channelID, classID string) string { - // since SendPacket did not prefix the classID, we must prefix classID here classPrefix := GetClassPrefix(portID, channelID) - // NOTE: sourcePrefix contains the trailing "/" return classID[len(classPrefix):] } diff --git a/modules/apps/nft-transfer/types/trace_test.go b/modules/apps/nft-transfer/types/trace_test.go new file mode 100644 index 00000000000..c668526dc94 --- /dev/null +++ b/modules/apps/nft-transfer/types/trace_test.go @@ -0,0 +1,76 @@ +package types + +import ( + "reflect" + "testing" +) + +func TestIsAwayFromOrigin(t *testing.T) { + type args struct { + sourcePort string + sourceChannel string + fullClassPath string + } + tests := []struct { + name string + args args + want bool + }{ + {"transfer forward by origin chain", args{"p1", "c1", "kitty"}, true}, + {"transfer forward by relay chain", args{"p3", "c3", "p2/c2/kitty"}, true}, + {"transfer forward by relay chain", args{"p5", "c5", "p4/c4/p2/c2/kitty"}, true}, + {"transfer back by relay chain", args{"p6", "c6", "p6/c6/p4/c4/p2/c2/kitty"}, false}, + {"transfer back by relay chain", args{"p4", "c4", "p4/c4/p2/c2/kitty"}, false}, + {"transfer back by relay chain", args{"p2", "c2", "p2/c2/kitty"}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsAwayFromOrigin(tt.args.sourcePort, tt.args.sourceChannel, tt.args.fullClassPath); got != tt.want { + t.Errorf("IsAwayFromOrigin() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestParseClassTrace(t *testing.T) { + type args struct { + rawClassID string + } + tests := []struct { + name string + args args + want ClassTrace + }{ + {"native class", args{"kitty"}, ClassTrace{Path: "", BaseClassId: "kitty"}}, + {"transfer to (p2,c2)", args{"p2/c2/kitty"}, ClassTrace{Path: "p2/c2", BaseClassId: "kitty"}}, + {"transfer to (p4,c4)", args{"p4/c4/p2/c2/kitty"}, ClassTrace{Path: "p4/c4/p2/c2", BaseClassId: "kitty"}}, + {"transfer to (p6,c6)", args{"p6/c6/p4/c4/p2/c2/kitty"}, ClassTrace{Path: "p6/c6/p4/c4/p2/c2", BaseClassId: "kitty"}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ParseClassTrace(tt.args.rawClassID); !reflect.DeepEqual(got, tt.want) { + t.Errorf("ParseClassTrace() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestClassTrace_GetFullClassPath(t *testing.T) { + tests := []struct { + name string + ct ClassTrace + want string + }{ + {"native class", ClassTrace{Path: "", BaseClassId: "kitty"}, "kitty"}, + {"first tranfer", ClassTrace{Path: "p2/c2", BaseClassId: "kitty"}, "p2/c2/kitty"}, + {"second tranfer", ClassTrace{Path: "p4/c4/p2/c2", BaseClassId: "kitty"}, "p4/c4/p2/c2/kitty"}, + {"third tranfer", ClassTrace{Path: "p6/c6/p4/c4/p2/c2", BaseClassId: "kitty"}, "p6/c6/p4/c4/p2/c2/kitty"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.ct.GetFullClassPath(); got != tt.want { + t.Errorf("ClassTrace.GetFullClassPath() = %v, want %v", got, tt.want) + } + }) + } +}